diff options
Diffstat (limited to 'src/network')
27 files changed, 206 insertions, 190 deletions
diff --git a/src/network/access/qhttpmultipart.h b/src/network/access/qhttpmultipart.h index c25beb7ae3..aea8421d30 100644 --- a/src/network/access/qhttpmultipart.h +++ b/src/network/access/qhttpmultipart.h @@ -92,8 +92,8 @@ public: AlternativeType }; - QHttpMultiPart(QObject *parent = 0); - QHttpMultiPart(ContentType contentType, QObject *parent = 0); + explicit QHttpMultiPart(QObject *parent = 0); + explicit QHttpMultiPart(ContentType contentType, QObject *parent = 0); ~QHttpMultiPart(); void append(const QHttpPart &httpPart); diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index f32251935b..1325f105cf 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -116,19 +116,18 @@ QByteArray QHttpNetworkRequestPrivate::methodName() const QByteArray QHttpNetworkRequestPrivate::uri(bool throughProxy) const { - QUrl::FormattingOptions format(QUrl::RemoveFragment); + QUrl::FormattingOptions format(QUrl::RemoveFragment | QUrl::RemoveUserInfo | QUrl::FullyEncoded); // for POST, query data is send as content if (operation == QHttpNetworkRequest::Post && !uploadByteDevice) format |= QUrl::RemoveQuery; // for requests through proxy, the Request-URI contains full url - if (throughProxy) - format |= QUrl::RemoveUserInfo; - else + if (!throughProxy) format |= QUrl::RemoveScheme | QUrl::RemoveAuthority; - QByteArray uri = url.toEncoded(format); - if (uri.isEmpty() || (throughProxy && url.path().isEmpty())) - uri += '/'; + QUrl copy = url; + if (copy.path().isEmpty()) + copy.setPath(QStringLiteral("/")); + QByteArray uri = copy.toEncoded(format); return uri; } @@ -163,7 +162,7 @@ QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request ba += "Content-Type: application/octet-stream\r\n"; } if (!request.d->uploadByteDevice && request.d->url.hasQuery()) { - QByteArray query = request.d->url.encodedQuery(); + QByteArray query = request.d->url.query(QUrl::FullyEncoded).toLatin1(); ba += "Content-Length: "; ba += QByteArray::number(query.size()); ba += "\r\n\r\n"; diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index c8b4c51e23..634340bb54 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -105,12 +105,12 @@ static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy) { - QByteArray result; + QString result; QUrl copy = url; bool isEncrypted = copy.scheme().toLower() == QLatin1String("https"); copy.setPort(copy.port(isEncrypted ? 443 : 80)); - result = copy.toEncoded(QUrl::RemoveUserInfo | QUrl::RemovePath | - QUrl::RemoveQuery | QUrl::RemoveFragment); + result = copy.toString(QUrl::RemoveUserInfo | QUrl::RemovePath | + QUrl::RemoveQuery | QUrl::RemoveFragment | QUrl::FullyEncoded); #ifndef QT_NO_NETWORKPROXY if (proxy && proxy->type() != QNetworkProxy::NoProxy) { @@ -134,15 +134,15 @@ static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy) key.setUserName(proxy->user()); key.setHost(proxy->hostName()); key.setPort(proxy->port()); - key.setEncodedQuery(result); - result = key.toEncoded(); + key.setQuery(result); + result = key.toString(QUrl::FullyEncoded); } } #else Q_UNUSED(proxy) #endif - return "http-connection:" + result; + return "http-connection:" + result.toLatin1(); } class QNetworkAccessCachedHttpConnection: public QHttpNetworkConnection, @@ -386,7 +386,7 @@ void QHttpThreadDelegate::finishedSlot() // it's an error reply QString msg = QLatin1String(QT_TRANSLATE_NOOP("QNetworkReply", "Error downloading %1 - server replied: %2")); - msg = msg.arg(QString::fromAscii(httpRequest.url().toEncoded()), httpReply->reasonPhrase()); + msg = msg.arg(httpRequest.url().toString(), httpReply->reasonPhrase()); emit error(statusCodeFromHttp(httpReply->statusCode(), httpRequest.url()), msg); } @@ -406,7 +406,7 @@ void QHttpThreadDelegate::synchronousFinishedSlot() // it's an error reply QString msg = QLatin1String(QT_TRANSLATE_NOOP("QNetworkReply", "Error downloading %1 - server replied: %2")); - incomingErrorDetail = msg.arg(QString::fromAscii(httpRequest.url().toEncoded()), httpReply->reasonPhrase()); + incomingErrorDetail = msg.arg(httpRequest.url().toString(), httpReply->reasonPhrase()); incomingErrorCode = statusCodeFromHttp(httpReply->statusCode(), httpRequest.url()); } diff --git a/src/network/access/qnetworkaccessdebugpipebackend.cpp b/src/network/access/qnetworkaccessdebugpipebackend.cpp index 5a4cd7b20d..3fb882b5e4 100644 --- a/src/network/access/qnetworkaccessdebugpipebackend.cpp +++ b/src/network/access/qnetworkaccessdebugpipebackend.cpp @@ -42,6 +42,7 @@ #include "qnetworkaccessdebugpipebackend_p.h" #include "QtCore/qdatastream.h" #include <QCoreApplication> +#include <QUrlQuery> #include "private/qnoncontiguousbytedevice_p.h" QT_BEGIN_NAMESPACE @@ -99,7 +100,7 @@ void QNetworkAccessDebugPipeBackend::open() // socket bytes written -> we can push more from upstream to socket connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64))); - bareProtocol = url().queryItemValue(QLatin1String("bare")) == QLatin1String("1"); + bareProtocol = QUrlQuery(url()).queryItemValue(QLatin1String("bare")) == QLatin1String("1"); if (operation() == QNetworkAccessManager::PutOperation) { uploadByteDevice = createUploadByteDevice(); diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 3a69ec4056..8d68f439f1 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -907,6 +907,17 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess } } +/*! + \internal + + Returns the network session currently in use. + This can be changed at any time, ownership remains with the QNetworkAccessManager +*/ +const QWeakPointer<const QNetworkSession> QNetworkAccessManagerPrivate::getNetworkSession(const QNetworkAccessManager *q) +{ + return q->d_func()->networkSession.toWeakRef(); +} + #endif // QT_NO_BEARERMANAGEMENT /*! diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index 4d23fcbcdc..85f963b52a 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -157,6 +157,7 @@ protected: private: friend class QNetworkReplyImplPrivate; friend class QNetworkReplyHttpImpl; + friend class QNetworkReplyHttpImplPrivate; Q_DECLARE_PRIVATE(QNetworkAccessManager) Q_PRIVATE_SLOT(d_func(), void _q_replyFinished()) diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index b0bcaabacc..8d62e78902 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -162,6 +162,7 @@ public: static inline QNetworkAccessCache *getObjectCache(QNetworkAccessBackend *backend) { return &backend->manager->objectCache; } Q_AUTOTEST_EXPORT static void clearCache(QNetworkAccessManager *manager); + Q_AUTOTEST_EXPORT static const QWeakPointer<const QNetworkSession> getNetworkSession(const QNetworkAccessManager *manager); Q_DECLARE_PUBLIC(QNetworkAccessManager) }; diff --git a/src/network/access/qnetworkcookie.h b/src/network/access/qnetworkcookie.h index 32307e305e..5553e857de 100644 --- a/src/network/access/qnetworkcookie.h +++ b/src/network/access/qnetworkcookie.h @@ -66,7 +66,7 @@ public: Full }; - QNetworkCookie(const QByteArray &name = QByteArray(), const QByteArray &value = QByteArray()); + explicit QNetworkCookie(const QByteArray &name = QByteArray(), const QByteArray &value = QByteArray()); QNetworkCookie(const QNetworkCookie &other); ~QNetworkCookie(); QNetworkCookie &operator=(const QNetworkCookie &other); diff --git a/src/network/access/qnetworkcookiejar.h b/src/network/access/qnetworkcookiejar.h index 513fb3b66c..8e6fa45ac5 100644 --- a/src/network/access/qnetworkcookiejar.h +++ b/src/network/access/qnetworkcookiejar.h @@ -57,7 +57,7 @@ class Q_NETWORK_EXPORT QNetworkCookieJar: public QObject { Q_OBJECT public: - QNetworkCookieJar(QObject *parent = 0); + explicit QNetworkCookieJar(QObject *parent = 0); virtual ~QNetworkCookieJar(); virtual QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const; diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index ac38f2efec..aefe07223f 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -131,6 +131,12 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() roaming to another access point. The request should be resubmitted and will be processed as soon as the connection is re-established. + \value NetworkSessionFailedError the connection was broken due + to disconnection from the network or failure to start the network. + + \value BackgroundRequestNotAllowedError the background request + is not currently allowed due to platform policy. + \value ProxyConnectionRefusedError the connection to the proxy server was refused (the proxy server is not accepting requests) diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index b8d606c260..e514779a0a 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -77,6 +77,8 @@ public: OperationCanceledError, SslHandshakeFailedError, TemporaryNetworkFailureError, + NetworkSessionFailedError, + BackgroundRequestNotAllowedError, UnknownNetworkError = 99, // proxy errors (101-199): @@ -155,7 +157,7 @@ Q_SIGNALS: void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); protected: - QNetworkReply(QObject *parent = 0); + explicit QNetworkReply(QObject *parent = 0); QNetworkReply(QNetworkReplyPrivate &dd, QObject *parent); virtual qint64 writeData(const char *data, qint64 len); diff --git a/src/network/access/qnetworkreplydataimpl.cpp b/src/network/access/qnetworkreplydataimpl.cpp index ab2c97b653..7a8d4ee3e0 100644 --- a/src/network/access/qnetworkreplydataimpl.cpp +++ b/src/network/access/qnetworkreplydataimpl.cpp @@ -88,7 +88,7 @@ QNetworkReplyDataImpl::QNetworkReplyDataImpl(QObject *parent, const QNetworkRequ } else { // something wrong with this URI const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend", - "Invalid URI: %1").arg(QString::fromLatin1(url.toEncoded())); + "Invalid URI: %1").arg(url.toString()); setError(QNetworkReply::ProtocolFailure, msg); QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolFailure)); diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index 7977704e38..cac8098057 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -1041,7 +1041,7 @@ void QNetworkReplyHttpImplPrivate::checkForRedirect(const int statusCode) // The response to a 303 MUST NOT be cached, while the response to // all of the others is cacheable if the headers indicate it to be QByteArray header = q->rawHeader("location"); - QUrl url = QUrl::fromEncoded(header); + QUrl url = QUrl(QString::fromUtf8(header)); if (!url.isValid()) url = QUrl(QLatin1String(header)); // FIXME? @@ -1531,6 +1531,8 @@ bool QNetworkReplyHttpImplPrivate::start() void QNetworkReplyHttpImplPrivate::_q_startOperation() { + Q_Q(QNetworkReplyHttpImpl); + // ensure this function is only being called once if (state == Working) { qDebug("QNetworkReplyImpl::_q_startOperation was called more than once"); @@ -1538,6 +1540,19 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation() } state = Working; +#ifndef QT_NO_BEARERMANAGEMENT + // Do not start background requests if they are not allowed by session policy + QSharedPointer<QNetworkSession> session(manager->d_func()->networkSession); + QVariant isBackground = request.attribute(QNetworkRequest::BackgroundRequestAttribute, QVariant::fromValue(false)); + if (isBackground.toBool() && session && session->usagePolicies().testFlag(QNetworkSession::NoBackgroundTrafficPolicy)) { + QMetaObject::invokeMethod(q, "_q_error", synchronous ? Qt::DirectConnection : Qt::QueuedConnection, + Q_ARG(QNetworkReply::NetworkError, QNetworkReply::BackgroundRequestNotAllowedError), + Q_ARG(QString, QCoreApplication::translate("QNetworkReply", "Background request not allowed."))); + QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection); + return; + } +#endif + if (!start()) { #ifndef QT_NO_BEARERMANAGEMENT // backend failed to start because the session state is not Connected. @@ -1547,8 +1562,6 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation() QNetworkSession *session = managerPrivate->networkSession.data(); if (session) { - Q_Q(QNetworkReplyHttpImpl); - QObject::connect(session, SIGNAL(error(QNetworkSession::SessionError)), q, SLOT(_q_networkSessionFailed())); @@ -1556,9 +1569,20 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation() session->open(); } else { qWarning("Backend is waiting for QNetworkSession to connect, but there is none!"); + QMetaObject::invokeMethod(q, "_q_error", synchronous ? Qt::DirectConnection : Qt::QueuedConnection, + Q_ARG(QNetworkReply::NetworkError, QNetworkReply::NetworkSessionFailedError), + Q_ARG(QString, QCoreApplication::translate("QNetworkReply", "Network session error."))); + QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection); + return; } -#endif +#else + qWarning("Backend start failed"); + QMetaObject::invokeMethod(q, "_q_error", synchronous ? Qt::DirectConnection : Qt::QueuedConnection, + Q_ARG(QNetworkReply::NetworkError, QNetworkReply::UnknownNetworkError), + Q_ARG(QString, QCoreApplication::translate("QNetworkReply", "backend start error."))); + QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection); return; +#endif } if (synchronous) { @@ -1728,8 +1752,13 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionFailed() // Abort waiting and working replies. if (state == WaitingForSession || state == Working) { state = Working; - error(QNetworkReplyImpl::UnknownNetworkError, - QCoreApplication::translate("QNetworkReply", "Network session error.")); + QSharedPointer<QNetworkSession> session(manager->d_func()->networkSession); + QString errorStr; + if (session) + errorStr = session->errorString(); + else + errorStr = QCoreApplication::translate("QNetworkReply", "Network session error."); + error(QNetworkReplyImpl::NetworkSessionFailedError, errorStr); finished(); } } diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 3ab846439b..5cdee5d040 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -90,6 +90,18 @@ void QNetworkReplyImplPrivate::_q_startOperation() return; } +#ifndef QT_NO_BEARERMANAGEMENT + // Do not start background requests if they are not allowed by session policy + QSharedPointer<QNetworkSession> session(manager->d_func()->networkSession); + QVariant isBackground = backend->request().attribute(QNetworkRequest::BackgroundRequestAttribute, QVariant::fromValue(false)); + if (isBackground.toBool() && session && session->usagePolicies().testFlag(QNetworkSession::NoBackgroundTrafficPolicy)) { + error(QNetworkReply::BackgroundRequestNotAllowedError, + QCoreApplication::translate("QNetworkReply", "Background request not allowed.")); + finished(); + return; + } +#endif + if (!backend->start()) { #ifndef QT_NO_BEARERMANAGEMENT // backend failed to start because the session state is not Connected. @@ -97,20 +109,20 @@ void QNetworkReplyImplPrivate::_q_startOperation() // state changes. state = WaitingForSession; - QNetworkSession *session = manager->d_func()->networkSession.data(); - if (session) { Q_Q(QNetworkReplyImpl); - QObject::connect(session, SIGNAL(error(QNetworkSession::SessionError)), + QObject::connect(session.data(), SIGNAL(error(QNetworkSession::SessionError)), q, SLOT(_q_networkSessionFailed())); - if (!session->isOpen()) + if (!session->isOpen()) { + session->setSessionProperty(QStringLiteral("ConnectInBackground"), isBackground); session->open(); + } } else { qWarning("Backend is waiting for QNetworkSession to connect, but there is none!"); state = Working; - error(QNetworkReplyImpl::UnknownNetworkError, + error(QNetworkReplyImpl::NetworkSessionFailedError, QCoreApplication::translate("QNetworkReply", "Network session error.")); finished(); } @@ -296,8 +308,13 @@ void QNetworkReplyImplPrivate::_q_networkSessionFailed() // Abort waiting and working replies. if (state == WaitingForSession || state == Working) { state = Working; - error(QNetworkReplyImpl::UnknownNetworkError, - QCoreApplication::translate("QNetworkReply", "Network session error.")); + QSharedPointer<QNetworkSession> session(manager->d_func()->networkSession); + QString errorStr; + if (session) + errorStr = session->errorString(); + else + errorStr = QCoreApplication::translate("QNetworkReply", "Network session error."); + error(QNetworkReplyImpl::NetworkSessionFailedError, errorStr); finished(); } } @@ -970,7 +987,7 @@ qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen) if (maxAvail == 0) return d->state == QNetworkReplyImplPrivate::Finished ? -1 : 0; // FIXME what about "Aborted" state? - qMemCopy(data, d->downloadBuffer + d->downloadBufferReadPosition, maxAvail); + memcpy(data, d->downloadBuffer + d->downloadBufferReadPosition, maxAvail); d->downloadBufferReadPosition += maxAvail; return maxAvail; } diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index f94337eaeb..1c8655e9ae 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -237,6 +237,14 @@ QT_BEGIN_NAMESPACE \omitvalue SynchronousRequestAttribute + \value BackgroundRequestAttribute + Type: QVariant::Bool (default: false) + Indicates that this is a background transfer, rather than a user initiated + transfer. Depending on the platform, background transfers may be subject + to different policies. + The QNetworkSession ConnectInBackground property will be set according to + this attribute. + \value User Special type. Additional information can be passed in QVariants with types ranging from User to UserMax. The default diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index 7f51826d17..68fc655b7a 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -87,6 +87,7 @@ public: MaximumDownloadBufferSizeAttribute, // internal DownloadBufferAttribute, // internal SynchronousRequestAttribute, // internal + BackgroundRequestAttribute, User = 1000, UserMax = 32767 diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp index ccf794633d..1a3c25a97f 100644 --- a/src/network/bearer/qnetworksession.cpp +++ b/src/network/bearer/qnetworksession.cpp @@ -149,6 +149,17 @@ QT_BEGIN_NAMESPACE */ /*! + \enum QNetworkSession::UsagePolicies + + These flags allow the system to inform the application of network usage restrictions that + may be in place. + + \value NoPolicy No policy in force, usage is unrestricted. + \value NoBackgroundTrafficPolicy Background network traffic (not user initiated) should be avoided + for example to save battery or data charges +*/ + +/*! \fn void QNetworkSession::stateChanged(QNetworkSession::State state) This signal is emitted whenever the state of the network session changes. @@ -222,6 +233,12 @@ QT_BEGIN_NAMESPACE */ /*! + \fn void QNetworkSession::usagePoliciesChanged(UsagePolicies) + + This signal is emitted when the usage policies in force are changed by the system. +*/ + +/*! Constructs a session based on \a connectionConfig with the given \a parent. \sa QNetworkConfiguration @@ -247,6 +264,8 @@ QNetworkSession::QNetworkSession(const QNetworkConfiguration &connectionConfig, this, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool))); connect(d, SIGNAL(newConfigurationActivated()), this, SIGNAL(newConfigurationActivated())); + connect(d, SIGNAL(usagePoliciesChanged(QNetworkSession::UsagePolicies)), + this, SIGNAL(usagePoliciesChanged(QNetworkSession::UsagePolicies))); break; } } @@ -254,6 +273,7 @@ QNetworkSession::QNetworkSession(const QNetworkConfiguration &connectionConfig, qRegisterMetaType<QNetworkSession::State>(); qRegisterMetaType<QNetworkSession::SessionError>(); + qRegisterMetaType<QNetworkSession::UsagePolicies>(); } /*! @@ -654,6 +674,26 @@ quint64 QNetworkSession::activeTime() const } /*! + Returns the network usage policies currently in force by the system. +*/ +QNetworkSession::UsagePolicies QNetworkSession::usagePolicies() const +{ + return d ? d->usagePolicies() : QNetworkSession::NoPolicy; +} + +/*! + \internal + Change usage policies for unit testing. + In normal use, the policies are published by the bearer plugin +*/ +void QNetworkSessionPrivate::setUsagePolicies(QNetworkSession &session, QNetworkSession::UsagePolicies policies) +{ + if (!session.d) + return; + session.d->setUsagePolicies(policies); +} + +/*! \internal This function is required to detect whether the client wants to control diff --git a/src/network/bearer/qnetworksession.h b/src/network/bearer/qnetworksession.h index 21d568ca13..d72fe0e759 100644 --- a/src/network/bearer/qnetworksession.h +++ b/src/network/bearer/qnetworksession.h @@ -83,6 +83,13 @@ public: InvalidConfigurationError }; + enum UsagePolicy { + NoPolicy = 0, + NoBackgroundTrafficPolicy = 1 + }; + + Q_DECLARE_FLAGS(UsagePolicies, UsagePolicy) + explicit QNetworkSession(const QNetworkConfiguration &connConfig, QObject *parent = 0); virtual ~QNetworkSession(); @@ -101,7 +108,9 @@ public: quint64 bytesWritten() const; quint64 bytesReceived() const; quint64 activeTime() const; - + + QNetworkSession::UsagePolicies usagePolicies() const; + bool waitForOpened(int msecs = 30000); public Q_SLOTS: @@ -122,6 +131,7 @@ Q_SIGNALS: void error(QNetworkSession::SessionError); void preferredConfigurationChanged(const QNetworkConfiguration &config, bool isSeamless); void newConfigurationActivated(); + void usagePoliciesChanged(QNetworkSession::UsagePolicies); protected: virtual void connectNotify(const char *signal); @@ -136,6 +146,7 @@ private: QT_END_NAMESPACE Q_DECLARE_METATYPE(QNetworkSession::State) Q_DECLARE_METATYPE(QNetworkSession::SessionError) +Q_DECLARE_METATYPE(QNetworkSession::UsagePolicies) QT_END_HEADER diff --git a/src/network/bearer/qnetworksession_p.h b/src/network/bearer/qnetworksession_p.h index 0eea06b085..4d036d601d 100644 --- a/src/network/bearer/qnetworksession_p.h +++ b/src/network/bearer/qnetworksession_p.h @@ -103,6 +103,10 @@ public: virtual quint64 bytesReceived() const = 0; virtual quint64 activeTime() const = 0; + virtual QNetworkSession::UsagePolicies usagePolicies() const = 0; + virtual void setUsagePolicies(QNetworkSession::UsagePolicies) = 0; + + static void setUsagePolicies(QNetworkSession&, QNetworkSession::UsagePolicies); //for unit testing protected: inline QNetworkConfigurationPrivatePointer privateConfiguration(const QNetworkConfiguration &config) const { @@ -124,6 +128,7 @@ Q_SIGNALS: void closed(); void newConfigurationActivated(); void preferredConfigurationChanged(const QNetworkConfiguration &config, bool isSeamless); + void usagePoliciesChanged(QNetworkSession::UsagePolicies); protected: QNetworkSession *q; diff --git a/src/network/kernel/qdnslookup.h b/src/network/kernel/qdnslookup.h index 198b19d8a8..89e8cbb852 100644 --- a/src/network/kernel/qdnslookup.h +++ b/src/network/kernel/qdnslookup.h @@ -191,7 +191,7 @@ public: TXT = 16 }; - QDnsLookup(QObject *parent = 0); + explicit QDnsLookup(QObject *parent = 0); QDnsLookup(Type type, const QString &name, QObject *parent = 0); ~QDnsLookup(); diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 230abb86aa..3c08717d11 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -41,6 +41,7 @@ #include "qhostaddress.h" #include "qhostaddress_p.h" +#include "private/qipaddress_p.h" #include "qdebug.h" #if defined(Q_OS_WIN) #include <winsock2.h> @@ -107,13 +108,14 @@ public: bool parse(); void clear(); + QString ipString; + QString scopeId; + quint32 a; // IPv4 address Q_IPV6ADDR a6; // IPv6 address QAbstractSocket::NetworkLayerProtocol protocol; - QString ipString; bool isParsed; - QString scopeId; friend class QHostAddress; }; @@ -175,28 +177,7 @@ void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_) isParsed = true; } -static bool parseIp4(const QString& address, quint32 *addr) -{ - QStringList ipv4 = address.split(QLatin1String(".")); - if (ipv4.count() != 4) - return false; - - quint32 ipv4Address = 0; - for (int i = 0; i < 4; ++i) { - bool ok = false; - uint byteValue = ipv4.at(i).toUInt(&ok); - if (!ok || byteValue > 255) - return false; - - ipv4Address <<= 8; - ipv4Address += byteValue; - } - - *addr = ipv4Address; - return true; -} - -static bool parseIp6(const QString &address, quint8 *addr, QString *scopeId) +static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr, QString *scopeId) { QString tmp = address; int scopeIdPos = tmp.lastIndexOf(QLatin1Char('%')); @@ -206,77 +187,7 @@ static bool parseIp6(const QString &address, quint8 *addr, QString *scopeId) } else { scopeId->clear(); } - - QStringList ipv6 = tmp.split(QLatin1String(":")); - int count = ipv6.count(); - if (count < 3 || count > 8) - return false; - - int colonColon = tmp.count(QLatin1String("::")); - if(count == 8 && colonColon > 1) - return false; - - // address can be compressed with a "::", but that - // may only appear once (see RFC 1884) - // the statement below means: - // if(shortened notation is not used AND - // ((pure IPv6 notation AND less than 8 parts) OR - // ((mixed IPv4/6 notation AND less than 7 parts))) - if(colonColon != 1 && count < (tmp.contains(QLatin1Char('.')) ? 7 : 8)) - return false; - - int mc = 16; - int fillCount = 9 - count; // number of 0 words to fill in the middle - for (int i = count - 1; i >= 0; --i) { - if (mc <= 0) - return false; - - if (ipv6.at(i).isEmpty()) { - if (i == count - 1) { - // special case: ":" is last character - if (!ipv6.at(i - 1).isEmpty()) - return false; - addr[--mc] = 0; - addr[--mc] = 0; - } else if (i == 0) { - // special case: ":" is first character - if (!ipv6.at(i + 1).isEmpty()) - return false; - addr[--mc] = 0; - addr[--mc] = 0; - } else { - for (int j = 0; j < fillCount; ++j) { - if (mc <= 0) - return false; - addr[--mc] = 0; - addr[--mc] = 0; - } - } - } else { - bool ok = false; - uint byteValue = ipv6.at(i).toUInt(&ok, 16); - if (ok && byteValue <= 0xffff) { - addr[--mc] = byteValue & 0xff; - addr[--mc] = (byteValue >> 8) & 0xff; - } else { - if (i != count - 1) - return false; - - // parse the ipv4 part of a mixed type - quint32 maybeIp4; - if (!parseIp4(ipv6.at(i), &maybeIp4)) - return false; - - addr[--mc] = maybeIp4 & 0xff; - addr[--mc] = (maybeIp4 >> 8) & 0xff; - addr[--mc] = (maybeIp4 >> 16) & 0xff; - addr[--mc] = (maybeIp4 >> 24) & 0xff; - --fillCount; - } - } - } - - return true; + return QIPAddressUtils::parseIp6(addr, tmp.constBegin(), tmp.constEnd()); } bool QHostAddressPrivate::parse() @@ -284,6 +195,8 @@ bool QHostAddressPrivate::parse() isParsed = true; protocol = QAbstractSocket::UnknownNetworkLayerProtocol; QString a = ipString.simplified(); + if (a.isEmpty()) + return false; // All IPv6 addresses contain a ':', and may contain a '.'. if (a.contains(QLatin1Char(':'))) { @@ -295,14 +208,11 @@ bool QHostAddressPrivate::parse() } } - // All IPv4 addresses contain a '.'. - if (a.contains(QLatin1Char('.'))) { - quint32 maybeIp4 = 0; - if (parseIp4(a, &maybeIp4)) { - setAddress(maybeIp4); - protocol = QAbstractSocket::IPv4Protocol; - return true; - } + quint32 maybeIp4 = 0; + if (QIPAddressUtils::parseIp4(maybeIp4, a.constBegin(), a.constEnd())) { + setAddress(maybeIp4); + protocol = QAbstractSocket::IPv4Protocol; + return true; } return false; @@ -556,23 +466,27 @@ QHostAddress::QHostAddress(const QHostAddress &address) QHostAddress::QHostAddress(SpecialAddress address) : d(new QHostAddressPrivate) { + Q_IPV6ADDR ip6; + memset(&ip6, 0, sizeof ip6); + switch (address) { case Null: break; case Broadcast: - setAddress(QLatin1String("255.255.255.255")); + d->setAddress(quint32(-1)); break; case LocalHost: - setAddress(QLatin1String("127.0.0.1")); + d->setAddress(0x7f000001); break; case LocalHostIPv6: - setAddress(QLatin1String("::1")); + ip6[15] = 1; + d->setAddress(ip6); break; case AnyIPv4: - setAddress(QLatin1String("0.0.0.0")); + setAddress(0u); break; case AnyIPv6: - setAddress(QLatin1String("::")); + d->setAddress(ip6); break; case Any: d->clear(); @@ -761,42 +675,13 @@ QString QHostAddress::toString() const || d->protocol == QAbstractSocket::AnyIPProtocol) { quint32 i = toIPv4Address(); QString s; - s.sprintf("%d.%d.%d.%d", (i>>24) & 0xff, (i>>16) & 0xff, - (i >> 8) & 0xff, i & 0xff); + QIPAddressUtils::toString(s, i); return s; } if (d->protocol == QAbstractSocket::IPv6Protocol) { - quint16 ugle[8]; - for (int i = 0; i < 8; i++) { - ugle[i] = (quint16(d->a6[2*i]) << 8) | quint16(d->a6[2*i+1]); - } QString s; - QString temp; - bool zeroDetected = false; - bool zeroShortened = false; - for (int i = 0; i < 8; i++) { - if ((ugle[i] != 0) || zeroShortened) { - temp.sprintf("%X", ugle[i]); - s.append(temp); - if (zeroDetected) - zeroShortened = true; - } else { - if (!zeroDetected) { - if (i<7 && (ugle[i+1] == 0)) { - s.append(QLatin1Char(':')); - zeroDetected = true; - } else { - temp.sprintf("%X", ugle[i]); - s.append(temp); - if (i<7) - s.append(QLatin1Char(':')); - } - } - } - if (i<7 && ((ugle[i] != 0) || zeroShortened || (i==0 && zeroDetected))) - s.append(QLatin1Char(':')); - } + QIPAddressUtils::toString(s, d->a6.c); if (!d->scopeId.isEmpty()) s.append(QLatin1Char('%') + d->scopeId); @@ -1142,9 +1027,10 @@ QDebug operator<<(QDebug d, const QHostAddress &address) } #endif -uint qHash(const QHostAddress &key) +uint qHash(const QHostAddress &key, uint seed) { - return qHash(key.toString()); + QT_ENSURE_PARSED(&key); + return qHash(QByteArray::fromRawData(reinterpret_cast<const char *>(key.d->a6.c), 16), seed); } #ifndef QT_NO_DATASTREAM diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h index fdf09ecc82..ce4470d32e 100644 --- a/src/network/kernel/qhostaddress.h +++ b/src/network/kernel/qhostaddress.h @@ -123,6 +123,7 @@ public: static QPair<QHostAddress, int> parseSubnet(const QString &subnet); + friend Q_NETWORK_EXPORT uint qHash(const QHostAddress &key, uint seed = 0); protected: QScopedPointer<QHostAddressPrivate> d; }; @@ -134,9 +135,6 @@ inline bool operator ==(QHostAddress::SpecialAddress address1, const QHostAddres Q_NETWORK_EXPORT QDebug operator<<(QDebug, const QHostAddress &); #endif - -Q_NETWORK_EXPORT uint qHash(const QHostAddress &key); - #ifndef QT_NO_DATASTREAM Q_NETWORK_EXPORT QDataStream &operator<<(QDataStream &, const QHostAddress &); Q_NETWORK_EXPORT QDataStream &operator>>(QDataStream &, QHostAddress &); diff --git a/src/network/kernel/qhostinfo.h b/src/network/kernel/qhostinfo.h index df377872c8..2fc87f3bdc 100644 --- a/src/network/kernel/qhostinfo.h +++ b/src/network/kernel/qhostinfo.h @@ -63,7 +63,7 @@ public: UnknownError }; - QHostInfo(int lookupId = -1); + explicit QHostInfo(int lookupId = -1); QHostInfo(const QHostInfo &d); QHostInfo &operator=(const QHostInfo &d); ~QHostInfo(); diff --git a/src/network/kernel/qnetworkproxy.h b/src/network/kernel/qnetworkproxy.h index 805f5cdb5c..2e5c3ed687 100644 --- a/src/network/kernel/qnetworkproxy.h +++ b/src/network/kernel/qnetworkproxy.h @@ -68,10 +68,10 @@ public: }; QNetworkProxyQuery(); - QNetworkProxyQuery(const QUrl &requestUrl, QueryType queryType = UrlRequest); + explicit QNetworkProxyQuery(const QUrl &requestUrl, QueryType queryType = UrlRequest); QNetworkProxyQuery(const QString &hostname, int port, const QString &protocolTag = QString(), QueryType queryType = TcpSocket); - QNetworkProxyQuery(quint16 bindPort, const QString &protocolTag = QString(), + explicit QNetworkProxyQuery(quint16 bindPort, const QString &protocolTag = QString(), QueryType queryType = TcpServer); QNetworkProxyQuery(const QNetworkProxyQuery &other); #ifndef QT_NO_BEARERMANAGEMENT diff --git a/src/network/socket/qlocalserver.h b/src/network/socket/qlocalserver.h index 291122e10d..f9499c69ba 100644 --- a/src/network/socket/qlocalserver.h +++ b/src/network/socket/qlocalserver.h @@ -74,7 +74,7 @@ public: }; Q_DECLARE_FLAGS(SocketOptions, SocketOption) - QLocalServer(QObject *parent = 0); + explicit QLocalServer(QObject *parent = 0); ~QLocalServer(); void close(); diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index b15d6e97bb..fbb38a9b46 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -82,8 +82,8 @@ public: EmailAddress }; - QSslCertificate(QIODevice *device, QSsl::EncodingFormat format = QSsl::Pem); - QSslCertificate(const QByteArray &data = QByteArray(), QSsl::EncodingFormat format = QSsl::Pem); + explicit QSslCertificate(QIODevice *device, QSsl::EncodingFormat format = QSsl::Pem); + explicit QSslCertificate(const QByteArray &data = QByteArray(), QSsl::EncodingFormat format = QSsl::Pem); QSslCertificate(const QSslCertificate &other); ~QSslCertificate(); QSslCertificate &operator=(const QSslCertificate &other); diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h index e420972041..195cbdf7c7 100644 --- a/src/network/ssl/qsslsocket.h +++ b/src/network/ssl/qsslsocket.h @@ -80,7 +80,7 @@ public: AutoVerifyPeer }; - QSslSocket(QObject *parent = 0); + explicit QSslSocket(QObject *parent = 0); ~QSslSocket(); void resume(); // to continue after proxy authentication required, SSL errors etc. |