17#include <QtNetwork/qhttpheaders.h>
25#define SECURITY_WIN32 1
27#elif QT_CONFIG(gssapi)
28#if defined(Q_OS_DARWIN)
31#include <gssapi/gssapi.h>
45static bool q_SSPI_library_load();
50#elif QT_CONFIG(gssapi)
51static bool qGssapiTestGetCredentials(
QStringView host);
361class QSSPIWindowsHandles
364 CredHandle credHandle;
365 CtxtHandle ctxHandle;
367#elif QT_CONFIG(gssapi)
371 gss_ctx_id_t gssCtx =
nullptr;
372 gss_name_t targetName;
392 int separatorPosn = 0;
396 if ((separatorPosn =
user.
indexOf(
"\\"_L1)) != -1) {
416 auto separator =
method.indexOf(
' ');
422 static const char methods[][10] = {
426#if QT_CONFIG(sspi) || QT_CONFIG(gssapi)
451#if !QT_CONFIG(gssapi)
469 for (
const auto ¤t : headers.
values(search)) {
485#if QT_CONFIG(sspi) || QT_CONFIG(gssapi)
490 if (!qGssapiTestGetCredentials(host))
506 auto privSetRealm = [
this](
QString newRealm) {
507 if (newRealm !=
realm) {
511 this->options[
"realm"_L1] =
realm;
545#if !QT_CONFIG(sspi) && !QT_CONFIG(gssapi)
555 methodString =
"Basic";
560 methodString =
"Digest";
565 methodString =
"NTLM";
570 phase1Token = qSspiStartup(
this,
method, host);
571 }
else if (!q_SSPI_library_load()) {
573 qWarning(
"Failed to load the SSPI libraries");
576 if (!phase1Token.isEmpty()) {
591 if (sspiWindowsHandles)
593 if (!phase3Token.isEmpty()) {
607 methodString =
"Negotiate";
611 phase1Token = qSspiStartup(
this,
method, host);
612#elif QT_CONFIG(gssapi)
613 phase1Token = qGssapiStartup(
this, host);
616 if (!phase1Token.isEmpty()) {
626 if (sspiWindowsHandles)
628#elif QT_CONFIG(gssapi)
632 if (!phase3Token.isEmpty()) {
645 return methodString +
' ' + response;
654 if (element ==
"auth"_L1)
660QHash<QByteArray, QByteArray>
663 QHash<QByteArray, QByteArray>
options;
668 while (
d <
end && (*
d ==
' ' || *
d ==
'\n' || *
d ==
'\r'))
671 while (
d <
end && *
d !=
'=')
684 bool backslash =
false;
685 if (*
d ==
'\\' &&
d <
end - 1) {
701 while (
d <
end && *
d !=
',')
708 if (!qop.isEmpty()) {
710 return QHash<QByteArray, QByteArray>();
749 hash.addData(userName);
753 hash.addData(password);
761 hash.addData(ha1.toHex());
765 hash.addData(cNonce);
774 hash.addData(digestUri);
777 hash.addData(hEntity);
788 hash.addData(nonceCount);
790 hash.addData(cNonce);
795 hash.addData(ha2hex);
796 return hash.result().toHex();
806 while (nonceCountString.size() < 8)
807 nonceCountString.prepend(
'0');
816 nonce, nonceCountString,
822 credentials +=
"username=\"" +
user.
toLatin1() +
"\", ";
824 credentials +=
"nonce=\"" + nonce +
"\", ";
825 credentials +=
"uri=\"" +
path +
"\", ";
827 credentials +=
"opaque=\"" + opaque +
"\", ";
828 credentials +=
"response=\"" + response +
'"';
830 credentials +=
", algorithm=" +
options.
value(
"algorithm");
832 credentials +=
", qop=" + qop +
", ";
833 credentials +=
"nc=" + nonceCountString +
", ";
834 credentials +=
"cnonce=\"" +
cnonce +
'"';
857#define NTLMSSP_NEGOTIATE_UNICODE 0x00000001
862#define NTLMSSP_NEGOTIATE_OEM 0x00000002
868#define NTLMSSP_REQUEST_TARGET 0x00000004
874#define NTLMSSP_NEGOTIATE_SIGN 0x00000010
880#define NTLMSSP_NEGOTIATE_SEAL 0x00000020
885#define NTLMSSP_NEGOTIATE_DATAGRAM 0x00000040
891#define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080
896#define NTLMSSP_NEGOTIATE_NTLM 0x00000200
904#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x00001000
911#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x00002000
918#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x00004000
924#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000
930#define NTLMSSP_TARGET_TYPE_DOMAIN 0x00010000
936#define NTLMSSP_TARGET_TYPE_SERVER 0x00020000
943#define NTLMSSP_TARGET_TYPE_SHARE 0x00040000
951#define NTLMSSP_NEGOTIATE_NTLM2 0x00080000
958#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x00800000
963#define NTLMSSP_NEGOTIATE_128 0x20000000
971#define NTLMSSP_NEGOTIATE_KEY_EXCHANGE 0x40000000
976#define NTLMSSP_NEGOTIATE_56 0x80000000
1079 return buf.offset +
buf.len;
1087 buf.len = 2 *
s.size();
1090 return buf.offset +
buf.len;
1096 s <<
b.len <<
b.maxLen <<
b.offset;
1102 s >>
b.len >>
b.maxLen >>
b.offset;
1154 s.writeRawData(
b.magic,
sizeof(
b.magic));
1159 if (!
b.domainStr.isEmpty())
1161 if (!
b.workstationStr.isEmpty())
1169 s.writeRawData(
b.magic,
sizeof(
b.magic));
1172 s <<
b.ntlmResponse;
1179 if (!
b.domainStr.isEmpty())
1184 if (!
b.workstationStr.isEmpty())
1210 unsigned short *
d = (
unsigned short*)rc.
data();
1221 unsigned short *
d = (
unsigned short*)
src.data();
1222 for (
int i = 0;
i <
src.size() / 2; ++
i) {
1254 Q_ASSERT_X(!(
key.isEmpty()),
"qEncodeHmacMd5",
"Empty key check");
1276 for(
int i = 0;
i<
key.size();
i++) {
1277 iKeyPad[
i] =
key[
i]^iKeyPad[
i];
1281 for(
int i = 0;
i<
key.size();
i++) {
1282 oKeyPad[
i] =
key[
i]^oKeyPad[
i];
1288 hash.addData(iKeyPad);
1295 hash.addData(oKeyPad);
1296 hmacDigest =
hash.result();
1316 if (phase3->v2Hash.size() == 0) {
1319 md4.addData(passUnicode);
1330 return phase3->v2Hash;
1354 timeArray.resize(avLen);
1388 if (
ch.targetInfo.len)
1394 if (timeArray.size()) {
1395 ds.
writeRawData(timeArray.constData(), timeArray.size());
1409 ds.
writeRawData(clientCh.constData(), clientCh.size());
1415 if (
ch.targetInfo.len > 0) {
1417 ch.targetInfoBuff.size());
1428 ntChallengeResp.append(temp);
1430 return ntChallengeResp;
1447 lmChallengeResp.append(clientCh);
1449 return lmChallengeResp;
1463 if (strncmp(
ch.magic,
"NTLMSSP", 8) != 0)
1470 ds >>
ch.targetName;
1474 ds >>
ch.context[0] >>
ch.context[1];
1475 ds >>
ch.targetInfo;
1477 if (
ch.targetName.len > 0) {
1484 if (
ch.targetInfo.len > 0) {
1485 if (
ch.targetInfo.len +
ch.targetInfo.offset > (
unsigned)
data.size())
1488 ch.targetInfoBuff =
data.mid(
ch.targetInfo.offset,
ch.targetInfo.len);
1526 if (
ctx->userDomain.isEmpty() && !
ctx->extractedUser.contains(u
'@')) {
1541 if (
ch.targetInfo.len > 0) {
1567static PSecurityFunctionTableW pSecurityFunctionTable =
nullptr;
1569static bool q_SSPI_library_load()
1574 if (pSecurityFunctionTable ==
nullptr)
1575 pSecurityFunctionTable = InitSecurityInterfaceW();
1577 if (pSecurityFunctionTable ==
nullptr)
1586 if (!q_SSPI_library_load())
1591 if (!
ctx->sspiWindowsHandles)
1592 ctx->sspiWindowsHandles.reset(
new QSSPIWindowsHandles);
1593 SecInvalidateHandle(&
ctx->sspiWindowsHandles->credHandle);
1594 SecInvalidateHandle(&
ctx->sspiWindowsHandles->ctxHandle);
1596 SEC_WINNT_AUTH_IDENTITY auth;
1597 auth.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1598 bool useAuth =
false;
1600 auth.Domain =
const_cast<ushort *
>(
reinterpret_cast<const ushort *
>(
ctx->userDomain.constData()));
1601 auth.DomainLength =
ctx->userDomain.size();
1602 auth.User =
const_cast<ushort *
>(
reinterpret_cast<const ushort *
>(
ctx->user.constData()));
1603 auth.UserLength =
ctx->user.size();
1604 auth.Password =
const_cast<ushort *
>(
reinterpret_cast<const ushort *
>(
ctx->password.constData()));
1605 auth.PasswordLength =
ctx->password.size();
1610 SECURITY_STATUS secStatus = pSecurityFunctionTable->AcquireCredentialsHandle(
1614 &
ctx->sspiWindowsHandles->credHandle, &expiry
1616 if (secStatus != SEC_E_OK) {
1617 ctx->sspiWindowsHandles.reset(
nullptr);
1621 return qSspiContinue(
ctx,
method, host);
1628 SecBuffer challengeBuf;
1629 SecBuffer responseBuf;
1630 SecBufferDesc challengeDesc;
1631 SecBufferDesc responseDesc;
1632 unsigned long attrs;
1638 challengeDesc.ulVersion = SECBUFFER_VERSION;
1639 challengeDesc.cBuffers = 1;
1640 challengeDesc.pBuffers = &challengeBuf;
1641 challengeBuf.BufferType = SECBUFFER_TOKEN;
1642 challengeBuf.pvBuffer = (PVOID)(challenge.
data());
1643 challengeBuf.cbBuffer = challenge.
length();
1647 responseDesc.ulVersion = SECBUFFER_VERSION;
1648 responseDesc.cBuffers = 1;
1649 responseDesc.pBuffers = &responseBuf;
1650 responseBuf.BufferType = SECBUFFER_TOKEN;
1651 responseBuf.pvBuffer =
nullptr;
1652 responseBuf.cbBuffer = 0;
1655 QString targetName =
ctx->options.value(
"spn"_L1).toString();
1657 targetName =
"HTTP/"_L1 + host;
1659 ? targetName :
QString()).toStdWString();
1662 SECURITY_STATUS secStatus = pSecurityFunctionTable->InitializeSecurityContext(
1663 &
ctx->sspiWindowsHandles->credHandle,
1664 !challenge.
isEmpty() ? &
ctx->sspiWindowsHandles->ctxHandle :
nullptr,
1665 const_cast<wchar_t*
>(targetNameW.data()),
1666 ISC_REQ_ALLOCATE_MEMORY,
1667 0, SECURITY_NATIVE_DREP,
1668 !challenge.
isEmpty() ? &challengeDesc :
nullptr,
1669 0, &
ctx->sspiWindowsHandles->ctxHandle,
1670 &responseDesc, &
attrs,
1674 if (secStatus == SEC_I_COMPLETE_NEEDED || secStatus == SEC_I_COMPLETE_AND_CONTINUE) {
1675 secStatus = pSecurityFunctionTable->CompleteAuthToken(&
ctx->sspiWindowsHandles->ctxHandle,
1679 if (secStatus != SEC_I_COMPLETE_AND_CONTINUE && secStatus != SEC_I_CONTINUE_NEEDED) {
1680 pSecurityFunctionTable->FreeCredentialsHandle(&
ctx->sspiWindowsHandles->credHandle);
1681 pSecurityFunctionTable->DeleteSecurityContext(&
ctx->sspiWindowsHandles->ctxHandle);
1682 ctx->sspiWindowsHandles.reset(
nullptr);
1685 result =
QByteArray((
const char*)responseBuf.pvBuffer, responseBuf.cbBuffer);
1686 pSecurityFunctionTable->FreeContextBuffer(responseBuf.pvBuffer);
1693#elif QT_CONFIG(gssapi)
1699static void q_GSSAPI_error_int(
const char *
message, OM_uint32 stat,
int type)
1701 OM_uint32 minStat, msgCtx = 0;
1702 gss_buffer_desc msg;
1705 gss_display_status(&minStat, stat,
type, GSS_C_NO_OID, &msgCtx, &msg);
1706 qCDebug(lcAuthenticator) <<
message <<
": " <<
reinterpret_cast<const char*
>(msg.value);
1707 gss_release_buffer(&minStat, &msg);
1712static void q_GSSAPI_error(
const char *
message, OM_uint32 majStat, OM_uint32 minStat)
1715 q_GSSAPI_error_int(
message, majStat, GSS_C_GSS_CODE);
1718 q_GSSAPI_error_int(
message, minStat, GSS_C_MECH_CODE);
1721static gss_name_t qGSsapiGetServiceName(
QStringView host)
1724 gss_buffer_desc nameDesc = {
static_cast<std::size_t
>(serviceName.
size()), serviceName.
data()};
1726 gss_name_t importedName;
1728 OM_uint32 majStat = gss_import_name(&minStat, &nameDesc,
1729 GSS_C_NT_HOSTBASED_SERVICE, &importedName);
1731 if (majStat != GSS_S_COMPLETE) {
1732 q_GSSAPI_error(
"gss_import_name error", majStat, minStat);
1735 return importedName;
1741 if (!
ctx->gssApiHandles)
1742 ctx->gssApiHandles.reset(
new QGssApiHandles);
1745 gss_name_t
name = qGSsapiGetServiceName(host);
1746 if (
name ==
nullptr) {
1747 ctx->gssApiHandles.reset(
nullptr);
1750 ctx->gssApiHandles->targetName =
name;
1753 ctx->gssApiHandles->gssCtx = GSS_C_NO_CONTEXT;
1754 return qGssapiContinue(
ctx);
1760 OM_uint32 majStat, minStat, ignored;
1762 gss_buffer_desc inBuf = {0,
nullptr};
1763 gss_buffer_desc outBuf;
1766 inBuf.value =
const_cast<char*
>(challenge.
data());
1767 inBuf.length = challenge.
size();
1770 majStat = gss_init_sec_context(&minStat,
1771 GSS_C_NO_CREDENTIAL,
1772 &
ctx->gssApiHandles->gssCtx,
1773 ctx->gssApiHandles->targetName,
1777 GSS_C_NO_CHANNEL_BINDINGS,
1778 challenge.
isEmpty() ? GSS_C_NO_BUFFER : &inBuf,
1784 if (outBuf.length != 0)
1785 result =
QByteArray(
reinterpret_cast<const char*
>(outBuf.value), outBuf.length);
1786 gss_release_buffer(&ignored, &outBuf);
1788 if (majStat != GSS_S_COMPLETE && majStat != GSS_S_CONTINUE_NEEDED) {
1789 q_GSSAPI_error(
"gss_init_sec_context error", majStat, minStat);
1790 gss_release_name(&ignored, &
ctx->gssApiHandles->targetName);
1791 if (
ctx->gssApiHandles->gssCtx)
1792 gss_delete_sec_context(&ignored, &
ctx->gssApiHandles->gssCtx, GSS_C_NO_BUFFER);
1793 ctx->gssApiHandles.reset(
nullptr);
1796 if (majStat == GSS_S_COMPLETE) {
1797 gss_release_name(&ignored, &
ctx->gssApiHandles->targetName);
1798 ctx->gssApiHandles.reset(
nullptr);
1804static bool qGssapiTestGetCredentials(
QStringView host)
1806 gss_name_t serviceName = qGSsapiGetServiceName(host);
1811 OM_uint32 majStat = gss_acquire_cred(&minStat, serviceName, GSS_C_INDEFINITE,
1812 GSS_C_NO_OID_SET, GSS_C_INITIATE, &cred,
nullptr,
1816 gss_release_name(&ignored, &serviceName);
1817 gss_release_cred(&ignored, &cred);
1819 if (majStat != GSS_S_COMPLETE) {
1820 q_GSSAPI_error(
"gss_acquire_cred", majStat, minStat);
static JNINativeMethod methods[]
static QHash< QByteArray, QByteArray > parseDigestAuthenticationChallenge(QByteArrayView challenge)
QByteArray calculateResponse(QByteArrayView method, QByteArrayView path, QStringView host)
QByteArray digestMd5Response(QByteArrayView challenge, QByteArrayView method, QByteArrayView path)
void parseHttpResponse(const QHttpHeaders &headers, bool isProxy, QStringView host)
static bool isMethodSupported(QByteArrayView method)
The QAuthenticator class provides an authentication object.
QString user() const
Returns the user used for authentication.
void setOption(const QString &opt, const QVariant &value)
~QAuthenticator()
Destructs the object.
void setPassword(const QString &password)
Sets the password used for authentication.
QAuthenticator & operator=(const QAuthenticator &other)
Assigns the contents of other to this authenticator.
QVariant option(const QString &opt) const
QAuthenticator()
Constructs an empty authentication object.
QString password() const
Returns the password used for authentication.
QString realm() const
Returns the realm requiring authentication.
bool isNull() const
Returns true if the object has not been initialized.
void setUser(const QString &user)
Sets the user used for authentication.
bool operator==(const QAuthenticator &other) const
Returns true if this authenticator is identical to other; otherwise returns false.
friend class QAuthenticatorPrivate
void setRealm(const QString &realm)
QVariantHash options() const
constexpr qsizetype length() const noexcept
constexpr QByteArrayView mid(qsizetype pos, qsizetype n=-1) const
constexpr QByteArrayView first(qsizetype n) const
constexpr bool isEmpty() const noexcept
constexpr qsizetype size() const noexcept
constexpr const_pointer data() const noexcept
QByteArray trimmed() const &
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
QByteArray right(qsizetype n) const &
static QByteArray fromBase64(const QByteArray &base64, Base64Options options=Base64Encoding)
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray toBase64(Base64Options options=Base64Encoding) const
static QByteArray hash(QByteArrayView data, Algorithm method)
Returns the hash of data using method.
\inmodule QtCore\reentrant
qint64 readRawData(char *, qint64 len)
Reads at most len bytes from the stream into s and returns the number of bytes read.
qint64 skipRawData(qint64 len)
qint64 writeRawData(const char *, qint64 len)
Writes len bytes from s to the stream.
void setByteOrder(ByteOrder)
Sets the serialization byte order to bo.
static qint64 currentSecsSinceEpoch() noexcept
T value(const Key &key) const noexcept
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
constexpr auto tokenize(Needle &&needle, Flags...flags) const noexcept(noexcept(qTokenize(std::declval< const QLatin1StringView & >(), std::forward< Needle >(needle), flags...))) -> decltype(qTokenize(*this, std::forward< Needle >(needle), flags...))
unsigned char challenge[8]
QByteArray targetInfoBuff
QByteArray ntlmResponseBuf
static Q_DECL_CONST_FUNCTION QRandomGenerator * system()
\threadsafe
const_iterator cend() const noexcept
const_iterator constFind(const T &value) const
QByteArray toLocal8Bit() const
Returns a local 8-bit representation of the string as a QByteArray.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString left(qsizetype n) const &
QByteArray toLatin1() const &
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString mid(qsizetype position, qsizetype n=-1) const &
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
void clear()
Clears the contents of the string and makes it null.
static QPartialOrdering compare(const QVariant &lhs, const QVariant &rhs)
Compares the objects at lhs and rhs for ordering.
QHash< int, QWidget * > hash
[35multi]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
static QByteArray clientChallenge(const QAuthenticatorPrivate *ctx)
static QByteArray qNtlmPhase1()
static QDataStream & operator<<(QDataStream &s, const QNtlmBuffer &b)
#define NTLMSSP_NEGOTIATE_NTLM2
#define NTLMSSP_NEGOTIATE_TARGET_INFO
static QByteArray qStringAsUcs2Le(const QString &src)
static QByteArray qEncodeLmv2Response(const QAuthenticatorPrivate *ctx, const QNtlmPhase2Block &ch, QNtlmPhase3Block *phase3)
static bool verifyDigestMD5(QByteArrayView value)
static bool containsAuth(QByteArrayView data)
static int qEncodeNtlmString(QNtlmBuffer &buf, int offset, const QString &s, bool unicode)
static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray &phase2data)
QByteArray qEncodeHmacMd5(QByteArray &key, QByteArrayView message)
#define NTLMSSP_NEGOTIATE_OEM
static QByteArray qEncodeNtlmv2Response(const QAuthenticatorPrivate *ctx, const QNtlmPhase2Block &ch, QNtlmPhase3Block *phase3)
static QByteArray digestMd5ResponseHelper(QByteArrayView alg, QByteArrayView userName, QByteArrayView realm, QByteArrayView password, QByteArrayView nonce, QByteArrayView nonceCount, QByteArrayView cNonce, QByteArrayView qop, QByteArrayView method, QByteArrayView digestUri, QByteArrayView hEntity)
static QDataStream & operator>>(QDataStream &s, QNtlmBuffer &b)
static QByteArray qCreatev2Hash(const QAuthenticatorPrivate *ctx, QNtlmPhase3Block *phase3)
static void qStreamNtlmBuffer(QDataStream &ds, const QByteArray &s)
#define NTLMSSP_REQUEST_TARGET
static QString qStringFromUcs2Le(QByteArray src)
static void qStreamNtlmString(QDataStream &ds, const QString &s, bool unicode)
#define NTLMSSP_NEGOTIATE_NTLM
static QByteArray qExtractServerTime(const QByteArray &targetInfoBuff)
#define NTLMSSP_NEGOTIATE_UNICODE
static int qEncodeNtlmBuffer(QNtlmBuffer &buf, int offset, const QByteArray &s)
const quint8 hirespversion
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN
static bool qNtlmDecodePhase2(const QByteArray &data, QNtlmPhase2Block &ch)
Q_CORE_EXPORT char * qstrncpy(char *dst, const char *src, size_t len)
QHash< QString, QVariant > QVariantHash
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 int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
static struct AttrInfo attrs[]
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
constexpr T qFromLittleEndian(T source)
constexpr T qToLittleEndian(T source)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLboolean GLboolean GLboolean b
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLenum GLsizei const GLchar * buf
GLuint GLsizei const GLchar * message
GLenum GLuint GLintptr offset
GLsizei const GLchar *const * path
#define Q_ASSERT_X(cond, x, msg)
unsigned long long quint64
static QString quote(const QString &str)