Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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;
71using namespace std::chrono_literals;
72
73Q_LOGGING_CATEGORY(lcQnam, "qt.network.access.manager")
74
76
77#if QT_CONFIG(private_tests)
78Q_GLOBAL_STATIC(QNetworkAccessDebugPipeBackendFactory, debugpipeBackend)
79#endif
80
82
83#if defined(Q_OS_MACOS)
84bool getProxyAuth(const QString& proxyHostname, const QString &scheme, QString& username, QString& password)
85{
86 CFStringRef protocolType = nullptr;
87 if (scheme.compare("ftp"_L1, Qt::CaseInsensitive) == 0) {
88 protocolType = kSecAttrProtocolFTPProxy;
89 } else if (scheme.compare("http"_L1, Qt::CaseInsensitive) == 0
90 || scheme.compare("preconnect-http"_L1, Qt::CaseInsensitive) == 0) {
91 protocolType = kSecAttrProtocolHTTPProxy;
92 } else if (scheme.compare("https"_L1,Qt::CaseInsensitive)==0
93 || scheme.compare("preconnect-https"_L1, Qt::CaseInsensitive) == 0) {
94 protocolType = kSecAttrProtocolHTTPSProxy;
95 } else {
96 qCWarning(lcQnam) << "Cannot query user name and password for a proxy, unnknown protocol:"
97 << scheme;
98 return false;
99 }
100
101 QCFType<CFMutableDictionaryRef> query(CFDictionaryCreateMutable(kCFAllocatorDefault,
102 0, nullptr, nullptr));
104
105 CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword);
106 CFDictionaryAddValue(query, kSecAttrProtocol, protocolType);
107
108 QCFType<CFStringRef> serverName; // Note the scope.
109 if (proxyHostname.size()) {
110 serverName = proxyHostname.toCFString();
111 CFDictionaryAddValue(query, kSecAttrServer, serverName);
112 }
113
114 // This is to get the user name in the result:
115 CFDictionaryAddValue(query, kSecReturnAttributes, kCFBooleanTrue);
116 // This one to get the password:
117 CFDictionaryAddValue(query, kSecReturnData, kCFBooleanTrue);
118
119 // The default for kSecMatchLimit key is 1 (the first match only), which is fine,
120 // so don't set this value explicitly.
121
122 QCFType<CFTypeRef> replyData;
123 if (SecItemCopyMatching(query, &replyData) != errSecSuccess) {
124 qCWarning(lcQnam, "Failed to extract user name and password from the keychain.");
125 return false;
126 }
127
128 if (!replyData || CFDictionaryGetTypeID() != CFGetTypeID(replyData)) {
129 qCWarning(lcQnam, "Query returned data in unexpected format.");
130 return false;
131 }
132
133 CFDictionaryRef accountData = replyData.as<CFDictionaryRef>();
134 const void *value = CFDictionaryGetValue(accountData, kSecAttrAccount);
135 if (!value || CFGetTypeID(value) != CFStringGetTypeID()) {
136 qCWarning(lcQnam, "Cannot find user name or its format is unknown.");
137 return false;
138 }
139 username = QString::fromCFString(static_cast<CFStringRef>(value));
140
141 value = CFDictionaryGetValue(accountData, kSecValueData);
142 if (!value || CFGetTypeID(value) != CFDataGetTypeID()) {
143 qCWarning(lcQnam, "Cannot find password or its format is unknown.");
144 return false;
145 }
146 const CFDataRef passData = static_cast<const CFDataRef>(value);
147 password = QString::fromLocal8Bit(reinterpret_cast<const char *>(CFDataGetBytePtr(passData)),
148 qsizetype(CFDataGetLength(passData)));
149 return true;
150}
151#endif // Q_OS_MACOS
152
153
154
155static void ensureInitialized()
156{
157#if QT_CONFIG(private_tests)
158 (void) debugpipeBackend();
159#endif
160
161 // leave this one last since it will query the special QAbstractFileEngines
162 (void) fileBackend();
163}
164
398{
400 d_func()->ensureBackendPluginsLoaded();
401
402 qRegisterMetaType<QNetworkReply::NetworkError>();
403#ifndef QT_NO_NETWORKPROXY
404 qRegisterMetaType<QNetworkProxy>();
405#endif
406#ifndef QT_NO_SSL
407 qRegisterMetaType<QList<QSslError> >();
408 qRegisterMetaType<QSslConfiguration>();
409 qRegisterMetaType<QSslPreSharedKeyAuthenticator *>();
410#endif
411 qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >();
412#if QT_CONFIG(http)
413 qRegisterMetaType<QHttpNetworkRequest>();
414#endif
415 qRegisterMetaType<QNetworkReply::NetworkError>();
416 qRegisterMetaType<QSharedPointer<char> >();
417}
418
427{
428#ifndef QT_NO_NETWORKPROXY
429 delete d_func()->proxyFactory;
430#endif
431
432 // Delete the QNetworkReply children first.
433 // Else a QAbstractNetworkCache might get deleted in ~QObject
434 // before a QNetworkReply that accesses the QAbstractNetworkCache
435 // object in its destructor.
436 qDeleteAll(findChildren<QNetworkReply *>());
437 // The other children will be deleted in this ~QObject
438 // FIXME instead of this "hack" make the QNetworkReplyImpl
439 // properly watch the cache deletion, e.g. via a QWeakPointer.
440}
441
442#ifndef QT_NO_NETWORKPROXY
451{
452 return d_func()->proxy;
453}
454
470{
472 delete d->proxyFactory;
473 d->proxy = proxy;
474 d->proxyFactory = nullptr;
475}
476
490{
491 return d_func()->proxyFactory;
492}
493
524{
526 delete d->proxyFactory;
527 d->proxyFactory = factory;
528 d->proxy = QNetworkProxy();
529}
530#endif
531
540{
541 Q_D(const QNetworkAccessManager);
542 return d->networkCache;
543}
544
562{
564 if (d->networkCache != cache) {
565 delete d->networkCache;
566 d->networkCache = cache;
567 if (d->networkCache)
568 d->networkCache->setParent(this);
569 }
570}
571
580{
581 Q_D(const QNetworkAccessManager);
582 if (!d->cookieJar)
583 d->createCookieJar();
584 return d->cookieJar;
585}
586
617{
619 d->cookieJarCreated = true;
620 if (d->cookieJar != cookieJar) {
621 if (d->cookieJar && d->cookieJar->parent() == this)
622 delete d->cookieJar;
623 d->cookieJar = cookieJar;
624 if (cookieJar && thread() == cookieJar->thread())
625 d->cookieJar->setParent(this);
626 }
627}
628
649
659{
660 Q_D(const QNetworkAccessManager);
661 return d->stsEnabled;
662}
663
685{
686#if QT_CONFIG(settings)
688 d->stsStore.reset(enabled ? new QHstsStore(storeDir) : nullptr);
689 d->stsCache.setStore(d->stsStore.data());
690#else
692 Q_UNUSED(storeDir);
693 qWarning("HSTS permanent store requires the feature 'settings' enabled");
694#endif // QT_CONFIG(settings)
695}
696
707{
708#if QT_CONFIG(settings)
709 Q_D(const QNetworkAccessManager);
710 return bool(d->stsStore.data());
711#else
712 return false;
713#endif // QT_CONFIG(settings)
714}
715
736void QNetworkAccessManager::addStrictTransportSecurityHosts(const QList<QHstsPolicy> &knownHosts)
737{
739 d->stsCache.updateFromPolicies(knownHosts);
740}
741
752{
753 Q_D(const QNetworkAccessManager);
754 return d->stsCache.policies();
755}
756
767
782
795{
796 QNetworkRequest newRequest(request);
797 return d_func()->postProcess(
799}
800
822
841
858
868{
869 Q_UNUSED(nptr);
870 QIODevice *dev = nullptr;
871
872 return d_func()->postProcess(createRequest(QNetworkAccessManager::PostOperation,
873 request,
874 dev));
875}
876
877#if QT_CONFIG(http) || defined(Q_OS_WASM)
891{
892 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
893 QIODevice *device = multiPart->d_func()->device;
894 QNetworkReply *reply = post(newRequest, device);
895 return reply;
896}
897
911{
912 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
913 QIODevice *device = multiPart->d_func()->device;
914 QNetworkReply *reply = put(newRequest, device);
915 return reply;
916}
917#endif // QT_CONFIG(http)
918
942
959
970{
971 Q_UNUSED(nptr);
972 QIODevice *dev = nullptr;
973
974 return d_func()->postProcess(createRequest(QNetworkAccessManager::PutOperation, request, dev));
975}
976
991
992#ifndef QT_NO_SSL
1012 const QSslConfiguration &sslConfiguration)
1013{
1014 connectToHostEncrypted(hostName, port, sslConfiguration, QString());
1015}
1016
1038 const QSslConfiguration &sslConfiguration,
1039 const QString &peerName)
1040{
1041 QUrl url;
1042 url.setHost(hostName);
1043 url.setPort(port);
1044 url.setScheme("preconnect-https"_L1);
1046 if (sslConfiguration != QSslConfiguration::defaultConfiguration())
1047 request.setSslConfiguration(sslConfiguration);
1048
1049 // There is no way to enable HTTP2 via a request after having established the connection,
1050 // so we need to check the ssl configuration whether HTTP2 is allowed here.
1053
1054 request.setPeerVerifyName(peerName);
1055 get(request);
1056}
1057#endif
1058
1071{
1072 QUrl url;
1073 url.setHost(hostName);
1074 url.setPort(port);
1075 url.setScheme("preconnect-http"_L1);
1077 get(request);
1078}
1079
1102
1111{
1112 Q_D(const QNetworkAccessManager);
1113 return d->redirectPolicy;
1114}
1115
1141
1160
1161#if QT_CONFIG(http) || defined(Q_OS_WASM)
1177{
1178 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
1179 QIODevice *device = multiPart->d_func()->device;
1180 QNetworkReply *reply = sendCustomRequest(newRequest, verb, device);
1181 return reply;
1182}
1183#endif // QT_CONFIG(http)
1184
1199 const QNetworkRequest &originalReq,
1200 QIODevice *outgoingData)
1201{
1203
1204 QNetworkRequest req(originalReq);
1208 }
1209
1210#if QT_CONFIG(http) || defined (Q_OS_WASM)
1211 if (req.transferTimeoutAsDuration() == 0ms)
1212 req.setTransferTimeout(transferTimeoutAsDuration());
1213#endif
1214
1215 if (autoDeleteReplies()
1218 }
1219
1220 bool isLocalFile = req.url().isLocalFile();
1221 QString scheme = req.url().scheme();
1222
1223 // Remap local+http to unix+http to make further processing easier
1224 if (scheme == "local+http"_L1) {
1225 scheme = u"unix+http"_s;
1226 QUrl url = req.url();
1227 url.setScheme(scheme);
1228 req.setUrl(url);
1229 }
1230
1231 // fast path for GET on file:// URLs
1232 // The QNetworkAccessFileBackend will right now only be used for PUT
1235 if (isLocalFile
1236#ifdef Q_OS_ANDROID
1237 || scheme == "assets"_L1
1238#endif
1239 || scheme == "qrc"_L1) {
1240 return new QNetworkReplyFileImpl(this, req, op);
1241 }
1242
1243 if (scheme == "data"_L1)
1244 return new QNetworkReplyDataImpl(this, req, op);
1245
1246 // A request with QNetworkRequest::AlwaysCache does not need any bearer management
1252 // FIXME Implement a QNetworkReplyCacheImpl instead, see QTBUG-15106
1254 QNetworkReplyImplPrivate *priv = reply->d_func();
1255 priv->manager = this;
1256 priv->backend = new QNetworkAccessCacheBackend();
1257 priv->backend->setManagerPrivate(this->d_func());
1258 priv->backend->setParent(reply);
1259 priv->backend->setReplyPrivate(priv);
1260 priv->setup(op, req, outgoingData);
1261 return reply;
1262 }
1263 }
1265 auto h = request.headers();
1266#ifndef Q_OS_WASM // Content-length header is not allowed to be set by user in wasm
1268 outgoingData && !outgoingData->isSequential()) {
1269 // request has no Content-Length
1270 // but the data that is outgoing is random-access
1272 QByteArray::number(outgoingData->size()));
1273 }
1274#endif
1275 if (static_cast<QNetworkRequest::LoadControl>
1278 if (d->cookieJar) {
1279 QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url());
1280 if (!cookies.isEmpty())
1283 }
1284 }
1285 request.setHeaders(std::move(h));
1286#ifdef Q_OS_WASM
1287 Q_UNUSED(isLocalFile);
1288 // Support http, https, and relative urls
1289 if (scheme == "http"_L1 || scheme == "https"_L1 || scheme.isEmpty()) {
1292 priv->manager = this;
1293 priv->setup(op, request, outgoingData);
1294 return reply;
1295 }
1296#endif
1297
1298#if QT_CONFIG(http)
1299 constexpr char16_t httpSchemes[][17] = {
1300 u"http",
1301 u"preconnect-http",
1302#ifndef QT_NO_SSL
1303 u"https",
1304 u"preconnect-https",
1305#endif
1306 u"unix+http",
1307 };
1308 // Since Qt 5 we use the new QNetworkReplyHttpImpl
1309 if (std::find(std::begin(httpSchemes), std::end(httpSchemes), scheme) != std::end(httpSchemes)) {
1310
1311#ifndef QT_NO_SSL
1312 const bool isLocalSocket = scheme.startsWith("unix"_L1);
1313 if (!isLocalSocket && isStrictTransportSecurityEnabled()
1314 && d->stsCache.isKnownHost(request.url())) {
1315 QUrl stsUrl(request.url());
1316 // RFC6797, 8.3:
1317 // The UA MUST replace the URI scheme with "https" [RFC2818],
1318 // and if the URI contains an explicit port component of "80",
1319 // then the UA MUST convert the port component to be "443", or
1320 // if the URI contains an explicit port component that is not
1321 // equal to "80", the port component value MUST be preserved;
1322 // otherwise,
1323 // if the URI does not contain an explicit port component, the UA
1324 // MUST NOT add one.
1325 if (stsUrl.port() == 80)
1326 stsUrl.setPort(443);
1327 stsUrl.setScheme("https"_L1);
1328 request.setUrl(stsUrl);
1329 }
1330#endif
1331 QNetworkReplyHttpImpl *reply = new QNetworkReplyHttpImpl(this, request, op, outgoingData);
1332 return reply;
1333 }
1334#endif // QT_CONFIG(http)
1335
1336 // first step: create the reply
1338 QNetworkReplyImplPrivate *priv = reply->d_func();
1339 priv->manager = this;
1340
1341 // second step: fetch cached credentials
1342 // This is not done for the time being, we should use signal emissions to request
1343 // the credentials from cache.
1344
1345 // third step: find a backend
1346 priv->backend = d->findBackend(op, request);
1347
1348 if (priv->backend) {
1349 priv->backend->setParent(reply);
1350 priv->backend->setReplyPrivate(priv);
1351 }
1352
1353#ifndef QT_NO_SSL
1354 reply->setSslConfiguration(request.sslConfiguration());
1355#endif
1356
1357 // fourth step: setup the reply
1358 priv->setup(op, request, outgoingData);
1359
1360 return reply;
1361}
1362
1373{
1374 QStringList schemes;
1375 QNetworkAccessManager *self = const_cast<QNetworkAccessManager *>(this); // We know we call a const slot
1376 QMetaObject::invokeMethod(self, "supportedSchemesImplementation", Qt::DirectConnection,
1377 Q_RETURN_ARG(QStringList, schemes));
1378 schemes.removeDuplicates();
1379 return schemes;
1380}
1381
1398{
1399 Q_D(const QNetworkAccessManager);
1400
1401 QStringList schemes = d->backendSupportedSchemes();
1402 // Those ones don't exist in backends
1403#if QT_CONFIG(http)
1404 schemes << QStringLiteral("http");
1405 schemes << QStringLiteral("unix+http");
1406 schemes << QStringLiteral("local+http");
1407#ifndef QT_NO_SSL
1409 schemes << QStringLiteral("https");
1410#endif
1411#endif
1412 schemes << QStringLiteral("data");
1413 return schemes;
1414}
1415
1430
1444
1445
1456{
1457 return d_func()->autoDeleteReplies;
1458}
1459
1475{
1476 d_func()->autoDeleteReplies = shouldAutoDelete;
1477}
1478
1509{
1510 return d_func()->transferTimeout;
1511}
1512
1530void QNetworkAccessManager::setTransferTimeout(std::chrono::milliseconds duration)
1531{
1532 d_func()->transferTimeout = duration;
1533}
1534
1543
1545{
1546#ifndef QT_NO_SSL
1548 emit q->encrypted(reply);
1549#else
1550 Q_UNUSED(reply);
1551#endif
1552}
1553
1554void QNetworkAccessManagerPrivate::_q_replySslErrors(const QList<QSslError> &errors)
1555{
1556#ifndef QT_NO_SSL
1558 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1559 if (reply)
1560 emit q->sslErrors(reply, errors);
1561#else
1562 Q_UNUSED(errors);
1563#endif
1564}
1565
1566#ifndef QT_NO_SSL
1568{
1570 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1571 if (reply)
1572 emit q->preSharedKeyAuthenticationRequired(reply, authenticator);
1573}
1574#endif
1575
1577{
1581 [this, reply]() { _q_replyFinished(reply); });
1582#ifndef QT_NO_SSL
1583 /* In case we're compiled without SSL support, we don't have this signal and we need to
1584 * avoid getting a connection error. */
1585 q->connect(reply, &QNetworkReply::encrypted, reply,
1586 [this, reply]() { _q_replyEncrypted(reply); });
1587 q->connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(_q_replySslErrors(QList<QSslError>)));
1589#endif
1590
1591 return reply;
1592}
1593
1595{
1596 if (!cookieJarCreated) {
1597 // keep the ugly hack in here
1599 that->cookieJar = new QNetworkCookieJar(that->q_func());
1600 that->cookieJarCreated = true;
1601 }
1602}
1603
1606 bool synchronous,
1607 QUrl &url,
1608 QUrl *urlForLastAuthentication,
1609 bool allowAuthenticationReuse)
1610{
1612
1613 // don't try the cache for the same URL twice in a row
1614 // being called twice for the same URL means the authentication failed
1615 // also called when last URL is empty, e.g. on first call
1616 if (allowAuthenticationReuse && (urlForLastAuthentication->isEmpty()
1617 || url != *urlForLastAuthentication)) {
1618 // if credentials are included in the url, then use them, unless they were already used
1619 if (!url.userName().isEmpty() && !url.password().isEmpty()
1620 && (url.userName() != authenticator->user()
1621 || url.password() != authenticator->password())) {
1622 authenticator->setUser(url.userName(QUrl::FullyDecoded));
1623 authenticator->setPassword(url.password(QUrl::FullyDecoded));
1624 *urlForLastAuthentication = url;
1625 authenticationManager->cacheCredentials(url, authenticator);
1626 return;
1627 }
1628
1629 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedCredentials(url, authenticator);
1630 if (!cred.isNull()
1631 && (cred.user != authenticator->user() || cred.password != authenticator->password())) {
1632 authenticator->setUser(cred.user);
1633 authenticator->setPassword(cred.password);
1634 *urlForLastAuthentication = url;
1635 return;
1636 }
1637 }
1638
1639 // if we emit a signal here in synchronous mode, the user might spin
1640 // an event loop, which might recurse and lead to problems
1641 if (synchronous)
1642 return;
1643
1644 *urlForLastAuthentication = url;
1645 emit q->authenticationRequired(reply, authenticator);
1646 if (allowAuthenticationReuse)
1647 authenticationManager->cacheCredentials(url, authenticator);
1648}
1649
1650#ifndef QT_NO_NETWORKPROXY
1652 const QNetworkProxy &proxy,
1653 bool synchronous,
1654 QAuthenticator *authenticator,
1655 QNetworkProxy *lastProxyAuthentication)
1656{
1659 if (proxy != *lastProxyAuthentication && (!priv || !priv->hasFailed)) {
1660 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1661 if (!cred.isNull()) {
1662 authenticator->setUser(cred.user);
1663 authenticator->setPassword(cred.password);
1664 return;
1665 }
1666 }
1667
1668#if defined(Q_OS_MACOS)
1669 //now we try to get the username and password from keychain
1670 //if not successful signal will be emitted
1671 QString username;
1672 QString password;
1673 if (getProxyAuth(proxy.hostName(), url.scheme(), username, password)) {
1674 // only cache the system credentials if they are correct (or if they have changed)
1675 // to not run into an endless loop in case they are wrong
1676 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1677 if (!priv->hasFailed || cred.user != username || cred.password != password) {
1678 authenticator->setUser(username);
1679 authenticator->setPassword(password);
1680 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1681 return;
1682 }
1683 }
1684#else
1685 Q_UNUSED(url);
1686#endif
1687
1688 // if we emit a signal here in synchronous mode, the user might spin
1689 // an event loop, which might recurse and lead to problems
1690 if (synchronous)
1691 return;
1692
1693 *lastProxyAuthentication = proxy;
1694 emit q->proxyAuthenticationRequired(proxy, authenticator);
1695 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1696}
1697
1699{
1700 QList<QNetworkProxy> proxies;
1701 if (proxyFactory) {
1702 proxies = proxyFactory->queryProxy(query);
1703 if (proxies.isEmpty()) {
1704 qWarning("QNetworkAccessManager: factory %p has returned an empty result set",
1705 proxyFactory);
1706 proxies << QNetworkProxy::NoProxy;
1707 }
1708 } else if (proxy.type() == QNetworkProxy::DefaultProxy) {
1709 // no proxy set, query the application
1711 } else {
1712 proxies << proxy;
1713 }
1714
1715 return proxies;
1716}
1717#endif
1718
1720{
1721 manager->d_func()->authenticationManager->clearCache();
1722}
1723
1725{
1726 manager->d_func()->objectCache.clear();
1727 manager->d_func()->destroyThread();
1728}
1729
1734
1736{
1737 if (!thread) {
1738 thread = new QThread;
1739 thread->setObjectName(QStringLiteral("QNetworkAccessManager thread"));
1740 thread->start();
1741 }
1743 return thread;
1744}
1745
1747{
1748 if (thread) {
1749 thread->quit();
1750 thread->wait(QDeadlineTimer(5000));
1751 if (thread->isFinished())
1752 delete thread;
1753 else
1754 QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
1755 thread = nullptr;
1756 }
1757}
1758
1759
1760#if QT_CONFIG(http) || defined(Q_OS_WASM)
1761
1762QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart)
1763{
1764 // copy the request, we probably need to add some headers
1765 QNetworkRequest newRequest(request);
1766 auto h = newRequest.headers();
1767
1768 // add Content-Type header if not there already
1770 QByteArray contentType;
1771 contentType.reserve(34 + multiPart->d_func()->boundary.size());
1772 contentType += "multipart/";
1773 switch (multiPart->d_func()->contentType) {
1775 contentType += "related";
1776 break;
1778 contentType += "form-data";
1779 break;
1781 contentType += "alternative";
1782 break;
1783 default:
1784 contentType += "mixed";
1785 break;
1786 }
1787 // putting the boundary into quotes, recommended in RFC 2046 section 5.1.1
1788 contentType += "; boundary=\"" + multiPart->d_func()->boundary + '"';
1790 }
1791
1792 // add MIME-Version header if not there already (we must include the header
1793 // if the message conforms to RFC 2045, see section 4 of that RFC)
1796
1797 newRequest.setHeaders(std::move(h));
1798
1799 QIODevice *device = multiPart->d_func()->device;
1800 if (!device->isReadable()) {
1801 if (!device->isOpen()) {
1802 if (!device->open(QIODevice::ReadOnly))
1803 qWarning("could not open device for reading");
1804 } else {
1805 qWarning("device is not readable");
1806 }
1807 }
1808
1809 return newRequest;
1810}
1811#endif // QT_CONFIG(http)
1812
1819{
1820 Q_CONSTINIT static QBasicMutex mutex;
1821 std::unique_lock locker(mutex);
1822 if (!qnabfLoader())
1823 return;
1824#if QT_CONFIG(library)
1825 qnabfLoader->update();
1826#endif
1827 int index = 0;
1828 while (qnabfLoader->instance(index))
1829 ++index;
1830}
1831
1833
1834#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:494
void reserve(qsizetype size)
Attempts to allocate memory for at least size bytes.
Definition qbytearray.h:634
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...
\inmodule QtCore
Q_NETWORK_EXPORT bool append(QAnyStringView name, QAnyStringView value)
Appends a header entry with name and value and returns true if successful.
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.
\inmodule QtCore
Definition qmutex.h:281
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)
void setTransferTimeout(int timeout)
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)
std::chrono::milliseconds transferTimeoutAsDuration() const
QAbstractNetworkCache * cache() const
void addStrictTransportSecurityHosts(const QList< QHstsPolicy > &knownHosts)
Operation
Indicates the operation this reply is processing.
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.
static QByteArray fromCookieList(const NetworkCookieList &cookies)
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 setHeaders(const QHttpHeaders &newHeaders)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void setSslConfiguration(const QSslConfiguration &configuration)
Sets this network request's SSL configuration to be config.
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.
void setPeerVerifyName(const QString &peerName)
QHttpHeaders headers() const
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:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1598
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
Definition qobject.h:127
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
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:129
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5455
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5949
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6664
void start(Priority=InheritPriority)
Definition qthread.cpp:996
bool isFinished() const
Definition qthread.cpp:1059
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
Definition qthread.cpp:1023
void quit()
Definition qthread.cpp:1008
\inmodule QtCore
Definition qurl.h:94
bool isLocalFile() const
Definition qurl.cpp:3445
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:2199
QString password(ComponentFormattingOptions=FullyDecoded) const
Returns the password of the URL if it is defined; otherwise an empty string is returned.
Definition qurl.cpp:2262
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1896
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1991
void setScheme(const QString &scheme)
Sets the scheme of the URL to scheme.
Definition qurl.cpp:1967
void setHost(const QString &host, ParsingMode mode=DecodedMode)
Sets the host of the URL to host.
Definition qurl.cpp:2289
@ FullyDecoded
Definition qurl.h:130
void setPort(int port)
Sets the port of the URL to port.
Definition qurl.cpp:2358
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.
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:166
#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:52
#define Q_RETURN_ARG(Type, data)
Definition qobjectdefs.h:64
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLenum mode
GLuint index
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum GLuint buffer
GLfloat GLfloat GLfloat GLfloat h
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:48
ptrdiff_t qsizetype
Definition qtypes.h:165
#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:45
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...