1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtNetwork module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qnetworkaccessmanager.h"
43 #include "qnetworkaccessmanager_p.h"
44 #include "qnetworkrequest.h"
45 #include "qnetworkreply.h"
46 #include "qnetworkreply_p.h"
47 #include "qnetworkcookie.h"
48 #include "qabstractnetworkcache.h"
50 #include "QtNetwork/qnetworksession.h"
51 #include "QtNetwork/private/qsharednetworksession_p.h"
53 #include "qnetworkaccesshttpbackend_p.h"
54 #include "qnetworkaccessftpbackend_p.h"
55 #include "qnetworkaccessfilebackend_p.h"
56 #include "qnetworkaccessdebugpipebackend_p.h"
57 #include "qnetworkaccesscachebackend_p.h"
58 #include "qnetworkreplydataimpl_p.h"
59 #include "qnetworkreplyfileimpl_p.h"
61 #include "QtCore/qbuffer.h"
62 #include "QtCore/qurl.h"
63 #include "QtCore/qvector.h"
64 #include "QtNetwork/qauthenticator.h"
65 #include "QtNetwork/qsslconfiguration.h"
66 #include "QtNetwork/qnetworkconfigmanager.h"
67 #include "QtNetwork/qhttpmultipart.h"
68 #include "qhttpmultipart_p.h"
75 Q_GLOBAL_STATIC(QNetworkAccessHttpBackendFactory, httpBackend)
77 Q_GLOBAL_STATIC(QNetworkAccessFileBackendFactory, fileBackend)
79 Q_GLOBAL_STATIC(QNetworkAccessFtpBackendFactory, ftpBackend)
82 #ifdef QT_BUILD_INTERNAL
83 Q_GLOBAL_STATIC(QNetworkAccessDebugPipeBackendFactory, debugpipeBackend)
86 static void ensureInitialized()
96 #ifdef QT_BUILD_INTERNAL
97 (void) debugpipeBackend();
100 // leave this one last since it will query the special QAbstractFileEngines
101 (void) fileBackend();
105 \class QNetworkAccessManager
106 \brief The QNetworkAccessManager class allows the application to
107 send network requests and receive replies
114 The Network Access API is constructed around one QNetworkAccessManager
115 object, which holds the common configuration and settings for the requests
116 it sends. It contains the proxy and cache configuration, as well as the
117 signals related to such issues, and reply signals that can be used to
118 monitor the progress of a network operation. One QNetworkAccessManager
119 should be enough for the whole Qt application.
121 Once a QNetworkAccessManager object has been created, the application can
122 use it to send requests over the network. A group of standard functions
123 are supplied that take a request and optional data, and each return a
124 QNetworkReply object. The returned object is used to obtain any data
125 returned in response to the corresponding request.
127 A simple download off the network could be accomplished with:
128 \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 0
130 QNetworkAccessManager has an asynchronous API.
131 When the \tt replyFinished slot above is called, the parameter it
132 takes is the QNetworkReply object containing the downloaded data
133 as well as meta-data (headers, etc.).
135 \note After the request has finished, it is the responsibility of the user
136 to delete the QNetworkReply object at an appropriate time. Do not directly
137 delete it inside the slot connected to finished(). You can use the
138 deleteLater() function.
140 \note QNetworkAccessManager queues the requests it receives. The number
141 of requests executed in parallel is dependent on the protocol.
142 Currently, for the HTTP protocol on desktop platforms, 6 requests are
143 executed in parallel for one host/port combination.
145 A more involved example, assuming the manager is already existent,
147 \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 1
149 \section1 Network and Roaming support
151 With the addition of the \l {Bearer Management} API to Qt 4.7
152 QNetworkAccessManager gained the ability to manage network connections.
153 QNetworkAccessManager can start the network interface if the device is
154 offline and terminates the interface if the current process is the last
155 one to use the uplink. Note that some platform utilize grace periods from
156 when the last application stops using a uplink until the system actually
157 terminates the connectivity link. Roaming is equally transparent. Any
158 queued/pending network requests are automatically transferred to new
161 Clients wanting to utilize this feature should not require any changes. In fact
162 it is likely that existing platform specific connection code can simply be
163 removed from the application.
165 \note The network and roaming support in QNetworkAccessManager is conditional
166 upon the platform supporting connection management. The
167 \l QNetworkConfigurationManager::NetworkSessionRequired can be used to
168 detect whether QNetworkAccessManager utilizes this feature. Currently only
169 Meego/Harmattan and Symbian platforms provide connection management support.
171 \note This feature cannot be used in combination with the Bearer Management
172 API as provided by QtMobility. Applications have to migrate to the Qt version
173 of Bearer Management.
175 \section1 Symbian Platform Security Requirements
177 On Symbian, processes which use this class must have the
178 \c NetworkServices platform security capability. If the client
179 process lacks this capability, operations will result in a panic.
181 Platform security capabilities are added via the
182 \l{qmake-variable-reference.html#target-capability}{TARGET.CAPABILITY}
185 \sa QNetworkRequest, QNetworkReply, QNetworkProxy
189 \enum QNetworkAccessManager::Operation
191 Indicates the operation this reply is processing.
193 \value HeadOperation retrieve headers operation (created
196 \value GetOperation retrieve headers and download contents
199 \value PutOperation upload contents operation (created
202 \value PostOperation send the contents of an HTML form for
203 processing via HTTP POST (created with post())
205 \value DeleteOperation delete contents operation (created with
208 \value CustomOperation custom operation (created with
209 sendCustomRequest()) \since 4.7
211 \omitvalue UnknownOperation
213 \sa QNetworkReply::operation()
217 \enum QNetworkAccessManager::NetworkAccessibility
219 Indicates whether the network is accessible via this network access manager.
221 \value UnknownAccessibility The network accessibility cannot be determined.
222 \value NotAccessible The network is not currently accessible, either because there
223 is currently no network coverage or network access has been
224 explicitly disabled by a call to setNetworkAccessible().
225 \value Accessible The network is accessible.
227 \sa networkAccessible
231 \property QNetworkAccessManager::networkAccessible
232 \brief whether the network is currently accessible via this network access manager.
236 If the network is \l {NotAccessible}{not accessible} the network access manager will not
237 process any new network requests, all such requests will fail with an error. Requests with
238 URLs with the file:// scheme will still be processed.
240 By default the value of this property reflects the physical state of the device. Applications
241 may override it to disable all network requests via this network access manager by calling
243 \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 4
245 Network requests can be reenabled again by calling
247 \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 5
249 \note Calling setNetworkAccessible() does not change the network state.
253 \fn void QNetworkAccessManager::networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible)
255 This signal is emitted when the value of the \l networkAccessible property changes.
256 \a accessible is the new network accessibility.
260 \fn void QNetworkAccessManager::networkSessionConnected()
266 This signal is emitted when the status of the network session changes into a usable (Connected)
267 state. It is used to signal to QNetworkReplys to start or migrate their network operation once
268 the network session has been opened or finished roaming.
272 \fn void QNetworkAccessManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
274 This signal is emitted whenever a proxy requests authentication
275 and QNetworkAccessManager cannot find a valid, cached
276 credential. The slot connected to this signal should fill in the
277 credentials for the proxy \a proxy in the \a authenticator object.
279 QNetworkAccessManager will cache the credentials internally. The
280 next time the proxy requests authentication, QNetworkAccessManager
281 will automatically send the same credential without emitting the
282 proxyAuthenticationRequired signal again.
284 If the proxy rejects the credentials, QNetworkAccessManager will
285 emit the signal again.
287 \sa proxy(), setProxy(), authenticationRequired()
291 \fn void QNetworkAccessManager::authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
293 This signal is emitted whenever a final server requests
294 authentication before it delivers the requested contents. The slot
295 connected to this signal should fill the credentials for the
296 contents (which can be determined by inspecting the \a reply
297 object) in the \a authenticator object.
299 QNetworkAccessManager will cache the credentials internally and
300 will send the same values if the server requires authentication
301 again, without emitting the authenticationRequired() signal. If it
302 rejects the credentials, this signal will be emitted again.
304 \note It is not possible to use a QueuedConnection to connect to
305 this signal, as the connection will fail if the authenticator has
306 not been filled in with new information when the signal returns.
308 \sa proxyAuthenticationRequired()
312 \fn void QNetworkAccessManager::finished(QNetworkReply *reply)
314 This signal is emitted whenever a pending network reply is
315 finished. The \a reply parameter will contain a pointer to the
316 reply that has just finished. This signal is emitted in tandem
317 with the QNetworkReply::finished() signal.
319 See QNetworkReply::finished() for information on the status that
320 the object will be in.
322 \note Do not delete the \a reply object in the slot connected to this
323 signal. Use deleteLater().
325 \sa QNetworkReply::finished(), QNetworkReply::error()
329 \fn void QNetworkAccessManager::sslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
331 This signal is emitted if the SSL/TLS session encountered errors
332 during the set up, including certificate verification errors. The
333 \a errors parameter contains the list of errors and \a reply is
334 the QNetworkReply that is encountering these errors.
336 To indicate that the errors are not fatal and that the connection
337 should proceed, the QNetworkReply::ignoreSslErrors() function should be called
338 from the slot connected to this signal. If it is not called, the
339 SSL session will be torn down before any data is exchanged
342 This signal can be used to display an error message to the user
343 indicating that security may be compromised and display the
344 SSL settings (see sslConfiguration() to obtain it). If the user
345 decides to proceed after analyzing the remote certificate, the
346 slot should call ignoreSslErrors().
348 \sa QSslSocket::sslErrors(), QNetworkReply::sslErrors(),
349 QNetworkReply::sslConfiguration(), QNetworkReply::ignoreSslErrors()
354 Constructs a QNetworkAccessManager object that is the center of
355 the Network Access API and sets \a parent as the parent object.
357 QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
358 : QObject(*new QNetworkAccessManagerPrivate, parent)
362 qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
366 Destroys the QNetworkAccessManager object and frees up any
367 resources. Note that QNetworkReply objects that are returned from
368 this class have this object set as their parents, which means that
369 they will be deleted along with it if you don't call
370 QObject::setParent() on them.
372 QNetworkAccessManager::~QNetworkAccessManager()
374 #ifndef QT_NO_NETWORKPROXY
375 delete d_func()->proxyFactory;
378 // Delete the QNetworkReply children first.
379 // Else a QAbstractNetworkCache might get deleted in ~QObject
380 // before a QNetworkReply that accesses the QAbstractNetworkCache
381 // object in its destructor.
382 qDeleteAll(findChildren<QNetworkReply *>());
383 // The other children will be deleted in this ~QObject
384 // FIXME instead of this "hack" make the QNetworkReplyImpl
385 // properly watch the cache deletion, e.g. via a QWeakPointer.
388 #ifndef QT_NO_NETWORKPROXY
390 Returns the QNetworkProxy that the requests sent using this
391 QNetworkAccessManager object will use. The default value for the
392 proxy is QNetworkProxy::DefaultProxy.
394 \sa setProxy(), setProxyFactory(), proxyAuthenticationRequired()
396 QNetworkProxy QNetworkAccessManager::proxy() const
398 return d_func()->proxy;
402 Sets the proxy to be used in future requests to be \a proxy. This
403 does not affect requests that have already been sent. The
404 proxyAuthenticationRequired() signal will be emitted if the proxy
405 requests authentication.
407 A proxy set with this function will be used for all requests
408 issued by QNetworkAccessManager. In some cases, it might be
409 necessary to select different proxies depending on the type of
410 request being sent or the destination host. If that's the case,
411 you should consider using setProxyFactory().
413 \sa proxy(), proxyAuthenticationRequired()
415 void QNetworkAccessManager::setProxy(const QNetworkProxy &proxy)
417 Q_D(QNetworkAccessManager);
418 delete d->proxyFactory;
424 \fn QNetworkProxyFactory *QNetworkAccessManager::proxyFactory() const
427 Returns the proxy factory that this QNetworkAccessManager object
428 is using to determine the proxies to be used for requests.
430 Note that the pointer returned by this function is managed by
431 QNetworkAccessManager and could be deleted at any time.
433 \sa setProxyFactory(), proxy()
435 QNetworkProxyFactory *QNetworkAccessManager::proxyFactory() const
437 return d_func()->proxyFactory;
443 Sets the proxy factory for this class to be \a factory. A proxy
444 factory is used to determine a more specific list of proxies to be
445 used for a given request, instead of trying to use the same proxy
446 value for all requests.
448 All queries sent by QNetworkAccessManager will have type
449 QNetworkProxyQuery::UrlRequest.
451 For example, a proxy factory could apply the following rules:
453 \o if the target address is in the local network (for example,
454 if the hostname contains no dots or if it's an IP address in
455 the organization's range), return QNetworkProxy::NoProxy
456 \o if the request is FTP, return an FTP proxy
457 \o if the request is HTTP or HTTPS, then return an HTTP proxy
458 \o otherwise, return a SOCKSv5 proxy server
461 The lifetime of the object \a factory will be managed by
462 QNetworkAccessManager. It will delete the object when necessary.
464 \note If a specific proxy is set with setProxy(), the factory will not
467 \sa proxyFactory(), setProxy(), QNetworkProxyQuery
469 void QNetworkAccessManager::setProxyFactory(QNetworkProxyFactory *factory)
471 Q_D(QNetworkAccessManager);
472 delete d->proxyFactory;
473 d->proxyFactory = factory;
474 d->proxy = QNetworkProxy();
481 Returns the cache that is used to store data obtained from the network.
485 QAbstractNetworkCache *QNetworkAccessManager::cache() const
487 Q_D(const QNetworkAccessManager);
488 return d->networkCache;
494 Sets the manager's network cache to be the \a cache specified. The cache
495 is used for all requests dispatched by the manager.
497 Use this function to set the network cache object to a class that implements
498 additional features, like saving the cookies to permanent storage.
500 \note QNetworkAccessManager takes ownership of the \a cache object.
502 QNetworkAccessManager by default does not have a set cache.
503 Qt provides a simple disk cache, QNetworkDiskCache, which can be used.
505 \sa cache(), QNetworkRequest::CacheLoadControl
507 void QNetworkAccessManager::setCache(QAbstractNetworkCache *cache)
509 Q_D(QNetworkAccessManager);
510 if (d->networkCache != cache) {
511 delete d->networkCache;
512 d->networkCache = cache;
514 d->networkCache->setParent(this);
519 Returns the QNetworkCookieJar that is used to store cookies
520 obtained from the network as well as cookies that are about to be
525 QNetworkCookieJar *QNetworkAccessManager::cookieJar() const
527 Q_D(const QNetworkAccessManager);
529 d->createCookieJar();
534 Sets the manager's cookie jar to be the \a cookieJar specified.
535 The cookie jar is used by all requests dispatched by the manager.
537 Use this function to set the cookie jar object to a class that
538 implements additional features, like saving the cookies to permanent
541 \note QNetworkAccessManager takes ownership of the \a cookieJar object.
543 If \a cookieJar is in the same thread as this QNetworkAccessManager,
544 it will set the parent of the \a cookieJar
545 so that the cookie jar is deleted when this
546 object is deleted as well. If you want to share cookie jars
547 between different QNetworkAccessManager objects, you may want to
548 set the cookie jar's parent to 0 after calling this function.
550 QNetworkAccessManager by default does not implement any cookie
551 policy of its own: it accepts all cookies sent by the server, as
552 long as they are well formed and meet the minimum security
553 requirements (cookie domain matches the request's and cookie path
554 matches the request's). In order to implement your own security
555 policy, override the QNetworkCookieJar::cookiesForUrl() and
556 QNetworkCookieJar::setCookiesFromUrl() virtual functions. Those
557 functions are called by QNetworkAccessManager when it detects a
560 \sa cookieJar(), QNetworkCookieJar::cookiesForUrl(), QNetworkCookieJar::setCookiesFromUrl()
562 void QNetworkAccessManager::setCookieJar(QNetworkCookieJar *cookieJar)
564 Q_D(QNetworkAccessManager);
565 d->cookieJarCreated = true;
566 if (d->cookieJar != cookieJar) {
567 if (d->cookieJar && d->cookieJar->parent() == this)
569 d->cookieJar = cookieJar;
570 if (thread() == cookieJar->thread())
571 d->cookieJar->setParent(this);
576 Posts a request to obtain the network headers for \a request
577 and returns a new QNetworkReply object which will contain such headers.
579 The function is named after the HTTP request associated (HEAD).
581 QNetworkReply *QNetworkAccessManager::head(const QNetworkRequest &request)
583 return d_func()->postProcess(createRequest(QNetworkAccessManager::HeadOperation, request));
587 Posts a request to obtain the contents of the target \a request
588 and returns a new QNetworkReply object opened for reading which emits the
589 \l{QIODevice::readyRead()}{readyRead()} signal whenever new data
592 The contents as well as associated headers will be downloaded.
594 \sa post(), put(), deleteResource(), sendCustomRequest()
596 QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
598 return d_func()->postProcess(createRequest(QNetworkAccessManager::GetOperation, request));
602 Sends an HTTP POST request to the destination specified by \a request
603 and returns a new QNetworkReply object opened for reading that will
604 contain the reply sent by the server. The contents of the \a data
605 device will be uploaded to the server.
607 \a data must be open for reading and must remain valid until the
608 finished() signal is emitted for this reply.
610 \note Sending a POST request on protocols other than HTTP and
611 HTTPS is undefined and will probably fail.
613 \sa get(), put(), deleteResource(), sendCustomRequest()
615 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data)
617 return d_func()->postProcess(createRequest(QNetworkAccessManager::PostOperation, request, data));
623 Sends the contents of the \a data byte array to the destination
624 specified by \a request.
626 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, const QByteArray &data)
628 QBuffer *buffer = new QBuffer;
629 buffer->setData(data);
630 buffer->open(QIODevice::ReadOnly);
632 QNetworkReply *reply = post(request, buffer);
633 buffer->setParent(reply);
642 Sends the contents of the \a multiPart message to the destination
643 specified by \a request.
645 This can be used for sending MIME multipart messages over HTTP.
647 \sa QHttpMultiPart, QHttpPart, put()
649 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
651 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
652 QIODevice *device = multiPart->d_func()->device;
653 QNetworkReply *reply = post(newRequest, device);
662 Sends the contents of the \a multiPart message to the destination
663 specified by \a request.
665 This can be used for sending MIME multipart messages over HTTP.
667 \sa QHttpMultiPart, QHttpPart, post()
669 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QHttpMultiPart *multiPart)
671 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
672 QIODevice *device = multiPart->d_func()->device;
673 QNetworkReply *reply = put(newRequest, device);
678 Uploads the contents of \a data to the destination \a request and
679 returnes a new QNetworkReply object that will be open for reply.
681 \a data must be opened for reading when this function is called
682 and must remain valid until the finished() signal is emitted for
685 Whether anything will be available for reading from the returned
686 object is protocol dependent. For HTTP, the server may send a
687 small HTML page indicating the upload was successful (or not).
688 Other protocols will probably have content in their replies.
690 \note For HTTP, this request will send a PUT request, which most servers
691 do not allow. Form upload mechanisms, including that of uploading
692 files through HTML forms, use the POST mechanism.
694 \sa get(), post(), deleteResource(), sendCustomRequest()
696 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QIODevice *data)
698 return d_func()->postProcess(createRequest(QNetworkAccessManager::PutOperation, request, data));
704 Sends the contents of the \a data byte array to the destination
705 specified by \a request.
707 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, const QByteArray &data)
709 QBuffer *buffer = new QBuffer;
710 buffer->setData(data);
711 buffer->open(QIODevice::ReadOnly);
713 QNetworkReply *reply = put(request, buffer);
714 buffer->setParent(reply);
721 Sends a request to delete the resource identified by the URL of \a request.
723 \note This feature is currently available for HTTP only, performing an
726 \sa get(), post(), put(), sendCustomRequest()
728 QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &request)
730 return d_func()->postProcess(createRequest(QNetworkAccessManager::DeleteOperation, request));
733 #ifndef QT_NO_BEARERMANAGEMENT
738 Sets the network configuration that will be used when creating the
739 \l {QNetworkSession}{network session} to \a config.
741 The network configuration is used to create and open a network session before any request that
742 requires network access is process. If no network configuration is explicitly set via this
743 function the network configuration returned by
744 QNetworkConfigurationManager::defaultConfiguration() will be used.
746 To restore the default network configuration set the network configuration to the value
747 returned from QNetworkConfigurationManager::defaultConfiguration().
749 \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 2
751 If an invalid network configuration is set, a network session will not be created. In this
752 case network requests will be processed regardless, but may fail. For example:
754 \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 3
756 \sa configuration(), QNetworkSession
758 void QNetworkAccessManager::setConfiguration(const QNetworkConfiguration &config)
760 d_func()->createSession(config);
766 Returns the network configuration that will be used to create the
767 \l {QNetworkSession}{network session} which will be used when processing network requests.
769 \sa setConfiguration(), activeConfiguration()
771 QNetworkConfiguration QNetworkAccessManager::configuration() const
773 Q_D(const QNetworkAccessManager);
775 if (d->networkSession)
776 return d->networkSession->configuration();
778 return QNetworkConfiguration();
784 Returns the current active network configuration.
786 If the network configuration returned by configuration() is of type
787 QNetworkConfiguration::ServiceNetwork this function will return the current active child
788 network configuration of that configuration. Otherwise returns the same network configuration
791 Use this function to return the actual network configuration currently in use by the network
796 QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const
798 Q_D(const QNetworkAccessManager);
800 if (d->networkSession) {
801 QNetworkConfigurationManager manager;
803 return manager.configurationFromIdentifier(
804 d->networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString());
806 return QNetworkConfiguration();
813 Overrides the reported network accessibility. If \a accessible is NotAccessible the reported
814 network accessiblity will always be NotAccessible. Otherwise the reported network
815 accessibility will reflect the actual device state.
817 void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible)
819 Q_D(QNetworkAccessManager);
821 if (d->networkAccessible != accessible) {
822 NetworkAccessibility previous = networkAccessible();
823 d->networkAccessible = accessible;
824 NetworkAccessibility current = networkAccessible();
825 if (previous != current)
826 emit networkAccessibleChanged(current);
833 Returns the current network accessibility.
835 QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const
837 Q_D(const QNetworkAccessManager);
839 if (d->networkSession) {
840 // d->online holds online/offline state of this network session.
842 return d->networkAccessible;
844 return NotAccessible;
846 // Network accessibility is either disabled or unknown.
847 return (d->networkAccessible == NotAccessible) ? NotAccessible : UnknownAccessibility;
851 #endif // QT_NO_BEARERMANAGEMENT
856 Sends a custom request to the server identified by the URL of \a request.
858 It is the user's responsibility to send a \a verb to the server that is valid
859 according to the HTTP specification.
861 This method provides means to send verbs other than the common ones provided
862 via get() or post() etc., for instance sending an HTTP OPTIONS command.
864 If \a data is not empty, the contents of the \a data
865 device will be uploaded to the server; in that case, data must be open for
866 reading and must remain valid until the finished() signal is emitted for this reply.
868 \note This feature is currently available for HTTP only.
870 \sa get(), post(), put(), deleteResource()
872 QNetworkReply *QNetworkAccessManager::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data)
874 QNetworkRequest newRequest(request);
875 newRequest.setAttribute(QNetworkRequest::CustomVerbAttribute, verb);
876 return d_func()->postProcess(createRequest(QNetworkAccessManager::CustomOperation, newRequest, data));
880 Returns a new QNetworkReply object to handle the operation \a op
881 and request \a req. The device \a outgoingData is always 0 for Get and
882 Head requests, but is the value passed to post() and put() in
883 those operations (the QByteArray variants will pass a QBuffer
886 The default implementation calls QNetworkCookieJar::cookiesForUrl()
887 on the cookie jar set with setCookieJar() to obtain the cookies to
888 be sent to the remote server.
890 The returned object must be in an open state.
892 QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op,
893 const QNetworkRequest &req,
894 QIODevice *outgoingData)
896 Q_D(QNetworkAccessManager);
898 bool isLocalFile = req.url().isLocalFile();
899 QString scheme = req.url().scheme().toLower();
901 // fast path for GET on file:// URLs
902 // The QNetworkAccessFileBackend will right now only be used for PUT
903 if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation)
904 && (isLocalFile || scheme == QLatin1String("qrc"))) {
905 return new QNetworkReplyFileImpl(this, req, op);
908 if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation)
909 && scheme == QLatin1String("data")) {
910 return new QNetworkReplyDataImpl(this, req, op);
913 // A request with QNetworkRequest::AlwaysCache does not need any bearer management
914 QNetworkRequest::CacheLoadControl mode =
915 static_cast<QNetworkRequest::CacheLoadControl>(
916 req.attribute(QNetworkRequest::CacheLoadControlAttribute,
917 QNetworkRequest::PreferNetwork).toInt());
918 if (mode == QNetworkRequest::AlwaysCache
919 && (op == QNetworkAccessManager::GetOperation
920 || op == QNetworkAccessManager::HeadOperation)) {
921 // FIXME Implement a QNetworkReplyCacheImpl instead, see QTBUG-15106
922 QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
923 QNetworkReplyImplPrivate *priv = reply->d_func();
924 priv->manager = this;
925 priv->backend = new QNetworkAccessCacheBackend();
926 priv->backend->manager = this->d_func();
927 priv->backend->setParent(reply);
928 priv->backend->reply = priv;
929 priv->setup(op, req, outgoingData);
933 #ifndef QT_NO_BEARERMANAGEMENT
934 // Return a disabled network reply if network access is disabled.
935 // Except if the scheme is empty or file://.
936 if (!d->networkAccessible && !isLocalFile) {
937 return new QDisabledNetworkReply(this, req, op);
940 if (!d->networkSession && (d->initializeSession || !d->networkConfiguration.isEmpty())) {
941 QNetworkConfigurationManager manager;
942 if (!d->networkConfiguration.isEmpty()) {
943 d->createSession(manager.configurationFromIdentifier(d->networkConfiguration));
945 if (manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired)
946 d->createSession(manager.defaultConfiguration());
948 d->initializeSession = false;
952 if (d->networkSession)
953 d->networkSession->setSessionProperty(QLatin1String("AutoCloseSessionTimeout"), -1);
956 QNetworkRequest request = req;
957 if (!request.header(QNetworkRequest::ContentLengthHeader).isValid() &&
958 outgoingData && !outgoingData->isSequential()) {
959 // request has no Content-Length
960 // but the data that is outgoing is random-access
961 request.setHeader(QNetworkRequest::ContentLengthHeader, outgoingData->size());
964 if (static_cast<QNetworkRequest::LoadControl>
965 (request.attribute(QNetworkRequest::CookieLoadControlAttribute,
966 QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Automatic) {
968 QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url());
969 if (!cookies.isEmpty())
970 request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies));
974 // first step: create the reply
975 QUrl url = request.url();
976 QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
977 #ifndef QT_NO_BEARERMANAGEMENT
979 connect(this, SIGNAL(networkSessionConnected()),
980 reply, SLOT(_q_networkSessionConnected()));
983 QNetworkReplyImplPrivate *priv = reply->d_func();
984 priv->manager = this;
986 // second step: fetch cached credentials
987 // This is not done for the time being, we should use signal emissions to request
988 // the credentials from cache.
990 // third step: find a backend
991 priv->backend = d->findBackend(op, request);
993 #ifndef QT_NO_NETWORKPROXY
994 QList<QNetworkProxy> proxyList = d->queryProxy(QNetworkProxyQuery(request.url()));
995 priv->proxyList = proxyList;
998 priv->backend->setParent(reply);
999 priv->backend->reply = priv;
1002 #ifndef QT_NO_OPENSSL
1003 reply->setSslConfiguration(request.sslConfiguration());
1006 // fourth step: setup the reply
1007 priv->setup(op, request, outgoingData);
1012 void QNetworkAccessManagerPrivate::_q_replyFinished()
1014 Q_Q(QNetworkAccessManager);
1016 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1018 emit q->finished(reply);
1020 #ifndef QT_NO_BEARERMANAGEMENT
1021 if (networkSession && q->findChildren<QNetworkReply *>().count() == 1)
1022 networkSession->setSessionProperty(QLatin1String("AutoCloseSessionTimeout"), 120000);
1026 void QNetworkAccessManagerPrivate::_q_replySslErrors(const QList<QSslError> &errors)
1028 #ifndef QT_NO_OPENSSL
1029 Q_Q(QNetworkAccessManager);
1030 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1032 emit q->sslErrors(reply, errors);
1038 QNetworkReply *QNetworkAccessManagerPrivate::postProcess(QNetworkReply *reply)
1040 Q_Q(QNetworkAccessManager);
1041 QNetworkReplyPrivate::setManager(reply, q);
1042 q->connect(reply, SIGNAL(finished()), SLOT(_q_replyFinished()));
1043 #ifndef QT_NO_OPENSSL
1044 /* In case we're compiled without SSL support, we don't have this signal and we need to
1045 * avoid getting a connection error. */
1046 q->connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(_q_replySslErrors(QList<QSslError>)));
1052 void QNetworkAccessManagerPrivate::createCookieJar() const
1054 if (!cookieJarCreated) {
1055 // keep the ugly hack in here
1056 QNetworkAccessManagerPrivate *that = const_cast<QNetworkAccessManagerPrivate *>(this);
1057 that->cookieJar = new QNetworkCookieJar(that->q_func());
1058 that->cookieJarCreated = true;
1062 void QNetworkAccessManagerPrivate::authenticationRequired(QNetworkAccessBackend *backend,
1063 QAuthenticator *authenticator)
1065 Q_Q(QNetworkAccessManager);
1067 // FIXME: Add support for domains (i.e., the leading path)
1068 QUrl url = backend->reply->url;
1070 // don't try the cache for the same URL twice in a row
1071 // being called twice for the same URL means the authentication failed
1072 // also called when last URL is empty, e.g. on first call
1073 if (backend->reply->urlForLastAuthentication.isEmpty()
1074 || url != backend->reply->urlForLastAuthentication) {
1075 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedCredentials(url, authenticator);
1076 if (!cred.isNull()) {
1077 authenticator->setUser(cred.user);
1078 authenticator->setPassword(cred.password);
1079 backend->reply->urlForLastAuthentication = url;
1084 // if we emit a signal here in synchronous mode, the user might spin
1085 // an event loop, which might recurse and lead to problems
1086 if (backend->isSynchronous())
1089 backend->reply->urlForLastAuthentication = url;
1090 emit q->authenticationRequired(backend->reply->q_func(), authenticator);
1091 authenticationManager->cacheCredentials(url, authenticator);
1094 #ifndef QT_NO_NETWORKPROXY
1095 void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(QNetworkAccessBackend *backend,
1096 const QNetworkProxy &proxy,
1097 QAuthenticator *authenticator)
1099 Q_Q(QNetworkAccessManager);
1100 // ### FIXME Tracking of successful authentications
1101 // This code is a bit broken right now for SOCKS authentication
1102 // first request: proxyAuthenticationRequired gets emitted, credentials gets saved
1103 // second request: (proxy != backend->reply->lastProxyAuthentication) does not evaluate to true,
1104 // proxyAuthenticationRequired gets emitted again
1105 // possible solution: some tracking inside the authenticator
1106 // or a new function proxyAuthenticationSucceeded(true|false)
1107 if (proxy != backend->reply->lastProxyAuthentication) {
1108 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1109 if (!cred.isNull()) {
1110 authenticator->setUser(cred.user);
1111 authenticator->setPassword(cred.password);
1116 // if we emit a signal here in synchronous mode, the user might spin
1117 // an event loop, which might recurse and lead to problems
1118 if (backend->isSynchronous())
1121 backend->reply->lastProxyAuthentication = proxy;
1122 emit q->proxyAuthenticationRequired(proxy, authenticator);
1123 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1126 QList<QNetworkProxy> QNetworkAccessManagerPrivate::queryProxy(const QNetworkProxyQuery &query)
1128 QList<QNetworkProxy> proxies;
1130 proxies = proxyFactory->queryProxy(query);
1131 if (proxies.isEmpty()) {
1132 qWarning("QNetworkAccessManager: factory %p has returned an empty result set",
1134 proxies << QNetworkProxy::NoProxy;
1136 } else if (proxy.type() == QNetworkProxy::DefaultProxy) {
1137 // no proxy set, query the application
1138 return QNetworkProxyFactory::proxyForQuery(query);
1147 void QNetworkAccessManagerPrivate::clearCache(QNetworkAccessManager *manager)
1149 manager->d_func()->objectCache.clear();
1150 manager->d_func()->authenticationManager->clearCache();
1152 if (manager->d_func()->httpThread) {
1153 // The thread will deleteLater() itself from its finished() signal
1154 manager->d_func()->httpThread->quit();
1155 manager->d_func()->httpThread = 0;
1159 QNetworkAccessManagerPrivate::~QNetworkAccessManagerPrivate()
1162 // The thread will deleteLater() itself from its finished() signal
1168 #ifndef QT_NO_BEARERMANAGEMENT
1169 void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &config)
1171 Q_Q(QNetworkAccessManager);
1173 initializeSession = false;
1175 QSharedPointer<QNetworkSession> newSession;
1176 if (config.isValid())
1177 newSession = QSharedNetworkSessionManager::getSession(config);
1179 if (networkSession) {
1180 //do nothing if new and old session are the same
1181 if (networkSession == newSession)
1183 //disconnect from old session
1184 QObject::disconnect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()));
1185 QObject::disconnect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()));
1186 QObject::disconnect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)),
1187 q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)));
1190 //switch to new session (null if config was invalid)
1191 networkSession = newSession;
1193 if (!networkSession) {
1196 if (networkAccessible == QNetworkAccessManager::NotAccessible)
1197 emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible);
1199 emit q->networkAccessibleChanged(QNetworkAccessManager::UnknownAccessibility);
1204 //connect to new session
1205 QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()), Qt::QueuedConnection);
1206 //QueuedConnection is used to avoid deleting the networkSession inside its closed signal
1207 QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()), Qt::QueuedConnection);
1208 QObject::connect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)),
1209 q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection);
1211 _q_networkSessionStateChanged(networkSession->state());
1214 void QNetworkAccessManagerPrivate::_q_networkSessionClosed()
1216 Q_Q(QNetworkAccessManager);
1217 if (networkSession) {
1218 networkConfiguration = networkSession->configuration().identifier();
1220 //disconnect from old session
1221 QObject::disconnect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()));
1222 QObject::disconnect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()));
1223 QObject::disconnect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)),
1224 q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)));
1225 networkSession.clear();
1229 void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession::State state)
1231 Q_Q(QNetworkAccessManager);
1233 //Do not emit the networkSessionConnected signal here, except for roaming -> connected
1234 //transition, otherwise it is emitted twice in a row when opening a connection.
1235 if (state == QNetworkSession::Connected && lastSessionState == QNetworkSession::Roaming)
1236 emit q->networkSessionConnected();
1237 lastSessionState = state;
1240 if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) {
1242 emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible);
1245 if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) {
1247 emit q->networkAccessibleChanged(networkAccessible);
1251 #endif // QT_NO_BEARERMANAGEMENT
1253 QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart)
1255 // copy the request, we probably need to add some headers
1256 QNetworkRequest newRequest(request);
1258 // add Content-Type header if not there already
1259 if (!request.header(QNetworkRequest::ContentTypeHeader).isValid()) {
1260 QByteArray contentType;
1261 contentType.reserve(34 + multiPart->d_func()->boundary.count());
1262 contentType += "multipart/";
1263 switch (multiPart->d_func()->contentType) {
1264 case QHttpMultiPart::RelatedType:
1265 contentType += "related";
1267 case QHttpMultiPart::FormDataType:
1268 contentType += "form-data";
1270 case QHttpMultiPart::AlternativeType:
1271 contentType += "alternative";
1274 contentType += "mixed";
1277 // putting the boundary into quotes, recommended in RFC 2046 section 5.1.1
1278 contentType += "; boundary=\"" + multiPart->d_func()->boundary + "\"";
1279 newRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType));
1282 // add MIME-Version header if not there already (we must include the header
1283 // if the message conforms to RFC 2045, see section 4 of that RFC)
1284 QByteArray mimeHeader("MIME-Version");
1285 if (!request.hasRawHeader(mimeHeader))
1286 newRequest.setRawHeader(mimeHeader, QByteArray("1.0"));
1288 QIODevice *device = multiPart->d_func()->device;
1289 if (!device->isReadable()) {
1290 if (!device->isOpen()) {
1291 if (!device->open(QIODevice::ReadOnly))
1292 qWarning("could not open device for reading");
1294 qWarning("device is not readable");
1303 #include "moc_qnetworkaccessmanager.cpp"