summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/access/qhttp2protocolhandler.cpp6
-rw-r--r--src/network/access/qhttp2protocolhandler_p.h1
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp3
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp25
-rw-r--r--src/network/access/qnetworkreply.cpp2
-rw-r--r--src/network/access/qnetworkreplyfileimpl.cpp8
-rw-r--r--src/network/access/qnetworkreplywasmimpl.cpp311
-rw-r--r--src/network/access/qnetworkreplywasmimpl_p.h14
-rw-r--r--src/network/configure.json6
-rw-r--r--src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp2
-rw-r--r--src/network/ssl/qsslcertificate.h8
-rw-r--r--src/network/ssl/qsslsocket_mac.cpp2
-rw-r--r--src/network/ssl/qsslsocket_mac_shared.cpp8
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp6
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp18
-rw-r--r--src/network/ssl/qsslsocket_qt.cpp3
16 files changed, 186 insertions, 237 deletions
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp
index efbeb17d39..ac90714132 100644
--- a/src/network/access/qhttp2protocolhandler.cpp
+++ b/src/network/access/qhttp2protocolhandler.cpp
@@ -220,6 +220,12 @@ void QHttp2ProtocolHandler::handleConnectionClosure()
goingAway = true;
}
+void QHttp2ProtocolHandler::ensureClientPrefaceSent()
+{
+ if (!prefaceSent)
+ sendClientPreface();
+}
+
void QHttp2ProtocolHandler::_q_uploadDataReadyRead()
{
if (!sender()) // QueuedConnection, firing after sender (byte device) was deleted.
diff --git a/src/network/access/qhttp2protocolhandler_p.h b/src/network/access/qhttp2protocolhandler_p.h
index 43fdb136cd..14deabd70b 100644
--- a/src/network/access/qhttp2protocolhandler_p.h
+++ b/src/network/access/qhttp2protocolhandler_p.h
@@ -93,6 +93,7 @@ public:
QHttp2ProtocolHandler &operator = (QHttp2ProtocolHandler &&rhs) = delete;
Q_INVOKABLE void handleConnectionClosure();
+ Q_INVOKABLE void ensureClientPrefaceSent();
private slots:
void _q_uploadDataReadyRead();
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 4ea98ff978..ba05e75794 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -478,6 +478,9 @@ void QHttpNetworkConnectionChannel::allDone()
QHttp2ProtocolHandler *h2c = static_cast<QHttp2ProtocolHandler *>(protocolHandler.data());
QMetaObject::invokeMethod(h2c, "_q_receiveReply", Qt::QueuedConnection);
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+ // If we only had one request sent with H2 allowed, we may fail to send
+ // a client preface and SETTINGS, which is required by RFC 7540, 3.2.
+ QMetaObject::invokeMethod(h2c, "ensureClientPrefaceSent", Qt::QueuedConnection);
return;
} else {
// Ok, whatever happened, we do not try HTTP/2 anymore ...
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 62cc760ada..63a816b9dc 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -1211,16 +1211,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
bool isLocalFile = req.url().isLocalFile();
QString scheme = req.url().scheme();
-#ifdef Q_OS_WASM
- // Support http, https, and relateive urls
- if (scheme == QLatin1String("http") || scheme == QLatin1String("https") || scheme.isEmpty()) {
- QNetworkReplyWasmImpl *reply = new QNetworkReplyWasmImpl(this);
- QNetworkReplyWasmImplPrivate *priv = reply->d_func();
- priv->manager = this;
- priv->setup(op, req, outgoingData);
- return reply;
- }
-#endif
+#ifndef Q_OS_WASM
// fast path for GET on file:// URLs
// The QNetworkAccessFileBackend will right now only be used for PUT
@@ -1273,7 +1264,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
if (!d->statusMonitor.isMonitoring() && !d->statusMonitor.start())
qWarning(lcNetMon, "failed to start network status monitoring");
}
-
+#endif
QNetworkRequest request = req;
if (!request.header(QNetworkRequest::ContentLengthHeader).isValid() &&
outgoingData && !outgoingData->isSequential()) {
@@ -1291,6 +1282,16 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies));
}
}
+#ifdef Q_OS_WASM
+ // Support http, https, and relative urls
+ if (scheme == QLatin1String("http") || scheme == QLatin1String("https") || scheme.isEmpty()) {
+ QNetworkReplyWasmImpl *reply = new QNetworkReplyWasmImpl(this);
+ QNetworkReplyWasmImplPrivate *priv = reply->d_func();
+ priv->manager = this;
+ priv->setup(op, request, outgoingData);
+ return reply;
+ }
+#endif
#if QT_CONFIG(http)
// Since Qt 5 we use the new QNetworkReplyHttpImpl
@@ -1632,7 +1633,7 @@ void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QUrl &url,
}
}
-#if defined(Q_OS_OSX)
+#if defined(Q_OS_MACOS)
//now we try to get the username and password from keychain
//if not successful signal will be emitted
QString username;
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index 6784bc734d..30e4e290ea 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -868,7 +868,7 @@ void QNetworkReply::setRequest(const QNetworkRequest &request)
Sets the error condition to be \a errorCode. The human-readable
message is set with \a errorString.
- Calling setError() does not emit the error(QNetworkReply::NetworkError)
+ Calling setError() does not emit the errorOccurred(QNetworkReply::NetworkError)
signal.
\sa error(), errorString()
diff --git a/src/network/access/qnetworkreplyfileimpl.cpp b/src/network/access/qnetworkreplyfileimpl.cpp
index afab8ffd94..68fac55feb 100644
--- a/src/network/access/qnetworkreplyfileimpl.cpp
+++ b/src/network/access/qnetworkreplyfileimpl.cpp
@@ -89,7 +89,7 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, con
// we handle only local files
QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString());
setError(QNetworkReply::ProtocolInvalidOperationError, msg);
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolInvalidOperationError));
fileOpenFinished(false);
return;
@@ -134,7 +134,7 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, con
if (fi.isDir()) {
QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url.toString());
setError(QNetworkReply::ContentOperationNotPermittedError, msg);
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ QMetaObject::invokeMethod(this, "errorOccured", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentOperationNotPermittedError));
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
return;
@@ -149,11 +149,11 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, con
if (fi.exists()) {
setError(QNetworkReply::ContentAccessDenied, msg);
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentAccessDenied));
} else {
setError(QNetworkReply::ContentNotFoundError, msg);
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentNotFoundError));
}
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp
index 8c0f9bdf55..af8b39bab6 100644
--- a/src/network/access/qnetworkreplywasmimpl.cpp
+++ b/src/network/access/qnetworkreplywasmimpl.cpp
@@ -50,180 +50,10 @@
#include <private/qnetworkfile_p.h>
#include <emscripten.h>
-#include <emscripten/bind.h>
-#include <emscripten/val.h>
+#include <emscripten/fetch.h>
QT_BEGIN_NAMESPACE
-using namespace emscripten;
-
-static void q_requestErrorCallback(val event)
-{
- if (event.isNull() || event.isUndefined())
- return;
-
- val xhr = event["target"];
- if (xhr.isNull() || xhr.isUndefined())
- return;
-
- quintptr func = xhr["data-handler"].as<quintptr>();
- QNetworkReplyWasmImplPrivate *reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(func);
- Q_ASSERT(reply);
-
- int statusCode = xhr["status"].as<int>();
-
- QString reasonStr = QString::fromStdString(xhr["statusText"].as<std::string>());
-
- reply->setReplyAttributes(func, statusCode, reasonStr);
-
- if (statusCode >= 400 && !reasonStr.isEmpty())
- reply->emitReplyError(reply->statusCodeFromHttp(statusCode, reply->request.url()), reasonStr);
-}
-
-static void q_progressCallback(val event)
-{
- if (event.isNull() || event.isUndefined())
- return;
-
- val xhr = event["target"];
- if (xhr.isNull() || xhr.isUndefined())
- return;
-
- QNetworkReplyWasmImplPrivate *reply =
- reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>());
- Q_ASSERT(reply);
-
- if (xhr["status"].as<int>() < 400)
- reply->emitDataReadProgress(event["loaded"].as<int>(), event["total"].as<int>());
-}
-
-static void q_loadCallback(val event)
-{
- if (event.isNull() || event.isUndefined())
- return;
-
- val xhr = event["target"];
- if (xhr.isNull() || xhr.isUndefined())
- return;
-
- QNetworkReplyWasmImplPrivate *reply =
- reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>());
- Q_ASSERT(reply);
-
- int status = xhr["status"].as<int>();
- if (status >= 300) {
- q_requestErrorCallback(event);
- return;
- }
- QString statusText = QString::fromStdString(xhr["statusText"].as<std::string>());
- int readyState = xhr["readyState"].as<int>();
-
- if (status == 200 || status == 203) {
- QString responseString;
- const std::string responseType = xhr["responseType"].as<std::string>();
- if (responseType.length() == 0 || responseType == "document" || responseType == "text") {
- responseString = QString::fromStdWString(xhr["responseText"].as<std::wstring>());
- } else if (responseType == "json") {
- responseString =
- QString::fromStdWString(val::global("JSON").call<std::wstring>("stringify", xhr["response"]));
- } else if (responseType == "arraybuffer" || responseType == "blob") {
- // handle this data in the FileReader, triggered by the call to readAsArrayBuffer
- val blob = xhr["response"];
- if (blob.isNull() || blob.isUndefined())
- return;
-
- val reader = val::global("FileReader").new_();
- if (reader.isNull() || reader.isUndefined())
- return;
-
- reader.set("onload", val::module_property("qt_QNetworkReplyWasmImplPrivate_readBinary"));
- reader.set("data-handler", xhr["data-handler"]);
-
- reader.call<void>("readAsArrayBuffer", blob);
- val::global("Module").delete_(reader);
- }
-
-
- if (readyState == 4) { // done
- reply->setReplyAttributes(xhr["data-handler"].as<quintptr>(), status, statusText);
- if (!responseString.isEmpty()) {
- QByteArray responseStringArray = responseString.toUtf8();
- reply->dataReceived(responseStringArray, responseStringArray.size());
- }
- }
- }
- if (status >= 400 && !statusText.isEmpty())
- reply->emitReplyError(reply->statusCodeFromHttp(status, reply->request.url()), statusText);
-}
-
-static void q_responseHeadersCallback(val event)
-{
- if (event.isNull() || event.isUndefined())
- return;
-
- val xhr = event["target"];
- if (xhr.isNull() || xhr.isUndefined())
- return;
-
- if (xhr["readyState"].as<int>() == 2) { // HEADERS_RECEIVED
- std::string responseHeaders = xhr.call<std::string>("getAllResponseHeaders");
- if (!responseHeaders.empty()) {
- QNetworkReplyWasmImplPrivate *reply =
- reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>());
- Q_ASSERT(reply);
-
- reply->headersReceived(QString::fromStdString(responseHeaders));
- }
- }
-}
-
-static void q_readBinary(val event)
-{
- if (event.isNull() || event.isUndefined())
- return;
-
- val fileReader = event["target"];
- if (fileReader.isNull() || fileReader.isUndefined())
- return;
-
- QNetworkReplyWasmImplPrivate *reply =
- reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fileReader["data-handler"].as<quintptr>());
- Q_ASSERT(reply);
-
- if (reply->state == QNetworkReplyPrivate::Finished || reply->state == QNetworkReplyPrivate::Aborted)
- return;
-
- // Set up source typed array
- val result = fileReader["result"]; // ArrayBuffer
- if (result.isNull() || result.isUndefined())
- return;
-
- val Uint8Array = val::global("Uint8Array");
- val sourceTypedArray = Uint8Array.new_(result);
-
- // Allocate and set up destination typed array
- const quintptr size = result["byteLength"].as<quintptr>();
- QByteArray buffer(size, Qt::Uninitialized);
-
- val destinationTypedArray = Uint8Array.new_(val::module_property("HEAPU8")["buffer"],
- reinterpret_cast<quintptr>(buffer.data()), size);
- destinationTypedArray.call<void>("set", sourceTypedArray);
- reply->dataReceived(buffer, buffer.size());
-
- event.delete_(fileReader);
- Uint8Array.delete_(sourceTypedArray);
-
- QCoreApplication::processEvents();
-}
-
-EMSCRIPTEN_BINDINGS(qtNetworkModule) {
- function("qt_QNetworkReplyWasmImplPrivate_requestErrorCallback", q_requestErrorCallback);
- function("qt_QNetworkReplyWasmImplPrivate_progressCallback", q_progressCallback);
- function("qt_QNetworkReplyWasmImplPrivate_loadCallback", q_loadCallback);
- function("qt_QNetworkReplyWasmImplPrivate_responseHeadersCallback", q_responseHeadersCallback);
- function("qt_QNetworkReplyWasmImplPrivate_readBinary", q_readBinary);
-}
-
QNetworkReplyWasmImplPrivate::QNetworkReplyWasmImplPrivate()
: QNetworkReplyPrivate()
, managerPrivate(0)
@@ -236,11 +66,7 @@ QNetworkReplyWasmImplPrivate::QNetworkReplyWasmImplPrivate()
QNetworkReplyWasmImplPrivate::~QNetworkReplyWasmImplPrivate()
{
- m_xhr.set("onerror", val::null());
- m_xhr.set("onload", val::null());
- m_xhr.set("onprogress", val::null());
- m_xhr.set("onreadystatechange", val::null());
- m_xhr.set("data-handler", val::null());
+ emscripten_fetch_close(m_fetch);
}
QNetworkReplyWasmImpl::QNetworkReplyWasmImpl(QObject *parent)
@@ -373,7 +199,11 @@ void QNetworkReplyWasmImplPrivate::setReplyAttributes(quintptr data, int statusC
void QNetworkReplyWasmImplPrivate::doAbort() const
{
- m_xhr.call<void>("abort");
+ emscripten_fetch_close(m_fetch);
+}
+
+constexpr int getArraySize (int factor) {
+ return 2 * factor + 1;
}
void QNetworkReplyWasmImplPrivate::doSendRequest()
@@ -381,38 +211,68 @@ void QNetworkReplyWasmImplPrivate::doSendRequest()
Q_Q(QNetworkReplyWasmImpl);
totalDownloadSize = 0;
- m_xhr = val::global("XMLHttpRequest").new_();
- std::string verb = q->methodName().toStdString();
+ emscripten_fetch_attr_t attr;
+ emscripten_fetch_attr_init(&attr);
+ strcpy(attr.requestMethod, q->methodName().constData());
- m_xhr.call<void>("open", verb, request.url().toString().toStdString());
+ QList<QByteArray> headersData = request.rawHeaderList();
+ int arrayLength = getArraySize(headersData.count());
- m_xhr.set("onerror", val::module_property("qt_QNetworkReplyWasmImplPrivate_requestErrorCallback"));
- m_xhr.set("onload", val::module_property("qt_QNetworkReplyWasmImplPrivate_loadCallback"));
- m_xhr.set("onprogress", val::module_property("qt_QNetworkReplyWasmImplPrivate_progressCallback"));
- m_xhr.set("onreadystatechange", val::module_property("qt_QNetworkReplyWasmImplPrivate_responseHeadersCallback"));
+ if (headersData.count() > 0) {
+ const char* customHeaders[arrayLength];
+ int i = 0;
+ for (i; i < headersData.count() * 2; (i = i + 2)) {
+ customHeaders[i] = headersData[i].constData();
+ customHeaders[i + 1] = request.rawHeader(headersData[i]).constData();
+ }
+ customHeaders[i] = nullptr;
+ attr.requestHeaders = customHeaders;
+ }
- m_xhr.set("data-handler", val(quintptr(reinterpret_cast<void *>(this))));
+ if (outgoingData) { // data from post request
+ // handle extra data
+ QByteArray extraData;
+ extraData = outgoingData->readAll(); // is there a size restriction here?
+ if (!extraData.isEmpty()) {
+ attr.requestData = extraData.constData();
+ attr.requestDataSize = extraData.size();
+ }
+ }
- QByteArray contentType = request.rawHeader("Content-Type");
+ // username & password
+ if (!request.url().userInfo().isEmpty()) {
+ attr.userName = request.url().userName().toUtf8();
+ attr.password = request.url().password().toUtf8();
+ }
- // handle extra data
- val dataToSend = val::null();
- QByteArray extraData;
+ attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_PERSIST_FILE | EMSCRIPTEN_FETCH_REPLACE;
- if (outgoingData) // data from post request
- extraData = outgoingData->readAll();
+ QNetworkRequest::CacheLoadControl CacheLoadControlAttribute =
+ (QNetworkRequest::CacheLoadControl)request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt();
- if (!extraData.isEmpty()) {
- dataToSend = val(typed_memory_view(extraData.size(),
- reinterpret_cast<const unsigned char *>
- (extraData.constData())));
+ if (CacheLoadControlAttribute == QNetworkRequest::AlwaysCache) {
+ attr.attributes += EMSCRIPTEN_FETCH_NO_DOWNLOAD;
}
- m_xhr.set("responseType", val("blob"));
- // set request headers
- for (auto header : request.rawHeaderList()) {
- m_xhr.call<void>("setRequestHeader", header.toStdString(), request.rawHeader(header).toStdString());
+ if (CacheLoadControlAttribute == QNetworkRequest::PreferCache) {
+ attr.attributes += EMSCRIPTEN_FETCH_APPEND;
}
- m_xhr.call<void>("send", dataToSend);
+
+ if (CacheLoadControlAttribute == QNetworkRequest::AlwaysNetwork ||
+ request.attribute(QNetworkRequest::CacheSaveControlAttribute, false).toBool()) {
+ attr.attributes -= EMSCRIPTEN_FETCH_PERSIST_FILE;
+ }
+
+ attr.onsuccess = QNetworkReplyWasmImplPrivate::downloadSucceeded;
+ attr.onerror = QNetworkReplyWasmImplPrivate::downloadFailed;
+ attr.onprogress = QNetworkReplyWasmImplPrivate::downloadProgress;
+ attr.onreadystatechange = QNetworkReplyWasmImplPrivate::stateChange;
+ attr.timeoutMSecs = 2 * 6000; // FIXME
+ attr.userData = reinterpret_cast<void *>(this);
+
+ QString dPath = QStringLiteral("/home/web_user/") + request.url().fileName();
+ attr.destinationPath = dPath.toUtf8();
+
+ m_fetch = emscripten_fetch(&attr, request.url().toString().toUtf8());
}
void QNetworkReplyWasmImplPrivate::emitReplyError(QNetworkReply::NetworkError errorCode, const QString &errorString)
@@ -511,7 +371,6 @@ void QNetworkReplyWasmImplPrivate::headersReceived(const QString &bufferString)
if (!bufferString.isEmpty()) {
QStringList headers = bufferString.split(QString::fromUtf8("\r\n"), Qt::SkipEmptyParts);
-
for (int i = 0; i < headers.size(); i++) {
QString headerName = headers.at(i).split(QString::fromUtf8(": ")).at(0);
QString headersValue = headers.at(i).split(QString::fromUtf8(": ")).at(1);
@@ -589,6 +448,56 @@ void QNetworkReplyWasmImplPrivate::_q_bufferOutgoingData()
}
}
+void QNetworkReplyWasmImplPrivate::downloadSucceeded(emscripten_fetch_t *fetch)
+{
+ QByteArray buffer(fetch->data, fetch->numBytes);
+
+ QNetworkReplyWasmImplPrivate *reply =
+ reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fetch->userData);
+ if (reply) {
+ reply->dataReceived(buffer, buffer.size());
+ }
+}
+
+void QNetworkReplyWasmImplPrivate::stateChange(emscripten_fetch_t *fetch)
+{
+ if (fetch->readyState == /*HEADERS_RECEIVED*/ 2) {
+ size_t headerLength = emscripten_fetch_get_response_headers_length(fetch);
+ char *dst = nullptr;
+ emscripten_fetch_get_response_headers(fetch, dst, headerLength + 1);
+ std::string str = dst;
+ QNetworkReplyWasmImplPrivate *reply =
+ reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fetch->userData);
+ reply->headersReceived(QString::fromStdString(str));
+ }
+}
+
+void QNetworkReplyWasmImplPrivate::downloadProgress(emscripten_fetch_t *fetch)
+{
+ QNetworkReplyWasmImplPrivate *reply =
+ reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fetch->userData);
+ Q_ASSERT(reply);
+
+ if (fetch->status < 400)
+ reply->emitDataReadProgress((fetch->dataOffset + fetch->numBytes), fetch->totalBytes);
+}
+
+void QNetworkReplyWasmImplPrivate::downloadFailed(emscripten_fetch_t *fetch)
+{
+ QNetworkReplyWasmImplPrivate *reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fetch->userData);
+ Q_ASSERT(reply);
+
+ QString reasonStr = QString::fromUtf8(fetch->statusText);
+
+ reply->setReplyAttributes(reinterpret_cast<quintptr>(fetch->userData), fetch->status, reasonStr);
+
+ if (fetch->status >= 400 && !reasonStr.isEmpty())
+ reply->emitReplyError(reply->statusCodeFromHttp(fetch->status, reply->request.url()), reasonStr);
+
+ if (fetch->status >= 400)
+ emscripten_fetch_close(fetch); // Also free data on failure.
+}
+
//taken from qhttpthreaddelegate.cpp
QNetworkReply::NetworkError QNetworkReplyWasmImplPrivate::statusCodeFromHttp(int httpStatusCode, const QUrl &url)
{
diff --git a/src/network/access/qnetworkreplywasmimpl_p.h b/src/network/access/qnetworkreplywasmimpl_p.h
index e1e6bf4e24..5463ce8a98 100644
--- a/src/network/access/qnetworkreplywasmimpl_p.h
+++ b/src/network/access/qnetworkreplywasmimpl_p.h
@@ -61,8 +61,7 @@
#include <private/qabstractfileengine_p.h>
#include <emscripten.h>
-#include <emscripten/html5.h>
-#include <emscripten/val.h>
+#include <emscripten/fetch.h>
QT_BEGIN_NAMESPACE
@@ -135,10 +134,17 @@ public:
QIODevice *outgoingData;
QSharedPointer<QRingBuffer> outgoingDataBuffer;
- emscripten::val m_xhr = emscripten::val::null();
- void doAbort() const;
+ void doAbort() const;
+
+ static void downloadProgress(emscripten_fetch_t *fetch);
+ static void downloadFailed(emscripten_fetch_t *fetch);
+ static void downloadSucceeded(emscripten_fetch_t *fetch);
+ static void stateChange(emscripten_fetch_t *fetch);
static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const QUrl &url);
+
+ emscripten_fetch_t *m_fetch;
+
Q_DECLARE_PUBLIC(QNetworkReplyWasmImpl)
};
diff --git a/src/network/configure.json b/src/network/configure.json
index 07f0e349f6..254a36d725 100644
--- a/src/network/configure.json
+++ b/src/network/configure.json
@@ -61,11 +61,11 @@
"export": "openssl",
"test": {
"tail": [
- "#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10100000L",
- "# error OpenSSL >= 1.1.0 is required",
+ "#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10101000L",
+ "# error OpenSSL >= 1.1.1 is required",
"#endif",
"#if !defined(OPENSSL_NO_EC) && !defined(SSL_CTRL_SET_CURVES)",
- "# error OpenSSL was reported as >= 1.1.0 but is missing required features, possibly it's libressl which is unsupported",
+ "# error OpenSSL was reported as >= 1.1.1 but is missing required features, possibly it's libressl which is unsupported",
"#endif"
]
},
diff --git a/src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp b/src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp
index d3a4cfc116..39a3199bf7 100644
--- a/src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp
+++ b/src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp
@@ -64,7 +64,7 @@ request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");
QNetworkReply *reply = manager->get(request);
connect(reply, &QIODevice::readyRead, this, &MyClass::slotReadyRead);
-connect(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error),
+connect(reply, &QNetworkReply::errorOccurred,
this, &MyClass::slotError);
connect(reply, &QNetworkReply::sslErrors,
this, &MyClass::slotSslErrors);
diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h
index b7d4f4fa3e..4d3f7d8ddb 100644
--- a/src/network/ssl/qsslcertificate.h
+++ b/src/network/ssl/qsslcertificate.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -141,9 +141,9 @@ public:
QByteArray toDer() const;
QString toText() const;
- static QList<QSslCertificate> fromPath(
- const QString &path, QSsl::EncodingFormat format = QSsl::Pem,
- PatternSyntax syntax = PatternSyntax::FixedString);
+ static QList<QSslCertificate> fromPath(const QString &path,
+ QSsl::EncodingFormat format = QSsl::Pem,
+ PatternSyntax syntax = PatternSyntax::FixedString);
static QList<QSslCertificate> fromDevice(
QIODevice *device, QSsl::EncodingFormat format = QSsl::Pem);
diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp
index fe1c43d992..1ae32b0330 100644
--- a/src/network/ssl/qsslsocket_mac.cpp
+++ b/src/network/ssl/qsslsocket_mac.cpp
@@ -66,7 +66,7 @@
#include <QtCore/private/qcore_mac_p.h>
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
#include <CoreServices/CoreServices.h>
#endif
diff --git a/src/network/ssl/qsslsocket_mac_shared.cpp b/src/network/ssl/qsslsocket_mac_shared.cpp
index 4f0adf16f9..0bc4647e8b 100644
--- a/src/network/ssl/qsslsocket_mac_shared.cpp
+++ b/src/network/ssl/qsslsocket_mac_shared.cpp
@@ -57,14 +57,14 @@
#include <QtCore/qdebug.h>
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
# include <Security/Security.h>
#endif
QT_BEGIN_NAMESPACE
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
namespace {
bool hasTrustedSslServerPolicy(SecPolicyRef policy, CFDictionaryRef props) {
@@ -119,7 +119,7 @@ bool isCaCertificateTrusted(SecCertificateRef cfCert, int domain)
}
} // anon namespace
-#endif // Q_OS_OSX
+#endif // Q_OS_MACOS
QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
{
@@ -127,7 +127,7 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
QList<QSslCertificate> systemCerts;
// SecTrustSettingsCopyCertificates is not defined on iOS.
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
// iterate through all enum members, order:
// kSecTrustSettingsDomainUser, kSecTrustSettingsDomainAdmin, kSecTrustSettingsDomainSystem
for (int dom = kSecTrustSettingsDomainUser; dom <= int(kSecTrustSettingsDomainSystem); dom++) {
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 2419ec5e38..69c4e04148 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -2154,6 +2154,12 @@ bool QSslSocketPrivate::ensureLibraryLoaded()
// Initialize OpenSSL.
if (q_OPENSSL_init_ssl(0, nullptr) != 1)
return false;
+
+ if (q_OpenSSL_version_num() < 0x10101000L) {
+ qCWarning(lcSsl, "QSslSocket: OpenSSL >= 1.1.1 is required; %s was found instead", q_OpenSSL_version(OPENSSL_VERSION));
+ return false;
+ }
+
q_SSL_load_error_strings();
q_OpenSSL_add_all_algorithms();
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index 93b1c8fbf9..2e4e5fd48c 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -1193,6 +1193,9 @@ QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime)
{
size_t lTimeLength = aTime->length;
char *pString = (char *) aTime->data;
+ auto isValidPointer = [pString, lTimeLength](const char *const probe){
+ return size_t(probe - pString) < lTimeLength;
+ };
if (aTime->type == V_ASN1_UTCTIME) {
@@ -1211,12 +1214,21 @@ QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime)
*pBuffer++ = '0';
} else {
*pBuffer++ = *pString++;
+ if (!isValidPointer(pString)) // Nah.
+ return {};
*pBuffer++ = *pString++;
+ if (!isValidPointer(pString)) // Nah.
+ return {};
// Skip any fractional seconds...
if (*pString == '.') {
pString++;
- while ((*pString >= '0') && (*pString <= '9'))
+ if (!isValidPointer(pString)) // Oh no, cannot dereference (see below).
+ return {};
+ while ((*pString >= '0') && (*pString <= '9')) {
pString++;
+ if (!isValidPointer(pString)) // No and no.
+ return {};
+ }
}
}
@@ -1230,6 +1242,10 @@ QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime)
if ((*pString != '+') && (*pString != '-'))
return QDateTime();
+ if (!isValidPointer(pString + 4)) {
+ // What kind of input parameters we were provided with? To hell with them!
+ return {};
+ }
lSecondsFromUCT = ((pString[1] - '0') * 10 + (pString[2] - '0')) * 60;
lSecondsFromUCT += (pString[3] - '0') * 10 + (pString[4] - '0');
lSecondsFromUCT *= 60;
diff --git a/src/network/ssl/qsslsocket_qt.cpp b/src/network/ssl/qsslsocket_qt.cpp
index 9ff9a66c05..2f5d692162 100644
--- a/src/network/ssl/qsslsocket_qt.cpp
+++ b/src/network/ssl/qsslsocket_qt.cpp
@@ -39,6 +39,7 @@
#include <QtCore/qbytearray.h>
#include <QtCore/qdatastream.h>
#include <QtCore/qmessageauthenticationcode.h>
+#include <QtCore/qrandom.h>
#include "qsslsocket_p.h"
#include "qasn1element_p.h"
@@ -138,7 +139,7 @@ static QByteArray _q_PKCS12_salt()
QByteArray salt;
salt.resize(8);
for (int i = 0; i < salt.size(); ++i)
- salt[i] = (qrand() & 0xff);
+ salt[i] = (QRandomGenerator::global()->generate() & 0xff);
return salt;
}