Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qnetworkaccessmanager.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtNetwork/private/qtnetworkglobal_p.h>
5
8#include "qnetworkrequest.h"
9#include "qnetworkreply.h"
10#include "qnetworkreply_p.h"
11#include "qnetworkcookie.h"
12#include "qnetworkcookiejar.h"
14#include "qhstspolicy.h"
15#include "qhsts_p.h"
16
17#if QT_CONFIG(settings)
18#include "qhstsstore_p.h"
19#endif // QT_CONFIG(settings)
20
26
28#include "qnetworkreplyimpl_p.h"
29
30#include "QtCore/qbuffer.h"
31#include "QtCore/qlist.h"
32#include "QtCore/qurl.h"
33#include "QtNetwork/private/qauthenticator_p.h"
34#include "QtNetwork/qsslconfiguration.h"
35
36#if QT_CONFIG(http)
37#include "QtNetwork/private/http2protocol_p.h"
38#include "qhttpmultipart.h"
39#include "qhttpmultipart_p.h"
41#endif
42
43#include "qthread.h"
44
45#include <QHostInfo>
46
47#include "QtCore/qapplicationstatic.h"
48#include "QtCore/qloggingcategory.h"
49#include <QtCore/private/qfactoryloader_p.h>
50
51#if defined(Q_OS_MACOS)
52#include <QtCore/private/qcore_mac_p.h>
53
54#include <CoreServices/CoreServices.h>
55#include <SystemConfiguration/SystemConfiguration.h>
56#include <Security/Security.h>
57#endif
58#ifdef Q_OS_WASM
60#include "qhttpmultipart.h"
61#include "qhttpmultipart_p.h"
62#endif
63
64#include "qnetconmonitor_p.h"
65
66#include <mutex>
67
69
70using namespace Qt::StringLiterals;
71
72Q_LOGGING_CATEGORY(lcQnam, "qt.network.access.manager")
73
75
76#ifdef QT_BUILD_INTERNAL
77Q_GLOBAL_STATIC(QNetworkAccessDebugPipeBackendFactory, debugpipeBackend)
78#endif
79
81
82#if defined(Q_OS_MACOS)
83bool getProxyAuth(const QString& proxyHostname, const QString &scheme, QString& username, QString& password)
84{
85 CFStringRef protocolType = nullptr;
86 if (scheme.compare("ftp"_L1, Qt::CaseInsensitive) == 0) {
87 protocolType = kSecAttrProtocolFTPProxy;
88 } else if (scheme.compare("http"_L1, Qt::CaseInsensitive) == 0
89 || scheme.compare("preconnect-http"_L1, Qt::CaseInsensitive) == 0) {
90 protocolType = kSecAttrProtocolHTTPProxy;
91 } else if (scheme.compare("https"_L1,Qt::CaseInsensitive)==0
92 || scheme.compare("preconnect-https"_L1, Qt::CaseInsensitive) == 0) {
93 protocolType = kSecAttrProtocolHTTPSProxy;
94 } else {
95 qCWarning(lcQnam) << "Cannot query user name and password for a proxy, unnknown protocol:"
96 << scheme;
97 return false;
98 }
99
100 QCFType<CFMutableDictionaryRef> query(CFDictionaryCreateMutable(kCFAllocatorDefault,
101 0, nullptr, nullptr));
103
104 CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword);
105 CFDictionaryAddValue(query, kSecAttrProtocol, protocolType);
106
107 QCFType<CFStringRef> serverName; // Note the scope.
108 if (proxyHostname.size()) {
109 serverName = proxyHostname.toCFString();
110 CFDictionaryAddValue(query, kSecAttrServer, serverName);
111 }
112
113 // This is to get the user name in the result:
114 CFDictionaryAddValue(query, kSecReturnAttributes, kCFBooleanTrue);
115 // This one to get the password:
116 CFDictionaryAddValue(query, kSecReturnData, kCFBooleanTrue);
117
118 // The default for kSecMatchLimit key is 1 (the first match only), which is fine,
119 // so don't set this value explicitly.
120
121 QCFType<CFTypeRef> replyData;
122 if (SecItemCopyMatching(query, &replyData) != errSecSuccess) {
123 qCWarning(lcQnam, "Failed to extract user name and password from the keychain.");
124 return false;
125 }
126
127 if (!replyData || CFDictionaryGetTypeID() != CFGetTypeID(replyData)) {
128 qCWarning(lcQnam, "Query returned data in unexpected format.");
129 return false;
130 }
131
132 CFDictionaryRef accountData = replyData.as<CFDictionaryRef>();
133 const void *value = CFDictionaryGetValue(accountData, kSecAttrAccount);
134 if (!value || CFGetTypeID(value) != CFStringGetTypeID()) {
135 qCWarning(lcQnam, "Cannot find user name or its format is unknown.");
136 return false;
137 }
138 username = QString::fromCFString(static_cast<CFStringRef>(value));
139
140 value = CFDictionaryGetValue(accountData, kSecValueData);
141 if (!value || CFGetTypeID(value) != CFDataGetTypeID()) {
142 qCWarning(lcQnam, "Cannot find password or its format is unknown.");
143 return false;
144 }
145 const CFDataRef passData = static_cast<const CFDataRef>(value);
146 password = QString::fromLocal8Bit(reinterpret_cast<const char *>(CFDataGetBytePtr(passData)),
147 qsizetype(CFDataGetLength(passData)));
148 return true;
149}
150#endif // Q_OS_MACOS
151
152
153
154static void ensureInitialized()
155{
156#ifdef QT_BUILD_INTERNAL
157 (void) debugpipeBackend();
158#endif
159
160 // leave this one last since it will query the special QAbstractFileEngines
161 (void) fileBackend();
162}
163
397{
399 d_func()->ensureBackendPluginsLoaded();
400
401 qRegisterMetaType<QNetworkReply::NetworkError>();
402#ifndef QT_NO_NETWORKPROXY
403 qRegisterMetaType<QNetworkProxy>();
404#endif
405#ifndef QT_NO_SSL
406 qRegisterMetaType<QList<QSslError> >();
407 qRegisterMetaType<QSslConfiguration>();
408 qRegisterMetaType<QSslPreSharedKeyAuthenticator *>();
409#endif
410 qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >();
411#if QT_CONFIG(http)
412 qRegisterMetaType<QHttpNetworkRequest>();
413#endif
414 qRegisterMetaType<QNetworkReply::NetworkError>();
415 qRegisterMetaType<QSharedPointer<char> >();
416}
417
426{
427#ifndef QT_NO_NETWORKPROXY
428 delete d_func()->proxyFactory;
429#endif
430
431 // Delete the QNetworkReply children first.
432 // Else a QAbstractNetworkCache might get deleted in ~QObject
433 // before a QNetworkReply that accesses the QAbstractNetworkCache
434 // object in its destructor.
435 qDeleteAll(findChildren<QNetworkReply *>());
436 // The other children will be deleted in this ~QObject
437 // FIXME instead of this "hack" make the QNetworkReplyImpl
438 // properly watch the cache deletion, e.g. via a QWeakPointer.
439}
440
441#ifndef QT_NO_NETWORKPROXY
450{
451 return d_func()->proxy;
452}
453
469{
471 delete d->proxyFactory;
472 d->proxy = proxy;
473 d->proxyFactory = nullptr;
474}
475
489{
490 return d_func()->proxyFactory;
491}
492
523{
525 delete d->proxyFactory;
526 d->proxyFactory = factory;
527 d->proxy = QNetworkProxy();
528}
529#endif
530
539{
540 Q_D(const QNetworkAccessManager);
541 return d->networkCache;
542}
543
561{
563 if (d->networkCache != cache) {
564 delete d->networkCache;
565 d->networkCache = cache;
566 if (d->networkCache)
567 d->networkCache->setParent(this);
568 }
569}
570
579{
580 Q_D(const QNetworkAccessManager);
581 if (!d->cookieJar)
582 d->createCookieJar();
583 return d->cookieJar;
584}
585
616{
618 d->cookieJarCreated = true;
619 if (d->cookieJar != cookieJar) {
620 if (d->cookieJar && d->cookieJar->parent() == this)
621 delete d->cookieJar;
622 d->cookieJar = cookieJar;
623 if (cookieJar && thread() == cookieJar->thread())
624 d->cookieJar->setParent(this);
625 }
626}
627
644{
646 d->stsEnabled = enabled;
647}
648
658{
659 Q_D(const QNetworkAccessManager);
660 return d->stsEnabled;
661}
662
684{
685#if QT_CONFIG(settings)
687 d->stsStore.reset(enabled ? new QHstsStore(storeDir) : nullptr);
688 d->stsCache.setStore(d->stsStore.data());
689#else
691 Q_UNUSED(storeDir);
692 qWarning("HSTS permanent store requires the feature 'settings' enabled");
693#endif // QT_CONFIG(settings)
694}
695
706{
707#if QT_CONFIG(settings)
708 Q_D(const QNetworkAccessManager);
709 return bool(d->stsStore.data());
710#else
711 return false;
712#endif // QT_CONFIG(settings)
713}
714
736{
738 d->stsCache.updateFromPolicies(knownHosts);
739}
740
751{
752 Q_D(const QNetworkAccessManager);
753 return d->stsCache.policies();
754}
755
763{
764 return d_func()->postProcess(createRequest(QNetworkAccessManager::HeadOperation, request));
765}
766
778{
779 return d_func()->postProcess(createRequest(QNetworkAccessManager::GetOperation, request));
780}
781
797{
798 return d_func()->postProcess(createRequest(QNetworkAccessManager::PostOperation, request, data));
799}
800
808{
809 QBuffer *buffer = new QBuffer;
812
814 buffer->setParent(reply);
815 return reply;
816}
817
818#if QT_CONFIG(http) || defined(Q_OS_WASM)
832{
833 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
834 QIODevice *device = multiPart->d_func()->device;
835 QNetworkReply *reply = post(newRequest, device);
836 return reply;
837}
838
852{
853 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
854 QIODevice *device = multiPart->d_func()->device;
855 QNetworkReply *reply = put(newRequest, device);
856 return reply;
857}
858#endif // QT_CONFIG(http)
859
880{
881 return d_func()->postProcess(createRequest(QNetworkAccessManager::PutOperation, request, data));
882}
883
891{
892 QBuffer *buffer = new QBuffer;
895
897 buffer->setParent(reply);
898 return reply;
899}
900
912{
913 return d_func()->postProcess(createRequest(QNetworkAccessManager::DeleteOperation, request));
914}
915
916#ifndef QT_NO_SSL
936 const QSslConfiguration &sslConfiguration)
937{
938 connectToHostEncrypted(hostName, port, sslConfiguration, QString());
939}
940
962 const QSslConfiguration &sslConfiguration,
963 const QString &peerName)
964{
965 QUrl url;
966 url.setHost(hostName);
968 url.setScheme("preconnect-https"_L1);
970 if (sslConfiguration != QSslConfiguration::defaultConfiguration())
971 request.setSslConfiguration(sslConfiguration);
972
973 // There is no way to enable HTTP2 via a request after having established the connection,
974 // so we need to check the ssl configuration whether HTTP2 is allowed here.
977
978 request.setPeerVerifyName(peerName);
979 get(request);
980}
981#endif
982
995{
996 QUrl url;
997 url.setHost(hostName);
999 url.setScheme("preconnect-http"_L1);
1001 get(request);
1002}
1003
1022{
1024 d->redirectPolicy = policy;
1025}
1026
1035{
1036 Q_D(const QNetworkAccessManager);
1037 return d->redirectPolicy;
1038}
1039
1060{
1061 QNetworkRequest newRequest(request);
1063 return d_func()->postProcess(createRequest(QNetworkAccessManager::CustomOperation, newRequest, data));
1064}
1065
1075{
1076 QBuffer *buffer = new QBuffer;
1079
1081 buffer->setParent(reply);
1082 return reply;
1083}
1084
1085#if QT_CONFIG(http) || defined(Q_OS_WASM)
1101{
1102 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
1103 QIODevice *device = multiPart->d_func()->device;
1104 QNetworkReply *reply = sendCustomRequest(newRequest, verb, device);
1105 return reply;
1106}
1107#endif // QT_CONFIG(http)
1108
1123 const QNetworkRequest &originalReq,
1124 QIODevice *outgoingData)
1125{
1127
1128 QNetworkRequest req(originalReq);
1132 }
1133
1134#if QT_CONFIG(http) || defined (Q_OS_WASM)
1135 if (!req.transferTimeout())
1136 req.setTransferTimeout(transferTimeout());
1137#endif
1138
1139 if (autoDeleteReplies()
1142 }
1143
1144 bool isLocalFile = req.url().isLocalFile();
1145 QString scheme = req.url().scheme();
1146
1147
1148 // fast path for GET on file:// URLs
1149 // The QNetworkAccessFileBackend will right now only be used for PUT
1152 if (isLocalFile
1153#ifdef Q_OS_ANDROID
1154 || scheme == "assets"_L1
1155#endif
1156 || scheme == "qrc"_L1) {
1157 return new QNetworkReplyFileImpl(this, req, op);
1158 }
1159
1160 if (scheme == "data"_L1)
1161 return new QNetworkReplyDataImpl(this, req, op);
1162
1163 // A request with QNetworkRequest::AlwaysCache does not need any bearer management
1169 // FIXME Implement a QNetworkReplyCacheImpl instead, see QTBUG-15106
1171 QNetworkReplyImplPrivate *priv = reply->d_func();
1172 priv->manager = this;
1173 priv->backend = new QNetworkAccessCacheBackend();
1174 priv->backend->setManagerPrivate(this->d_func());
1175 priv->backend->setParent(reply);
1176 priv->backend->setReplyPrivate(priv);
1177 priv->setup(op, req, outgoingData);
1178 return reply;
1179 }
1180 }
1182#ifndef Q_OS_WASM // Content-length header is not allowed to be set by user in wasm
1184 outgoingData && !outgoingData->isSequential()) {
1185 // request has no Content-Length
1186 // but the data that is outgoing is random-access
1188 }
1189#endif
1190 if (static_cast<QNetworkRequest::LoadControl>
1193 if (d->cookieJar) {
1194 QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url());
1195 if (!cookies.isEmpty())
1197 }
1198 }
1199#ifdef Q_OS_WASM
1200 Q_UNUSED(isLocalFile);
1201 // Support http, https, and relative urls
1202 if (scheme == "http"_L1 || scheme == "https"_L1 || scheme.isEmpty()) {
1205 priv->manager = this;
1206 priv->setup(op, request, outgoingData);
1207 return reply;
1208 }
1209#endif
1210
1211#if QT_CONFIG(http)
1212 constexpr char16_t httpSchemes[][17] = {
1213 u"http",
1214 u"preconnect-http",
1215#ifndef QT_NO_SSL
1216 u"https",
1217 u"preconnect-https",
1218#endif
1219 };
1220 // Since Qt 5 we use the new QNetworkReplyHttpImpl
1221 if (std::find(std::begin(httpSchemes), std::end(httpSchemes), scheme) != std::end(httpSchemes)) {
1222#ifndef QT_NO_SSL
1223 if (isStrictTransportSecurityEnabled() && d->stsCache.isKnownHost(request.url())) {
1224 QUrl stsUrl(request.url());
1225 // RFC6797, 8.3:
1226 // The UA MUST replace the URI scheme with "https" [RFC2818],
1227 // and if the URI contains an explicit port component of "80",
1228 // then the UA MUST convert the port component to be "443", or
1229 // if the URI contains an explicit port component that is not
1230 // equal to "80", the port component value MUST be preserved;
1231 // otherwise,
1232 // if the URI does not contain an explicit port component, the UA
1233 // MUST NOT add one.
1234 if (stsUrl.port() == 80)
1235 stsUrl.setPort(443);
1236 stsUrl.setScheme("https"_L1);
1237 request.setUrl(stsUrl);
1238 }
1239#endif
1240 QNetworkReplyHttpImpl *reply = new QNetworkReplyHttpImpl(this, request, op, outgoingData);
1241 return reply;
1242 }
1243#endif // QT_CONFIG(http)
1244
1245 // first step: create the reply
1247 QNetworkReplyImplPrivate *priv = reply->d_func();
1248 priv->manager = this;
1249
1250 // second step: fetch cached credentials
1251 // This is not done for the time being, we should use signal emissions to request
1252 // the credentials from cache.
1253
1254 // third step: find a backend
1255 priv->backend = d->findBackend(op, request);
1256
1257 if (priv->backend) {
1258 priv->backend->setParent(reply);
1259 priv->backend->setReplyPrivate(priv);
1260 }
1261
1262#ifndef QT_NO_SSL
1263 reply->setSslConfiguration(request.sslConfiguration());
1264#endif
1265
1266 // fourth step: setup the reply
1267 priv->setup(op, request, outgoingData);
1268
1269 return reply;
1270}
1271
1282{
1283 QStringList schemes;
1284 QNetworkAccessManager *self = const_cast<QNetworkAccessManager *>(this); // We know we call a const slot
1285 QMetaObject::invokeMethod(self, "supportedSchemesImplementation", Qt::DirectConnection,
1286 Q_RETURN_ARG(QStringList, schemes));
1287 schemes.removeDuplicates();
1288 return schemes;
1289}
1290
1307{
1308 Q_D(const QNetworkAccessManager);
1309
1310 QStringList schemes = d->backendSupportedSchemes();
1311 // Those ones don't exist in backends
1312#if QT_CONFIG(http)
1313 schemes << QStringLiteral("http");
1314#ifndef QT_NO_SSL
1316 schemes << QStringLiteral("https");
1317#endif
1318#endif
1319 schemes << QStringLiteral("data");
1320 return schemes;
1321}
1322
1333{
1336}
1337
1348{
1350}
1351
1352
1363{
1364 return d_func()->autoDeleteReplies;
1365}
1366
1382{
1383 d_func()->autoDeleteReplies = shouldAutoDelete;
1384}
1385
1395{
1396 return d_func()->transferTimeout;
1397}
1398
1417{
1418 d_func()->transferTimeout = timeout;
1419}
1420
1422{
1424
1425 emit q->finished(reply);
1428}
1429
1431{
1432#ifndef QT_NO_SSL
1434 emit q->encrypted(reply);
1435#else
1436 Q_UNUSED(reply);
1437#endif
1438}
1439
1441{
1442#ifndef QT_NO_SSL
1444 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1445 if (reply)
1446 emit q->sslErrors(reply, errors);
1447#else
1448 Q_UNUSED(errors);
1449#endif
1450}
1451
1452#ifndef QT_NO_SSL
1454{
1456 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1457 if (reply)
1458 emit q->preSharedKeyAuthenticationRequired(reply, authenticator);
1459}
1460#endif
1461
1463{
1467 [this, reply]() { _q_replyFinished(reply); });
1468#ifndef QT_NO_SSL
1469 /* In case we're compiled without SSL support, we don't have this signal and we need to
1470 * avoid getting a connection error. */
1471 q->connect(reply, &QNetworkReply::encrypted, reply,
1472 [this, reply]() { _q_replyEncrypted(reply); });
1475#endif
1476
1477 return reply;
1478}
1479
1481{
1482 if (!cookieJarCreated) {
1483 // keep the ugly hack in here
1485 that->cookieJar = new QNetworkCookieJar(that->q_func());
1486 that->cookieJarCreated = true;
1487 }
1488}
1489
1492 bool synchronous,
1493 QUrl &url,
1494 QUrl *urlForLastAuthentication,
1495 bool allowAuthenticationReuse)
1496{
1498
1499 // don't try the cache for the same URL twice in a row
1500 // being called twice for the same URL means the authentication failed
1501 // also called when last URL is empty, e.g. on first call
1502 if (allowAuthenticationReuse && (urlForLastAuthentication->isEmpty()
1503 || url != *urlForLastAuthentication)) {
1504 // if credentials are included in the url, then use them, unless they were already used
1505 if (!url.userName().isEmpty() && !url.password().isEmpty()
1506 && (url.userName() != authenticator->user()
1507 || url.password() != authenticator->password())) {
1508 authenticator->setUser(url.userName(QUrl::FullyDecoded));
1509 authenticator->setPassword(url.password(QUrl::FullyDecoded));
1510 *urlForLastAuthentication = url;
1511 authenticationManager->cacheCredentials(url, authenticator);
1512 return;
1513 }
1514
1515 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedCredentials(url, authenticator);
1516 if (!cred.isNull()
1517 && (cred.user != authenticator->user() || cred.password != authenticator->password())) {
1518 authenticator->setUser(cred.user);
1519 authenticator->setPassword(cred.password);
1520 *urlForLastAuthentication = url;
1521 return;
1522 }
1523 }
1524
1525 // if we emit a signal here in synchronous mode, the user might spin
1526 // an event loop, which might recurse and lead to problems
1527 if (synchronous)
1528 return;
1529
1530 *urlForLastAuthentication = url;
1531 emit q->authenticationRequired(reply, authenticator);
1532 if (allowAuthenticationReuse)
1533 authenticationManager->cacheCredentials(url, authenticator);
1534}
1535
1536#ifndef QT_NO_NETWORKPROXY
1538 const QNetworkProxy &proxy,
1539 bool synchronous,
1540 QAuthenticator *authenticator,
1541 QNetworkProxy *lastProxyAuthentication)
1542{
1545 if (proxy != *lastProxyAuthentication && (!priv || !priv->hasFailed)) {
1546 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1547 if (!cred.isNull()) {
1548 authenticator->setUser(cred.user);
1549 authenticator->setPassword(cred.password);
1550 return;
1551 }
1552 }
1553
1554#if defined(Q_OS_MACOS)
1555 //now we try to get the username and password from keychain
1556 //if not successful signal will be emitted
1557 QString username;
1558 QString password;
1559 if (getProxyAuth(proxy.hostName(), url.scheme(), username, password)) {
1560 // only cache the system credentials if they are correct (or if they have changed)
1561 // to not run into an endless loop in case they are wrong
1562 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1563 if (!priv->hasFailed || cred.user != username || cred.password != password) {
1564 authenticator->setUser(username);
1565 authenticator->setPassword(password);
1566 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1567 return;
1568 }
1569 }
1570#else
1571 Q_UNUSED(url);
1572#endif
1573
1574 // if we emit a signal here in synchronous mode, the user might spin
1575 // an event loop, which might recurse and lead to problems
1576 if (synchronous)
1577 return;
1578
1579 *lastProxyAuthentication = proxy;
1580 emit q->proxyAuthenticationRequired(proxy, authenticator);
1581 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1582}
1583
1585{
1586 QList<QNetworkProxy> proxies;
1587 if (proxyFactory) {
1588 proxies = proxyFactory->queryProxy(query);
1589 if (proxies.isEmpty()) {
1590 qWarning("QNetworkAccessManager: factory %p has returned an empty result set",
1591 proxyFactory);
1592 proxies << QNetworkProxy::NoProxy;
1593 }
1594 } else if (proxy.type() == QNetworkProxy::DefaultProxy) {
1595 // no proxy set, query the application
1597 } else {
1598 proxies << proxy;
1599 }
1600
1601 return proxies;
1602}
1603#endif
1604
1606{
1607 manager->d_func()->authenticationManager->clearCache();
1608}
1609
1611{
1612 manager->d_func()->objectCache.clear();
1613 manager->d_func()->destroyThread();
1614}
1615
1617{
1618 destroyThread();
1619}
1620
1622{
1623 if (!thread) {
1624 thread = new QThread;
1625 thread->setObjectName(QStringLiteral("QNetworkAccessManager thread"));
1626 thread->start();
1627 }
1629 return thread;
1630}
1631
1633{
1634 if (thread) {
1635 thread->quit();
1636 thread->wait(QDeadlineTimer(5000));
1637 if (thread->isFinished())
1638 delete thread;
1639 else
1640 QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
1641 thread = nullptr;
1642 }
1643}
1644
1645
1646#if QT_CONFIG(http) || defined(Q_OS_WASM)
1647
1648QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart)
1649{
1650 // copy the request, we probably need to add some headers
1651 QNetworkRequest newRequest(request);
1652
1653 // add Content-Type header if not there already
1655 QByteArray contentType;
1656 contentType.reserve(34 + multiPart->d_func()->boundary.size());
1657 contentType += "multipart/";
1658 switch (multiPart->d_func()->contentType) {
1660 contentType += "related";
1661 break;
1663 contentType += "form-data";
1664 break;
1666 contentType += "alternative";
1667 break;
1668 default:
1669 contentType += "mixed";
1670 break;
1671 }
1672 // putting the boundary into quotes, recommended in RFC 2046 section 5.1.1
1673 contentType += "; boundary=\"" + multiPart->d_func()->boundary + '"';
1674 newRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType));
1675 }
1676
1677 // add MIME-Version header if not there already (we must include the header
1678 // if the message conforms to RFC 2045, see section 4 of that RFC)
1679 QByteArray mimeHeader("MIME-Version");
1680 if (!request.hasRawHeader(mimeHeader))
1681 newRequest.setRawHeader(mimeHeader, QByteArray("1.0"));
1682
1683 QIODevice *device = multiPart->d_func()->device;
1684 if (!device->isReadable()) {
1685 if (!device->isOpen()) {
1686 if (!device->open(QIODevice::ReadOnly))
1687 qWarning("could not open device for reading");
1688 } else {
1689 qWarning("device is not readable");
1690 }
1691 }
1692
1693 return newRequest;
1694}
1695#endif // QT_CONFIG(http)
1696
1703{
1704 Q_CONSTINIT static QBasicMutex mutex;
1705 std::unique_lock locker(mutex);
1706 if (!qnabfLoader())
1707 return;
1708#if QT_CONFIG(library)
1709 qnabfLoader->update();
1710#endif
1711 int index = 0;
1712 while (qnabfLoader->instance(index))
1713 ++index;
1714}
1715
1717
1718#include "moc_qnetworkaccessmanager.cpp"
IOBluetoothDevice * device
The QAbstractNetworkCache class provides the interface for cache implementations.
static QAuthenticatorPrivate * getPrivate(QAuthenticator &auth)
The QAuthenticator class provides an authentication object.
QString user() const
Returns the user used for authentication.
void setPassword(const QString &password)
Sets the password used for authentication.
QString password() const
Returns the password used for authentication.
void setUser(const QString &user)
Sets the user used for authentication.
\inmodule QtCore \reentrant
Definition qbuffer.h:16
void setData(const QByteArray &data)
Sets the contents of the internal buffer to be data.
Definition qbuffer.cpp:259
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
void reserve(qsizetype size)
Attempts to allocate memory for at least size bytes.
Definition qbytearray.h:557
X as() const
\inmodule QtCore
The QHttpMultiPart class resembles a MIME multipart message to be sent over HTTP.
QByteArray boundary() const
returns the boundary.
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
\inmodule QtCore
Definition qmutex.h:285
QList< QNetworkProxy > queryProxy(const QNetworkProxyQuery &query)
QNetworkReply * postProcess(QNetworkReply *reply)
void proxyAuthenticationRequired(const QUrl &url, const QNetworkProxy &proxy, bool synchronous, QAuthenticator *authenticator, QNetworkProxy *lastProxyAuthentication)
void _q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator)
void authenticationRequired(QAuthenticator *authenticator, QNetworkReply *reply, bool synchronous, QUrl &url, QUrl *urlForLastAuthentication, bool allowAuthenticationReuse=true)
std::shared_ptr< QNetworkAccessAuthenticationManager > authenticationManager
void _q_replyFinished(QNetworkReply *reply)
void _q_replyEncrypted(QNetworkReply *reply)
void _q_replySslErrors(const QList< QSslError > &errors)
static Q_AUTOTEST_EXPORT void clearConnectionCache(QNetworkAccessManager *manager)
static Q_AUTOTEST_EXPORT void clearAuthenticationCache(QNetworkAccessManager *manager)
The QNetworkAccessManager class allows the application to send network requests and receive replies.
void setCookieJar(QNetworkCookieJar *cookieJar)
Sets the manager's cookie jar to be the cookieJar specified.
QNetworkReply * put(const QNetworkRequest &request, QIODevice *data)
Uploads the contents of data to the destination request and returns a new QNetworkReply object that w...
void connectToHost(const QString &hostName, quint16 port=80)
~QNetworkAccessManager()
Destroys the QNetworkAccessManager object and frees up any resources.
QNetworkReply * head(const QNetworkRequest &request)
Posts a request to obtain the network headers for request and returns a new QNetworkReply object whic...
bool isStrictTransportSecurityStoreEnabled() const
QList< QHstsPolicy > strictTransportSecurityHosts() const
virtual QStringList supportedSchemes() const
QNetworkRequest::RedirectPolicy redirectPolicy() const
QNetworkReply * post(const QNetworkRequest &request, QIODevice *data)
Sends an HTTP POST request to the destination specified by request and returns a new QNetworkReply ob...
void setProxy(const QNetworkProxy &proxy)
Sets the proxy to be used in future requests to be proxy.
QStringList supportedSchemesImplementation() const
void setAutoDeleteReplies(bool autoDelete)
bool isStrictTransportSecurityEnabled() const
QNetworkReply * get(const QNetworkRequest &request)
Posts a request to obtain the contents of the target request and returns a new QNetworkReply object o...
void setRedirectPolicy(QNetworkRequest::RedirectPolicy policy)
QNetworkReply * sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data=nullptr)
QNetworkProxy proxy() const
Returns the QNetworkProxy that the requests sent using this QNetworkAccessManager object will use.
virtual QNetworkReply * createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData=nullptr)
Returns a new QNetworkReply object to handle the operation op and request originalReq.
void setStrictTransportSecurityEnabled(bool enabled)
QAbstractNetworkCache * cache() const
void addStrictTransportSecurityHosts(const QList< QHstsPolicy > &knownHosts)
Operation
Indicates the operation this reply is processing.
void setTransferTimeout(int timeout=QNetworkRequest::DefaultTransferTimeoutConstant)
QNetworkReply * deleteResource(const QNetworkRequest &request)
void connectToHostEncrypted(const QString &hostName, quint16 port=443, const QSslConfiguration &sslConfiguration=QSslConfiguration::defaultConfiguration())
void setProxyFactory(QNetworkProxyFactory *factory)
QNetworkProxyFactory * proxyFactory() const
void setCache(QAbstractNetworkCache *cache)
QNetworkCookieJar * cookieJar() const
Returns the QNetworkCookieJar that is used to store cookies obtained from the network as well as cook...
void enableStrictTransportSecurityStore(bool enabled, const QString &storeDir=QString())
QNetworkAccessManager(QObject *parent=nullptr)
Constructs a QNetworkAccessManager object that is the center of the Network Access API and sets paren...
The QNetworkCookieJar class implements a simple jar of QNetworkCookie objects.
The QNetworkProxyFactory class provides fine-grained proxy selection.
virtual QList< QNetworkProxy > queryProxy(const QNetworkProxyQuery &query=QNetworkProxyQuery())=0
This function takes the query request, query, examines the details of the type of socket or request a...
static QList< QNetworkProxy > proxyForQuery(const QNetworkProxyQuery &query)
This function takes the query request, query, examines the details of the type of socket or request a...
The QNetworkProxyQuery class is used to query the proxy settings for a socket.
The QNetworkProxy class provides a network layer proxy.
QNetworkProxy::ProxyType type() const
Returns the proxy type for this instance.
QString hostName() const
Returns the host name of the proxy host.
static void setManager(QNetworkReply *reply, QNetworkAccessManager *manager)
The QNetworkReply class contains the data and headers for a request sent with QNetworkAccessManager.
void finished()
This signal is emitted when the reply has finished processing.
QNetworkRequest request() const
Returns the request that was posted for this reply.
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
void setSslConfiguration(const QSslConfiguration &configuration)
Sets this network request's SSL configuration to be config.
void setHeader(KnownHeaders header, const QVariant &value)
Sets the value of the known header header to be value, overriding any previously set headers.
void setAttribute(Attribute code, const QVariant &value)
Sets the attribute associated with code code to be value value.
QVariant attribute(Attribute code, const QVariant &defaultValue=QVariant()) const
Returns the attribute associated with the code code.
QVariant header(KnownHeaders header) const
Returns the value of the known network header header if it is present in this request.
void setRawHeader(const QByteArray &headerName, const QByteArray &value)
Sets the header headerName to be of value headerValue.
void setPeerVerifyName(const QString &peerName)
bool hasRawHeader(const QByteArray &headerName) const
Returns true if the raw header headerName is present in this network request.
void setUrl(const QUrl &url)
Sets the URL this network request is referring to be url.
QUrl url() const
Returns the URL this network request is referring to.
CacheLoadControl
Controls the caching mechanism of QNetworkAccessManager.
QSslConfiguration sslConfiguration() const
Returns this network request's SSL configuration.
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1561
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
Definition qobject.h:114
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
The QSslConfiguration class holds the configuration and state of an SSL connection.
QList< QByteArray > allowedNextProtocols() const
static const char ALPNProtocolHTTP2[]
static QSslConfiguration defaultConfiguration()
Returns the default SSL configuration to be used in new SSL connections.
The QSslPreSharedKeyAuthenticator class provides authentication data for pre shared keys (PSK) cipher...
static bool supportsSsl()
Returns true if this platform supports SSL; otherwise, returns false.
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5788
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6498
void start(Priority=InheritPriority)
Definition qthread.cpp:923
bool isFinished() const
Definition qthread.cpp:981
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
Definition qthread.cpp:950
void quit()
Definition qthread.cpp:935
\inmodule QtCore
Definition qurl.h:94
bool isLocalFile() const
Definition qurl.cpp:3431
QString userName(ComponentFormattingOptions options=FullyDecoded) const
Returns the user name of the URL if it is defined; otherwise an empty string is returned.
Definition qurl.cpp:2196
QString password(ComponentFormattingOptions=FullyDecoded) const
Returns the password of the URL if it is defined; otherwise an empty string is returned.
Definition qurl.cpp:2259
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1888
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1983
void setScheme(const QString &scheme)
Sets the scheme of the URL to scheme.
Definition qurl.cpp:1959
void setHost(const QString &host, ParsingMode mode=DecodedMode)
Sets the host of the URL to host.
Definition qurl.cpp:2286
int port(int defaultPort=-1) const
Definition qurl.cpp:2380
@ FullyDecoded
Definition qurl.h:130
void setPort(int port)
Sets the port of the URL to port.
Definition qurl.cpp:2355
\inmodule QtCore
Definition qvariant.h:64
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
bool toBool() const
Returns the variant as a bool if the variant has userType() Bool.
bool isNull() const
Returns true if this is a null variant, false otherwise.
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:531
qDeleteAll(list.begin(), list.end())
QCache< int, Employee > cache
[0]
Combined button and popup list for selecting options.
@ CaseInsensitive
@ QueuedConnection
@ DirectConnection
#define Q_APPLICATION_STATIC(TYPE, NAME,...)
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 return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
EGLOutputPortEXT port
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qWarning
Definition qlogging.h:162
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
static const QMetaObjectPrivate * priv(const uint *data)
#define QNetworkAccessBackendFactory_iid
static void ensureInitialized()
#define SLOT(a)
Definition qobjectdefs.h:51
#define Q_RETURN_ARG(Type, data)
Definition qobjectdefs.h:63
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLenum mode
GLuint index
[2]
GLbitfield GLuint64 timeout
[4]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum GLuint buffer
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum query
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
#define emit
#define Q_UNUSED(x)
unsigned short quint16
Definition qtypes.h:43
ptrdiff_t qsizetype
Definition qtypes.h:70
#define enabled
QUrl url("example.com")
[constructor-url-reference]
QMutex mutex
[2]
QItemEditorFactory * factory
QSizePolicy policy
QNetworkAccessManager manager
QHttpMultiPart * multiPart
[0]
QNetworkRequest request(url)
QNetworkReply * reply
QNetworkProxy proxy
[0]
bool contains(const AT &t) const noexcept
Definition qlist.h:44
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent