summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/access/qftp.cpp4
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp25
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp2
-rw-r--r--src/network/access/qhttpnetworkreply.cpp8
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp5
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp15
-rw-r--r--src/network/access/qnetworkaccessbackend_p.h2
-rw-r--r--src/network/access/qnetworkcookie.cpp18
-rw-r--r--src/network/access/qnetworkdiskcache.cpp6
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp28
-rw-r--r--src/network/access/qnetworkreplyimpl_p.h2
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.cpp2
-rw-r--r--src/network/kernel/qhostinfo_win.cpp38
-rw-r--r--src/network/kernel/qnetworkinterface_win.cpp21
-rw-r--r--src/network/kernel/qnetworkproxy.cpp6
-rw-r--r--src/network/kernel/qnetworkproxy_generic.cpp31
-rw-r--r--src/network/socket/qhttpsocketengine.cpp4
-rw-r--r--src/network/socket/qlocalserver_unix.cpp8
-rw-r--r--src/network/ssl/qssl.cpp36
-rw-r--r--src/network/ssl/qssl.h12
-rw-r--r--src/network/ssl/qsslcertificate.cpp3
-rw-r--r--src/network/ssl/qsslconfiguration.cpp29
-rw-r--r--src/network/ssl/qsslconfiguration.h4
-rw-r--r--src/network/ssl/qsslconfiguration_p.h5
-rw-r--r--src/network/ssl/qsslsocket.cpp2
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp41
26 files changed, 257 insertions, 100 deletions
diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp
index 50a3b1e..eccfea6 100644
--- a/src/network/access/qftp.cpp
+++ b/src/network/access/qftp.cpp
@@ -1851,11 +1851,11 @@ int QFtp::cd(const QString &dir)
int QFtp::get(const QString &file, QIODevice *dev, TransferType type)
{
QStringList cmds;
- cmds << QLatin1String("SIZE ") + file + QLatin1String("\r\n");
if (type == Binary)
cmds << QLatin1String("TYPE I\r\n");
else
cmds << QLatin1String("TYPE A\r\n");
+ cmds << QLatin1String("SIZE ") + file + QLatin1String("\r\n");
cmds << QLatin1String(d_func()->transferMode == Passive ? "PASV\r\n" : "PORT\r\n");
cmds << QLatin1String("RETR ") + file + QLatin1String("\r\n");
return d_func()->addCommand(new QFtpCommand(Get, cmds, dev));
@@ -2336,7 +2336,7 @@ void QFtpPrivate::_q_piError(int errorCode, const QString &text)
// non-fatal errors
if (c->command == QFtp::Get && pi.currentCommand().startsWith(QLatin1String("SIZE "))) {
- pi.dtp.setBytesTotal(-1);
+ pi.dtp.setBytesTotal(0);
return;
} else if (c->command==QFtp::Put && pi.currentCommand().startsWith(QLatin1String("ALLO "))) {
return;
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 6101eea..0365703 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -48,6 +48,7 @@
#include <private/qauthenticator_p.h>
#include <qnetworkproxy.h>
#include <qauthenticator.h>
+#include <qcoreapplication.h>
#include <qbuffer.h>
#include <qpair.h>
@@ -386,6 +387,11 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket
// send any pending requests
copyCredentials(i, auth, isProxy);
}
+ } else if (priv->phase == QAuthenticatorPrivate::Start) {
+ // If the url's authenticator has a 'user' set we will end up here (phase is only set to 'Done' by
+ // parseHttpResponse above if 'user' is empty). So if credentials were supplied with the request,
+ // such as in the case of an XMLHttpRequest, this is our only opportunity to cache them.
+ emit reply->cacheCredentials(reply->request(), auth);
}
// - Changing values in QAuthenticator will reset the 'phase'. Therefore if it is still "Done"
// then nothing was filled in by the user or the cache
@@ -665,32 +671,31 @@ QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError e
QString errorString;
switch (errorCode) {
case QNetworkReply::HostNotFoundError:
- errorString = QString::fromLatin1(QT_TRANSLATE_NOOP("QHttp", "Host %1 not found"))
- .arg(socket->peerName());
+ errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(socket->peerName());
break;
case QNetworkReply::ConnectionRefusedError:
- errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Connection refused"));
+ errorString = QCoreApplication::translate("QHttp", "Connection refused");
break;
case QNetworkReply::RemoteHostClosedError:
- errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Connection closed"));
+ errorString = QCoreApplication::translate("QHttp", "Connection closed");
break;
case QNetworkReply::TimeoutError:
- errorString = QLatin1String(QT_TRANSLATE_NOOP("QAbstractSocket", "Socket operation timed out"));
+ errorString = QCoreApplication::translate("QAbstractSocket", "Socket operation timed out");
break;
case QNetworkReply::ProxyAuthenticationRequiredError:
- errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Proxy requires authentication"));
+ errorString = QCoreApplication::translate("QHttp", "Proxy requires authentication");
break;
case QNetworkReply::AuthenticationRequiredError:
- errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Host requires authentication"));
+ errorString = QCoreApplication::translate("QHttp", "Host requires authentication");
break;
case QNetworkReply::ProtocolFailure:
- errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Data corrupted"));
+ errorString = QCoreApplication::translate("QHttp", "Data corrupted");
break;
case QNetworkReply::ProtocolUnknownError:
- errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Unknown protocol specified"));
+ errorString = QCoreApplication::translate("QHttp", "Unknown protocol specified");
break;
case QNetworkReply::SslHandshakeFailedError:
- errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "SSL handshake failed"));
+ errorString = QCoreApplication::translate("QHttp", "SSL handshake failed");
break;
default:
// all other errors are treated as QNetworkReply::UnknownNetworkError
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 9b2a6e8..b9db7fe 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -201,7 +201,6 @@ bool QHttpNetworkConnectionChannel::sendRequest()
|| (!url.password().isEmpty() && url.password() != auth.password())) {
auth.setUser(url.userName());
auth.setPassword(url.password());
- emit reply->cacheCredentials(request, &auth);
connection->d_func()->copyCredentials(connection->d_func()->indexOf(socket), &auth, false);
}
// clear the userinfo, since we use the same request for resending
@@ -789,6 +788,7 @@ void QHttpNetworkConnectionChannel::detectPipeliningSupport()
&& (!serverHeaderField.contains("Netscape-Enterprise/3."))
// this is adpoted from the knowledge of the Nokia 7.x browser team (DEF143319)
&& (!serverHeaderField.contains("WebLogic"))
+ && (!serverHeaderField.startsWith("Rocket")) // a Python Web Server, see Web2py.com
) {
pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningProbablySupported;
} else {
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index 1a02200..3dc8b2f 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -472,8 +472,10 @@ int QHttpNetworkReplyPrivate::gunzipBodyPartially(QByteArray &compressed, QByteA
void QHttpNetworkReplyPrivate::gunzipBodyPartiallyEnd()
{
- inflateEnd(&inflateStrm);
- initInflate = false;
+ if (initInflate) {
+ inflateEnd(&inflateStrm);
+ initInflate = false;
+ }
}
#endif
@@ -891,7 +893,7 @@ bool QHttpNetworkReplyPrivate::expectContent()
|| statusCode == 204 || statusCode == 304)
return false;
if (request.operation() == QHttpNetworkRequest::Head)
- return !shouldEmitSignals();
+ return false; // no body expected for HEAD request
qint64 expectedContentLength = contentLength();
if (expectedContentLength == 0)
return false;
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 092fa7d..68c2292 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -312,8 +312,6 @@ void QHttpThreadDelegate::startRequest()
// some signals are only interesting when normal asynchronous style is used
connect(httpReply,SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
connect(httpReply,SIGNAL(dataReadProgress(int, int)), this, SLOT(dataReadProgressSlot(int,int)));
- connect(httpReply, SIGNAL(cacheCredentials(QHttpNetworkRequest,QAuthenticator*)),
- this, SLOT(cacheCredentialsSlot(QHttpNetworkRequest,QAuthenticator*)));
#ifndef QT_NO_OPENSSL
connect(httpReply,SIGNAL(sslErrors(const QList<QSslError>)), this, SLOT(sslErrorsSlot(QList<QSslError>)));
#endif
@@ -325,6 +323,9 @@ void QHttpThreadDelegate::startRequest()
connect(httpReply, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
this, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
}
+
+ connect(httpReply, SIGNAL(cacheCredentials(QHttpNetworkRequest,QAuthenticator*)),
+ this, SLOT(cacheCredentialsSlot(QHttpNetworkRequest,QAuthenticator*)));
}
// This gets called from the user thread or by the synchronous HTTP timeout timer
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 2fae7d6..1dc1268 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -57,20 +57,25 @@
QT_BEGIN_NAMESPACE
-static bool factoryDataShutdown = false;
class QNetworkAccessBackendFactoryData: public QList<QNetworkAccessBackendFactory *>
{
public:
- QNetworkAccessBackendFactoryData() : mutex(QMutex::Recursive) { }
+ QNetworkAccessBackendFactoryData() : mutex(QMutex::Recursive)
+ {
+ valid.ref();
+ }
~QNetworkAccessBackendFactoryData()
{
QMutexLocker locker(&mutex); // why do we need to lock?
- factoryDataShutdown = true;
+ valid.deref();
}
QMutex mutex;
+ //this is used to avoid (re)constructing factory data from destructors of other global classes
+ static QBasicAtomicInt valid;
};
Q_GLOBAL_STATIC(QNetworkAccessBackendFactoryData, factoryData)
+QBasicAtomicInt QNetworkAccessBackendFactoryData::valid = Q_BASIC_ATOMIC_INITIALIZER(0);
QNetworkAccessBackendFactory::QNetworkAccessBackendFactory()
{
@@ -80,7 +85,7 @@ QNetworkAccessBackendFactory::QNetworkAccessBackendFactory()
QNetworkAccessBackendFactory::~QNetworkAccessBackendFactory()
{
- if (!factoryDataShutdown) {
+ if (QNetworkAccessBackendFactoryData::valid) {
QMutexLocker locker(&factoryData()->mutex);
factoryData()->removeAll(this);
}
@@ -89,7 +94,7 @@ QNetworkAccessBackendFactory::~QNetworkAccessBackendFactory()
QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessManager::Operation op,
const QNetworkRequest &request)
{
- if (!factoryDataShutdown) {
+ if (QNetworkAccessBackendFactoryData::valid) {
QMutexLocker locker(&factoryData()->mutex);
QNetworkAccessBackendFactoryData::ConstIterator it = factoryData()->constBegin(),
end = factoryData()->constEnd();
diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h
index ff05306..7f6aff9 100644
--- a/src/network/access/qnetworkaccessbackend_p.h
+++ b/src/network/access/qnetworkaccessbackend_p.h
@@ -110,9 +110,7 @@ public:
// socket).
virtual void open() = 0;
-#ifndef QT_NO_BEARERMANAGEMENT
virtual bool start();
-#endif
virtual void closeDownstreamChannel() = 0;
// slot-like:
diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp
index 0670738..a9bb318 100644
--- a/src/network/access/qnetworkcookie.cpp
+++ b/src/network/access/qnetworkcookie.cpp
@@ -372,7 +372,7 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
// parse the first part, before the equal sign
for (i = position; i < length; ++i) {
register char c = text.at(i);
- if (c == ';' || c == ',' || c == '=')
+ if (c == ';' || c == '=')
break;
}
@@ -423,7 +423,7 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
for ( ; i < length; ++i) {
register char c = text.at(i);
- if (c == ',' || c == ';')
+ if (c == ';')
break;
}
position = i;
@@ -434,7 +434,7 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
register char c = text.at(i);
// for name value pairs, we want to parse until reaching the next ';'
// and not break when reaching a space char
- if (c == ',' || c == ';' || ((isNameValue && (c == '\n' || c == '\r')) || (!isNameValue && isLWS(c))))
+ if (c == ';' || ((isNameValue && (c == '\n' || c == '\r')) || (!isNameValue && isLWS(c))))
break;
}
@@ -461,8 +461,7 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
\value Full makes toRawForm() return the full
cookie contents, as suitable for sending to a client in a
- server's "Set-Cookie:" header. Multiple cookies are separated
- by commas in a "Set-Cookie:" header.
+ server's "Set-Cookie:" header.
Note that only the Full form of the cookie can be parsed back into
its original contents.
@@ -488,7 +487,6 @@ QByteArray QNetworkCookie::toRawForm(RawForm form) const
result = d->name;
result += '=';
if ((d->value.contains(';') ||
- d->value.contains(',') ||
d->value.contains('"')) &&
(!d->value.startsWith('"') &&
!d->value.endsWith('"'))) {
@@ -967,14 +965,8 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt
cookie.setValue(field.second);
position = nextNonWhitespace(cookieString, position);
- bool endOfCookie = false;
- while (!endOfCookie && position < length) {
+ while (position < length) {
switch (cookieString.at(position++)) {
- case ',':
- // end of the cookie
- endOfCookie = true;
- break;
-
case ';':
// new field in the cookie
field = nextField(cookieString, position, false);
diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp
index 1c515c2..a567c2d 100644
--- a/src/network/access/qnetworkdiskcache.cpp
+++ b/src/network/access/qnetworkdiskcache.cpp
@@ -429,7 +429,7 @@ QIODevice *QNetworkDiskCache::data(const QUrl &url)
// ### verify that QFile uses the fd size and not the file name
qint64 size = file->size() - file->pos();
const uchar *p = 0;
-#if !defined(Q_OS_WINCE) && !defined(Q_OS_INTEGRITY)
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_SYMBIAN)
p = file->map(file->pos(), size);
#endif
if (p) {
@@ -478,7 +478,7 @@ void QNetworkDiskCache::updateMetaData(const QNetworkCacheMetaData &metaData)
}
/*!
- Returns the current maximum size for the disk cache.
+ Returns the current maximum size in bytes for the disk cache.
\sa setMaximumCacheSize()
*/
@@ -489,7 +489,7 @@ qint64 QNetworkDiskCache::maximumCacheSize() const
}
/*!
- Sets the maximum size of the disk cache to be \a size.
+ Sets the maximum size of the disk cache to be \a size in bytes.
If the new size is smaller then the current cache size then the cache will call expire().
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 58eb0d8..6f2daec 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -275,6 +275,11 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected()
if (session->state() != QNetworkSession::Connected)
return;
+ #ifndef QT_NO_NETWORKPROXY
+ // Re-set proxies here as new session might have changed them
+ proxyList = manager->d_func()->queryProxy(QNetworkProxyQuery(request.url()));
+ #endif
+
switch (state) {
case QNetworkReplyImplPrivate::Buffering:
case QNetworkReplyImplPrivate::Working:
@@ -466,6 +471,7 @@ bool QNetworkReplyImplPrivate::isCachingEnabled() const
void QNetworkReplyImplPrivate::setCachingEnabled(bool enable)
{
+ Q_Q(QNetworkReplyImpl);
if (!enable && !cacheEnabled)
return; // nothing to do
if (enable && cacheEnabled)
@@ -488,15 +494,27 @@ void QNetworkReplyImplPrivate::setCachingEnabled(bool enable)
networkCache()->remove(url);
cacheSaveDevice = 0;
cacheEnabled = false;
+ QObject::disconnect(networkCache(), SIGNAL(destroyed()), q, SLOT(_q_cacheDestroyed()));
}
}
+void QNetworkReplyImplPrivate::_q_cacheDestroyed()
+{
+ //destruction of cache invalidates cacheSaveDevice
+ cacheSaveDevice = 0;
+ cacheEnabled = false;
+}
+
void QNetworkReplyImplPrivate::completeCacheSave()
{
- if (cacheEnabled && errorCode != QNetworkReplyImpl::NoError) {
- networkCache()->remove(url);
- } else if (cacheEnabled && cacheSaveDevice) {
- networkCache()->insert(cacheSaveDevice);
+ Q_Q(QNetworkReplyImpl);
+ if (cacheEnabled) {
+ if (errorCode != QNetworkReplyImpl::NoError) {
+ networkCache()->remove(url);
+ } else if (cacheSaveDevice) {
+ networkCache()->insert(cacheSaveDevice);
+ }
+ QObject::disconnect(networkCache(), SIGNAL(destroyed()), q, SLOT(_q_cacheDestroyed()));
}
cacheSaveDevice = 0;
cacheEnabled = false;
@@ -556,6 +574,8 @@ void QNetworkReplyImplPrivate::initCacheSaveDevice()
networkCache()->remove(url);
cacheSaveDevice = 0;
cacheEnabled = false;
+ } else {
+ q->connect(networkCache(), SIGNAL(destroyed()), SLOT(_q_cacheDestroyed()));
}
}
diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h
index 089c87e..286d8ea 100644
--- a/src/network/access/qnetworkreplyimpl_p.h
+++ b/src/network/access/qnetworkreplyimpl_p.h
@@ -104,6 +104,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
#endif
+ Q_PRIVATE_SLOT(d_func(), void _q_cacheDestroyed())
};
class QNetworkReplyImplPrivate: public QNetworkReplyPrivate
@@ -140,6 +141,7 @@ public:
void _q_networkSessionConnected();
void _q_networkSessionFailed();
#endif
+ void _q_cacheDestroyed();
void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
QIODevice *outgoingData);
diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp
index 18e29af..96a534d 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.cpp
+++ b/src/network/bearer/qnetworkconfigmanager_p.cpp
@@ -60,7 +60,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
#endif
QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
- : QObject(), pollTimer(0), mutex(QMutex::Recursive), forcedPolling(0), firstUpdate(true)
+ : QObject(), pollTimer(0), bearerThread(0), mutex(QMutex::Recursive), forcedPolling(0), firstUpdate(true)
{
qRegisterMetaType<QNetworkConfiguration>("QNetworkConfiguration");
qRegisterMetaType<QNetworkConfigurationPrivatePointer>("QNetworkConfigurationPrivatePointer");
diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp
index 6fc5b7b..58a5bee 100644
--- a/src/network/kernel/qhostinfo_win.cpp
+++ b/src/network/kernel/qhostinfo_win.cpp
@@ -45,9 +45,7 @@
#include "private/qnativesocketengine_p.h"
#include <ws2tcpip.h>
#include <private/qsystemlibrary_p.h>
-#include <qmutex.h>
#include <qurl.h>
-#include <private/qmutexpool_p.h>
QT_BEGIN_NAMESPACE
@@ -84,38 +82,38 @@ static void resolveLibrary()
{
// Attempt to resolve getaddrinfo(); without it we'll have to fall
// back to gethostbyname(), which has no IPv6 support.
+ static bool triedResolve = false;
+ if (triedResolve)
+ return;
+
#if !defined(Q_OS_WINCE)
- local_getaddrinfo = (getaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getaddrinfo");
- local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "freeaddrinfo");
- local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getnameinfo");
+ QSystemLibrary ws2lib(QLatin1String("ws2_32"));
#else
- local_getaddrinfo = (getaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "getaddrinfo");
- local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "freeaddrinfo");
- local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "getnameinfo");
+ QSystemLibrary ws2lib(QLatin1String("ws2"));
#endif
+ if (ws2lib.load()) {
+ local_getaddrinfo = (getaddrinfoProto)ws2lib.resolve("getaddrinfo");
+ local_freeaddrinfo = (freeaddrinfoProto)ws2lib.resolve("freeaddrinfo");
+ local_getnameinfo = (getnameinfoProto)ws2lib.resolve("getnameinfo");
+ }
+
+ triedResolve = true;
}
#if defined(Q_OS_WINCE)
#include <qmutex.h>
-QMutex qPrivCEMutex;
+Q_GLOBAL_STATIC(QMutex, qPrivCEMutex)
#endif
QHostInfo QHostInfoAgent::fromName(const QString &hostName)
{
+ resolveLibrary();
+
#if defined(Q_OS_WINCE)
- QMutexLocker locker(&qPrivCEMutex);
+ QMutexLocker locker(qPrivCEMutex());
#endif
- QWindowsSockInit winSock;
- // Load res_init on demand.
- static volatile bool triedResolve = false;
- if (!triedResolve) {
- QMutexLocker locker(QMutexPool::globalInstanceGet(&local_getaddrinfo));
- if (!triedResolve) {
- resolveLibrary();
- triedResolve = true;
- }
- }
+ QWindowsSockInit winSock;
QHostInfo results;
diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp
index e8b96f6..a624468 100644
--- a/src/network/kernel/qnetworkinterface_win.cpp
+++ b/src/network/kernel/qnetworkinterface_win.cpp
@@ -63,23 +63,14 @@ static void resolveLibs()
{
// try to find the functions we need from Iphlpapi.dll
static bool done = false;
-
if (!done) {
+ QSystemLibrary iphlpapi(QLatin1String("iphlpapi"));
+ if (iphlpapi.load()) {
+ ptrGetAdaptersInfo = (PtrGetAdaptersInfo)iphlpapi.resolve("GetAdaptersInfo");
+ ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)iphlpapi.resolve("GetAdaptersAddresses");
+ ptrGetNetworkParams = (PtrGetNetworkParams)iphlpapi.resolve("GetNetworkParams");
+ }
done = true;
-
- HINSTANCE iphlpapiHnd = QSystemLibrary::load(L"iphlpapi");
- if (iphlpapiHnd == NULL)
- return;
-
-#if defined(Q_OS_WINCE)
- ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, L"GetAdaptersInfo");
- ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddress(iphlpapiHnd, L"GetAdaptersAddresses");
- ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddress(iphlpapiHnd, L"GetNetworkParams");
-#else
- ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, "GetAdaptersInfo");
- ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddress(iphlpapiHnd, "GetAdaptersAddresses");
- ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddress(iphlpapiHnd, "GetNetworkParams");
-#endif
}
}
diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp
index 71d61a4..4167b6d 100644
--- a/src/network/kernel/qnetworkproxy.cpp
+++ b/src/network/kernel/qnetworkproxy.cpp
@@ -1384,9 +1384,9 @@ void QNetworkProxyFactory::setApplicationProxyFactory(QNetworkProxyFactory *fact
SOCKS server for all queries. If SOCKS isn't enabled, it will use
the HTTPS proxy for all TcpSocket and UrlRequest queries.
- On other systems, there is no standardised method of obtaining the
- system proxy configuration. This function may be improved in
- future versions to support those systems.
+ On other systems, this function will pick up proxy settings from
+ the "http_proxy" environment variable. This variable must be a URL
+ using one of the following schemes: "http", "socks5" or "socks5h".
\section1 Limitations
diff --git a/src/network/kernel/qnetworkproxy_generic.cpp b/src/network/kernel/qnetworkproxy_generic.cpp
index e9eaee9..f78f63d 100644
--- a/src/network/kernel/qnetworkproxy_generic.cpp
+++ b/src/network/kernel/qnetworkproxy_generic.cpp
@@ -41,17 +41,44 @@
#include "qnetworkproxy.h"
+#include <QtCore/QByteArray>
+#include <QtCore/QUrl>
+
#ifndef QT_NO_NETWORKPROXY
/*
- * No system proxy. Just return a list with NoProxy.
+ * Construct a proxy from the environment variable http_proxy.
+ * Or no system proxy. Just return a list with NoProxy.
*/
QT_BEGIN_NAMESPACE
QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &)
{
- return QList<QNetworkProxy>() << QNetworkProxy::NoProxy;
+ QList<QNetworkProxy> proxyList;
+
+ QByteArray proxy_env = qgetenv("http_proxy");
+ if (!proxy_env.isEmpty()) {
+ QUrl url = QUrl(QString::fromLocal8Bit(proxy_env));
+ if (url.scheme() == QLatin1String("socks5")) {
+ QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, url.host(),
+ url.port() ? url.port() : 1080, url.userName(), url.password());
+ proxyList << proxy;
+ } else if (url.scheme() == QLatin1String("socks5h")) {
+ QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, url.host(),
+ url.port() ? url.port() : 1080, url.userName(), url.password());
+ proxy.setCapabilities(QNetworkProxy::HostNameLookupCapability);
+ proxyList << proxy;
+ } else if (url.scheme() == QLatin1String("http") || url.scheme().isEmpty()) {
+ QNetworkProxy proxy(QNetworkProxy::HttpProxy, url.host(),
+ url.port() ? url.port() : 8080, url.userName(), url.password());
+ proxyList << proxy;
+ }
+ }
+ if (proxyList.isEmpty())
+ proxyList << QNetworkProxy::NoProxy;
+
+ return proxyList;
}
QT_END_NAMESPACE
diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp
index 5c672ec..b62bc05 100644
--- a/src/network/socket/qhttpsocketengine.cpp
+++ b/src/network/socket/qhttpsocketengine.cpp
@@ -614,6 +614,10 @@ void QHttpSocketEngine::slotSocketReadNotification()
bool willClose;
QString proxyConnectionHeader = responseHeader.value(QLatin1String("Proxy-Connection"));
+ // Although most proxies use the unofficial Proxy-Connection header, the Connection header
+ // from http spec is also allowed.
+ if (proxyConnectionHeader.isEmpty())
+ proxyConnectionHeader = responseHeader.value(QLatin1String("Connection"));
proxyConnectionHeader = proxyConnectionHeader.toLower();
if (proxyConnectionHeader == QLatin1String("close")) {
willClose = true;
diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp
index 851e898..390712c 100644
--- a/src/network/socket/qlocalserver_unix.cpp
+++ b/src/network/socket/qlocalserver_unix.cpp
@@ -167,16 +167,16 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
*/
void QLocalServerPrivate::closeServer()
{
- if (-1 != listenSocket)
- QT_CLOSE(listenSocket);
- listenSocket = -1;
-
if (socketNotifier) {
socketNotifier->setEnabled(false); // Otherwise, closed socket is checked before deleter runs
socketNotifier->deleteLater();
socketNotifier = 0;
}
+ if (-1 != listenSocket)
+ QT_CLOSE(listenSocket);
+ listenSocket = -1;
+
if (!fullServerName.isEmpty())
QFile::remove(fullServerName);
}
diff --git a/src/network/ssl/qssl.cpp b/src/network/ssl/qssl.cpp
index 586c894..01297c9 100644
--- a/src/network/ssl/qssl.cpp
+++ b/src/network/ssl/qssl.cpp
@@ -120,4 +120,40 @@ QT_BEGIN_NAMESPACE
the correct setting for your protocol.
*/
+/*!
+ \enum QSsl::SslOption
+
+ Describes the options that can be used to control the details of
+ SSL behaviour. These options are generally used to turn features off
+ to work around buggy servers.
+
+ \value SslOptionDisableEmptyFragments Disables the insertion of empty
+ fragments into the data when using block ciphers. When enabled, this
+ prevents some attacks (such as the BEAST attack), however it is
+ incompatible with some servers.
+ \value SslOptionDisableSessionTickets Disables the SSL session ticket
+ extension. This can cause slower connection setup, however some servers
+ are not compatible with the extension.
+ \value SslOptionDisableCompression Disables the SSL compression
+ extension. When enabled, this allows the data being passed over SSL to
+ be compressed, however some servers are not compatible with this
+ extension.
+ \value SslOptionDisableServerNameIndication Disables the SSL server
+ name indication extension. When enabled, this tells the server the virtual
+ host being accessed allowing it to respond with the correct certificate.
+ \value SslOptionDisableLegacyRenegotiation Disables the older insecure
+ mechanism for renegotiating the connection parameters. When enabled, this
+ option can allow connections for legacy servers, but it introduces the
+ possibility that an attacker could inject plaintext into the SSL session.
+
+ By default, SslOptionDisableEmptyFragments is turned on since this causes
+ problems with a large number of servers. SslOptionDisableLegacyRenegotiation
+ is also turned on, since it introduces a security risk. The other options
+ are turned off.
+
+ Note: Availability of above options depends on the version of the SSL
+ backend in use.
+*/
+
+
QT_END_NAMESPACE
diff --git a/src/network/ssl/qssl.h b/src/network/ssl/qssl.h
index 2ecd1c3..571aa1f 100644
--- a/src/network/ssl/qssl.h
+++ b/src/network/ssl/qssl.h
@@ -44,6 +44,7 @@
#define QSSL_H
#include <QtCore/qglobal.h>
+#include <QtCore/QFlags>
QT_BEGIN_HEADER
@@ -81,8 +82,19 @@ namespace QSsl {
SecureProtocols,
UnknownProtocol = -1
};
+
+ enum SslOption {
+ SslOptionDisableEmptyFragments = 0x01,
+ SslOptionDisableSessionTickets = 0x02,
+ SslOptionDisableCompression = 0x04,
+ SslOptionDisableServerNameIndication = 0x08,
+ SslOptionDisableLegacyRenegotiation = 0x10
+ };
+ Q_DECLARE_FLAGS(SslOptions, SslOption)
}
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSsl::SslOptions)
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index 2a2ad55..85cd06c 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -814,6 +814,9 @@ static const char *certificate_blacklist[] = {
// "(has not been seen in the wild so far)", "Stichting TTP Infos CA," // compromised during DigiNotar breach
"1184640175", "DigiNotar Root CA", // DigiNotar intermediate cross-signed by Entrust
"1184644297", "DigiNotar Root CA", // DigiNotar intermediate cross-signed by Entrust
+
+ "120001705", "Digisign Server ID (Enrich)", // (Malaysian) Digicert Sdn. Bhd. cross-signed by Verizon CyberTrust
+ "1276011370", "Digisign Server ID - (Enrich)", // (Malaysian) Digicert Sdn. Bhd. cross-signed by Entrust
0
};
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index 69d3b66..727130b 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -167,7 +167,8 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
d->caCertificates == other.d->caCertificates &&
d->protocol == other.d->protocol &&
d->peerVerifyMode == other.d->peerVerifyMode &&
- d->peerVerifyDepth == other.d->peerVerifyDepth;
+ d->peerVerifyDepth == other.d->peerVerifyDepth &&
+ d->sslOptions == other.d->sslOptions;
}
/*!
@@ -199,7 +200,8 @@ bool QSslConfiguration::isNull() const
d->localCertificate.isNull() &&
d->privateKey.isNull() &&
d->peerCertificate.isNull() &&
- d->peerCertificateChain.count() == 0);
+ d->peerCertificateChain.count() == 0 &&
+ d->sslOptions == QSsl::SslOptionDisableEmptyFragments|QSsl::SslOptionDisableLegacyRenegotiation);
}
/*!
@@ -507,6 +509,29 @@ void QSslConfiguration::setCaCertificates(const QList<QSslCertificate> &certific
}
/*!
+ Enables or disables an SSL compatibility option.
+
+ \sa testSSlOption()
+*/
+void QSslConfiguration::setSslOption(QSsl::SslOption option, bool on)
+{
+ if (on)
+ d->sslOptions |= option;
+ else
+ d->sslOptions &= ~option;
+}
+
+/*!
+ Returns true if the specified SSL compatibility option is enabled.
+
+ \sa testSSlOption()
+*/
+bool QSslConfiguration::testSslOption(QSsl::SslOption option) const
+{
+ return d->sslOptions & option;
+}
+
+/*!
Returns the default SSL configuration to be used in new SSL
connections.
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index 258b454..ff8c8fc 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -59,6 +59,7 @@
#include <QtCore/qshareddata.h>
#include <QtNetwork/qsslsocket.h>
+#include <QtNetwork/qssl.h>
QT_BEGIN_HEADER
@@ -118,6 +119,9 @@ public:
QList<QSslCertificate> caCertificates() const;
void setCaCertificates(const QList<QSslCertificate> &certificates);
+ void setSslOption(QSsl::SslOption option, bool on);
+ bool testSslOption(QSsl::SslOption option) const;
+
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h
index af80e4c..a711eeb 100644
--- a/src/network/ssl/qsslconfiguration_p.h
+++ b/src/network/ssl/qsslconfiguration_p.h
@@ -82,7 +82,8 @@ public:
QSslConfigurationPrivate()
: protocol(QSsl::SecureProtocols),
peerVerifyMode(QSslSocket::AutoVerifyPeer),
- peerVerifyDepth(0)
+ peerVerifyDepth(0),
+ sslOptions(QSsl::SslOptionDisableEmptyFragments|QSsl::SslOptionDisableLegacyRenegotiation)
{ }
QSslCertificate peerCertificate;
@@ -98,6 +99,8 @@ public:
QSslSocket::PeerVerifyMode peerVerifyMode;
int peerVerifyDepth;
+ QSsl::SslOptions sslOptions;
+
// in qsslsocket.cpp:
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index df61fb6..3ac8f18 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -896,6 +896,7 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
d->configuration.peerVerifyDepth = configuration.peerVerifyDepth();
d->configuration.peerVerifyMode = configuration.peerVerifyMode();
d->configuration.protocol = configuration.protocol();
+ d->configuration.sslOptions = configuration.d->sslOptions;
d->allowRootCertOnDemandLoading = false;
}
@@ -2027,6 +2028,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
ptr->protocol = global->protocol;
ptr->peerVerifyMode = global->peerVerifyMode;
ptr->peerVerifyDepth = global->peerVerifyDepth;
+ ptr->sslOptions = global->sslOptions;
}
/*!
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 8e53974..5f520f7 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -285,12 +285,37 @@ init_context:
return false;
}
- // Enable all bug workarounds.
- if (configuration.protocol == QSsl::TlsV1SslV3 || configuration.protocol == QSsl::SecureProtocols) {
- q_SSL_CTX_set_options(ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2);
- } else {
- q_SSL_CTX_set_options(ctx, SSL_OP_ALL);
- }
+ // Enable bug workarounds.
+ long options;
+ if (configuration.protocol == QSsl::TlsV1SslV3 || configuration.protocol == QSsl::SecureProtocols)
+ options = SSL_OP_ALL|SSL_OP_NO_SSLv2;
+ else
+ options = SSL_OP_ALL;
+
+ // This option is disabled by default, so we need to be able to clear it
+ if (configuration.sslOptions & QSsl::SslOptionDisableEmptyFragments)
+ options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+ else
+ options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+
+#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
+ // This option is disabled by default, so we need to be able to clear it
+ if (configuration.sslOptions & QSsl::SslOptionDisableLegacyRenegotiation)
+ options &= ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
+ else
+ options |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
+#endif
+
+#ifdef SSL_OP_NO_TICKET
+ if (configuration.sslOptions & QSsl::SslOptionDisableSessionTickets)
+ options |= SSL_OP_NO_TICKET;
+#endif
+#ifdef SSL_OP_NO_COMPRESSION
+ if (configuration.sslOptions & QSsl::SslOptionDisableCompression)
+ options |= SSL_OP_NO_COMPRESSION;
+#endif
+
+ q_SSL_CTX_set_options(ctx, options);
// Initialize ciphers
QByteArray cipherString;
@@ -419,7 +444,9 @@ init_context:
tlsHostName = hostName;
QByteArray ace = QUrl::toAce(tlsHostName);
// only send the SNI header if the URL is valid and not an IP
- if (!ace.isEmpty() && !QHostAddress().setAddress(tlsHostName)) {
+ if (!ace.isEmpty()
+ && !QHostAddress().setAddress(tlsHostName)
+ && !(configuration.sslOptions & QSsl::SslOptionDisableServerNameIndication)) {
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
if (!q_SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, ace.data()))
#else