summaryrefslogtreecommitdiffstats
path: root/src/network/access/qnetworkaccessmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/access/qnetworkaccessmanager.cpp')
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp129
1 files changed, 123 insertions, 6 deletions
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 7e75045da6..5a7521e33e 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -64,6 +64,8 @@
#include "QtNetwork/qauthenticator.h"
#include "QtNetwork/qsslconfiguration.h"
#include "QtNetwork/qnetworkconfigmanager.h"
+#include "QtNetwork/qhttpmultipart.h"
+#include "qhttpmultipart_p.h"
#include "qthread.h"
@@ -629,6 +631,46 @@ QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, const
}
/*!
+ \since 4.8
+
+ \overload
+
+ Sends the contents of the \a multiPart message to the destination
+ specified by \a request.
+
+ This can be used for sending MIME multipart messages over HTTP.
+
+ \sa QHttpMultiPart, QHttpPart, put()
+*/
+QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
+{
+ QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
+ QIODevice *device = multiPart->d_func()->device;
+ QNetworkReply *reply = post(newRequest, device);
+ return reply;
+}
+
+/*!
+ \since 4.8
+
+ \overload
+
+ Sends the contents of the \a multiPart message to the destination
+ specified by \a request.
+
+ This can be used for sending MIME multipart messages over HTTP.
+
+ \sa QHttpMultiPart, QHttpPart, post()
+*/
+QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QHttpMultiPart *multiPart)
+{
+ QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
+ QIODevice *device = multiPart->d_func()->device;
+ QNetworkReply *reply = put(newRequest, device);
+ return reply;
+}
+
+/*!
Uploads the contents of \a data to the destination \a request and
returnes a new QNetworkReply object that will be open for reply.
@@ -654,7 +696,8 @@ QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QIODev
/*!
\overload
- Sends the contents of the \a data byte array to the destination
+
+ Sends the contents of the \a data byte array to the destination
specified by \a request.
*/
QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, const QByteArray &data)
@@ -1125,8 +1168,25 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co
initializeSession = false;
- if (!config.isValid()) {
- networkSession.clear();
+ QSharedPointer<QNetworkSession> newSession;
+ if (config.isValid())
+ newSession = QSharedNetworkSessionManager::getSession(config);
+
+ if (networkSession) {
+ //do nothing if new and old session are the same
+ if (networkSession == newSession)
+ return;
+ //disconnect from old session
+ QObject::disconnect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()));
+ QObject::disconnect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()));
+ QObject::disconnect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)),
+ q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)));
+ }
+
+ //switch to new session (null if config was invalid)
+ networkSession = newSession;
+
+ if (!networkSession) {
online = false;
if (networkAccessible == QNetworkAccessManager::NotAccessible)
@@ -1137,8 +1197,7 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co
return;
}
- networkSession = QSharedNetworkSessionManager::getSession(config);
-
+ //connect to new session
QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()), Qt::QueuedConnection);
//QueuedConnection is used to avoid deleting the networkSession inside its closed signal
QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()), Qt::QueuedConnection);
@@ -1150,9 +1209,15 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co
void QNetworkAccessManagerPrivate::_q_networkSessionClosed()
{
+ Q_Q(QNetworkAccessManager);
if (networkSession) {
networkConfiguration = networkSession->configuration().identifier();
+ //disconnect from old session
+ QObject::disconnect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()));
+ QObject::disconnect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()));
+ QObject::disconnect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)),
+ q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)));
networkSession.clear();
}
}
@@ -1161,8 +1226,12 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession
{
Q_Q(QNetworkAccessManager);
- if (state == QNetworkSession::Connected)
+ //Do not emit the networkSessionConnected signal here, except for roaming -> connected
+ //transition, otherwise it is emitted twice in a row when opening a connection.
+ if (state == QNetworkSession::Connected && lastSessionState == QNetworkSession::Roaming)
emit q->networkSessionConnected();
+ lastSessionState = state;
+
if (online) {
if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) {
online = false;
@@ -1177,6 +1246,54 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession
}
#endif // QT_NO_BEARERMANAGEMENT
+QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart)
+{
+ // copy the request, we probably need to add some headers
+ QNetworkRequest newRequest(request);
+
+ // add Content-Type header if not there already
+ if (!request.header(QNetworkRequest::ContentTypeHeader).isValid()) {
+ QByteArray contentType;
+ contentType.reserve(34 + multiPart->d_func()->boundary.count());
+ contentType += "multipart/";
+ switch (multiPart->d_func()->contentType) {
+ case QHttpMultiPart::RelatedType:
+ contentType += "related";
+ break;
+ case QHttpMultiPart::FormDataType:
+ contentType += "form-data";
+ break;
+ case QHttpMultiPart::AlternativeType:
+ contentType += "alternative";
+ break;
+ default:
+ contentType += "mixed";
+ break;
+ }
+ // putting the boundary into quotes, recommended in RFC 2046 section 5.1.1
+ contentType += "; boundary=\"" + multiPart->d_func()->boundary + "\"";
+ newRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType));
+ }
+
+ // add MIME-Version header if not there already (we must include the header
+ // if the message conforms to RFC 2045, see section 4 of that RFC)
+ QByteArray mimeHeader("MIME-Version");
+ if (!request.hasRawHeader(mimeHeader))
+ newRequest.setRawHeader(mimeHeader, QByteArray("1.0"));
+
+ QIODevice *device = multiPart->d_func()->device;
+ if (!device->isReadable()) {
+ if (!device->isOpen()) {
+ if (!device->open(QIODevice::ReadOnly))
+ qWarning("could not open device for reading");
+ } else {
+ qWarning("device is not readable");
+ }
+ }
+
+ return newRequest;
+}
+
QT_END_NAMESPACE
#include "moc_qnetworkaccessmanager.cpp"