summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorShane Kearns <shane.kearns@accenture.com>2011-04-11 10:48:44 (GMT)
committerShane Kearns <shane.kearns@accenture.com>2011-04-11 10:48:44 (GMT)
commit1062da14facb7dd10f0928a4c242549d3626f9ba (patch)
tree4462fcaa82b45c47eddcdcb1d89e1cc03de45a85 /src/network
parent847df81a5680fe4d71196d0afe5e68e41ae49700 (diff)
parentdd60cf7ba8afdf5c84f5793c1e1d08ab18303a74 (diff)
downloadQt-1062da14facb7dd10f0928a4c242549d3626f9ba.zip
Qt-1062da14facb7dd10f0928a4c242549d3626f9ba.tar.gz
Qt-1062da14facb7dd10f0928a4c242549d3626f9ba.tar.bz2
Merge branch 'master' of scm.dev.troll.no:qt/qt-earth-team into symbian-socket-engine
Conflicts: src/s60installs/bwins/QtCoreu.def src/s60installs/bwins/QtGuiu.def src/s60installs/bwins/QtNetworku.def src/s60installs/eabi/QtCoreu.def src/s60installs/eabi/QtGuiu.def src/s60installs/eabi/QtNetworku.def src/s60installs/eabi/QtOpenVGu.def tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp
Diffstat (limited to 'src/network')
-rw-r--r--src/network/access/qftp.cpp4
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp5
-rw-r--r--src/network/access/qnetworkaccesshttpbackend.cpp45
-rw-r--r--src/network/access/qnetworkaccesshttpbackend_p.h2
-rw-r--r--src/network/access/qnetworkdiskcache.cpp82
-rw-r--r--src/network/access/qnetworkdiskcache_p.h5
-rw-r--r--src/network/bearer/qsharednetworksession_p.h2
-rw-r--r--src/network/socket/qabstractsocketengine_p.h6
-rw-r--r--src/network/socket/qhttpsocketengine.cpp2
-rw-r--r--src/network/socket/qhttpsocketengine_p.h2
-rw-r--r--src/network/socket/qlocalsocket_win.cpp10
-rw-r--r--src/network/socket/qnativesocketengine.cpp5
-rw-r--r--src/network/socket/qnativesocketengine_p.h6
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp3
-rw-r--r--src/network/socket/qsocks5socketengine.cpp2
-rw-r--r--src/network/socket/qsocks5socketengine_p.h2
-rw-r--r--src/network/socket/qudpsocket.cpp4
-rw-r--r--src/network/socket/qudpsocket.h2
-rw-r--r--src/network/ssl/qsslcertificate.cpp34
-rw-r--r--src/network/ssl/qsslcertificate_p.h1
-rw-r--r--src/network/ssl/qsslconfiguration.cpp44
-rw-r--r--src/network/ssl/qsslconfiguration.h2
-rw-r--r--src/network/ssl/qsslerror.cpp4
-rw-r--r--src/network/ssl/qsslerror.h1
-rw-r--r--src/network/ssl/qsslsocket.cpp11
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp9
26 files changed, 209 insertions, 86 deletions
diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp
index 45fc11f..4ff45ba 100644
--- a/src/network/access/qftp.cpp
+++ b/src/network/access/qftp.cpp
@@ -371,9 +371,9 @@ qint64 QFtpDTP::read(char *data, qint64 maxlen)
if (socket && socket->state() == QTcpSocket::ConnectedState) {
read = socket->read(data, maxlen);
} else {
- read = bytesFromSocket.size();
+ read = qMin(maxlen, qint64(bytesFromSocket.size()));
memcpy(data, bytesFromSocket.data(), read);
- bytesFromSocket.clear();
+ bytesFromSocket.remove(0, read);
}
bytesDone += read;
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 73277e3..7a17a7f 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -79,6 +79,11 @@ static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const
code = QNetworkReply::ProxyAuthenticationRequiredError;
break;
+ case 418: // I'm a teapot
+ code = QNetworkReply::ProtocolInvalidOperationError;
+ break;
+
+
default:
if (httpStatusCode > 500) {
// some kind of server error
diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp
index 8016ef4..b0ca9e0 100644
--- a/src/network/access/qnetworkaccesshttpbackend.cpp
+++ b/src/network/access/qnetworkaccesshttpbackend.cpp
@@ -220,7 +220,7 @@ QNetworkAccessHttpBackend::~QNetworkAccessHttpBackend()
2) If we have a cache entry for this url populate headers so the server can return 304
3) Calculate if response_is_fresh and if so send the cache and set loadedFromCache to true
*/
-void QNetworkAccessHttpBackend::validateCache(QHttpNetworkRequest &httpRequest, bool &loadedFromCache)
+bool QNetworkAccessHttpBackend::loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest)
{
QNetworkRequest::CacheLoadControl CacheLoadControlAttribute =
(QNetworkRequest::CacheLoadControl)request().attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt();
@@ -231,24 +231,24 @@ void QNetworkAccessHttpBackend::validateCache(QHttpNetworkRequest &httpRequest,
httpRequest.setHeaderField("Cache-Control", "no-cache");
httpRequest.setHeaderField("Pragma", "no-cache");
}
- return;
+ return false;
}
// The disk cache API does not currently support partial content retrieval.
// That is why we don't use the disk cache for any such requests.
if (request().hasRawHeader("Range"))
- return;
+ return false;
QAbstractNetworkCache *nc = networkCache();
if (!nc)
- return; // no local cache
+ return false; // no local cache
QNetworkCacheMetaData metaData = nc->metaData(url());
if (!metaData.isValid())
- return; // not in cache
+ return false; // not in cache
if (!metaData.saveToDisk())
- return;
+ return false;
QNetworkHeadersPrivate cacheHeaders;
QNetworkHeadersPrivate::RawHeadersList::ConstIterator it;
@@ -263,11 +263,16 @@ void QNetworkAccessHttpBackend::validateCache(QHttpNetworkRequest &httpRequest,
httpRequest.setHeaderField("If-Modified-Since", QNetworkHeadersPrivate::toHttpDate(lastModified));
if (CacheLoadControlAttribute == QNetworkRequest::PreferNetwork) {
+ // PreferNetwork == send request with "If-None-Match" and "If-Modified-Since" header,
+ // which will return a 304 Not Modifed if resource has not been changed.
+ // We might read from cache later, if receiving a 304.
+ return false;
+ } else if (CacheLoadControlAttribute == QNetworkRequest::PreferCache) {
it = cacheHeaders.findRawHeader("Cache-Control");
if (it != cacheHeaders.rawHeaders.constEnd()) {
QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second);
if (cacheControl.contains("must-revalidate"))
- return;
+ return false;
}
}
@@ -339,14 +344,12 @@ void QNetworkAccessHttpBackend::validateCache(QHttpNetworkRequest &httpRequest,
#endif
if (!response_is_fresh)
- return;
+ return false;
- loadedFromCache = true;
#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
qDebug() << "response_is_fresh" << CacheLoadControlAttribute;
#endif
- if (!sendCacheContents(metaData))
- loadedFromCache = false;
+ return sendCacheContents(metaData);
}
static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio)
@@ -443,12 +446,12 @@ void QNetworkAccessHttpBackend::postRequest()
switch (operation()) {
case QNetworkAccessManager::GetOperation:
httpRequest.setOperation(QHttpNetworkRequest::Get);
- validateCache(httpRequest, loadedFromCache);
+ loadedFromCache = loadFromCacheIfAllowed(httpRequest);
break;
case QNetworkAccessManager::HeadOperation:
httpRequest.setOperation(QHttpNetworkRequest::Head);
- validateCache(httpRequest, loadedFromCache);
+ loadedFromCache = loadFromCacheIfAllowed(httpRequest);
break;
case QNetworkAccessManager::PostOperation:
@@ -480,6 +483,13 @@ void QNetworkAccessHttpBackend::postRequest()
break; // can't happen
}
+ if (loadedFromCache) {
+ // commented this out since it will be called later anyway
+ // by copyFinished()
+ //QNetworkAccessBackend::finished();
+ return; // no need to send the request! :)
+ }
+
QList<QByteArray> headers = request().rawHeaderList();
if (resumeOffset != 0) {
if (headers.contains("Range")) {
@@ -507,13 +517,6 @@ void QNetworkAccessHttpBackend::postRequest()
foreach (const QByteArray &header, headers)
httpRequest.setHeaderField(header, request().rawHeader(header));
- if (loadedFromCache) {
- // commented this out since it will be called later anyway
- // by copyFinished()
- //QNetworkAccessBackend::finished();
- return; // no need to send the request! :)
- }
-
if (request().attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true)
httpRequest.setPipeliningAllowed(true);
@@ -1153,7 +1156,7 @@ QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetwo
attributes.insert(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
attributes.insert(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase);
} else {
- // this is a redirection, keep the attributes intact
+ // this is the server telling us the resource has not changed, keep the attributes intact
attributes = oldMetaData.attributes();
}
metaData.setAttributes(attributes);
diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h
index 712dd2f..4778bd0 100644
--- a/src/network/access/qnetworkaccesshttpbackend_p.h
+++ b/src/network/access/qnetworkaccesshttpbackend_p.h
@@ -148,7 +148,7 @@ private:
quint64 resumeOffset;
- void validateCache(QHttpNetworkRequest &httpRequest, bool &loadedFromCache);
+ bool loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest);
void invalidateCache();
void postRequest();
void readFromHttp();
diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp
index 2040b01..271494d 100644
--- a/src/network/access/qnetworkdiskcache.cpp
+++ b/src/network/access/qnetworkdiskcache.cpp
@@ -50,13 +50,15 @@
#include <qdir.h>
#include <qdatetime.h>
#include <qdiriterator.h>
-#include <qcryptographichash.h>
#include <qurl.h>
-
+#include <qcryptographichash.h>
#include <qdebug.h>
-#define CACHE_PREFIX QLatin1String("cache_")
-#define CACHE_POSTFIX QLatin1String(".cache")
+#define CACHE_POSTFIX QLatin1String(".d")
+#define PREPARED_SLASH QLatin1String("prepared/")
+#define CACHE_VERSION 7
+#define DATA_DIR QLatin1String("data")
+
#define MAX_COMPRESSION_SIZE (1024 * 1024 * 3)
#ifndef QT_NO_NETWORKDISKCACHE
@@ -153,6 +155,9 @@ void QNetworkDiskCache::setCacheDirectory(const QString &cacheDir)
d->cacheDirectory = dir.absolutePath();
if (!d->cacheDirectory.endsWith(QLatin1Char('/')))
d->cacheDirectory += QLatin1Char('/');
+
+ d->dataDirectory = d->cacheDirectory + DATA_DIR + QString::number(CACHE_VERSION) + QLatin1Char('/');
+ d->prepareLayout();
}
/*!
@@ -244,6 +249,26 @@ void QNetworkDiskCache::insert(QIODevice *device)
d->inserting.erase(it);
}
+
+/*!
+ Create subdirectories and other housekeeping on the filesystem.
+ Prevents too many files from being present in any single directory.
+*/
+void QNetworkDiskCachePrivate::prepareLayout()
+{
+ QDir helper;
+ helper.mkpath(cacheDirectory + PREPARED_SLASH);
+
+ //Create directory and subdirectories 0-F
+ helper.mkpath(dataDirectory);
+ for (uint i = 0; i < 16 ; i++) {
+ QString str = QString::number(i, 16);
+ QString subdir = dataDirectory + str;
+ helper.mkdir(subdir);
+ }
+}
+
+
void QNetworkDiskCachePrivate::storeItem(QCacheItem *cacheItem)
{
Q_Q(QNetworkDiskCache);
@@ -324,7 +349,7 @@ bool QNetworkDiskCachePrivate::removeFile(const QString &file)
return false;
QFileInfo info(file);
QString fileName = info.fileName();
- if (!fileName.endsWith(CACHE_POSTFIX) || !fileName.startsWith(CACHE_PREFIX))
+ if (!fileName.endsWith(CACHE_POSTFIX))
return false;
qint64 size = info.size();
if (QFile::remove(file)) {
@@ -508,6 +533,9 @@ qint64 QNetworkDiskCache::expire()
return 0;
}
+ // close file handle to prevent "in use" error when QFile::remove() is called
+ d->lastItem.reset();
+
QDir::Filters filters = QDir::AllDirs | QDir:: Files | QDir::NoDotAndDotDot;
QDirIterator it(cacheDirectory(), filters, QDirIterator::Subdirectories);
@@ -517,7 +545,7 @@ qint64 QNetworkDiskCache::expire()
QString path = it.next();
QFileInfo info = it.fileInfo();
QString fileName = info.fileName();
- if (fileName.endsWith(CACHE_POSTFIX) && fileName.startsWith(CACHE_PREFIX)) {
+ if (fileName.endsWith(CACHE_POSTFIX)) {
cacheItems.insert(info.created(), path);
totalSize += info.size();
}
@@ -544,8 +572,6 @@ qint64 QNetworkDiskCache::expire()
<< "Kept:" << cacheItems.count() - removedFiles;
}
#endif
- if (removedFiles > 0)
- d->lastItem.reset();
return totalSize;
}
@@ -564,7 +590,10 @@ void QNetworkDiskCache::clear()
d->maximumCacheSize = size;
}
-QByteArray QNetworkDiskCachePrivate::generateId(const QUrl &url) const
+/*!
+ Given a URL, generates a unique enough filename (and subdirectory)
+ */
+QString QNetworkDiskCachePrivate::uniqueFileName(const QUrl &url)
{
QUrl cleanUrl = url;
cleanUrl.setPassword(QString());
@@ -572,29 +601,32 @@ QByteArray QNetworkDiskCachePrivate::generateId(const QUrl &url) const
QCryptographicHash hash(QCryptographicHash::Sha1);
hash.addData(cleanUrl.toEncoded());
- return hash.result().toHex();
+ // convert sha1 to base36 form and return first 8 bytes for use as string
+ QByteArray id = QByteArray::number(*(qlonglong*)hash.result().data(), 36).left(8);
+ // generates <one-char subdir>/<8-char filname.d>
+ uint code = (uint)id.at(id.length()-1) % 16;
+ QString pathFragment = QString::number(code, 16) + QLatin1Char('/')
+ + QLatin1String(id) + CACHE_POSTFIX;
+
+ return pathFragment;
}
QString QNetworkDiskCachePrivate::tmpCacheFileName() const
{
- QDir dir;
- dir.mkpath(cacheDirectory + QLatin1String("prepared/"));
- return cacheDirectory + QLatin1String("prepared/") + CACHE_PREFIX + QLatin1String("XXXXXX") + CACHE_POSTFIX;
+ //The subdirectory is presumed to be already read for use.
+ return cacheDirectory + PREPARED_SLASH + QLatin1String("XXXXXX") + CACHE_POSTFIX;
}
+/*!
+ Generates fully qualified path of cached resource from a URL.
+ */
QString QNetworkDiskCachePrivate::cacheFileName(const QUrl &url) const
{
if (!url.isValid())
return QString();
- QString directory = cacheDirectory + url.scheme() + QLatin1Char('/');
- if (!QFile::exists(directory)) {
- // ### make a static QDir function for this...
- QDir dir;
- dir.mkpath(directory);
- }
- QString fileName = CACHE_PREFIX + QLatin1String(generateId(url)) + CACHE_POSTFIX;
- return directory + fileName;
+ QString fullpath = dataDirectory + uniqueFileName(url);
+ return fullpath;
}
/*!
@@ -631,7 +663,7 @@ bool QCacheItem::canCompress() const
enum
{
CacheMagic = 0xe8,
- CurrentCacheVersion = 7
+ CurrentCacheVersion = CACHE_VERSION
};
void QCacheItem::writeHeader(QFile *device) const
@@ -682,6 +714,12 @@ bool QCacheItem::read(QFile *device, bool readData)
data.setData(qUncompress(dataBA));
data.open(QBuffer::ReadOnly);
}
+
+ // quick and dirty check if metadata's URL field and the file's name are in synch
+ QString expectedFilename = QNetworkDiskCachePrivate::uniqueFileName(metaData.url());
+ if (!device->fileName().endsWith(expectedFilename))
+ return false;
+
return metaData.isValid();
}
diff --git a/src/network/access/qnetworkdiskcache_p.h b/src/network/access/qnetworkdiskcache_p.h
index 8659066..13db04f 100644
--- a/src/network/access/qnetworkdiskcache_p.h
+++ b/src/network/access/qnetworkdiskcache_p.h
@@ -104,14 +104,17 @@ public:
, currentCacheSize(-1)
{}
- QByteArray generateId(const QUrl &url) const;
+ static QString uniqueFileName(const QUrl &url);
QString cacheFileName(const QUrl &url) const;
QString tmpCacheFileName() const;
bool removeFile(const QString &file);
void storeItem(QCacheItem *item);
+ void prepareLayout();
+ static quint32 crc32(const char *data, uint len);
mutable QCacheItem lastItem;
QString cacheDirectory;
+ QString dataDirectory;
qint64 maximumCacheSize;
qint64 currentCacheSize;
diff --git a/src/network/bearer/qsharednetworksession_p.h b/src/network/bearer/qsharednetworksession_p.h
index 57b3a49..25b4ec2 100644
--- a/src/network/bearer/qsharednetworksession_p.h
+++ b/src/network/bearer/qsharednetworksession_p.h
@@ -64,6 +64,8 @@
QT_BEGIN_NAMESPACE
+uint qHash(const QNetworkConfiguration& config);
+
class QSharedNetworkSessionManager
{
public:
diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h
index c00b6d7..ee6dad6 100644
--- a/src/network/socket/qabstractsocketengine_p.h
+++ b/src/network/socket/qabstractsocketengine_p.h
@@ -61,7 +61,9 @@ QT_BEGIN_NAMESPACE
class QAuthenticator;
class QAbstractSocketEnginePrivate;
+#ifndef QT_NO_NETWORKINTERFACE
class QNetworkInterface;
+#endif
class QNetworkProxy;
class QAbstractSocketEngineReceiver {
@@ -121,12 +123,14 @@ public:
virtual qint64 write(const char *data, qint64 len) = 0;
#ifndef QT_NO_UDPSOCKET
+#ifndef QT_NO_NETWORKINTERFACE
virtual bool joinMulticastGroup(const QHostAddress &groupAddress,
const QNetworkInterface &iface) = 0;
virtual bool leaveMulticastGroup(const QHostAddress &groupAddress,
const QNetworkInterface &iface) = 0;
virtual QNetworkInterface multicastInterface() const = 0;
virtual bool setMulticastInterface(const QNetworkInterface &iface) = 0;
+#endif // QT_NO_NETWORKINTERFACE
virtual qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0,
quint16 *port = 0) = 0;
@@ -134,7 +138,7 @@ public:
quint16 port) = 0;
virtual bool hasPendingDatagrams() const = 0;
virtual qint64 pendingDatagramSize() const = 0;
-#endif
+#endif // QT_NO_UDPSOCKET
virtual qint64 bytesToWrite() const = 0;
diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp
index c580b03..7846056 100644
--- a/src/network/socket/qhttpsocketengine.cpp
+++ b/src/network/socket/qhttpsocketengine.cpp
@@ -243,6 +243,7 @@ qint64 QHttpSocketEngine::write(const char *data, qint64 len)
}
#ifndef QT_NO_UDPSOCKET
+#ifndef QT_NO_NETWORKINTERFACE
bool QHttpSocketEngine::joinMulticastGroup(const QHostAddress &,
const QNetworkInterface &)
{
@@ -270,6 +271,7 @@ bool QHttpSocketEngine::setMulticastInterface(const QNetworkInterface &)
QLatin1String("Operation on socket is not supported"));
return false;
}
+#endif // QT_NO_NETWORKINTERFACE
qint64 QHttpSocketEngine::readDatagram(char *, qint64, QHostAddress *,
quint16 *)
diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h
index 2ecd708..361ef5c 100644
--- a/src/network/socket/qhttpsocketengine_p.h
+++ b/src/network/socket/qhttpsocketengine_p.h
@@ -102,12 +102,14 @@ public:
qint64 write(const char *data, qint64 len);
#ifndef QT_NO_UDPSOCKET
+#ifndef QT_NO_NETWORKINTERFACE
bool joinMulticastGroup(const QHostAddress &groupAddress,
const QNetworkInterface &interface);
bool leaveMulticastGroup(const QHostAddress &groupAddress,
const QNetworkInterface &interface);
QNetworkInterface multicastInterface() const;
bool setMulticastInterface(const QNetworkInterface &iface);
+#endif // QT_NO_NETWORKINTERFACE
qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0,
quint16 *port = 0);
diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp
index 7bbe275..14f5af8 100644
--- a/src/network/socket/qlocalsocket_win.cpp
+++ b/src/network/socket/qlocalsocket_win.cpp
@@ -79,6 +79,11 @@ void QLocalSocketPrivate::setErrorString(const QString &function)
errorString = QLocalSocket::tr("%1: Invalid name").arg(function);
state = QLocalSocket::UnconnectedState;
break;
+ case ERROR_ACCESS_DENIED:
+ error = QLocalSocket::SocketAccessError;
+ errorString = QLocalSocket::tr("%1: Access denied").arg(function);
+ state = QLocalSocket::UnconnectedState;
+ break;
default:
error = QLocalSocket::UnknownSocketError;
errorString = QLocalSocket::tr("%1: Unknown error %2").arg(function).arg(windowsError);
@@ -348,6 +353,11 @@ qint64 QLocalSocket::writeData(const char *data, qint64 maxSize)
void QLocalSocket::abort()
{
+ Q_D(QLocalSocket);
+ if (d->pipeWriter) {
+ delete d->pipeWriter;
+ d->pipeWriter = 0;
+ }
close();
}
diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp
index efa4f6f..f5a88e2 100644
--- a/src/network/socket/qnativesocketengine.cpp
+++ b/src/network/socket/qnativesocketengine.cpp
@@ -646,6 +646,8 @@ int QNativeSocketEngine::accept()
return d->nativeAccept();
}
+#ifndef QT_NO_NETWORKINTERFACE
+
/*!
\since 4.8
*/
@@ -681,7 +683,6 @@ QNetworkInterface QNativeSocketEngine::multicastInterface() const
return d->nativeMulticastInterface();
}
-
/*! \since 4.8 */
bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface)
{
@@ -691,6 +692,8 @@ bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface)
return d->nativeSetMulticastInterface(iface);
}
+#endif // QT_NO_NETWORKINTERFACE
+
/*!
Returns the number of bytes that are currently available for
reading. On error, -1 is returned.
diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index a186911..35054fb 100644
--- a/src/network/socket/qnativesocketengine_p.h
+++ b/src/network/socket/qnativesocketengine_p.h
@@ -96,7 +96,9 @@ union qt_sockaddr {
};
class QNativeSocketEnginePrivate;
+#ifndef QT_NO_NETWORKINTERFACE
class QNetworkInterface;
+#endif
class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine
{
@@ -119,12 +121,14 @@ public:
int accept();
void close();
+#ifndef QT_NO_NETWORKINTERFACE
bool joinMulticastGroup(const QHostAddress &groupAddress,
const QNetworkInterface &iface);
bool leaveMulticastGroup(const QHostAddress &groupAddress,
const QNetworkInterface &iface);
QNetworkInterface multicastInterface() const;
bool setMulticastInterface(const QNetworkInterface &iface);
+#endif
qint64 bytesAvailable() const;
@@ -240,12 +244,14 @@ public:
bool nativeBind(const QHostAddress &address, quint16 port);
bool nativeListen(int backlog);
int nativeAccept();
+#ifndef QT_NO_NETWORKINTERFACE
bool nativeJoinMulticastGroup(const QHostAddress &groupAddress,
const QNetworkInterface &iface);
bool nativeLeaveMulticastGroup(const QHostAddress &groupAddress,
const QNetworkInterface &iface);
QNetworkInterface nativeMulticastInterface() const;
bool nativeSetMulticastInterface(const QNetworkInterface &iface);
+#endif
qint64 nativeBytesAvailable() const;
bool nativeHasPendingDatagrams() const;
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 3d850a1..4318427 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -591,6 +591,7 @@ int QNativeSocketEnginePrivate::nativeAccept()
return acceptedDescriptor;
}
+#ifndef QT_NO_NETWORKINTERFACE
static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d,
int how6,
@@ -756,6 +757,8 @@ bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInter
return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, sizeof(v)) != -1);
}
+#endif // QT_NO_NETWORKINTERFACE
+
qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
{
int nbytes = 0;
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index 16c0faa..c365635 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -1554,6 +1554,7 @@ qint64 QSocks5SocketEngine::write(const char *data, qint64 len)
}
#ifndef QT_NO_UDPSOCKET
+#ifndef QT_NO_NETWORKINTERFACE
bool QSocks5SocketEngine::joinMulticastGroup(const QHostAddress &,
const QNetworkInterface &)
{
@@ -1582,6 +1583,7 @@ bool QSocks5SocketEngine::setMulticastInterface(const QNetworkInterface &)
QLatin1String("Operation on socket is not supported"));
return false;
}
+#endif // QT_NO_NETWORKINTERFACE
qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr,
quint16 *port)
diff --git a/src/network/socket/qsocks5socketengine_p.h b/src/network/socket/qsocks5socketengine_p.h
index b85fd62..9492d45 100644
--- a/src/network/socket/qsocks5socketengine_p.h
+++ b/src/network/socket/qsocks5socketengine_p.h
@@ -92,12 +92,14 @@ public:
qint64 write(const char *data, qint64 len);
#ifndef QT_NO_UDPSOCKET
+#ifndef QT_NO_NETWORKINTERFACE
bool joinMulticastGroup(const QHostAddress &groupAddress,
const QNetworkInterface &interface);
bool leaveMulticastGroup(const QHostAddress &groupAddress,
const QNetworkInterface &interface);
QNetworkInterface multicastInterface() const;
bool setMulticastInterface(const QNetworkInterface &iface);
+#endif // QT_NO_NETWORKINTERFACE
qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0,
quint16 *port = 0);
diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp
index dc473c6..f8bcd1b 100644
--- a/src/network/socket/qudpsocket.cpp
+++ b/src/network/socket/qudpsocket.cpp
@@ -338,6 +338,8 @@ bool QUdpSocket::bind(quint16 port, BindMode mode)
return bind(QHostAddress::Any, port, mode);
}
+#ifndef QT_NO_NETWORKINTERFACE
+
/*!
\since 4.8
@@ -444,6 +446,8 @@ void QUdpSocket::setMulticastInterface(const QNetworkInterface &iface)
d->socketEngine->setMulticastInterface(iface);
}
+#endif // QT_NO_NETWORKINTERFACE
+
/*!
Returns true if at least one datagram is waiting to be read;
otherwise returns false.
diff --git a/src/network/socket/qudpsocket.h b/src/network/socket/qudpsocket.h
index 82266cb..7502349 100644
--- a/src/network/socket/qudpsocket.h
+++ b/src/network/socket/qudpsocket.h
@@ -77,6 +77,7 @@ public:
bool bind(quint16 port, BindMode mode);
// ### Qt 5: Merge the bind functions
+#ifndef QT_NO_NETWORKINTERFACE
bool joinMulticastGroup(const QHostAddress &groupAddress);
bool joinMulticastGroup(const QHostAddress &groupAddress,
const QNetworkInterface &iface);
@@ -86,6 +87,7 @@ public:
QNetworkInterface multicastInterface() const;
void setMulticastInterface(const QNetworkInterface &iface);
+#endif
bool hasPendingDatagrams() const;
qint64 pendingDatagramSize() const;
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index 618ac79..a5cdf01 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -219,17 +219,19 @@ bool QSslCertificate::isNull() const
Returns true if this certificate is valid; otherwise returns
false.
- Note: Currently, this function only checks that the current
+ Note: Currently, this function checks that the current
data-time is within the date-time range during which the
- certificate is considered valid. No other checks are
- currently performed.
+ certificate is considered valid, and checks that the
+ certificate is not in a blacklist of fraudulent certificates.
\sa isNull()
*/
bool QSslCertificate::isValid() const
{
const QDateTime currentTime = QDateTime::currentDateTime();
- return currentTime >= d->notValidBefore && currentTime <= d->notValidAfter;
+ return currentTime >= d->notValidBefore &&
+ currentTime <= d->notValidAfter &&
+ ! QSslCertificatePrivate::isBlacklisted(*this);
}
/*!
@@ -798,6 +800,30 @@ QList<QSslCertificate> QSslCertificatePrivate::certificatesFromDer(const QByteAr
return certificates;
}
+// These certificates are known to be fraudulent and were created during the comodo
+// compromise. See http://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html
+static const char *certificate_blacklist[] = {
+ "04:7e:cb:e9:fc:a5:5f:7b:d0:9e:ae:36:e1:0c:ae:1e",
+ "f5:c8:6a:f3:61:62:f1:3a:64:f5:4f:6d:c9:58:7c:06",
+ "d7:55:8f:da:f5:f1:10:5b:b2:13:28:2b:70:77:29:a3",
+ "39:2a:43:4f:0e:07:df:1f:8a:a3:05:de:34:e0:c2:29",
+ "3e:75:ce:d4:6b:69:30:21:21:88:30:ae:86:a8:2a:71",
+ "e9:02:8b:95:78:e4:15:dc:1a:71:0a:2b:88:15:44:47",
+ "92:39:d5:34:8f:40:d1:69:5a:74:54:70:e1:f2:3f:43",
+ "b0:b7:13:3e:d0:96:f9:b5:6f:ae:91:c8:74:bd:3a:c0",
+ "d8:f3:5f:4e:b7:87:2b:2d:ab:06:92:e3:15:38:2f:b0",
+ 0
+};
+
+bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate)
+{
+ for (int a = 0; certificate_blacklist[a] != 0; a++) {
+ if (certificate.serialNumber() == certificate_blacklist[a])
+ return true;
+ }
+ return false;
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QSslCertificate &certificate)
{
diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h
index cdceb0f..1ce33d3 100644
--- a/src/network/ssl/qsslcertificate_p.h
+++ b/src/network/ssl/qsslcertificate_p.h
@@ -96,6 +96,7 @@ public:
static QSslCertificate QSslCertificate_from_X509(X509 *x509);
static QList<QSslCertificate> certificatesFromPem(const QByteArray &pem, int count = -1);
static QList<QSslCertificate> certificatesFromDer(const QByteArray &der, int count = -1);
+ static bool isBlacklisted(const QSslCertificate &certificate);
friend class QSslSocketBackendPrivate;
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index 150f77e..c8dbaed 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -47,18 +47,6 @@
QT_BEGIN_NAMESPACE
-template<> void QSharedDataPointer<QSslConfigurationPrivate>::detach()
-{
- if (d && d->ref == 1)
- return;
- QSslConfigurationPrivate *x = (d ? new QSslConfigurationPrivate(*d)
- : new QSslConfigurationPrivate);
- x->ref.ref();
- if (d && !d->ref.deref())
- delete d;
- d = x;
-}
-
/*!
\class QSslConfiguration
\brief The QSslConfiguration class holds the configuration and state of an SSL connection
@@ -126,7 +114,7 @@ template<> void QSharedDataPointer<QSslConfigurationPrivate>::detach()
Once any setter methods are called, isNull() will return false.
*/
QSslConfiguration::QSslConfiguration()
- : d(0)
+ : d(new QSslConfigurationPrivate)
{
}
@@ -203,7 +191,15 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
*/
bool QSslConfiguration::isNull() const
{
- return d == 0;
+ return (d->protocol == QSsl::SecureProtocols &&
+ d->peerVerifyMode == QSslSocket::AutoVerifyPeer &&
+ d->peerVerifyDepth == 0 &&
+ d->caCertificates.count() == 0 &&
+ d->ciphers.count() == 0 &&
+ d->localCertificate.isNull() &&
+ d->privateKey.isNull() &&
+ d->peerCertificate.isNull() &&
+ d->peerCertificateChain.count() == 0);
}
/*!
@@ -213,7 +209,7 @@ bool QSslConfiguration::isNull() const
*/
QSsl::SslProtocol QSslConfiguration::protocol() const
{
- return d ? d->protocol : QSsl::SecureProtocols;
+ return d->protocol;
}
/*!
@@ -243,7 +239,7 @@ void QSslConfiguration::setProtocol(QSsl::SslProtocol protocol)
*/
QSslSocket::PeerVerifyMode QSslConfiguration::peerVerifyMode() const
{
- return d ? d->peerVerifyMode : QSslSocket::AutoVerifyPeer;
+ return d->peerVerifyMode;
}
/*!
@@ -276,7 +272,7 @@ void QSslConfiguration::setPeerVerifyMode(QSslSocket::PeerVerifyMode mode)
*/
int QSslConfiguration::peerVerifyDepth() const
{
- return d ? d->peerVerifyDepth : 0;
+ return d->peerVerifyDepth;
}
/*!
@@ -307,7 +303,7 @@ void QSslConfiguration::setPeerVerifyDepth(int depth)
*/
QSslCertificate QSslConfiguration::localCertificate() const
{
- return d ? d->localCertificate : QSslCertificate();
+ return d->localCertificate;
}
/*!
@@ -361,7 +357,7 @@ void QSslConfiguration::setLocalCertificate(const QSslCertificate &certificate)
*/
QSslCertificate QSslConfiguration::peerCertificate() const
{
- return d ? d->peerCertificate : QSslCertificate();
+ return d->peerCertificate;
}
/*!
@@ -393,7 +389,7 @@ QSslCertificate QSslConfiguration::peerCertificate() const
*/
QList<QSslCertificate> QSslConfiguration::peerCertificateChain() const
{
- return d ? d->peerCertificateChain : QList<QSslCertificate>();
+ return d->peerCertificateChain;
}
/*!
@@ -411,7 +407,7 @@ QList<QSslCertificate> QSslConfiguration::peerCertificateChain() const
*/
QSslCipher QSslConfiguration::sessionCipher() const
{
- return d ? d->sessionCipher : QSslCipher();
+ return d->sessionCipher;
}
/*!
@@ -422,7 +418,7 @@ QSslCipher QSslConfiguration::sessionCipher() const
*/
QSslKey QSslConfiguration::privateKey() const
{
- return d ? d->privateKey : QSslKey();
+ return d->privateKey;
}
/*!
@@ -464,7 +460,7 @@ void QSslConfiguration::setPrivateKey(const QSslKey &key)
*/
QList<QSslCipher> QSslConfiguration::ciphers() const
{
- return d ? d->ciphers : QList<QSslCipher>();
+ return d->ciphers;
}
/*!
@@ -494,7 +490,7 @@ void QSslConfiguration::setCiphers(const QList<QSslCipher> &ciphers)
*/
QList<QSslCertificate> QSslConfiguration::caCertificates() const
{
- return d ? d->caCertificates : QList<QSslCertificate>();
+ return d->caCertificates;
}
/*!
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index 69dd145..143566b 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -86,7 +86,7 @@ public:
inline bool operator!=(const QSslConfiguration &other) const
{ return !(*this == other); }
- bool isNull() const;
+ bool isNull() const; // ### Qt 5: remove; who would need this?
QSsl::SslProtocol protocol() const;
void setProtocol(QSsl::SslProtocol protocol);
diff --git a/src/network/ssl/qsslerror.cpp b/src/network/ssl/qsslerror.cpp
index 198b1f5..ae18b47 100644
--- a/src/network/ssl/qsslerror.cpp
+++ b/src/network/ssl/qsslerror.cpp
@@ -86,6 +86,7 @@
\value HostNameMismatch
\value UnspecifiedError
\value NoSslSupport
+ \value CertificateBlacklisted
\sa QSslError::errorString()
*/
@@ -281,6 +282,9 @@ QString QSslError::errorString() const
break;
case NoSslSupport:
break;
+ case CertificateBlacklisted:
+ errStr = QSslSocket::tr("The peer certificate is blacklisted");
+ break;
default:
errStr = QSslSocket::tr("Unknown error");
break;
diff --git a/src/network/ssl/qsslerror.h b/src/network/ssl/qsslerror.h
index ce4c749..c30c02a 100644
--- a/src/network/ssl/qsslerror.h
+++ b/src/network/ssl/qsslerror.h
@@ -83,6 +83,7 @@ public:
NoPeerCertificate,
HostNameMismatch,
NoSslSupport,
+ CertificateBlacklisted,
UnspecifiedError = -1
};
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 5b943ab..0dbf4b5 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -828,14 +828,8 @@ void QSslSocket::setReadBufferSize(qint64 size)
Q_D(QSslSocket);
d->readBufferMaxSize = size;
- // set the plain socket's buffer size to 1k if we have a limit
- // see also the same logic in QSslSocketPrivate::createPlainSocket
- if (d->plainSocket) {
- if (d->mode == UnencryptedMode)
- d->plainSocket->setReadBufferSize(size);
- else
- d->plainSocket->setReadBufferSize(size ? 1024 : 0);
- }
+ if (d->plainSocket)
+ d->plainSocket->setReadBufferSize(size);
}
/*!
@@ -902,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->allowRootCertOnDemandLoading = false;
}
/*!
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index d6967fe..78a78a2 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -1241,6 +1241,15 @@ bool QSslSocketBackendPrivate::startHandshake()
// Start translating errors.
QList<QSslError> errors;
+
+ if (QSslCertificatePrivate::isBlacklisted(configuration.peerCertificate)) {
+ QSslError error(QSslError::CertificateBlacklisted, configuration.peerCertificate);
+ errors << error;
+ emit q->peerVerifyError(error);
+ if (q->state() != QAbstractSocket::ConnectedState)
+ return false;
+ }
+
bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
|| (configuration.peerVerifyMode == QSslSocket::AutoVerifyPeer
&& mode == QSslSocket::SslClientMode);