5#include <QtNetwork/private/qtnetworkglobal_p.h>
18#if QT_CONFIG(settings)
19#include "qhstsstore_p.h"
31#include "QtCore/qbuffer.h"
32#include "QtCore/qlist.h"
33#include "QtCore/qurl.h"
34#include "QtNetwork/private/qauthenticator_p.h"
35#include "QtNetwork/qsslconfiguration.h"
38#include "QtNetwork/private/http2protocol_p.h"
39#include "qhttpmultipart.h"
40#include "qhttpmultipart_p.h"
41#include "qnetworkreplyhttpimpl_p.h"
48#include "QtCore/qapplicationstatic.h"
49#include "QtCore/qloggingcategory.h"
50#include <QtCore/private/qfactoryloader_p.h>
52#if defined(Q_OS_MACOS)
53#include <QtCore/private/qcore_mac_p.h>
55#include <CoreServices/CoreServices.h>
56#include <SystemConfiguration/SystemConfiguration.h>
57#include <Security/Security.h>
60#include "qnetworkreplywasmimpl_p.h"
61#include "qhttpmultipart.h"
62#include "qhttpmultipart_p.h"
70using namespace Qt::StringLiterals;
71using namespace std::chrono_literals;
73#if defined(Q_OS_MACOS)
74Q_STATIC_LOGGING_CATEGORY(lcQnam,
"qt.network.access.manager")
77Q_APPLICATION_STATIC(QNetworkAccessFileBackendFactory, fileBackend)
79#if QT_CONFIG(private_tests)
80Q_GLOBAL_STATIC(QNetworkAccessDebugPipeBackendFactory, debugpipeBackend)
85#if defined(Q_OS_MACOS)
86bool getProxyAuth(
const QString& proxyHostname,
const QString &scheme, QString& username, QString& password)
88 CFStringRef protocolType =
nullptr;
89 if (scheme.compare(
"ftp"_L1, Qt::CaseInsensitive) == 0) {
90 protocolType = kSecAttrProtocolFTPProxy;
91 }
else if (scheme.compare(
"http"_L1, Qt::CaseInsensitive) == 0
92 || scheme.compare(
"preconnect-http"_L1, Qt::CaseInsensitive) == 0) {
93 protocolType = kSecAttrProtocolHTTPProxy;
94 }
else if (scheme.compare(
"https"_L1,Qt::CaseInsensitive)==0
95 || scheme.compare(
"preconnect-https"_L1, Qt::CaseInsensitive) == 0) {
96 protocolType = kSecAttrProtocolHTTPSProxy;
98 qCWarning(lcQnam) <<
"Cannot query user name and password for a proxy, unnknown protocol:"
103 QCFType<CFMutableDictionaryRef> query(CFDictionaryCreateMutable(kCFAllocatorDefault,
104 0,
nullptr,
nullptr));
107 CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword);
108 CFDictionaryAddValue(query, kSecAttrProtocol, protocolType);
110 QCFType<CFStringRef> serverName;
111 if (proxyHostname.size()) {
112 serverName = proxyHostname.toCFString();
113 CFDictionaryAddValue(query, kSecAttrServer, serverName);
117 CFDictionaryAddValue(query, kSecReturnAttributes, kCFBooleanTrue);
119 CFDictionaryAddValue(query, kSecReturnData, kCFBooleanTrue);
124 QCFType<CFTypeRef> replyData;
125 if (SecItemCopyMatching(query, &replyData) != errSecSuccess) {
126 qCWarning(lcQnam,
"Failed to extract user name and password from the keychain.");
130 if (!replyData || CFDictionaryGetTypeID() != CFGetTypeID(replyData)) {
131 qCWarning(lcQnam,
"Query returned data in unexpected format.");
135 CFDictionaryRef accountData = replyData.as<CFDictionaryRef>();
136 const void *value = CFDictionaryGetValue(accountData, kSecAttrAccount);
137 if (!value || CFGetTypeID(value) != CFStringGetTypeID()) {
138 qCWarning(lcQnam,
"Cannot find user name or its format is unknown.");
141 username = QString::fromCFString(
static_cast<CFStringRef>(value));
143 value = CFDictionaryGetValue(accountData, kSecValueData);
144 if (!value || CFGetTypeID(value) != CFDataGetTypeID()) {
145 qCWarning(lcQnam,
"Cannot find password or its format is unknown.");
148 const CFDataRef passData =
static_cast<
const CFDataRef>(value);
149 password = QString::fromLocal8Bit(
reinterpret_cast<
const char *>(CFDataGetBytePtr(passData)),
150 qsizetype(CFDataGetLength(passData)));
157static void ensureInitialized()
159#if QT_CONFIG(private_tests)
160 (
void) debugpipeBackend();
164 (
void) fileBackend();
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
264
265
266
267
268
269
270
271
272
273
274
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
413
414
415
416QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
417 : QObject(*
new QNetworkAccessManagerPrivate, parent)
420 d_func()->ensureBackendPluginsLoaded();
422 qRegisterMetaType<QNetworkReply::NetworkError>();
423#ifndef QT_NO_NETWORKPROXY
424 qRegisterMetaType<QNetworkProxy>();
427 qRegisterMetaType<QList<QSslError> >();
428 qRegisterMetaType<QSslConfiguration>();
429 qRegisterMetaType<QSslPreSharedKeyAuthenticator *>();
431 qRegisterMetaType<QList<std::pair<QByteArray, QByteArray>>>();
433 qRegisterMetaType<QHttpNetworkRequest>();
435 qRegisterMetaType<QNetworkReply::NetworkError>();
436 qRegisterMetaType<QSharedPointer<
char> >();
440
441
442
443
444
445
446QNetworkAccessManager::~QNetworkAccessManager()
448#ifndef QT_NO_NETWORKPROXY
449 delete d_func()->proxyFactory;
456 qDeleteAll(findChildren<QNetworkReply *>());
462#ifndef QT_NO_NETWORKPROXY
464
465
466
467
468
469
470QNetworkProxy QNetworkAccessManager::proxy()
const
472 return d_func()->proxy;
476
477
478
479
480
481
482
483
484
485
486
487
488
489void QNetworkAccessManager::setProxy(
const QNetworkProxy &proxy)
491 Q_D(QNetworkAccessManager);
492 delete d->proxyFactory;
494 d->proxyFactory =
nullptr;
498
499
500
501
502
503
504
505
506
507
508
509QNetworkProxyFactory *QNetworkAccessManager::proxyFactory()
const
511 return d_func()->proxyFactory;
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543void QNetworkAccessManager::setProxyFactory(QNetworkProxyFactory *factory)
545 Q_D(QNetworkAccessManager);
546 delete d->proxyFactory;
547 d->proxyFactory = factory;
548 d->proxy = QNetworkProxy();
553
554
555
556
557
558
559QAbstractNetworkCache *QNetworkAccessManager::cache()
const
561 Q_D(
const QNetworkAccessManager);
562 return d->networkCache;
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581void QNetworkAccessManager::setCache(QAbstractNetworkCache *cache)
583 Q_D(QNetworkAccessManager);
584 if (d->networkCache != cache) {
585 delete d->networkCache;
586 d->networkCache = cache;
588 d->networkCache->setParent(
this);
593
594
595
596
597
598
599QNetworkCookieJar *QNetworkAccessManager::cookieJar()
const
601 Q_D(
const QNetworkAccessManager);
603 d->createCookieJar();
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636void QNetworkAccessManager::setCookieJar(QNetworkCookieJar *cookieJar)
638 Q_D(QNetworkAccessManager);
639 d->cookieJarCreated =
true;
640 if (d->cookieJar != cookieJar) {
641 if (d->cookieJar && d->cookieJar->parent() ==
this)
643 d->cookieJar = cookieJar;
644 if (cookieJar && thread() == cookieJar->thread())
645 d->cookieJar->setParent(
this);
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664void QNetworkAccessManager::setStrictTransportSecurityEnabled(
bool enabled)
666 Q_D(QNetworkAccessManager);
667 d->stsEnabled = enabled;
671
672
673
674
675
676
677
678bool QNetworkAccessManager::isStrictTransportSecurityEnabled()
const
680 Q_D(
const QNetworkAccessManager);
681 return d->stsEnabled;
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
716void QNetworkAccessManager::enableStrictTransportSecurityStore(
bool enabled,
const QString &storeDir)
718#if QT_CONFIG(settings)
719 Q_D(QNetworkAccessManager);
720 d->stsStore.reset(enabled ?
new QHstsStore(storeDir) :
nullptr);
721 d->stsCache.setStore(d->stsStore.get());
725 qWarning(
"HSTS permanent store requires the feature 'settings' enabled");
730
731
732
733
734
735
736
738bool QNetworkAccessManager::isStrictTransportSecurityStoreEnabled()
const
740#if QT_CONFIG(settings)
741 Q_D(
const QNetworkAccessManager);
742 return bool(d->stsStore);
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
768void QNetworkAccessManager::addStrictTransportSecurityHosts(
const QList<QHstsPolicy> &knownHosts)
770 Q_D(QNetworkAccessManager);
771 d->stsCache.updateFromPolicies(knownHosts);
775
776
777
778
779
780
781
782
783QList<QHstsPolicy> QNetworkAccessManager::strictTransportSecurityHosts()
const
785 Q_D(
const QNetworkAccessManager);
786 return d->stsCache.policies();
790
791
792
793
794
795QNetworkReply *QNetworkAccessManager::head(
const QNetworkRequest &request)
797 return d_func()->postProcess(createRequest(QNetworkAccessManager::HeadOperation, request));
801
802
803
804
805
806
807
808
809
810QNetworkReply *QNetworkAccessManager::get(
const QNetworkRequest &request)
812 return d_func()->postProcess(createRequest(QNetworkAccessManager::GetOperation, request));
816
817
818
819
820
821
822
823
824
826QNetworkReply *QNetworkAccessManager::get(
const QNetworkRequest &request, QIODevice *data)
828 QNetworkRequest newRequest(request);
829 return d_func()->postProcess(
830 createRequest(QNetworkAccessManager::GetOperation, newRequest, data));
834
835
836
837
838
839
840
841
842
844QNetworkReply *QNetworkAccessManager::get(
const QNetworkRequest &request,
const QByteArray &data)
846 QBuffer *buffer =
new QBuffer;
847 buffer->setData(data);
848 buffer->open(QIODevice::ReadOnly);
850 QNetworkReply *reply = get(request, buffer);
851 buffer->setParent(reply);
856
857
858
859
860
861
862
863
864
865
866
867
868
869QNetworkReply *QNetworkAccessManager::post(
const QNetworkRequest &request, QIODevice *data)
871 return d_func()->postProcess(createRequest(QNetworkAccessManager::PostOperation, request, data));
875
876
877
878
879
880QNetworkReply *QNetworkAccessManager::post(
const QNetworkRequest &request,
const QByteArray &data)
882 QBuffer *buffer =
new QBuffer;
883 buffer->setData(data);
884 buffer->open(QIODevice::ReadOnly);
886 QNetworkReply *reply = post(request, buffer);
887 buffer->setParent(reply);
892
893
894
895
896
897
898
899
900
902#if QT_CONFIG(http) || defined(Q_OS_WASM)
904
905
906
907
908
909
910
911
912
913
914
915QNetworkReply *QNetworkAccessManager::post(
const QNetworkRequest &request, QHttpMultiPart *multiPart)
917 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
918 QIODevice *device = multiPart->d_func()->device;
919 QNetworkReply *reply = post(newRequest, device);
924
925
926
927
928
929
930
931
932
933
934
935QNetworkReply *QNetworkAccessManager::put(
const QNetworkRequest &request, QHttpMultiPart *multiPart)
937 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
938 QIODevice *device = multiPart->d_func()->device;
939 QNetworkReply *reply = put(newRequest, device);
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963QNetworkReply *QNetworkAccessManager::put(
const QNetworkRequest &request, QIODevice *data)
965 return d_func()->postProcess(createRequest(QNetworkAccessManager::PutOperation, request, data));
969
970
971
972
973
974QNetworkReply *QNetworkAccessManager::put(
const QNetworkRequest &request,
const QByteArray &data)
976 QBuffer *buffer =
new QBuffer;
977 buffer->setData(data);
978 buffer->open(QIODevice::ReadOnly);
980 QNetworkReply *reply = put(request, buffer);
981 buffer->setParent(reply);
986
987
988
989
990
991
992
993
994
997
998
999
1000
1001
1002
1003
1004
1005
1006QNetworkReply *QNetworkAccessManager::deleteResource(
const QNetworkRequest &request)
1008 return d_func()->postProcess(createRequest(QNetworkAccessManager::DeleteOperation, request));
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1030void QNetworkAccessManager::connectToHostEncrypted(
const QString &hostName, quint16 port,
1031 const QSslConfiguration &sslConfiguration)
1033 connectToHostEncrypted(hostName, port, sslConfiguration, QString());
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1056void QNetworkAccessManager::connectToHostEncrypted(
const QString &hostName, quint16 port,
1057 const QSslConfiguration &sslConfiguration,
1058 const QString &peerName)
1061 url.setHost(hostName);
1063 url.setScheme(
"preconnect-https"_L1);
1064 QNetworkRequest request(url);
1065 if (sslConfiguration != QSslConfiguration::defaultConfiguration())
1066 request.setSslConfiguration(sslConfiguration);
1070 if (!sslConfiguration.allowedNextProtocols().contains(QSslConfiguration::ALPNProtocolHTTP2))
1071 request.setAttribute(QNetworkRequest::Http2AllowedAttribute,
false);
1073 request.setPeerVerifyName(peerName);
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089void QNetworkAccessManager::connectToHost(
const QString &hostName, quint16 port)
1092 url.setHost(hostName);
1094 url.setScheme(
"preconnect-http"_L1);
1095 QNetworkRequest request(url);
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116void QNetworkAccessManager::setRedirectPolicy(QNetworkRequest::RedirectPolicy policy)
1118 Q_D(QNetworkAccessManager);
1119 d->redirectPolicy = policy;
1123
1124
1125
1126
1127
1128
1129QNetworkRequest::RedirectPolicy QNetworkAccessManager::redirectPolicy()
const
1131 Q_D(
const QNetworkAccessManager);
1132 return d->redirectPolicy;
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154QNetworkReply *QNetworkAccessManager::sendCustomRequest(
const QNetworkRequest &request,
const QByteArray &verb, QIODevice *data)
1156 QNetworkRequest newRequest(request);
1157 newRequest.setAttribute(QNetworkRequest::CustomVerbAttribute, verb);
1158 return d_func()->postProcess(createRequest(QNetworkAccessManager::CustomOperation, newRequest, data));
1162
1163
1164
1165
1166
1167
1168
1171
1172
1173
1174
1175
1176
1177
1178QNetworkReply *QNetworkAccessManager::sendCustomRequest(
const QNetworkRequest &request,
const QByteArray &verb,
const QByteArray &data)
1180 QBuffer *buffer =
new QBuffer;
1181 buffer->setData(data);
1182 buffer->open(QIODevice::ReadOnly);
1184 QNetworkReply *reply = sendCustomRequest(request, verb, buffer);
1185 buffer->setParent(reply);
1189#if QT_CONFIG(http) || defined(Q_OS_WASM)
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204QNetworkReply *QNetworkAccessManager::sendCustomRequest(
const QNetworkRequest &request,
const QByteArray &verb, QHttpMultiPart *multiPart)
1206 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
1207 QIODevice *device = multiPart->d_func()->device;
1208 QNetworkReply *reply = sendCustomRequest(newRequest, verb, device);
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op,
1227 const QNetworkRequest &originalReq,
1228 QIODevice *outgoingData)
1230 Q_D(QNetworkAccessManager);
1232 QNetworkRequest req(originalReq);
1233 if (redirectPolicy() != QNetworkRequest::NoLessSafeRedirectPolicy
1234 && req.attribute(QNetworkRequest::RedirectPolicyAttribute).isNull()) {
1235 req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, redirectPolicy());
1238#if QT_CONFIG(http) || defined (Q_OS_WASM)
1239 if (req.transferTimeoutAsDuration() == 0ms)
1240 req.setTransferTimeout(transferTimeoutAsDuration());
1243 if (autoDeleteReplies()
1244 && req.attribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute).isNull()) {
1245 req.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute,
true);
1248 bool isLocalFile = req.url().isLocalFile();
1249 QString scheme = req.url().scheme();
1252 if (scheme ==
"local+http"_L1) {
1253 scheme = u"unix+http"_s;
1254 QUrl url = req.url();
1255 url.setScheme(scheme);
1261 if (op == QNetworkAccessManager::GetOperation
1262 || op == QNetworkAccessManager::HeadOperation) {
1265 || scheme ==
"assets"_L1
1267 || scheme ==
"qrc"_L1) {
1268 return new QNetworkReplyFileImpl(
this, req, op);
1271 if (scheme ==
"data"_L1)
1272 return new QNetworkReplyDataImpl(
this, req, op);
1275 QNetworkRequest::CacheLoadControl mode =
1276 static_cast<QNetworkRequest::CacheLoadControl>(
1277 req.attribute(QNetworkRequest::CacheLoadControlAttribute,
1278 QNetworkRequest::PreferNetwork).toInt());
1279 if (mode == QNetworkRequest::AlwaysCache) {
1281 QNetworkReplyImpl *reply =
new QNetworkReplyImpl(
this);
1282 QNetworkReplyImplPrivate *priv = reply->d_func();
1283 priv->manager =
this;
1284 priv->backend =
new QNetworkAccessCacheBackend();
1285 priv->backend->setManagerPrivate(
this->d_func());
1286 priv->backend->setParent(reply);
1287 priv->backend->setReplyPrivate(priv);
1288 priv->setup(op, req, outgoingData);
1292 QNetworkRequest request = req;
1293 auto h = request.headers();
1295 if (!h.contains(QHttpHeaders::WellKnownHeader::ContentLength) &&
1296 outgoingData && !outgoingData->isSequential() && outgoingData->size()) {
1299 h.append(QHttpHeaders::WellKnownHeader::ContentLength,
1300 QByteArray::number(outgoingData->size()));
1303 if (
static_cast<QNetworkRequest::LoadControl>
1304 (request.attribute(QNetworkRequest::CookieLoadControlAttribute,
1305 QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Automatic) {
1307 QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url());
1308 if (!cookies.isEmpty())
1309 h.replaceOrAppend(QHttpHeaders::WellKnownHeader::Cookie,
1310 QNetworkHeadersPrivate::fromCookieList(cookies));
1313 request.setHeaders(std::move(h));
1315 Q_UNUSED(isLocalFile);
1317 if (scheme ==
"http"_L1 || scheme ==
"https"_L1 || scheme.isEmpty()) {
1318 QNetworkReplyWasmImpl *reply =
new QNetworkReplyWasmImpl(
this);
1319 QNetworkReplyWasmImplPrivate *priv = reply->d_func();
1320 priv->manager =
this;
1321 priv->setup(op, request, outgoingData);
1327 constexpr char16_t httpSchemes[][17] = {
1332 u"preconnect-https",
1337 if (std::find(std::begin(httpSchemes), std::end(httpSchemes), scheme) != std::end(httpSchemes)) {
1340 const bool isLocalSocket = scheme.startsWith(
"unix"_L1);
1341 if (!isLocalSocket && isStrictTransportSecurityEnabled()
1342 && d->stsCache.isKnownHost(request.url())) {
1343 QUrl stsUrl(request.url());
1353 if (stsUrl.port() == 80)
1354 stsUrl.setPort(443);
1355 stsUrl.setScheme(
"https"_L1);
1356 request.setUrl(stsUrl);
1359 QNetworkReplyHttpImpl *reply =
new QNetworkReplyHttpImpl(
this, request, op, outgoingData);
1365 QNetworkReplyImpl *reply =
new QNetworkReplyImpl(
this);
1366 QNetworkReplyImplPrivate *priv = reply->d_func();
1367 priv->manager =
this;
1374 priv->backend = d->findBackend(op, request);
1376 if (priv->backend) {
1377 priv->backend->setParent(reply);
1378 priv->backend->setReplyPrivate(priv);
1382 reply->setSslConfiguration(request.sslConfiguration());
1386 priv->setup(op, request, outgoingData);
1392
1393
1394
1395
1396
1397
1398
1399
1400QStringList QNetworkAccessManager::supportedSchemes()
const
1402 QStringList schemes;
1403 QNetworkAccessManager *self =
const_cast<QNetworkAccessManager *>(
this);
1404 QMetaObject::invokeMethod(self,
"supportedSchemesImplementation", Qt::DirectConnection,
1405 Q_RETURN_ARG(QStringList, schemes));
1406 schemes.removeDuplicates();
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425QStringList QNetworkAccessManager::supportedSchemesImplementation()
const
1427 Q_D(
const QNetworkAccessManager);
1429 QStringList schemes = d->backendSupportedSchemes();
1432 schemes << QStringLiteral(
"http");
1433 schemes << QStringLiteral(
"unix+http");
1434 schemes << QStringLiteral(
"local+http");
1436 if (QSslSocket::supportsSsl())
1437 schemes << QStringLiteral(
"https");
1440 schemes << QStringLiteral(
"data");
1445
1446
1447
1448
1449
1450
1451
1452
1453void QNetworkAccessManager::clearAccessCache()
1455 QNetworkAccessManagerPrivate::clearAuthenticationCache(
this);
1456 QNetworkAccessManagerPrivate::clearConnectionCache(
this);
1460
1461
1462
1463
1464
1465
1466
1467
1468void QNetworkAccessManager::clearConnectionCache()
1470 QNetworkAccessManagerPrivate::clearConnectionCache(
this);
1475
1476
1477
1478
1479
1480
1481
1482
1483bool QNetworkAccessManager::autoDeleteReplies()
const
1485 return d_func()->autoDeleteReplies;
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502void QNetworkAccessManager::setAutoDeleteReplies(
bool shouldAutoDelete)
1504 d_func()->autoDeleteReplies = shouldAutoDelete;
1508
1509
1510
1511
1512
1513
1514
1517
1518
1519
1520
1521
1522
1523
1524
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536std::chrono::milliseconds QNetworkAccessManager::transferTimeoutAsDuration()
const
1538 return d_func()->transferTimeout;
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558void QNetworkAccessManager::setTransferTimeout(std::chrono::milliseconds duration)
1560 d_func()->transferTimeout = duration;
1563void QNetworkAccessManagerPrivate::_q_replyFinished(QNetworkReply *reply)
1565 Q_Q(QNetworkAccessManager);
1567 emit q->finished(reply);
1568 if (reply->request().attribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute,
false).toBool())
1569 QMetaObject::invokeMethod(reply, [reply] { reply->deleteLater(); }, Qt::QueuedConnection);
1572void QNetworkAccessManagerPrivate::_q_replyEncrypted(QNetworkReply *reply)
1575 Q_Q(QNetworkAccessManager);
1576 emit q->encrypted(reply);
1582void QNetworkAccessManagerPrivate::_q_replySslErrors(
const QList<QSslError> &errors)
1585 Q_Q(QNetworkAccessManager);
1586 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1588 emit q->sslErrors(reply, errors);
1595void QNetworkAccessManagerPrivate::_q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator)
1597 Q_Q(QNetworkAccessManager);
1598 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1600 emit q->preSharedKeyAuthenticationRequired(reply, authenticator);
1604QNetworkReply *QNetworkAccessManagerPrivate::postProcess(QNetworkReply *reply)
1606 Q_Q(QNetworkAccessManager);
1607 QNetworkReplyPrivate::setManager(reply, q);
1608 q->connect(reply, &QNetworkReply::finished, reply,
1609 [
this, reply]() { _q_replyFinished(reply); });
1612
1613 q->connect(reply, &QNetworkReply::encrypted, reply,
1614 [
this, reply]() { _q_replyEncrypted(reply); });
1615 q->connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(_q_replySslErrors(QList<QSslError>)));
1616 q->connect(reply, SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)), SLOT(_q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)));
1622void QNetworkAccessManagerPrivate::createCookieJar()
const
1624 if (!cookieJarCreated) {
1626 QNetworkAccessManagerPrivate *that =
const_cast<QNetworkAccessManagerPrivate *>(
this);
1627 that->cookieJar =
new QNetworkCookieJar(that->q_func());
1628 that->cookieJarCreated =
true;
1632void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authenticator,
1633 QNetworkReply *reply,
1636 QUrl *urlForLastAuthentication,
1637 bool allowAuthenticationReuse)
1639 Q_Q(QNetworkAccessManager);
1644 if (allowAuthenticationReuse && (urlForLastAuthentication->isEmpty()
1645 || url != *urlForLastAuthentication)) {
1647 if (!url.userName().isEmpty() && !url.password().isEmpty()
1648 && (url.userName() != authenticator->user()
1649 || url.password() != authenticator->password())) {
1650 authenticator->setUser(url.userName(QUrl::FullyDecoded));
1651 authenticator->setPassword(url.password(QUrl::FullyDecoded));
1652 *urlForLastAuthentication = url;
1653 authenticationManager->cacheCredentials(url, authenticator);
1657 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedCredentials(url, authenticator);
1659 && (cred.user != authenticator->user() || cred.password != authenticator->password())) {
1660 authenticator->setUser(cred.user);
1661 authenticator->setPassword(cred.password);
1662 *urlForLastAuthentication = url;
1672 *urlForLastAuthentication = url;
1673 emit q->authenticationRequired(reply, authenticator);
1674 if (allowAuthenticationReuse)
1675 authenticationManager->cacheCredentials(url, authenticator);
1678#ifndef QT_NO_NETWORKPROXY
1679void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(
const QUrl &url,
1680 const QNetworkProxy &proxy,
1682 QAuthenticator *authenticator,
1683 QNetworkProxy *lastProxyAuthentication)
1685 Q_Q(QNetworkAccessManager);
1686 QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(*authenticator);
1687 if (proxy != *lastProxyAuthentication && (!priv || !priv->hasFailed)) {
1688 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1689 if (!cred.isNull()) {
1690 authenticator->setUser(cred.user);
1691 authenticator->setPassword(cred.password);
1696#if defined(Q_OS_MACOS)
1701 if (getProxyAuth(proxy.hostName(), url.scheme(), username, password)) {
1704 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1705 if (!priv->hasFailed || cred.user != username || cred.password != password) {
1706 authenticator->setUser(username);
1707 authenticator->setPassword(password);
1708 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1721 *lastProxyAuthentication = proxy;
1722 emit q->proxyAuthenticationRequired(proxy, authenticator);
1723 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1726QList<QNetworkProxy> QNetworkAccessManagerPrivate::queryProxy(
const QNetworkProxyQuery &query)
1728 QList<QNetworkProxy> proxies;
1730 proxies = proxyFactory->queryProxy(query);
1731 if (proxies.isEmpty()) {
1732 qWarning(
"QNetworkAccessManager: factory %p has returned an empty result set",
1734 proxies << QNetworkProxy::NoProxy;
1736 }
else if (proxy.type() == QNetworkProxy::DefaultProxy) {
1738 return QNetworkProxyFactory::proxyForQuery(query);
1747void QNetworkAccessManagerPrivate::clearAuthenticationCache(QNetworkAccessManager *manager)
1749 manager->d_func()->authenticationManager->clearCache();
1752void QNetworkAccessManagerPrivate::clearConnectionCache(QNetworkAccessManager *manager)
1754 manager->d_func()->destroyThread();
1757QNetworkAccessManagerPrivate::~QNetworkAccessManagerPrivate()
1762QThread * QNetworkAccessManagerPrivate::createThread()
1765 thread =
new QThread;
1766 thread->setObjectName(QStringLiteral(
"QNetworkAccessManager thread"));
1773void QNetworkAccessManagerPrivate::destroyThread()
1777 thread->wait(QDeadlineTimer(5000));
1778 if (thread->isFinished())
1781 QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
1787#if QT_CONFIG(http) || defined(Q_OS_WASM)
1789QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(
const QNetworkRequest &request, QHttpMultiPart *multiPart)
1792 QNetworkRequest newRequest(request);
1793 auto h = newRequest.headers();
1796 if (!h.contains(QHttpHeaders::WellKnownHeader::ContentType)) {
1797 QByteArray contentType;
1798 contentType.reserve(34 + multiPart->d_func()->boundary.size());
1799 contentType +=
"multipart/";
1800 switch (multiPart->d_func()->contentType) {
1801 case QHttpMultiPart::RelatedType:
1802 contentType +=
"related";
1804 case QHttpMultiPart::FormDataType:
1805 contentType +=
"form-data";
1807 case QHttpMultiPart::AlternativeType:
1808 contentType +=
"alternative";
1811 contentType +=
"mixed";
1815 contentType +=
"; boundary=\"" + multiPart->d_func()->boundary +
'"';
1816 h.append(QHttpHeaders::WellKnownHeader::ContentType, contentType);
1821 if (!h.contains(QHttpHeaders::WellKnownHeader::MIMEVersion))
1822 h.append(QHttpHeaders::WellKnownHeader::MIMEVersion,
"1.0"_ba);
1824 newRequest.setHeaders(std::move(h));
1826 QIODevice *device = multiPart->d_func()->device;
1827 if (!device->isReadable()) {
1828 if (!device->isOpen()) {
1829 if (!device->open(QIODevice::ReadOnly))
1830 qWarning(
"could not open device for reading");
1832 qWarning(
"device is not readable");
1841
1842
1843
1844
1845void QNetworkAccessManagerPrivate::ensureBackendPluginsLoaded()
1847 Q_CONSTINIT
static QBasicMutex mutex;
1848 std::unique_lock locker(mutex);
1851#if QT_CONFIG(library)
1852 qnabfLoader->update();
1854 const int pluginCount = qnabfLoader->metaData().size();
1855 for (
int i = 0; i < pluginCount; ++i)
1856 qnabfLoader->instance(i);
1861#include "moc_qnetworkaccessmanager.cpp"
Combined button and popup list for selecting options.
#define QNetworkAccessBackendFactory_iid