diff options
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/access/qhttp2protocolhandler.cpp | 6 | ||||
-rw-r--r-- | src/network/access/qhttp2protocolhandler_p.h | 1 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnectionchannel.cpp | 3 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessmanager.cpp | 25 | ||||
-rw-r--r-- | src/network/access/qnetworkreply.cpp | 2 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyfileimpl.cpp | 8 | ||||
-rw-r--r-- | src/network/access/qnetworkreplywasmimpl.cpp | 311 | ||||
-rw-r--r-- | src/network/access/qnetworkreplywasmimpl_p.h | 14 | ||||
-rw-r--r-- | src/network/configure.json | 6 | ||||
-rw-r--r-- | src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslcertificate.h | 8 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_mac.cpp | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_mac_shared.cpp | 8 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl.cpp | 6 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl_symbols.cpp | 18 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_qt.cpp | 3 |
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; } |