QtBase  v6.3.1
qnetworkaccessmanager.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include <QtNetwork/private/qtnetworkglobal_p.h>
41 
42 #include "qnetworkaccessmanager.h"
44 #include "qnetworkrequest.h"
45 #include "qnetworkreply.h"
46 #include "qnetworkreply_p.h"
47 #include "qnetworkcookie.h"
48 #include "qnetworkcookiejar.h"
49 #include "qabstractnetworkcache.h"
50 #include "qhstspolicy.h"
51 #include "qhsts_p.h"
52 
53 #if QT_CONFIG(settings)
54 #include "qhstsstore_p.h"
55 #endif // QT_CONFIG(settings)
56 
62 
64 #include "qnetworkreplyimpl_p.h"
65 
66 #include "QtCore/qbuffer.h"
67 #include "QtCore/qlist.h"
68 #include "QtCore/qurl.h"
69 #include "QtNetwork/private/qauthenticator_p.h"
70 #include "QtNetwork/qsslconfiguration.h"
71 #include "QtNetwork/private/http2protocol_p.h"
72 
73 #if QT_CONFIG(http)
74 #include "qhttpmultipart.h"
75 #include "qhttpmultipart_p.h"
77 #endif
78 
79 #include "qthread.h"
80 
81 #include <QHostInfo>
82 
83 #include "QtCore/qapplicationstatic.h"
84 #include <QtCore/private/qfactoryloader_p.h>
85 
86 #if defined(Q_OS_MACOS)
87 #include <CoreServices/CoreServices.h>
88 #include <SystemConfiguration/SystemConfiguration.h>
89 #include <Security/SecKeychain.h>
90 #endif
91 #ifdef Q_OS_WASM
93 #include "qhttpmultipart.h"
94 #include "qhttpmultipart_p.h"
95 #endif
96 
97 #include "qnetconmonitor_p.h"
98 
99 #include <mutex>
100 
102 
104 
105 #ifdef QT_BUILD_INTERNAL
106 Q_GLOBAL_STATIC(QNetworkAccessDebugPipeBackendFactory, debugpipeBackend)
107 #endif
108 
110  QLatin1String("/networkaccess"))
111 
112 #if defined(Q_OS_MACOS)
113 bool getProxyAuth(const QString& proxyHostname, const QString &scheme, QString& username, QString& password)
114 {
115  OSStatus err;
116  SecKeychainItemRef itemRef;
117  bool retValue = false;
118  SecProtocolType protocolType = kSecProtocolTypeAny;
119  if (scheme.compare(QLatin1String("ftp"),Qt::CaseInsensitive)==0) {
120  protocolType = kSecProtocolTypeFTPProxy;
121  } else if (scheme.compare(QLatin1String("http"),Qt::CaseInsensitive)==0
122  || scheme.compare(QLatin1String("preconnect-http"),Qt::CaseInsensitive)==0) {
123  protocolType = kSecProtocolTypeHTTPProxy;
124  } else if (scheme.compare(QLatin1String("https"),Qt::CaseInsensitive)==0
125  || scheme.compare(QLatin1String("preconnect-https"),Qt::CaseInsensitive)==0) {
126  protocolType = kSecProtocolTypeHTTPSProxy;
127  }
128  QByteArray proxyHostnameUtf8(proxyHostname.toUtf8());
129  err = SecKeychainFindInternetPassword(NULL,
130  proxyHostnameUtf8.length(), proxyHostnameUtf8.constData(),
131  0,NULL,
132  0, NULL,
133  0, NULL,
134  0,
135  protocolType,
136  kSecAuthenticationTypeAny,
137  0, NULL,
138  &itemRef);
139  if (err == noErr) {
140 
141  SecKeychainAttribute attr;
142  SecKeychainAttributeList attrList;
143  UInt32 length;
144  void *outData;
145 
146  attr.tag = kSecAccountItemAttr;
147  attr.length = 0;
148  attr.data = NULL;
149 
150  attrList.count = 1;
151  attrList.attr = &attr;
152 
153  if (SecKeychainItemCopyContent(itemRef, NULL, &attrList, &length, &outData) == noErr) {
154  username = QString::fromUtf8((const char*)attr.data, attr.length);
155  password = QString::fromUtf8((const char*)outData, length);
156  SecKeychainItemFreeContent(&attrList,outData);
157  retValue = true;
158  }
159  CFRelease(itemRef);
160  }
161  return retValue;
162 }
163 #endif
164 
165 
166 
167 static void ensureInitialized()
168 {
169 #ifdef QT_BUILD_INTERNAL
170  (void) debugpipeBackend();
171 #endif
172 
173  // leave this one last since it will query the special QAbstractFileEngines
174  (void) fileBackend();
175 }
176 
410 {
411  ensureInitialized();
412  d_func()->ensureBackendPluginsLoaded();
413 
414  qRegisterMetaType<QNetworkReply::NetworkError>();
415 #ifndef QT_NO_NETWORKPROXY
416  qRegisterMetaType<QNetworkProxy>();
417 #endif
418 #ifndef QT_NO_SSL
419  qRegisterMetaType<QList<QSslError> >();
420  qRegisterMetaType<QSslConfiguration>();
421  qRegisterMetaType<QSslPreSharedKeyAuthenticator *>();
422 #endif
423  qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >();
424 #if QT_CONFIG(http)
425  qRegisterMetaType<QHttpNetworkRequest>();
426 #endif
427  qRegisterMetaType<QNetworkReply::NetworkError>();
428  qRegisterMetaType<QSharedPointer<char> >();
429 }
430 
439 {
440 #ifndef QT_NO_NETWORKPROXY
441  delete d_func()->proxyFactory;
442 #endif
443 
444  // Delete the QNetworkReply children first.
445  // Else a QAbstractNetworkCache might get deleted in ~QObject
446  // before a QNetworkReply that accesses the QAbstractNetworkCache
447  // object in its destructor.
448  qDeleteAll(findChildren<QNetworkReply *>());
449  // The other children will be deleted in this ~QObject
450  // FIXME instead of this "hack" make the QNetworkReplyImpl
451  // properly watch the cache deletion, e.g. via a QWeakPointer.
452 }
453 
454 #ifndef QT_NO_NETWORKPROXY
463 {
464  return d_func()->proxy;
465 }
466 
482 {
484  delete d->proxyFactory;
485  d->proxy = proxy;
486  d->proxyFactory = nullptr;
487 }
488 
502 {
503  return d_func()->proxyFactory;
504 }
505 
536 {
538  delete d->proxyFactory;
539  d->proxyFactory = factory;
540  d->proxy = QNetworkProxy();
541 }
542 #endif
543 
552 {
553  Q_D(const QNetworkAccessManager);
554  return d->networkCache;
555 }
556 
574 {
576  if (d->networkCache != cache) {
577  delete d->networkCache;
578  d->networkCache = cache;
579  if (d->networkCache)
580  d->networkCache->setParent(this);
581  }
582 }
583 
592 {
593  Q_D(const QNetworkAccessManager);
594  if (!d->cookieJar)
595  d->createCookieJar();
596  return d->cookieJar;
597 }
598 
629 {
631  d->cookieJarCreated = true;
632  if (d->cookieJar != cookieJar) {
633  if (d->cookieJar && d->cookieJar->parent() == this)
634  delete d->cookieJar;
635  d->cookieJar = cookieJar;
636  if (cookieJar && thread() == cookieJar->thread())
637  d->cookieJar->setParent(this);
638  }
639 }
640 
657 {
659  d->stsEnabled = enabled;
660 }
661 
671 {
672  Q_D(const QNetworkAccessManager);
673  return d->stsEnabled;
674 }
675 
697 {
698 #if QT_CONFIG(settings)
700  d->stsStore.reset(enabled ? new QHstsStore(storeDir) : nullptr);
701  d->stsCache.setStore(d->stsStore.data());
702 #else
703  Q_UNUSED(enabled);
705  qWarning("HSTS permanent store requires the feature 'settings' enabled");
706 #endif // QT_CONFIG(settings)
707 }
708 
719 {
720 #if QT_CONFIG(settings)
721  Q_D(const QNetworkAccessManager);
722  return bool(d->stsStore.data());
723 #else
724  return false;
725 #endif // QT_CONFIG(settings)
726 }
727 
749 {
751  d->stsCache.updateFromPolicies(knownHosts);
752 }
753 
764 {
765  Q_D(const QNetworkAccessManager);
766  return d->stsCache.policies();
767 }
768 
776 {
777  return d_func()->postProcess(createRequest(QNetworkAccessManager::HeadOperation, request));
778 }
779 
791 {
792  return d_func()->postProcess(createRequest(QNetworkAccessManager::GetOperation, request));
793 }
794 
810 {
811  return d_func()->postProcess(createRequest(QNetworkAccessManager::PostOperation, request, data));
812 }
813 
821 {
822  QBuffer *buffer = new QBuffer;
823  buffer->setData(data);
825 
827  buffer->setParent(reply);
828  return reply;
829 }
830 
831 #if QT_CONFIG(http) || defined(Q_OS_WASM)
845 {
846  QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
847  QIODevice *device = multiPart->d_func()->device;
848  QNetworkReply *reply = post(newRequest, device);
849  return reply;
850 }
851 
865 {
866  QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
867  QIODevice *device = multiPart->d_func()->device;
868  QNetworkReply *reply = put(newRequest, device);
869  return reply;
870 }
871 #endif // QT_CONFIG(http)
872 
893 {
894  return d_func()->postProcess(createRequest(QNetworkAccessManager::PutOperation, request, data));
895 }
896 
904 {
905  QBuffer *buffer = new QBuffer;
906  buffer->setData(data);
908 
910  buffer->setParent(reply);
911  return reply;
912 }
913 
925 {
926  return d_func()->postProcess(createRequest(QNetworkAccessManager::DeleteOperation, request));
927 }
928 
929 #ifndef QT_NO_SSL
949  const QSslConfiguration &sslConfiguration)
950 {
951  connectToHostEncrypted(hostName, port, sslConfiguration, QString());
952 }
953 
975  const QSslConfiguration &sslConfiguration,
976  const QString &peerName)
977 {
978  QUrl url;
979  url.setHost(hostName);
980  url.setPort(port);
981  url.setScheme(QLatin1String("preconnect-https"));
983  if (sslConfiguration != QSslConfiguration::defaultConfiguration())
984  request.setSslConfiguration(sslConfiguration);
985 
986  // There is no way to enable HTTP2 via a request after having established the connection,
987  // so we need to check the ssl configuration whether HTTP2 is allowed here.
990 
991  request.setPeerVerifyName(peerName);
992  get(request);
993 }
994 #endif
995 
1008 {
1009  QUrl url;
1010  url.setHost(hostName);
1011  url.setPort(port);
1012  url.setScheme(QLatin1String("preconnect-http"));
1014  get(request);
1015 }
1016 
1035 {
1036  Q_D(QNetworkAccessManager);
1037  d->redirectPolicy = policy;
1038 }
1039 
1048 {
1049  Q_D(const QNetworkAccessManager);
1050  return d->redirectPolicy;
1051 }
1052 
1073 {
1074  QNetworkRequest newRequest(request);
1076  return d_func()->postProcess(createRequest(QNetworkAccessManager::CustomOperation, newRequest, data));
1077 }
1078 
1088 {
1089  QBuffer *buffer = new QBuffer;
1090  buffer->setData(data);
1091  buffer->open(QIODevice::ReadOnly);
1092 
1094  buffer->setParent(reply);
1095  return reply;
1096 }
1097 
1098 #if QT_CONFIG(http) || defined(Q_OS_WASM)
1114 {
1115  QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
1116  QIODevice *device = multiPart->d_func()->device;
1117  QNetworkReply *reply = sendCustomRequest(newRequest, verb, device);
1118  return reply;
1119 }
1120 #endif // QT_CONFIG(http)
1121 
1136  const QNetworkRequest &originalReq,
1137  QIODevice *outgoingData)
1138 {
1139  Q_D(QNetworkAccessManager);
1140 
1141  QNetworkRequest req(originalReq);
1145  }
1146 
1147 #if QT_CONFIG(http) || defined (Q_OS_WASM)
1148  if (!req.transferTimeout())
1149  req.setTransferTimeout(transferTimeout());
1150 #endif
1151 
1152  if (autoDeleteReplies()
1155  }
1156 
1157  bool isLocalFile = req.url().isLocalFile();
1158  QString scheme = req.url().scheme();
1159 
1160 
1161  // fast path for GET on file:// URLs
1162  // The QNetworkAccessFileBackend will right now only be used for PUT
1165  if (isLocalFile
1166 #ifdef Q_OS_ANDROID
1167  || scheme == QLatin1String("assets")
1168 #endif
1169  || scheme == QLatin1String("qrc")) {
1170  return new QNetworkReplyFileImpl(this, req, op);
1171  }
1172 
1173  if (scheme == QLatin1String("data"))
1174  return new QNetworkReplyDataImpl(this, req, op);
1175 
1176  // A request with QNetworkRequest::AlwaysCache does not need any bearer management
1178  static_cast<QNetworkRequest::CacheLoadControl>(
1182  // FIXME Implement a QNetworkReplyCacheImpl instead, see QTBUG-15106
1184  QNetworkReplyImplPrivate *priv = reply->d_func();
1185  priv->manager = this;
1186  priv->backend = new QNetworkAccessCacheBackend();
1187  priv->backend->setManagerPrivate(this->d_func());
1188  priv->backend->setParent(reply);
1189  priv->backend->setReplyPrivate(priv);
1190  priv->setup(op, req, outgoingData);
1191  return reply;
1192  }
1193  }
1194  QNetworkRequest request = req;
1195 #ifndef Q_OS_WASM // Content-length header is not allowed to be set by user in wasm
1197  outgoingData && !outgoingData->isSequential()) {
1198  // request has no Content-Length
1199  // but the data that is outgoing is random-access
1201  }
1202 #endif
1203  if (static_cast<QNetworkRequest::LoadControl>
1206  if (d->cookieJar) {
1207  QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url());
1208  if (!cookies.isEmpty())
1210  }
1211  }
1212 #ifdef Q_OS_WASM
1213  Q_UNUSED(isLocalFile);
1214  // Support http, https, and relative urls
1215  if (scheme == QLatin1String("http") || scheme == QLatin1String("https") || scheme.isEmpty()) {
1217  QNetworkReplyWasmImplPrivate *priv = reply->d_func();
1218  priv->manager = this;
1219  priv->setup(op, request, outgoingData);
1220  return reply;
1221  }
1222 #endif
1223 
1224 #if QT_CONFIG(http)
1225  constexpr char16_t httpSchemes[][17] = {
1226  u"http",
1227  u"preconnect-http",
1228 #ifndef QT_NO_SSL
1229  u"https",
1230  u"preconnect-https",
1231 #endif
1232  };
1233  // Since Qt 5 we use the new QNetworkReplyHttpImpl
1234  if (std::find(std::begin(httpSchemes), std::end(httpSchemes), scheme) != std::end(httpSchemes)) {
1235 #ifndef QT_NO_SSL
1236  if (isStrictTransportSecurityEnabled() && d->stsCache.isKnownHost(request.url())) {
1237  QUrl stsUrl(request.url());
1238  // RFC6797, 8.3:
1239  // The UA MUST replace the URI scheme with "https" [RFC2818],
1240  // and if the URI contains an explicit port component of "80",
1241  // then the UA MUST convert the port component to be "443", or
1242  // if the URI contains an explicit port component that is not
1243  // equal to "80", the port component value MUST be preserved;
1244  // otherwise,
1245  // if the URI does not contain an explicit port component, the UA
1246  // MUST NOT add one.
1247  if (stsUrl.port() == 80)
1248  stsUrl.setPort(443);
1249  stsUrl.setScheme(QLatin1String("https"));
1250  request.setUrl(stsUrl);
1251  }
1252 #endif
1253  QNetworkReplyHttpImpl *reply = new QNetworkReplyHttpImpl(this, request, op, outgoingData);
1254  return reply;
1255  }
1256 #endif // QT_CONFIG(http)
1257 
1258  // first step: create the reply
1260  QNetworkReplyImplPrivate *priv = reply->d_func();
1261  priv->manager = this;
1262 
1263  // second step: fetch cached credentials
1264  // This is not done for the time being, we should use signal emissions to request
1265  // the credentials from cache.
1266 
1267  // third step: find a backend
1268  priv->backend = d->findBackend(op, request);
1269 
1270  if (priv->backend) {
1271  priv->backend->setParent(reply);
1272  priv->backend->setReplyPrivate(priv);
1273  }
1274 
1275 #ifndef QT_NO_SSL
1276  reply->setSslConfiguration(request.sslConfiguration());
1277 #endif
1278 
1279  // fourth step: setup the reply
1280  priv->setup(op, request, outgoingData);
1281 
1282  return reply;
1283 }
1284 
1295 {
1296  QStringList schemes;
1297  QNetworkAccessManager *self = const_cast<QNetworkAccessManager *>(this); // We know we call a const slot
1298  QMetaObject::invokeMethod(self, "supportedSchemesImplementation", Qt::DirectConnection,
1299  Q_RETURN_ARG(QStringList, schemes));
1300  schemes.removeDuplicates();
1301  return schemes;
1302 }
1303 
1320 {
1321  Q_D(const QNetworkAccessManager);
1322 
1323  QStringList schemes = d->backendSupportedSchemes();
1324  // Those ones don't exist in backends
1325 #if QT_CONFIG(http)
1326  schemes << QStringLiteral("http");
1327 #ifndef QT_NO_SSL
1329  schemes << QStringLiteral("https");
1330 #endif
1331 #endif
1332  schemes << QStringLiteral("data");
1333  return schemes;
1334 }
1335 
1346 {
1349 }
1350 
1361 {
1363 }
1364 
1365 
1376 {
1377  return d_func()->autoDeleteReplies;
1378 }
1379 
1395 {
1396  d_func()->autoDeleteReplies = shouldAutoDelete;
1397 }
1398 
1408 {
1409  return d_func()->transferTimeout;
1410 }
1411 
1430 {
1431  d_func()->transferTimeout = timeout;
1432 }
1433 
1435 {
1436  Q_Q(QNetworkAccessManager);
1437 
1438  emit q->finished(reply);
1441 }
1442 
1444 {
1445 #ifndef QT_NO_SSL
1446  Q_Q(QNetworkAccessManager);
1447  emit q->encrypted(reply);
1448 #else
1449  Q_UNUSED(reply);
1450 #endif
1451 }
1452 
1454 {
1455 #ifndef QT_NO_SSL
1456  Q_Q(QNetworkAccessManager);
1457  QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1458  if (reply)
1459  emit q->sslErrors(reply, errors);
1460 #else
1461  Q_UNUSED(errors);
1462 #endif
1463 }
1464 
1465 #ifndef QT_NO_SSL
1467 {
1468  Q_Q(QNetworkAccessManager);
1469  QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1470  if (reply)
1471  emit q->preSharedKeyAuthenticationRequired(reply, authenticator);
1472 }
1473 #endif
1474 
1476 {
1477  Q_Q(QNetworkAccessManager);
1479  q->connect(reply, &QNetworkReply::finished, reply,
1480  [this, reply]() { _q_replyFinished(reply); });
1481 #ifndef QT_NO_SSL
1482  /* In case we're compiled without SSL support, we don't have this signal and we need to
1483  * avoid getting a connection error. */
1484  q->connect(reply, &QNetworkReply::encrypted, reply,
1485  [this, reply]() { _q_replyEncrypted(reply); });
1488 #endif
1489 
1490  return reply;
1491 }
1492 
1494 {
1495  if (!cookieJarCreated) {
1496  // keep the ugly hack in here
1497  QNetworkAccessManagerPrivate *that = const_cast<QNetworkAccessManagerPrivate *>(this);
1498  that->cookieJar = new QNetworkCookieJar(that->q_func());
1499  that->cookieJarCreated = true;
1500  }
1501 }
1502 
1505  bool synchronous,
1506  QUrl &url,
1507  QUrl *urlForLastAuthentication,
1508  bool allowAuthenticationReuse)
1509 {
1510  Q_Q(QNetworkAccessManager);
1511 
1512  // don't try the cache for the same URL twice in a row
1513  // being called twice for the same URL means the authentication failed
1514  // also called when last URL is empty, e.g. on first call
1515  if (allowAuthenticationReuse && (urlForLastAuthentication->isEmpty()
1516  || url != *urlForLastAuthentication)) {
1517  // if credentials are included in the url, then use them, unless they were already used
1518  if (!url.userName().isEmpty() && !url.password().isEmpty()
1519  && (url.userName() != authenticator->user()
1520  || url.password() != authenticator->password())) {
1521  authenticator->setUser(url.userName(QUrl::FullyDecoded));
1522  authenticator->setPassword(url.password(QUrl::FullyDecoded));
1523  *urlForLastAuthentication = url;
1524  authenticationManager->cacheCredentials(url, authenticator);
1525  return;
1526  }
1527 
1528  QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedCredentials(url, authenticator);
1529  if (!cred.isNull()
1530  && (cred.user != authenticator->user() || cred.password != authenticator->password())) {
1531  authenticator->setUser(cred.user);
1532  authenticator->setPassword(cred.password);
1533  *urlForLastAuthentication = url;
1534  return;
1535  }
1536  }
1537 
1538  // if we emit a signal here in synchronous mode, the user might spin
1539  // an event loop, which might recurse and lead to problems
1540  if (synchronous)
1541  return;
1542 
1543  *urlForLastAuthentication = url;
1544  emit q->authenticationRequired(reply, authenticator);
1545  if (allowAuthenticationReuse)
1546  authenticationManager->cacheCredentials(url, authenticator);
1547 }
1548 
1549 #ifndef QT_NO_NETWORKPROXY
1551  const QNetworkProxy &proxy,
1552  bool synchronous,
1553  QAuthenticator *authenticator,
1554  QNetworkProxy *lastProxyAuthentication)
1555 {
1556  Q_Q(QNetworkAccessManager);
1558  if (proxy != *lastProxyAuthentication && (!priv || !priv->hasFailed)) {
1559  QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1560  if (!cred.isNull()) {
1561  authenticator->setUser(cred.user);
1562  authenticator->setPassword(cred.password);
1563  return;
1564  }
1565  }
1566 
1567 #if defined(Q_OS_MACOS)
1568  //now we try to get the username and password from keychain
1569  //if not successful signal will be emitted
1570  QString username;
1571  QString password;
1572  if (getProxyAuth(proxy.hostName(), url.scheme(), username, password)) {
1573  // only cache the system credentials if they are correct (or if they have changed)
1574  // to not run into an endless loop in case they are wrong
1575  QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1576  if (!priv->hasFailed || cred.user != username || cred.password != password) {
1577  authenticator->setUser(username);
1578  authenticator->setPassword(password);
1579  authenticationManager->cacheProxyCredentials(proxy, authenticator);
1580  return;
1581  }
1582  }
1583 #else
1584  Q_UNUSED(url);
1585 #endif
1586 
1587  // if we emit a signal here in synchronous mode, the user might spin
1588  // an event loop, which might recurse and lead to problems
1589  if (synchronous)
1590  return;
1591 
1592  *lastProxyAuthentication = proxy;
1593  emit q->proxyAuthenticationRequired(proxy, authenticator);
1594  authenticationManager->cacheProxyCredentials(proxy, authenticator);
1595 }
1596 
1598 {
1599  QList<QNetworkProxy> proxies;
1600  if (proxyFactory) {
1601  proxies = proxyFactory->queryProxy(query);
1602  if (proxies.isEmpty()) {
1603  qWarning("QNetworkAccessManager: factory %p has returned an empty result set",
1604  proxyFactory);
1605  proxies << QNetworkProxy::NoProxy;
1606  }
1607  } else if (proxy.type() == QNetworkProxy::DefaultProxy) {
1608  // no proxy set, query the application
1610  } else {
1611  proxies << proxy;
1612  }
1613 
1614  return proxies;
1615 }
1616 #endif
1617 
1619 {
1620  manager->d_func()->authenticationManager->clearCache();
1621 }
1622 
1624 {
1625  manager->d_func()->objectCache.clear();
1626  manager->d_func()->destroyThread();
1627 }
1628 
1630 {
1631  destroyThread();
1632 }
1633 
1635 {
1636  if (!thread) {
1637  thread = new QThread;
1638  thread->setObjectName(QStringLiteral("QNetworkAccessManager thread"));
1639  thread->start();
1640  }
1641  Q_ASSERT(thread);
1642  return thread;
1643 }
1644 
1646 {
1647  if (thread) {
1648  thread->quit();
1649  thread->wait(QDeadlineTimer(5000));
1650  if (thread->isFinished())
1651  delete thread;
1652  else
1653  QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
1654  thread = nullptr;
1655  }
1656 }
1657 
1658 
1659 #if QT_CONFIG(http) || defined(Q_OS_WASM)
1660 
1661 QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart)
1662 {
1663  // copy the request, we probably need to add some headers
1664  QNetworkRequest newRequest(request);
1665 
1666  // add Content-Type header if not there already
1669  contentType.reserve(34 + multiPart->d_func()->boundary.count());
1670  contentType += "multipart/";
1671  switch (multiPart->d_func()->contentType) {
1673  contentType += "related";
1674  break;
1676  contentType += "form-data";
1677  break;
1679  contentType += "alternative";
1680  break;
1681  default:
1682  contentType += "mixed";
1683  break;
1684  }
1685  // putting the boundary into quotes, recommended in RFC 2046 section 5.1.1
1686  contentType += "; boundary=\"" + multiPart->d_func()->boundary + '"';
1688  }
1689 
1690  // add MIME-Version header if not there already (we must include the header
1691  // if the message conforms to RFC 2045, see section 4 of that RFC)
1692  QByteArray mimeHeader("MIME-Version");
1693  if (!request.hasRawHeader(mimeHeader))
1694  newRequest.setRawHeader(mimeHeader, QByteArray("1.0"));
1695 
1696  QIODevice *device = multiPart->d_func()->device;
1697  if (!device->isReadable()) {
1698  if (!device->isOpen()) {
1699  if (!device->open(QIODevice::ReadOnly))
1700  qWarning("could not open device for reading");
1701  } else {
1702  qWarning("device is not readable");
1703  }
1704  }
1705 
1706  return newRequest;
1707 }
1708 #endif // QT_CONFIG(http)
1709 
1716 {
1717  static QBasicMutex mutex;
1718  std::unique_lock locker(mutex);
1719  if (!loader())
1720  return;
1721 #if QT_CONFIG(library)
1722  loader->update();
1723 #endif
1724  int index = 0;
1725  while (loader->instance(index))
1726  ++index;
1727 }
1728 
1730 
1731 #include "moc_qnetworkaccessmanager.cpp"
small capitals from c petite p scientific f u
Definition: afcover.h:88
The QAbstractNetworkCache class provides the interface for cache implementations.
The QAuthenticator class provides an authentication object.
QString user() const
void setPassword(const QString &password)
QString password() const
void setUser(const QString &user)
static QAuthenticatorPrivate * getPrivate(QAuthenticator &auth)
The QBuffer class provides a QIODevice interface for a QByteArray.
Definition: qbuffer.h:52
void setData(const QByteArray &data)
Definition: qbuffer.cpp:295
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
const char * constData() const noexcept
Definition: qbytearray.h:144
qsizetype length() const noexcept
Definition: qbytearray.h:472
qsizetype count(char c) const
The QDeadlineTimer class marks a deadline in the future.
The QHttpMultiPart class resembles a MIME multipart message to be sent over HTTP.
QByteArray boundary() const
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:70
virtual qint64 size() const
Definition: qiodevice.cpp:874
virtual bool isSequential() const
Definition: qiodevice.cpp:527
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
bool isEmpty() const noexcept
Definition: qlist.h:418
The QMutex class provides access serialization between threads.
Definition: qmutex.h:285
The QNetworkAccessManager class allows the application to send network requests and receive replies.
void setCookieJar(QNetworkCookieJar *cookieJar)
QNetworkReply * put(const QNetworkRequest &request, QIODevice *data)
void connectToHost(const QString &hostName, quint16 port=80)
QNetworkReply * head(const QNetworkRequest &request)
bool isStrictTransportSecurityStoreEnabled() const
QList< QHstsPolicy > strictTransportSecurityHosts() const
virtual QStringList supportedSchemes() const
QNetworkRequest::RedirectPolicy redirectPolicy() const
QNetworkReply * post(const QNetworkRequest &request, QIODevice *data)
void setProxy(const QNetworkProxy &proxy)
QStringList supportedSchemesImplementation() const
void setAutoDeleteReplies(bool autoDelete)
bool isStrictTransportSecurityEnabled() const
QNetworkReply * get(const QNetworkRequest &request)
void setRedirectPolicy(QNetworkRequest::RedirectPolicy policy)
QNetworkReply * sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data=nullptr)
QNetworkProxy proxy() const
virtual QNetworkReply * createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData=nullptr)
void setStrictTransportSecurityEnabled(bool enabled)
QAbstractNetworkCache * cache() const
void addStrictTransportSecurityHosts(const QList< QHstsPolicy > &knownHosts)
void setTransferTimeout(int timeout=QNetworkRequest::DefaultTransferTimeoutConstant)
QNetworkReply * deleteResource(const QNetworkRequest &request)
void connectToHostEncrypted(const QString &hostName, quint16 port=443, const QSslConfiguration &sslConfiguration=QSslConfiguration::defaultConfiguration())
void setProxyFactory(QNetworkProxyFactory *factory)
QNetworkProxyFactory * proxyFactory() const
void setCache(QAbstractNetworkCache *cache)
QNetworkCookieJar * cookieJar() const
void enableStrictTransportSecurityStore(bool enabled, const QString &storeDir=QString())
QNetworkAccessManager(QObject *parent=nullptr)
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 QNetworkProxyFactory class provides fine-grained proxy selection.
virtual QList< QNetworkProxy > queryProxy(const QNetworkProxyQuery &query=QNetworkProxyQuery())=0
static QList< QNetworkProxy > proxyForQuery(const QNetworkProxyQuery &query)
The QNetworkProxy class provides a network layer proxy.
QNetworkProxy::ProxyType type() const
QString hostName() const
The QNetworkProxyQuery class is used to query the proxy settings for a socket.
Definition: qnetworkproxy.h:57
The QNetworkReply class contains the data and headers for a request sent with QNetworkAccessManager.
Definition: qnetworkreply.h:63
QNetworkRequest request() const
QNetworkAccessBackend * backend
void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData)
QPointer< QNetworkAccessManager > manager
static void setManager(QNetworkReply *reply, QNetworkAccessManager *manager)
void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData)
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
void setSslConfiguration(const QSslConfiguration &configuration)
@ AutoDeleteReplyOnFinishAttribute
void setHeader(KnownHeaders header, const QVariant &value)
void setAttribute(Attribute code, const QVariant &value)
QVariant attribute(Attribute code, const QVariant &defaultValue=QVariant()) const
QVariant header(KnownHeaders header) const
void setRawHeader(const QByteArray &headerName, const QByteArray &value)
void setPeerVerifyName(const QString &peerName)
bool hasRawHeader(const QByteArray &headerName) const
void setUrl(const QUrl &url)
QSslConfiguration sslConfiguration() const
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Definition: qobject.cpp:2772
void setParent(QObject *parent)
Definition: qobject.cpp:2108
QThread * thread() const
Definition: qobject.cpp:1527
void setObjectName(const QString &name)
Definition: qobject.cpp:1261
void deleteLater()
Definition: qobject.cpp:2319
The QSslConfiguration class holds the configuration and state of an SSL connection.
QList< QByteArray > allowedNextProtocols() const
static const char ALPNProtocolHTTP2[]
static QSslConfiguration defaultConfiguration()
The QSslPreSharedKeyAuthenticator class provides authentication data for pre shared keys (PSK) cipher...
static bool supportsSsl()
The QString class provides a Unicode character string.
Definition: qstring.h:388
void reserve(qsizetype size)
Definition: qstring.h:1307
static QString fromUtf8(QByteArrayView utf8)
Definition: qstring.cpp:5632
bool isEmpty() const
Definition: qstring.h:1216
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition: qstring.cpp:6263
QByteArray toUtf8() const &
Definition: qstring.h:749
The QStringList class provides a list of strings.
void start(Priority=InheritPriority)
Definition: qthread.cpp:836
bool isFinished() const
Definition: qthread.cpp:894
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
Definition: qthread.cpp:863
void quit()
Definition: qthread.cpp:848
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:130
bool isLocalFile() const
Definition: qurl.cpp:3450
QString userName(ComponentFormattingOptions options=FullyDecoded) const
Definition: qurl.cpp:2219
QString password(ComponentFormattingOptions=FullyDecoded) const
Definition: qurl.cpp:2282
bool isEmpty() const
Definition: qurl.cpp:1911
QString scheme() const
Definition: qurl.cpp:2006
void setScheme(const QString &scheme)
Definition: qurl.cpp:1982
void setHost(const QString &host, ParsingMode mode=DecodedMode)
Definition: qurl.cpp:2309
int port(int defaultPort=-1) const
Definition: qurl.cpp:2403
@ FullyDecoded
Definition: qurl.h:166
void setPort(int port)
Definition: qurl.cpp:2378
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
static auto fromValue(const T &value) -> std::enable_if_t< std::is_copy_constructible_v< T >, QVariant >
Definition: qvariant.h:391
bool isValid() const
Definition: qvariant.h:582
int toInt(bool *ok=nullptr) const
Definition: qvariant.cpp:1833
bool toBool() const
Definition: qvariant.cpp:1906
bool isNull() const
Definition: qvariant.cpp:2483
qDeleteAll(list.begin(), list.end())
QCache< int, Employee > cache
[0]
#define NULL
Definition: ftobjs.h:61
@ CaseInsensitive
Definition: qnamespace.h:1283
@ QueuedConnection
Definition: qnamespace.h:1307
@ DirectConnection
Definition: qnamespace.h:1306
#define QString()
Definition: parse-defines.h:51
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld endif[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld SRC pixld MASK if DST_R else pixld DST_R endif if
set set set set set set set macro pixldst1 op
void
Definition: png.h:1080
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputPortEXT port
unsigned short quint16
Definition: qglobal.h:286
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qWarning
Definition: qlogging.h:179
#define QNetworkAccessBackendFactory_iid
QT_BEGIN_NAMESPACE Q_APPLICATION_STATIC(QFactoryLoader, loader, QNetworkAccessBackendFactory_iid, QLatin1String("/networkaccess")) static void ensureInitialized()
#define SLOT(a)
Definition: qobjectdefs.h:87
#define SIGNAL(a)
Definition: qobjectdefs.h:88
#define Q_RETURN_ARG(type, data)
Definition: qobjectdefs.h:99
GLenum GLuint GLenum GLsizei length
Definition: qopengl.h:270
GLenum mode
GLuint index
[2]
GLuint GLuint end
GLbitfield GLuint64 timeout
[4]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum GLuint buffer
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum query
Definition: qopenglext.h:2738
GLdouble GLdouble GLdouble GLdouble q
Definition: qopenglext.h:259
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
#define QStringLiteral(str)
#define emit
Definition: qtmetamacros.h:85
#define enabled
Definition: qopenglext.h:3098
Q_UNUSED(salary)
[21]
QUrl url("http://www.example.com/List of holidays.xml")
[0]
QItemEditorFactory * factory
QSizePolicy policy
QString contentType
QNetworkAccessManager manager
QHttpMultiPart * multiPart
[0]
QNetworkRequest request(url)
QNetworkReply * reply
QNetworkProxy proxy
[0]
bool contains(const AT &t) const noexcept
Definition: qlist.h:78
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())
T1_FIELD_DICT_PRIVATE password
Definition: t1tokens.h:64
const QLatin1String storeDir(".")
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent
QDomElement find(const QString &tagName, const QDomElement &e)
Definition: main.cpp:39
QMutex mutex
XmlOutput::xml_output attr(const QString &name, const QString &value)
Definition: xmloutput.h:202