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
1169QNetworkReply *QNetworkAccessManager::sendCustomRequest(
const QNetworkRequest &request,
const QByteArray &verb,
const QByteArray &data)
1171 QBuffer *buffer =
new QBuffer;
1172 buffer->setData(data);
1173 buffer->open(QIODevice::ReadOnly);
1175 QNetworkReply *reply = sendCustomRequest(request, verb, buffer);
1176 buffer->setParent(reply);
1180#if QT_CONFIG(http) || defined(Q_OS_WASM)
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195QNetworkReply *QNetworkAccessManager::sendCustomRequest(
const QNetworkRequest &request,
const QByteArray &verb, QHttpMultiPart *multiPart)
1197 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
1198 QIODevice *device = multiPart->d_func()->device;
1199 QNetworkReply *reply = sendCustomRequest(newRequest, verb, device);
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op,
1218 const QNetworkRequest &originalReq,
1219 QIODevice *outgoingData)
1221 Q_D(QNetworkAccessManager);
1223 QNetworkRequest req(originalReq);
1224 if (redirectPolicy() != QNetworkRequest::NoLessSafeRedirectPolicy
1225 && req.attribute(QNetworkRequest::RedirectPolicyAttribute).isNull()) {
1226 req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, redirectPolicy());
1229#if QT_CONFIG(http) || defined (Q_OS_WASM)
1230 if (req.transferTimeoutAsDuration() == 0ms)
1231 req.setTransferTimeout(transferTimeoutAsDuration());
1234 if (autoDeleteReplies()
1235 && req.attribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute).isNull()) {
1236 req.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute,
true);
1239 bool isLocalFile = req.url().isLocalFile();
1240 QString scheme = req.url().scheme();
1243 if (scheme ==
"local+http"_L1) {
1244 scheme = u"unix+http"_s;
1245 QUrl url = req.url();
1246 url.setScheme(scheme);
1252 if (op == QNetworkAccessManager::GetOperation
1253 || op == QNetworkAccessManager::HeadOperation) {
1256 || scheme ==
"assets"_L1
1258 || scheme ==
"qrc"_L1) {
1259 return new QNetworkReplyFileImpl(
this, req, op);
1262 if (scheme ==
"data"_L1)
1263 return new QNetworkReplyDataImpl(
this, req, op);
1266 QNetworkRequest::CacheLoadControl mode =
1267 static_cast<QNetworkRequest::CacheLoadControl>(
1268 req.attribute(QNetworkRequest::CacheLoadControlAttribute,
1269 QNetworkRequest::PreferNetwork).toInt());
1270 if (mode == QNetworkRequest::AlwaysCache) {
1272 QNetworkReplyImpl *reply =
new QNetworkReplyImpl(
this);
1273 QNetworkReplyImplPrivate *priv = reply->d_func();
1274 priv->manager =
this;
1275 priv->backend =
new QNetworkAccessCacheBackend();
1276 priv->backend->setManagerPrivate(
this->d_func());
1277 priv->backend->setParent(reply);
1278 priv->backend->setReplyPrivate(priv);
1279 priv->setup(op, req, outgoingData);
1283 QNetworkRequest request = req;
1284 auto h = request.headers();
1286 if (!h.contains(QHttpHeaders::WellKnownHeader::ContentLength) &&
1287 outgoingData && !outgoingData->isSequential() && outgoingData->size()) {
1290 h.append(QHttpHeaders::WellKnownHeader::ContentLength,
1291 QByteArray::number(outgoingData->size()));
1294 if (
static_cast<QNetworkRequest::LoadControl>
1295 (request.attribute(QNetworkRequest::CookieLoadControlAttribute,
1296 QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Automatic) {
1298 QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url());
1299 if (!cookies.isEmpty())
1300 h.replaceOrAppend(QHttpHeaders::WellKnownHeader::Cookie,
1301 QNetworkHeadersPrivate::fromCookieList(cookies));
1304 request.setHeaders(std::move(h));
1306 Q_UNUSED(isLocalFile);
1308 if (scheme ==
"http"_L1 || scheme ==
"https"_L1 || scheme.isEmpty()) {
1309 QNetworkReplyWasmImpl *reply =
new QNetworkReplyWasmImpl(
this);
1310 QNetworkReplyWasmImplPrivate *priv = reply->d_func();
1311 priv->manager =
this;
1312 priv->setup(op, request, outgoingData);
1318 constexpr char16_t httpSchemes[][17] = {
1323 u"preconnect-https",
1328 if (std::find(std::begin(httpSchemes), std::end(httpSchemes), scheme) != std::end(httpSchemes)) {
1331 const bool isLocalSocket = scheme.startsWith(
"unix"_L1);
1332 if (!isLocalSocket && isStrictTransportSecurityEnabled()
1333 && d->stsCache.isKnownHost(request.url())) {
1334 QUrl stsUrl(request.url());
1344 if (stsUrl.port() == 80)
1345 stsUrl.setPort(443);
1346 stsUrl.setScheme(
"https"_L1);
1347 request.setUrl(stsUrl);
1350 QNetworkReplyHttpImpl *reply =
new QNetworkReplyHttpImpl(
this, request, op, outgoingData);
1356 QNetworkReplyImpl *reply =
new QNetworkReplyImpl(
this);
1357 QNetworkReplyImplPrivate *priv = reply->d_func();
1358 priv->manager =
this;
1365 priv->backend = d->findBackend(op, request);
1367 if (priv->backend) {
1368 priv->backend->setParent(reply);
1369 priv->backend->setReplyPrivate(priv);
1373 reply->setSslConfiguration(request.sslConfiguration());
1377 priv->setup(op, request, outgoingData);
1383
1384
1385
1386
1387
1388
1389
1390
1391QStringList QNetworkAccessManager::supportedSchemes()
const
1393 QStringList schemes;
1394 QNetworkAccessManager *self =
const_cast<QNetworkAccessManager *>(
this);
1395 QMetaObject::invokeMethod(self,
"supportedSchemesImplementation", Qt::DirectConnection,
1396 Q_RETURN_ARG(QStringList, schemes));
1397 schemes.removeDuplicates();
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416QStringList QNetworkAccessManager::supportedSchemesImplementation()
const
1418 Q_D(
const QNetworkAccessManager);
1420 QStringList schemes = d->backendSupportedSchemes();
1423 schemes << QStringLiteral(
"http");
1424 schemes << QStringLiteral(
"unix+http");
1425 schemes << QStringLiteral(
"local+http");
1427 if (QSslSocket::supportsSsl())
1428 schemes << QStringLiteral(
"https");
1431 schemes << QStringLiteral(
"data");
1436
1437
1438
1439
1440
1441
1442
1443
1444void QNetworkAccessManager::clearAccessCache()
1446 QNetworkAccessManagerPrivate::clearAuthenticationCache(
this);
1447 QNetworkAccessManagerPrivate::clearConnectionCache(
this);
1451
1452
1453
1454
1455
1456
1457
1458
1459void QNetworkAccessManager::clearConnectionCache()
1461 QNetworkAccessManagerPrivate::clearConnectionCache(
this);
1466
1467
1468
1469
1470
1471
1472
1473
1474bool QNetworkAccessManager::autoDeleteReplies()
const
1476 return d_func()->autoDeleteReplies;
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493void QNetworkAccessManager::setAutoDeleteReplies(
bool shouldAutoDelete)
1495 d_func()->autoDeleteReplies = shouldAutoDelete;
1499
1500
1501
1502
1503
1504
1505
1508
1509
1510
1511
1512
1513
1514
1515
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527std::chrono::milliseconds QNetworkAccessManager::transferTimeoutAsDuration()
const
1529 return d_func()->transferTimeout;
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549void QNetworkAccessManager::setTransferTimeout(std::chrono::milliseconds duration)
1551 d_func()->transferTimeout = duration;
1554void QNetworkAccessManagerPrivate::_q_replyFinished(QNetworkReply *reply)
1556 Q_Q(QNetworkAccessManager);
1558 emit q->finished(reply);
1559 if (reply->request().attribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute,
false).toBool())
1560 QMetaObject::invokeMethod(reply, [reply] { reply->deleteLater(); }, Qt::QueuedConnection);
1563void QNetworkAccessManagerPrivate::_q_replyEncrypted(QNetworkReply *reply)
1566 Q_Q(QNetworkAccessManager);
1567 emit q->encrypted(reply);
1573void QNetworkAccessManagerPrivate::_q_replySslErrors(
const QList<QSslError> &errors)
1576 Q_Q(QNetworkAccessManager);
1577 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1579 emit q->sslErrors(reply, errors);
1586void QNetworkAccessManagerPrivate::_q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator)
1588 Q_Q(QNetworkAccessManager);
1589 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1591 emit q->preSharedKeyAuthenticationRequired(reply, authenticator);
1595QNetworkReply *QNetworkAccessManagerPrivate::postProcess(QNetworkReply *reply)
1597 Q_Q(QNetworkAccessManager);
1598 QNetworkReplyPrivate::setManager(reply, q);
1599 q->connect(reply, &QNetworkReply::finished, reply,
1600 [
this, reply]() { _q_replyFinished(reply); });
1603
1604 q->connect(reply, &QNetworkReply::encrypted, reply,
1605 [
this, reply]() { _q_replyEncrypted(reply); });
1606 q->connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(_q_replySslErrors(QList<QSslError>)));
1607 q->connect(reply, SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)), SLOT(_q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)));
1613void QNetworkAccessManagerPrivate::createCookieJar()
const
1615 if (!cookieJarCreated) {
1617 QNetworkAccessManagerPrivate *that =
const_cast<QNetworkAccessManagerPrivate *>(
this);
1618 that->cookieJar =
new QNetworkCookieJar(that->q_func());
1619 that->cookieJarCreated =
true;
1623void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authenticator,
1624 QNetworkReply *reply,
1627 QUrl *urlForLastAuthentication,
1628 bool allowAuthenticationReuse)
1630 Q_Q(QNetworkAccessManager);
1635 if (allowAuthenticationReuse && (urlForLastAuthentication->isEmpty()
1636 || url != *urlForLastAuthentication)) {
1638 if (!url.userName().isEmpty() && !url.password().isEmpty()
1639 && (url.userName() != authenticator->user()
1640 || url.password() != authenticator->password())) {
1641 authenticator->setUser(url.userName(QUrl::FullyDecoded));
1642 authenticator->setPassword(url.password(QUrl::FullyDecoded));
1643 *urlForLastAuthentication = url;
1644 authenticationManager->cacheCredentials(url, authenticator);
1648 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedCredentials(url, authenticator);
1650 && (cred.user != authenticator->user() || cred.password != authenticator->password())) {
1651 authenticator->setUser(cred.user);
1652 authenticator->setPassword(cred.password);
1653 *urlForLastAuthentication = url;
1663 *urlForLastAuthentication = url;
1664 emit q->authenticationRequired(reply, authenticator);
1665 if (allowAuthenticationReuse)
1666 authenticationManager->cacheCredentials(url, authenticator);
1669#ifndef QT_NO_NETWORKPROXY
1670void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(
const QUrl &url,
1671 const QNetworkProxy &proxy,
1673 QAuthenticator *authenticator,
1674 QNetworkProxy *lastProxyAuthentication)
1676 Q_Q(QNetworkAccessManager);
1677 QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(*authenticator);
1678 if (proxy != *lastProxyAuthentication && (!priv || !priv->hasFailed)) {
1679 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1680 if (!cred.isNull()) {
1681 authenticator->setUser(cred.user);
1682 authenticator->setPassword(cred.password);
1687#if defined(Q_OS_MACOS)
1692 if (getProxyAuth(proxy.hostName(), url.scheme(), username, password)) {
1695 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1696 if (!priv->hasFailed || cred.user != username || cred.password != password) {
1697 authenticator->setUser(username);
1698 authenticator->setPassword(password);
1699 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1712 *lastProxyAuthentication = proxy;
1713 emit q->proxyAuthenticationRequired(proxy, authenticator);
1714 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1717QList<QNetworkProxy> QNetworkAccessManagerPrivate::queryProxy(
const QNetworkProxyQuery &query)
1719 QList<QNetworkProxy> proxies;
1721 proxies = proxyFactory->queryProxy(query);
1722 if (proxies.isEmpty()) {
1723 qWarning(
"QNetworkAccessManager: factory %p has returned an empty result set",
1725 proxies << QNetworkProxy::NoProxy;
1727 }
else if (proxy.type() == QNetworkProxy::DefaultProxy) {
1729 return QNetworkProxyFactory::proxyForQuery(query);
1738void QNetworkAccessManagerPrivate::clearAuthenticationCache(QNetworkAccessManager *manager)
1740 manager->d_func()->authenticationManager->clearCache();
1743void QNetworkAccessManagerPrivate::clearConnectionCache(QNetworkAccessManager *manager)
1745 manager->d_func()->destroyThread();
1748QNetworkAccessManagerPrivate::~QNetworkAccessManagerPrivate()
1753QThread * QNetworkAccessManagerPrivate::createThread()
1756 thread =
new QThread;
1757 thread->setObjectName(QStringLiteral(
"QNetworkAccessManager thread"));
1764void QNetworkAccessManagerPrivate::destroyThread()
1768 thread->wait(QDeadlineTimer(5000));
1769 if (thread->isFinished())
1772 QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
1778#if QT_CONFIG(http) || defined(Q_OS_WASM)
1780QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(
const QNetworkRequest &request, QHttpMultiPart *multiPart)
1783 QNetworkRequest newRequest(request);
1784 auto h = newRequest.headers();
1787 if (!h.contains(QHttpHeaders::WellKnownHeader::ContentType)) {
1788 QByteArray contentType;
1789 contentType.reserve(34 + multiPart->d_func()->boundary.size());
1790 contentType +=
"multipart/";
1791 switch (multiPart->d_func()->contentType) {
1792 case QHttpMultiPart::RelatedType:
1793 contentType +=
"related";
1795 case QHttpMultiPart::FormDataType:
1796 contentType +=
"form-data";
1798 case QHttpMultiPart::AlternativeType:
1799 contentType +=
"alternative";
1802 contentType +=
"mixed";
1806 contentType +=
"; boundary=\"" + multiPart->d_func()->boundary +
'"';
1807 h.append(QHttpHeaders::WellKnownHeader::ContentType, contentType);
1812 if (!h.contains(QHttpHeaders::WellKnownHeader::MIMEVersion))
1813 h.append(QHttpHeaders::WellKnownHeader::MIMEVersion,
"1.0"_ba);
1815 newRequest.setHeaders(std::move(h));
1817 QIODevice *device = multiPart->d_func()->device;
1818 if (!device->isReadable()) {
1819 if (!device->isOpen()) {
1820 if (!device->open(QIODevice::ReadOnly))
1821 qWarning(
"could not open device for reading");
1823 qWarning(
"device is not readable");
1832
1833
1834
1835
1836void QNetworkAccessManagerPrivate::ensureBackendPluginsLoaded()
1838 Q_CONSTINIT
static QBasicMutex mutex;
1839 std::unique_lock locker(mutex);
1842#if QT_CONFIG(library)
1843 qnabfLoader->update();
1846 while (qnabfLoader->instance(index))
1852#include "moc_qnetworkaccessmanager.cpp"
Combined button and popup list for selecting options.
#define QNetworkAccessBackendFactory_iid