From 67123c81d3020db30c6f45dd24a314299fa53d74 Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Tue, 6 Dec 2016 14:54:05 +0100 Subject: [PATCH 1/2] Rebase Qt patches on 5.6 #3449 Also get rid of the list of different version. We always only support one Qt version for macOS and Windows, and the list of patches will be based on that supported version. --- ...-OS-if-PAC-URL-contains-non-URL-lega.patch | 42 -- ...rash-when-passing-an-invalid-PAC-URL.patch | 38 - ...-script-retrieval-returns-a-null-CFD.patch | 39 - .../0004-Cocoa-Fix-systray-SVG-icons.patch | 32 - .../0005-OSX-Fix-disapearing-tray-icon.patch | 115 --- ...corruptions-when-server-closes-conne.patch | 691 ------------------ ...ork-Fix-up-previous-corruption-patch.patch | 434 ----------- ...eadlocks-on-server-closing-connectio.patch | 64 -- ...er-channel-before-sslErrors-emission.patch | 33 - ...-http-sockets-pass-as-valid-connecti.patch | 121 --- ...-report-correct-NetworkAccessibility.patch | 113 --- ...tworkAccessibilityChanged-is-emitted.patch | 233 ------ ...nownAccessibility-not-block-requests.patch | 52 -- ...stem-proxy-if-internet-settings-chan.patch | 152 ---- ...rash-if-SSL-context-is-gone-after-ro.patch | 32 - ...-icon-is-prepared-even-when-menu-bar.patch | 39 - admin/qt/patches/README.md | 57 +- ...ix-force-debug-info-with-macx-clang.patch} | 21 +- ...tform-code-in-QSslSocket-for-OS-X-1.patch} | 39 +- ...uate-CAs-in-all-keychain-categories.patch} | 29 +- 20 files changed, 50 insertions(+), 2326 deletions(-) delete mode 100644 admin/qt/patches/0001-Fix-crash-on-Mac-OS-if-PAC-URL-contains-non-URL-lega.patch delete mode 100644 admin/qt/patches/0002-Fix-possible-crash-when-passing-an-invalid-PAC-URL.patch delete mode 100644 admin/qt/patches/0003-Fix-crash-if-PAC-script-retrieval-returns-a-null-CFD.patch delete mode 100644 admin/qt/patches/0004-Cocoa-Fix-systray-SVG-icons.patch delete mode 100644 admin/qt/patches/0005-OSX-Fix-disapearing-tray-icon.patch delete mode 100644 admin/qt/patches/0007-QNAM-Fix-upload-corruptions-when-server-closes-conne.patch delete mode 100644 admin/qt/patches/0007-X-Network-Fix-up-previous-corruption-patch.patch delete mode 100644 admin/qt/patches/0008-QNAM-Fix-reply-deadlocks-on-server-closing-connectio.patch delete mode 100644 admin/qt/patches/0009-QNAM-Assign-proper-channel-before-sslErrors-emission.patch delete mode 100644 admin/qt/patches/0010-Don-t-let-closed-http-sockets-pass-as-valid-connecti.patch delete mode 100644 admin/qt/patches/0011-Make-sure-to-report-correct-NetworkAccessibility.patch delete mode 100644 admin/qt/patches/0012-Make-sure-networkAccessibilityChanged-is-emitted.patch delete mode 100644 admin/qt/patches/0013-Make-UnknownAccessibility-not-block-requests.patch delete mode 100644 admin/qt/patches/0017-Win32-Re-init-system-proxy-if-internet-settings-chan.patch delete mode 100644 admin/qt/patches/0018-Windows-Do-not-crash-if-SSL-context-is-gone-after-ro.patch delete mode 100644 admin/qt/patches/0019-Ensure-system-tray-icon-is-prepared-even-when-menu-bar.patch rename admin/qt/patches/{0006-Fix-force-debug-info-with-macx-clang_NOUPSTREAM.patch => qtbase/0001-NOUPSTREAM-Fix-force-debug-info-with-macx-clang.patch} (64%) rename admin/qt/patches/{0015-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch => qtbase/0002-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch} (84%) rename admin/qt/patches/{0016-QSslSocket-evaluate-CAs-in-all-keychain-categories.patch => qtbase/0003-QSslSocket-evaluate-CAs-in-all-keychain-categories.patch} (93%) diff --git a/admin/qt/patches/0001-Fix-crash-on-Mac-OS-if-PAC-URL-contains-non-URL-lega.patch b/admin/qt/patches/0001-Fix-crash-on-Mac-OS-if-PAC-URL-contains-non-URL-lega.patch deleted file mode 100644 index 1e46cd9fb66..00000000000 --- a/admin/qt/patches/0001-Fix-crash-on-Mac-OS-if-PAC-URL-contains-non-URL-lega.patch +++ /dev/null @@ -1,42 +0,0 @@ -From ea4dcc5931d455e4ee3e958ffa54a9f54ab022c8 Mon Sep 17 00:00:00 2001 -From: Daniel Molkentin -Date: Mon, 5 Jan 2015 10:45:25 +0100 -Subject: [PATCH 1/3] Fix crash on Mac OS if PAC URL contains non-URL legal - chars - -macQueryInternal() was retrieving the PAC URL string as-entered by -the user in the 'Proxies' tab of the system network settings dialog -and passing it to CFURLCreateWithString(). - -CFURLCreateWithString() returns null if the input string contains -non-URL legal chars or is empty. - -Change-Id: I9166d0433a62c7b2274b5435a7dea0a16997d10e -Patch-By: Robert Knight -Task-number: QTBUG-36787 -Reviewed-by: Peter Hartmann -Reviewed-by: Markus Goetz ---- - src/network/kernel/qnetworkproxy_mac.cpp | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp -index 7d26246..81bce0c 100644 ---- a/src/network/kernel/qnetworkproxy_mac.cpp -+++ b/src/network/kernel/qnetworkproxy_mac.cpp -@@ -221,7 +221,11 @@ QList macQueryInternal(const QNetworkProxyQuery &query) - int enabled; - if (CFNumberGetValue(pacEnabled, kCFNumberIntType, &enabled) && enabled) { - // PAC is enabled -- CFStringRef cfPacLocation = (CFStringRef)CFDictionaryGetValue(dict, kSCPropNetProxiesProxyAutoConfigURLString); -+ // kSCPropNetProxiesProxyAutoConfigURLString returns the URL string -+ // as entered in the system proxy configuration dialog -+ CFStringRef pacLocationSetting = (CFStringRef)CFDictionaryGetValue(dict, kSCPropNetProxiesProxyAutoConfigURLString); -+ QCFType cfPacLocation = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, pacLocationSetting, NULL, NULL, -+ kCFStringEncodingUTF8); - - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - QCFType pacData; --- -1.8.3.4 (Apple Git-47) - diff --git a/admin/qt/patches/0002-Fix-possible-crash-when-passing-an-invalid-PAC-URL.patch b/admin/qt/patches/0002-Fix-possible-crash-when-passing-an-invalid-PAC-URL.patch deleted file mode 100644 index 275b3479a94..00000000000 --- a/admin/qt/patches/0002-Fix-possible-crash-when-passing-an-invalid-PAC-URL.patch +++ /dev/null @@ -1,38 +0,0 @@ -From a83e4d1d9dd90d4563ce60f27dfb7802a780e33e Mon Sep 17 00:00:00 2001 -From: Daniel Molkentin -Date: Mon, 5 Jan 2015 11:42:52 +0100 -Subject: [PATCH 2/3] Fix possible crash when passing an invalid PAC URL - -This commit checks whether CFURLCreateWithString() succeeded. - -It does not appear to be possible to enter an empty URL directly in the -PAC configuration dialog but I can't rule out the possibility -that it could find its way into the settings via some other means. - -Change-Id: I6c2053d385503bf0330f5ae9fb1ec36a473d425d -Patch-By: Robert Knight -Task-number: QTBUG-36787 -Reviewed-by: Markus Goetz -Reviewed-by: Peter Hartmann ---- - src/network/kernel/qnetworkproxy_mac.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp -index 81bce0c..6be032e 100644 ---- a/src/network/kernel/qnetworkproxy_mac.cpp -+++ b/src/network/kernel/qnetworkproxy_mac.cpp -@@ -230,6 +230,10 @@ QList macQueryInternal(const QNetworkProxyQuery &query) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - QCFType pacData; - QCFType pacUrl = CFURLCreateWithString(kCFAllocatorDefault, cfPacLocation, NULL); -+ if (!pacUrl) { -+ qWarning("Invalid PAC URL \"%s\"", qPrintable(QCFString::toQString(cfPacLocation))); -+ return result; -+ } - SInt32 errorCode; - if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, pacUrl, &pacData, NULL, NULL, &errorCode)) { - QString pacLocation = QCFString::toQString(cfPacLocation); --- -1.8.3.4 (Apple Git-47) - diff --git a/admin/qt/patches/0003-Fix-crash-if-PAC-script-retrieval-returns-a-null-CFD.patch b/admin/qt/patches/0003-Fix-crash-if-PAC-script-retrieval-returns-a-null-CFD.patch deleted file mode 100644 index c144c2d97ff..00000000000 --- a/admin/qt/patches/0003-Fix-crash-if-PAC-script-retrieval-returns-a-null-CFD.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 83bd9393e5564ea9168fda90c0f44456633a483a Mon Sep 17 00:00:00 2001 -From: Daniel Molkentin -Date: Mon, 5 Jan 2015 15:22:57 +0100 -Subject: [PATCH 3/3] Fix crash if PAC script retrieval returns a null CFData - instance - -The documentation for CFURLCreateDataAndPropertiesFromResource() -does not make this clear but from looking at the CFNetwork implementation -and a user stacktrace it appears that this function can return true -but not set the data argument under certain circumstances. - -Change-Id: I48034a640d6f47a51cd5883bbafacad4bcbd0415 -Task-number: QTBUG-36787 -Patch-By: Robert Knight -Reviewed-by: Markus Goetz -Reviewed-by: Peter Hartmann ---- - src/network/kernel/qnetworkproxy_mac.cpp | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp -index 6be032e..a1ac349 100644 ---- a/src/network/kernel/qnetworkproxy_mac.cpp -+++ b/src/network/kernel/qnetworkproxy_mac.cpp -@@ -240,7 +240,10 @@ QList macQueryInternal(const QNetworkProxyQuery &query) - qWarning("Unable to get the PAC script at \"%s\" (%s)", qPrintable(pacLocation), cfurlErrorDescription(errorCode)); - return result; - } -- -+ if (!pacData) { -+ qWarning("\"%s\" returned an empty PAC script", qPrintable(QCFString::toQString(cfPacLocation))); -+ return result; -+ } - QCFType pacScript = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, pacData, kCFStringEncodingISOLatin1); - if (!pacScript) { - // This should never happen, but the documentation says it may return NULL if there was a problem creating the object. --- -1.8.3.4 (Apple Git-47) - diff --git a/admin/qt/patches/0004-Cocoa-Fix-systray-SVG-icons.patch b/admin/qt/patches/0004-Cocoa-Fix-systray-SVG-icons.patch deleted file mode 100644 index 011b9a0f849..00000000000 --- a/admin/qt/patches/0004-Cocoa-Fix-systray-SVG-icons.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 22f3d359350fd65e4bbe2e9420fcc4460e8a590a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= -Date: Tue, 10 Mar 2015 22:37:39 +0100 -Subject: [PATCH] Cocoa: Fix systray SVG icons. - -Regression caused by f3699510. - -Task-number: QTBUG-44686 -Change-Id: I546422a67d4da29fac196025b09bddcb45c1b641 -Reviewed-by: Timur Pocheptsov ---- - src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm -index e449fd3..8a35705 100755 ---- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm -+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm -@@ -234,6 +234,10 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) - } - } - -+ // Handle SVG icons, which do not return anything for availableSizes(). -+ if (!selectedSize.isValid()) -+ selectedSize = icon.actualSize(QSize(maxPixmapHeight, maxPixmapHeight), mode); -+ - QPixmap pixmap = icon.pixmap(selectedSize, mode); - - // Draw a low-resolution icon if there is not enough pixels for a retina --- -1.9.1 - diff --git a/admin/qt/patches/0005-OSX-Fix-disapearing-tray-icon.patch b/admin/qt/patches/0005-OSX-Fix-disapearing-tray-icon.patch deleted file mode 100644 index df6b4eff3ed..00000000000 --- a/admin/qt/patches/0005-OSX-Fix-disapearing-tray-icon.patch +++ /dev/null @@ -1,115 +0,0 @@ -From ee7fea33383726f0bb72e8082a357820e3ee3675 Mon Sep 17 00:00:00 2001 -From: Jocelyn Turcotte -Date: Tue, 24 Feb 2015 17:02:02 +0100 -Subject: [PATCH] OSX Fix disapearing tray icon -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -It would happen together with an error: - QPainter::begin: Paint device returned engine == 0 -and would be caused by the size provided to QIcon::pixmap being empty, -itself caused by the availableSizes list being empty for the Selected -mode. - -This bug was most often hidden by the fact that the Selected icon mode -was not triggered properly since we usually only set menuVisible after -calling updateIcon, and most of the time when it did, we would overwrite -it right after with a Normal mode icon. - -Fix the issue by disabling the broken feature completely since the -default Selected icon is grayed out while tray icons are now usually -black (or white when selected). To support the dark menu bar mode on -10.10 we'll need to use NSImage's setTemplate anyway and that -knowing in advance if we can invert the colors ourselves would also -better solve the menuVisible usecase. - -Task-number: QTBUG-42910 -Change-Id: If9ec9659af28ecceb841bfc2f11721e6029fe891 -Reviewed-by: Morten Johan Sørvig ---- - src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | 17 +++-------------- - 1 file changed, 3 insertions(+), 14 deletions(-) - -diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm -index 8a35705..d366a3c 100755 ---- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm -+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm -@@ -102,7 +102,6 @@ QT_USE_NAMESPACE - QCocoaSystemTrayIcon *systray; - NSStatusItem *item; - QCocoaMenu *menu; -- bool menuVisible; - QIcon icon; - QT_MANGLE_NAMESPACE(QNSImageView) *imageCell; - } -@@ -202,8 +201,6 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) - - m_sys->item->icon = icon; - -- const bool menuVisible = m_sys->item->menu && m_sys->item->menuVisible; -- - // The reccomended maximum title bar icon height is 18 points - // (device independent pixels). The menu height on past and - // current OS X versions is 22 points. Provide some future-proofing -@@ -218,9 +215,8 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) - // devicePixelRatio for the "best" screen on the system. - qreal devicePixelRatio = qApp->devicePixelRatio(); - const int maxPixmapHeight = maxImageHeight * devicePixelRatio; -- const QIcon::Mode mode = menuVisible ? QIcon::Selected : QIcon::Normal; - QSize selectedSize; -- Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes(mode))) { -+ Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes())) { - // Select a pixmap based on the height. We want the largest pixmap - // with a height smaller or equal to maxPixmapHeight. The pixmap - // may rectangular; assume it has a reasonable size. If there is -@@ -236,9 +232,9 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) - - // Handle SVG icons, which do not return anything for availableSizes(). - if (!selectedSize.isValid()) -- selectedSize = icon.actualSize(QSize(maxPixmapHeight, maxPixmapHeight), mode); -+ selectedSize = icon.actualSize(QSize(maxPixmapHeight, maxPixmapHeight)); - -- QPixmap pixmap = icon.pixmap(selectedSize, mode); -+ QPixmap pixmap = icon.pixmap(selectedSize); - - // Draw a low-resolution icon if there is not enough pixels for a retina - // icon. This prevents showing a small icon on retina displays. -@@ -385,9 +381,6 @@ QT_END_NAMESPACE - Q_UNUSED(notification); - down = NO; - -- parent->systray->updateIcon(parent->icon); -- parent->menuVisible = false; -- - [self setNeedsDisplay:YES]; - } - -@@ -397,8 +390,6 @@ QT_END_NAMESPACE - int clickCount = [mouseEvent clickCount]; - [self setNeedsDisplay:YES]; - -- parent->systray->updateIcon(parent->icon); -- - if (clickCount == 2) { - [self menuTrackingDone:nil]; - [parent doubleClickSelector:self]; -@@ -454,7 +445,6 @@ QT_END_NAMESPACE - if (self) { - item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain]; - menu = 0; -- menuVisible = false; - systray = sys; - imageCell = [[QNSImageView alloc] initWithParent:self]; - [item setView: imageCell]; -@@ -498,7 +488,6 @@ QT_END_NAMESPACE - selector:@selector(menuTrackingDone:) - name:NSMenuDidEndTrackingNotification - object:m]; -- menuVisible = true; - [item popUpStatusItemMenu: m]; - } - } --- -1.9.1 - diff --git a/admin/qt/patches/0007-QNAM-Fix-upload-corruptions-when-server-closes-conne.patch b/admin/qt/patches/0007-QNAM-Fix-upload-corruptions-when-server-closes-conne.patch deleted file mode 100644 index edd46eb7e29..00000000000 --- a/admin/qt/patches/0007-QNAM-Fix-upload-corruptions-when-server-closes-conne.patch +++ /dev/null @@ -1,691 +0,0 @@ -From cff39fba10ffc10ee4dcfdc66ff6528eb26462d3 Mon Sep 17 00:00:00 2001 -From: Markus Goetz -Date: Fri, 10 Apr 2015 14:09:53 +0200 -Subject: [PATCH] QNAM: Fix upload corruptions when server closes connection - -This patch fixes several upload corruptions if the server closes the connection -while/before we send data into it. They happen inside multiple places in the HTTP -layer and are explained in the comments. -Corruptions are: -* The upload byte device has an in-flight signal with pending upload data, if -it gets reset (because server closes the connection) then the re-send of the -request was sometimes taking this stale in-flight pending upload data. -* Because some signals were DirectConnection and some were QueuedConnection, there -was a chance that a direct signal overtakes a queued signal. The state machine -then sent data down the socket which was buffered there (and sent later) although -it did not match the current state of the state machine when it was actually sent. -* A socket was seen as being able to have requests sent even though it was not -encrypted yet. This relates to the previous corruption where data is stored inside -the socket's buffer and then sent later. - -The included auto test produces all fixed corruptions, I detected no regressions -via the other tests. -This code also adds a bit of sanity checking to protect from possible further -problems. - -[ChangeLog][QtNetwork] Fix HTTP(s) upload corruption when server closes connection - -Change-Id: I54c883925ec897050941498f139c4b523030432e -Reviewed-by: Peter Hartmann ---- - src/corelib/io/qnoncontiguousbytedevice.cpp | 18 +++ - src/corelib/io/qnoncontiguousbytedevice_p.h | 4 + - .../access/qhttpnetworkconnectionchannel.cpp | 35 ++++- - .../access/qhttpnetworkconnectionchannel_p.h | 2 + - src/network/access/qhttpprotocolhandler.cpp | 7 + - src/network/access/qhttpthreaddelegate_p.h | 36 ++++- - src/network/access/qnetworkreplyhttpimpl.cpp | 25 ++- - src/network/access/qnetworkreplyhttpimpl_p.h | 7 +- - .../access/qnetworkreply/tst_qnetworkreply.cpp | 175 ++++++++++++++++++++- - 9 files changed, 279 insertions(+), 30 deletions(-) - -diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp -index 11510a8..760ca3d 100644 ---- a/src/corelib/io/qnoncontiguousbytedevice.cpp -+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp -@@ -236,6 +236,11 @@ qint64 QNonContiguousByteDeviceByteArrayImpl::size() - return byteArray->size(); - } - -+qint64 QNonContiguousByteDeviceByteArrayImpl::pos() -+{ -+ return currentPosition; -+} -+ - QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QSharedPointer rb) - : QNonContiguousByteDevice(), currentPosition(0) - { -@@ -273,6 +278,11 @@ bool QNonContiguousByteDeviceRingBufferImpl::atEnd() - return currentPosition >= size(); - } - -+qint64 QNonContiguousByteDeviceRingBufferImpl::pos() -+{ -+ return currentPosition; -+} -+ - bool QNonContiguousByteDeviceRingBufferImpl::reset() - { - if (resetDisabled) -@@ -406,6 +416,14 @@ qint64 QNonContiguousByteDeviceIoDeviceImpl::size() - return device->size() - initialPosition; - } - -+qint64 QNonContiguousByteDeviceIoDeviceImpl::pos() -+{ -+ if (device->isSequential()) -+ return -1; -+ -+ return device->pos(); -+} -+ - QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)0) - { - byteDevice = bd; -diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h -index c05ae11..4d7b7b0 100644 ---- a/src/corelib/io/qnoncontiguousbytedevice_p.h -+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h -@@ -61,6 +61,7 @@ public: - virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0; - virtual bool advanceReadPointer(qint64 amount) = 0; - virtual bool atEnd() = 0; -+ virtual qint64 pos() { return -1; } - virtual bool reset() = 0; - void disableReset(); - bool isResetDisabled() { return resetDisabled; } -@@ -106,6 +107,7 @@ public: - bool atEnd(); - bool reset(); - qint64 size(); -+ qint64 pos() Q_DECL_OVERRIDE; - protected: - QByteArray* byteArray; - qint64 currentPosition; -@@ -121,6 +123,7 @@ public: - bool atEnd(); - bool reset(); - qint64 size(); -+ qint64 pos() Q_DECL_OVERRIDE; - protected: - QSharedPointer ringBuffer; - qint64 currentPosition; -@@ -138,6 +141,7 @@ public: - bool atEnd(); - bool reset(); - qint64 size(); -+ qint64 pos() Q_DECL_OVERRIDE; - protected: - QIODevice* device; - QByteArray* currentReadBuffer; -diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp -index 9f63280..49c6793 100644 ---- a/src/network/access/qhttpnetworkconnectionchannel.cpp -+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp -@@ -106,15 +106,19 @@ void QHttpNetworkConnectionChannel::init() - socket->setProxy(QNetworkProxy::NoProxy); - #endif - -+ // We want all signals (except the interactive ones) be connected as QueuedConnection -+ // because else we're falling into cases where we recurse back into the socket code -+ // and mess up the state. Always going to the event loop (and expecting that when reading/writing) -+ // is safer. - QObject::connect(socket, SIGNAL(bytesWritten(qint64)), - this, SLOT(_q_bytesWritten(qint64)), -- Qt::DirectConnection); -+ Qt::QueuedConnection); - QObject::connect(socket, SIGNAL(connected()), - this, SLOT(_q_connected()), -- Qt::DirectConnection); -+ Qt::QueuedConnection); - QObject::connect(socket, SIGNAL(readyRead()), - this, SLOT(_q_readyRead()), -- Qt::DirectConnection); -+ Qt::QueuedConnection); - - // The disconnected() and error() signals may already come - // while calling connectToHost(). -@@ -143,13 +147,13 @@ void QHttpNetworkConnectionChannel::init() - // won't be a sslSocket if encrypt is false - QObject::connect(sslSocket, SIGNAL(encrypted()), - this, SLOT(_q_encrypted()), -- Qt::DirectConnection); -+ Qt::QueuedConnection); - QObject::connect(sslSocket, SIGNAL(sslErrors(QList)), - this, SLOT(_q_sslErrors(QList)), - Qt::DirectConnection); - QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)), - this, SLOT(_q_encryptedBytesWritten(qint64)), -- Qt::DirectConnection); -+ Qt::QueuedConnection); - - if (ignoreAllSslErrors) - sslSocket->ignoreSslErrors(); -@@ -186,8 +190,11 @@ void QHttpNetworkConnectionChannel::close() - // pendingEncrypt must only be true in between connected and encrypted states - pendingEncrypt = false; - -- if (socket) -+ if (socket) { -+ // socket can be 0 since the host lookup is done from qhttpnetworkconnection.cpp while -+ // there is no socket yet. - socket->close(); -+ } - } - - -@@ -353,6 +360,14 @@ bool QHttpNetworkConnectionChannel::ensureConnection() - } - return false; - } -+ -+ // This code path for ConnectedState -+ if (pendingEncrypt) { -+ // Let's only be really connected when we have received the encrypted() signal. Else the state machine seems to mess up -+ // and corrupt the things sent to the server. -+ return false; -+ } -+ - return true; - } - -@@ -659,6 +674,12 @@ bool QHttpNetworkConnectionChannel::isSocketReading() const - void QHttpNetworkConnectionChannel::_q_bytesWritten(qint64 bytes) - { - Q_UNUSED(bytes); -+ if (ssl) { -+ // In the SSL case we want to send data from encryptedBytesWritten signal since that one -+ // is the one going down to the actual network, not only into some SSL buffer. -+ return; -+ } -+ - // bytes have been written to the socket. write even more of them :) - if (isSocketWriting()) - sendRequest(); -@@ -734,7 +755,7 @@ void QHttpNetworkConnectionChannel::_q_connected() - - // ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again! - //channels[i].reconnectAttempts = 2; -- if (pendingEncrypt) { -+ if (ssl || pendingEncrypt) { // FIXME: Didn't work properly with pendingEncrypt only, we should refactor this into an EncrypingState - #ifndef QT_NO_SSL - if (connection->sslContext().isNull()) { - // this socket is making the 1st handshake for this connection, -diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h -index 692c0e6..231fe11 100644 ---- a/src/network/access/qhttpnetworkconnectionchannel_p.h -+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h -@@ -83,6 +83,8 @@ typedef QPair HttpMessagePair; - class QHttpNetworkConnectionChannel : public QObject { - Q_OBJECT - public: -+ // TODO: Refactor this to add an EncryptingState (and remove pendingEncrypt). -+ // Also add an Unconnected state so IdleState does not have double meaning. - enum ChannelState { - IdleState = 0, // ready to send request - ConnectingState = 1, // connecting to host -diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp -index 28e10f7..3357948 100644 ---- a/src/network/access/qhttpprotocolhandler.cpp -+++ b/src/network/access/qhttpprotocolhandler.cpp -@@ -368,6 +368,13 @@ bool QHttpProtocolHandler::sendRequest() - // nothing to read currently, break the loop - break; - } else { -+ if (m_channel->written != uploadByteDevice->pos()) { -+ // Sanity check. This was useful in tracking down an upload corruption. -+ qWarning() << "QHttpProtocolHandler: Internal error in sendRequest. Expected to write at position" << m_channel->written << "but read device is at" << uploadByteDevice->pos(); -+ Q_ASSERT(m_channel->written == uploadByteDevice->pos()); -+ m_connection->d_func()->emitReplyError(m_socket, m_reply, QNetworkReply::ProtocolFailure); -+ return false; -+ } - qint64 currentWriteSize = m_socket->write(readPointer, currentReadSize); - if (currentWriteSize == -1 || currentWriteSize != currentReadSize) { - // socket broke down -diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h -index 1661082..b553409 100644 ---- a/src/network/access/qhttpthreaddelegate_p.h -+++ b/src/network/access/qhttpthreaddelegate_p.h -@@ -187,6 +187,7 @@ protected: - QByteArray m_dataArray; - bool m_atEnd; - qint64 m_size; -+ qint64 m_pos; // to match calls of haveDataSlot with the expected position - public: - QNonContiguousByteDeviceThreadForwardImpl(bool aE, qint64 s) - : QNonContiguousByteDevice(), -@@ -194,7 +195,8 @@ public: - m_amount(0), - m_data(0), - m_atEnd(aE), -- m_size(s) -+ m_size(s), -+ m_pos(0) - { - } - -@@ -202,6 +204,11 @@ public: - { - } - -+ qint64 pos() Q_DECL_OVERRIDE -+ { -+ return m_pos; -+ } -+ - const char* readPointer(qint64 maximumLength, qint64 &len) - { - if (m_amount > 0) { -@@ -229,11 +236,10 @@ public: - - m_amount -= a; - m_data += a; -+ m_pos += a; - -- // To main thread to inform about our state -- emit processedData(a); -- -- // FIXME possible optimization, already ask user thread for some data -+ // To main thread to inform about our state. The m_pos will be sent as a sanity check. -+ emit processedData(m_pos, a); - - return true; - } -@@ -250,10 +256,21 @@ public: - { - m_amount = 0; - m_data = 0; -+ m_dataArray.clear(); -+ -+ if (wantDataPending) { -+ // had requested the user thread to send some data (only 1 in-flight at any moment) -+ wantDataPending = false; -+ } - - // Communicate as BlockingQueuedConnection - bool b = false; - emit resetData(&b); -+ if (b) { -+ // the reset succeeded, we're at pos 0 again -+ m_pos = 0; -+ // the HTTP code will anyway abort the request if !b. -+ } - return b; - } - -@@ -264,8 +281,13 @@ public: - - public slots: - // From user thread: -- void haveDataSlot(QByteArray dataArray, bool dataAtEnd, qint64 dataSize) -+ void haveDataSlot(qint64 pos, QByteArray dataArray, bool dataAtEnd, qint64 dataSize) - { -+ if (pos != m_pos) { -+ // Sometimes when re-sending a request in the qhttpnetwork* layer there is a pending haveData from the -+ // user thread on the way to us. We need to ignore it since it is the data for the wrong(later) chunk. -+ return; -+ } - wantDataPending = false; - - m_dataArray = dataArray; -@@ -285,7 +307,7 @@ signals: - - // to main thread: - void wantData(qint64); -- void processedData(qint64); -+ void processedData(qint64 pos, qint64 amount); - void resetData(bool *b); - }; - -diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp -index 4ce7303..974a101 100644 ---- a/src/network/access/qnetworkreplyhttpimpl.cpp -+++ b/src/network/access/qnetworkreplyhttpimpl.cpp -@@ -424,6 +424,7 @@ QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate() - , synchronous(false) - , state(Idle) - , statusCode(0) -+ , uploadByteDevicePosition(false) - , uploadDeviceChoking(false) - , outgoingData(0) - , bytesUploaded(-1) -@@ -863,9 +864,9 @@ void QNetworkReplyHttpImplPrivate::postRequest() - q, SLOT(uploadByteDeviceReadyReadSlot()), - Qt::QueuedConnection); - -- // From main thread to user thread: -- QObject::connect(q, SIGNAL(haveUploadData(QByteArray,bool,qint64)), -- forwardUploadDevice, SLOT(haveDataSlot(QByteArray,bool,qint64)), Qt::QueuedConnection); -+ // From user thread to http thread: -+ QObject::connect(q, SIGNAL(haveUploadData(qint64,QByteArray,bool,qint64)), -+ forwardUploadDevice, SLOT(haveDataSlot(qint64,QByteArray,bool,qint64)), Qt::QueuedConnection); - QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()), - forwardUploadDevice, SIGNAL(readyRead()), - Qt::QueuedConnection); -@@ -873,8 +874,8 @@ void QNetworkReplyHttpImplPrivate::postRequest() - // From http thread to user thread: - QObject::connect(forwardUploadDevice, SIGNAL(wantData(qint64)), - q, SLOT(wantUploadDataSlot(qint64))); -- QObject::connect(forwardUploadDevice, SIGNAL(processedData(qint64)), -- q, SLOT(sentUploadDataSlot(qint64))); -+ QObject::connect(forwardUploadDevice,SIGNAL(processedData(qint64, qint64)), -+ q, SLOT(sentUploadDataSlot(qint64,qint64))); - QObject::connect(forwardUploadDevice, SIGNAL(resetData(bool*)), - q, SLOT(resetUploadDataSlot(bool*)), - Qt::BlockingQueuedConnection); // this is the only one with BlockingQueued! -@@ -1268,12 +1269,22 @@ void QNetworkReplyHttpImplPrivate::replySslConfigurationChanged(const QSslConfig - void QNetworkReplyHttpImplPrivate::resetUploadDataSlot(bool *r) - { - *r = uploadByteDevice->reset(); -+ if (*r) { -+ // reset our own position which is used for the inter-thread communication -+ uploadByteDevicePosition = 0; -+ } - } - - // Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread --void QNetworkReplyHttpImplPrivate::sentUploadDataSlot(qint64 amount) -+void QNetworkReplyHttpImplPrivate::sentUploadDataSlot(qint64 pos, qint64 amount) - { -+ if (uploadByteDevicePosition + amount != pos) { -+ // Sanity check, should not happen. -+ error(QNetworkReply::UnknownNetworkError, ""); -+ return; -+ } - uploadByteDevice->advanceReadPointer(amount); -+ uploadByteDevicePosition += amount; - } - - // Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread -@@ -1298,7 +1309,7 @@ void QNetworkReplyHttpImplPrivate::wantUploadDataSlot(qint64 maxSize) - QByteArray dataArray(data, currentUploadDataLength); - - // Communicate back to HTTP thread -- emit q->haveUploadData(dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size()); -+ emit q->haveUploadData(uploadByteDevicePosition, dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size()); - } - - void QNetworkReplyHttpImplPrivate::uploadByteDeviceReadyReadSlot() -diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h -index 77d9c5a..1940922 100644 ---- a/src/network/access/qnetworkreplyhttpimpl_p.h -+++ b/src/network/access/qnetworkreplyhttpimpl_p.h -@@ -120,7 +120,7 @@ public: - - Q_PRIVATE_SLOT(d_func(), void resetUploadDataSlot(bool *r)) - Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64)) -- Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64)) -+ Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64,qint64)) - Q_PRIVATE_SLOT(d_func(), void uploadByteDeviceReadyReadSlot()) - Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64)) - Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose()) -@@ -144,7 +144,7 @@ signals: - - void startHttpRequestSynchronously(); - -- void haveUploadData(QByteArray dataArray, bool dataAtEnd, qint64 dataSize); -+ void haveUploadData(const qint64 pos, QByteArray dataArray, bool dataAtEnd, qint64 dataSize); - }; - - class QNetworkReplyHttpImplPrivate: public QNetworkReplyPrivate -@@ -195,6 +195,7 @@ public: - // upload - QNonContiguousByteDevice* createUploadByteDevice(); - QSharedPointer uploadByteDevice; -+ qint64 uploadByteDevicePosition; - bool uploadDeviceChoking; // if we couldn't readPointer() any data at the moment - QIODevice *outgoingData; - QSharedPointer outgoingDataBuffer; -@@ -283,7 +284,7 @@ public: - // From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread: - void resetUploadDataSlot(bool *r); - void wantUploadDataSlot(qint64); -- void sentUploadDataSlot(qint64); -+ void sentUploadDataSlot(qint64, qint64); - - // From user's QNonContiguousByteDevice - void uploadByteDeviceReadyReadSlot(); -diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp -index 3ccedf6..d2edf67 100644 ---- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp -+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp -@@ -457,6 +457,10 @@ private Q_SLOTS: - - void putWithRateLimiting(); - -+#ifndef QT_NO_SSL -+ void putWithServerClosingConnectionImmediately(); -+#endif -+ - // NOTE: This test must be last! - void parentingRepliesToTheApp(); - private: -@@ -4718,18 +4722,22 @@ void tst_QNetworkReply::ioPostToHttpNoBufferFlag() - class SslServer : public QTcpServer { - Q_OBJECT - public: -- SslServer() : socket(0) {}; -+ SslServer() : socket(0), m_ssl(true) {} - void incomingConnection(qintptr socketDescriptor) { - QSslSocket *serverSocket = new QSslSocket; - serverSocket->setParent(this); - - if (serverSocket->setSocketDescriptor(socketDescriptor)) { -+ connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot())); -+ if (!m_ssl) { -+ emit newPlainConnection(serverSocket); -+ return; -+ } - QString testDataDir = QFileInfo(QFINDTESTDATA("rfc3252.txt")).absolutePath(); - if (testDataDir.isEmpty()) - testDataDir = QCoreApplication::applicationDirPath(); - - connect(serverSocket, SIGNAL(encrypted()), this, SLOT(encryptedSlot())); -- connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot())); - serverSocket->setProtocol(QSsl::AnyProtocol); - connect(serverSocket, SIGNAL(sslErrors(QList)), serverSocket, SLOT(ignoreSslErrors())); - serverSocket->setLocalCertificate(testDataDir + "/certs/server.pem"); -@@ -4740,11 +4748,12 @@ public: - } - } - signals: -- void newEncryptedConnection(); -+ void newEncryptedConnection(QSslSocket *s); -+ void newPlainConnection(QSslSocket *s); - public slots: - void encryptedSlot() { - socket = (QSslSocket*) sender(); -- emit newEncryptedConnection(); -+ emit newEncryptedConnection(socket); - } - void readyReadSlot() { - // for the incoming sockets, not the server socket -@@ -4753,6 +4762,7 @@ public slots: - - public: - QSslSocket *socket; -+ bool m_ssl; - }; - - // very similar to ioPostToHttpUploadProgress but for SSL -@@ -4780,7 +4790,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress() - QNetworkReplyPtr reply(manager.post(request, sourceFile)); - - QSignalSpy spy(reply.data(), SIGNAL(uploadProgress(qint64,qint64))); -- connect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop())); -+ connect(&server, SIGNAL(newEncryptedConnection(QSslSocket*)), &QTestEventLoop::instance(), SLOT(exitLoop())); - connect(reply, SIGNAL(sslErrors(QList)), reply.data(), SLOT(ignoreSslErrors())); - - // get the request started and the incoming socket connected -@@ -4788,7 +4798,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress() - QVERIFY(!QTestEventLoop::instance().timeout()); - QTcpSocket *incomingSocket = server.socket; - QVERIFY(incomingSocket); -- disconnect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop())); -+ disconnect(&server, SIGNAL(newEncryptedConnection(QSslSocket*)), &QTestEventLoop::instance(), SLOT(exitLoop())); - - - incomingSocket->setReadBufferSize(1*1024); -@@ -7905,6 +7915,159 @@ void tst_QNetworkReply::putWithRateLimiting() - } - - -+#ifndef QT_NO_SSL -+ -+class PutWithServerClosingConnectionImmediatelyHandler: public QObject -+{ -+ Q_OBJECT -+public: -+ bool m_parsedHeaders; -+ QByteArray m_receivedData; -+ QByteArray m_expectedData; -+ QSslSocket *m_socket; -+ PutWithServerClosingConnectionImmediatelyHandler(QSslSocket *s, QByteArray expected) :m_parsedHeaders(false), m_expectedData(expected), m_socket(s) -+ { -+ m_socket->setParent(this); -+ connect(m_socket, SIGNAL(readyRead()), SLOT(readyReadSlot())); -+ connect(m_socket, SIGNAL(disconnected()), SLOT(disconnectedSlot())); -+ } -+signals: -+ void correctFileUploadReceived(); -+ void corruptFileUploadReceived(); -+ -+public slots: -+ void closeDelayed() { -+ m_socket->close(); -+ } -+ -+ void readyReadSlot() -+ { -+ QByteArray data = m_socket->readAll(); -+ m_receivedData += data; -+ if (!m_parsedHeaders && m_receivedData.contains("\r\n\r\n")) { -+ m_parsedHeaders = true; -+ QTimer::singleShot(qrand()%10, this, SLOT(closeDelayed())); // simulate random network latency -+ // This server simulates a web server connection closing, e.g. because of Apaches MaxKeepAliveRequests or KeepAliveTimeout -+ // In this case QNAM needs to re-send the upload data but it had a bug which then corrupts the upload -+ // This test catches that. -+ } -+ -+ } -+ void disconnectedSlot() -+ { -+ if (m_parsedHeaders) { -+ //qDebug() << m_receivedData.left(m_receivedData.indexOf("\r\n\r\n")); -+ m_receivedData = m_receivedData.mid(m_receivedData.indexOf("\r\n\r\n")+4); // check only actual data -+ } -+ if (m_receivedData.length() > 0 && !m_expectedData.startsWith(m_receivedData)) { -+ // We had received some data but it is corrupt! -+ qDebug() << "CORRUPT" << m_receivedData.count(); -+ -+ // Use this to track down the pattern of the corruption and conclude the source -+// QFile a("/tmp/corrupt"); -+// a.open(QIODevice::WriteOnly); -+// a.write(m_receivedData); -+// a.close(); -+ -+// QFile b("/tmp/correct"); -+// b.open(QIODevice::WriteOnly); -+// b.write(m_expectedData); -+// b.close(); -+ //exit(1); -+ emit corruptFileUploadReceived(); -+ } else { -+ emit correctFileUploadReceived(); -+ } -+ } -+}; -+ -+class PutWithServerClosingConnectionImmediatelyServer: public SslServer -+{ -+ Q_OBJECT -+public: -+ int m_correctUploads; -+ int m_corruptUploads; -+ int m_repliesFinished; -+ int m_expectedReplies; -+ QByteArray m_expectedData; -+ PutWithServerClosingConnectionImmediatelyServer() : SslServer(), m_correctUploads(0), m_corruptUploads(0), m_repliesFinished(0), m_expectedReplies(0) -+ { -+ QObject::connect(this, SIGNAL(newEncryptedConnection(QSslSocket*)), this, SLOT(createHandlerForConnection(QSslSocket*))); -+ QObject::connect(this, SIGNAL(newPlainConnection(QSslSocket*)), this, SLOT(createHandlerForConnection(QSslSocket*))); -+ } -+ -+public slots: -+ void createHandlerForConnection(QSslSocket* s) { -+ PutWithServerClosingConnectionImmediatelyHandler *handler = new PutWithServerClosingConnectionImmediatelyHandler(s, m_expectedData); -+ handler->setParent(this); -+ QObject::connect(handler, SIGNAL(correctFileUploadReceived()), this, SLOT(increaseCorrect())); -+ QObject::connect(handler, SIGNAL(corruptFileUploadReceived()), this, SLOT(increaseCorrupt())); -+ } -+ void increaseCorrect() { -+ m_correctUploads++; -+ } -+ void increaseCorrupt() { -+ m_corruptUploads++; -+ } -+ void replyFinished() { -+ m_repliesFinished++; -+ if (m_repliesFinished == m_expectedReplies) { -+ QTestEventLoop::instance().exitLoop(); -+ } -+ } -+}; -+ -+ -+ -+void tst_QNetworkReply::putWithServerClosingConnectionImmediately() -+{ -+ const int numUploads = 40; -+ qint64 wantedSize = 512*1024; // 512 kB -+ QByteArray sourceFile; -+ for (int i = 0; i < wantedSize; ++i) { -+ sourceFile += (char)'a' +(i%26); -+ } -+ bool withSsl = false; -+ -+ for (int s = 0; s <= 1; s++) { -+ withSsl = (s == 1); -+ // Test also needs to run several times because of 9c2ecf89 -+ for (int j = 0; j < 20; j++) { -+ // emulate a minimal https server -+ PutWithServerClosingConnectionImmediatelyServer server; -+ server.m_ssl = withSsl; -+ server.m_expectedData = sourceFile; -+ server.m_expectedReplies = numUploads; -+ server.listen(QHostAddress(QHostAddress::LocalHost), 0); -+ -+ for (int i = 0; i < numUploads; i++) { -+ // create the request -+ QUrl url = QUrl(QString("http%1://127.0.0.1:%2/file=%3").arg(withSsl ? "s" : "").arg(server.serverPort()).arg(i)); -+ QNetworkRequest request(url); -+ QNetworkReply *reply = manager.put(request, sourceFile); -+ connect(reply, SIGNAL(sslErrors(QList)), reply, SLOT(ignoreSslErrors())); -+ connect(reply, SIGNAL(finished()), &server, SLOT(replyFinished())); -+ reply->setParent(&server); -+ } -+ -+ // get the request started and the incoming socket connected -+ QTestEventLoop::instance().enterLoop(10); -+ -+ //qDebug() << "correct=" << server.m_correctUploads << "corrupt=" << server.m_corruptUploads << "expected=" < 5); -+ // Because actually important is that we don't get any corruption: -+ QCOMPARE(server.m_corruptUploads, 0); -+ -+ server.close(); -+ } -+ } -+ -+ -+} -+ -+#endif - - // NOTE: This test must be last testcase in tst_qnetworkreply! - void tst_QNetworkReply::parentingRepliesToTheApp() --- -1.9.1 - diff --git a/admin/qt/patches/0007-X-Network-Fix-up-previous-corruption-patch.patch b/admin/qt/patches/0007-X-Network-Fix-up-previous-corruption-patch.patch deleted file mode 100644 index 4e2fe417eca..00000000000 --- a/admin/qt/patches/0007-X-Network-Fix-up-previous-corruption-patch.patch +++ /dev/null @@ -1,434 +0,0 @@ -From eae0cb09f1310e755c2aff7c1112f7a6c09d7a53 Mon Sep 17 00:00:00 2001 -From: Markus Goetz -Date: Fri, 19 Jun 2015 15:35:34 +0200 -Subject: [PATCH] Network: Fix up previous corruption patch - -This is a fix-up for cff39fba10ffc10ee4dcfdc66ff6528eb26462d3. -That patch lead to some internal state issues that lead to the QTBUG-47048 -or to QNetworkReply objects erroring with "Connection Closed" when -the server closed the Keep-Alive connection. - -This patch changes the QNAM socket slot connections to be DirectConnection. -We don't close the socket anymore in slots where it is anyway in a closed state -afterwards. This prevents event/stack recursions. -We also flush QSslSocket/QTcpSocket receive buffers when receiving a disconnect -so that the developer always gets the full decrypted data from the buffers. - -[ChangeLog][QtNetwork] Fix HTTP issues with "Unknown Error" and "Connection Closed" -[ChangeLog][QtNetwork][Sockets] Read OS/encrypted read buffers when connection -closed by server. - -Change-Id: Ib4d6a2d0d988317e3a5356f36e8dbcee4590beed -Task-number: QTBUG-47048 -Reviewed-by: Kai Koehne -Reviewed-by: Richard J. Moore ---- - src/network/access/qhttpnetworkconnection.cpp | 1 - - .../access/qhttpnetworkconnectionchannel.cpp | 108 +++++++++++++-------- - .../access/qhttpnetworkconnectionchannel_p.h | 1 + - src/network/access/qhttpnetworkreply.cpp | 2 +- - src/network/access/qhttpprotocolhandler.cpp | 1 - - src/network/socket/qabstractsocket.cpp | 7 +- - src/network/ssl/qsslsocket.cpp | 8 ++ - src/network/ssl/qsslsocket_openssl.cpp | 7 ++ - .../access/qnetworkreply/tst_qnetworkreply.cpp | 9 +- - 9 files changed, 94 insertions(+), 50 deletions(-) - -diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp -index 365ce55..543c70e 100644 ---- a/src/network/access/qhttpnetworkconnection.cpp -+++ b/src/network/access/qhttpnetworkconnection.cpp -@@ -917,7 +917,6 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() - for (int i = 0; i < channelCount; ++i) { - if (channels[i].resendCurrent && (channels[i].state != QHttpNetworkConnectionChannel::ClosingState)) { - channels[i].resendCurrent = false; -- channels[i].state = QHttpNetworkConnectionChannel::IdleState; - - // if this is not possible, error will be emitted and connection terminated - if (!channels[i].resetUploadData()) -diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp -index 49c6793..e2f6307 100644 ---- a/src/network/access/qhttpnetworkconnectionchannel.cpp -+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp -@@ -58,6 +58,11 @@ QT_BEGIN_NAMESPACE - - // TODO: Put channel specific stuff here so it does not polute qhttpnetworkconnection.cpp - -+// Because in-flight when sending a request, the server might close our connection (because the persistent HTTP -+// connection times out) -+// We use 3 because we can get a _q_error 3 times depending on the timing: -+static const int reconnectAttemptsDefault = 3; -+ - QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() - : socket(0) - , ssl(false) -@@ -69,7 +74,7 @@ QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() - , resendCurrent(false) - , lastStatus(0) - , pendingEncrypt(false) -- , reconnectAttempts(2) -+ , reconnectAttempts(reconnectAttemptsDefault) - , authMethod(QAuthenticatorPrivate::None) - , proxyAuthMethod(QAuthenticatorPrivate::None) - , authenticationCredentialsSent(false) -@@ -106,19 +111,18 @@ void QHttpNetworkConnectionChannel::init() - socket->setProxy(QNetworkProxy::NoProxy); - #endif - -- // We want all signals (except the interactive ones) be connected as QueuedConnection -- // because else we're falling into cases where we recurse back into the socket code -- // and mess up the state. Always going to the event loop (and expecting that when reading/writing) -- // is safer. -+ // After some back and forth in all the last years, this is now a DirectConnection because otherwise -+ // the state inside the *Socket classes gets messed up, also in conjunction with the socket notifiers -+ // which behave slightly differently on Windows vs Linux - QObject::connect(socket, SIGNAL(bytesWritten(qint64)), - this, SLOT(_q_bytesWritten(qint64)), -- Qt::QueuedConnection); -+ Qt::DirectConnection); - QObject::connect(socket, SIGNAL(connected()), - this, SLOT(_q_connected()), -- Qt::QueuedConnection); -+ Qt::DirectConnection); - QObject::connect(socket, SIGNAL(readyRead()), - this, SLOT(_q_readyRead()), -- Qt::QueuedConnection); -+ Qt::DirectConnection); - - // The disconnected() and error() signals may already come - // while calling connectToHost(). -@@ -129,10 +133,10 @@ void QHttpNetworkConnectionChannel::init() - qRegisterMetaType(); - QObject::connect(socket, SIGNAL(disconnected()), - this, SLOT(_q_disconnected()), -- Qt::QueuedConnection); -+ Qt::DirectConnection); - QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), - this, SLOT(_q_error(QAbstractSocket::SocketError)), -- Qt::QueuedConnection); -+ Qt::DirectConnection); - - - #ifndef QT_NO_NETWORKPROXY -@@ -147,13 +151,13 @@ void QHttpNetworkConnectionChannel::init() - // won't be a sslSocket if encrypt is false - QObject::connect(sslSocket, SIGNAL(encrypted()), - this, SLOT(_q_encrypted()), -- Qt::QueuedConnection); -+ Qt::DirectConnection); - QObject::connect(sslSocket, SIGNAL(sslErrors(QList)), - this, SLOT(_q_sslErrors(QList)), - Qt::DirectConnection); - QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)), - this, SLOT(_q_encryptedBytesWritten(qint64)), -- Qt::QueuedConnection); -+ Qt::DirectConnection); - - if (ignoreAllSslErrors) - sslSocket->ignoreSslErrors(); -@@ -397,7 +401,7 @@ void QHttpNetworkConnectionChannel::allDone() - - // reset the reconnection attempts after we receive a complete reply. - // in case of failures, each channel will attempt two reconnects before emitting error. -- reconnectAttempts = 2; -+ reconnectAttempts = reconnectAttemptsDefault; - - // now the channel can be seen as free/idle again, all signal emissions for the reply have been done - if (state != QHttpNetworkConnectionChannel::ClosingState) -@@ -651,6 +655,15 @@ void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest() - QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); - } - -+void QHttpNetworkConnectionChannel::resendCurrentRequest() -+{ -+ requeueCurrentlyPipelinedRequests(); -+ if (reply) -+ resendCurrent = true; -+ if (qobject_cast(connection)) -+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); -+} -+ - bool QHttpNetworkConnectionChannel::isSocketBusy() const - { - return (state & QHttpNetworkConnectionChannel::BusyState); -@@ -694,8 +707,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected() - return; - } - -- // read the available data before closing -- if (isSocketWaiting() || isSocketReading()) { -+ // read the available data before closing (also done in _q_error for other codepaths) -+ if ((isSocketWaiting() || isSocketReading()) && socket->bytesAvailable()) { - if (reply) { - state = QHttpNetworkConnectionChannel::ReadingState; - _q_receiveReply(); -@@ -707,7 +720,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected() - state = QHttpNetworkConnectionChannel::IdleState; - - requeueCurrentlyPipelinedRequests(); -- close(); -+ -+ pendingEncrypt = false; - } - - -@@ -789,11 +803,19 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket - errorCode = QNetworkReply::ConnectionRefusedError; - break; - case QAbstractSocket::RemoteHostClosedError: -- // try to reconnect/resend before sending an error. -- // while "Reading" the _q_disconnected() will handle this. -- if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) { -+ // This error for SSL comes twice in a row, first from SSL layer ("The TLS/SSL connection has been closed") then from TCP layer. -+ // Depending on timing it can also come three times in a row (first time when we try to write into a closing QSslSocket). -+ // The reconnectAttempts handling catches the cases where we can re-send the request. -+ if (!reply && state == QHttpNetworkConnectionChannel::IdleState) { -+ // Not actually an error, it is normal for Keep-Alive connections to close after some time if no request -+ // is sent on them. No need to error the other replies below. Just bail out here. -+ // The _q_disconnected will handle the possibly pipelined replies -+ return; -+ } else if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) { -+ // Try to reconnect/resend before sending an error. -+ // While "Reading" the _q_disconnected() will handle this. - if (reconnectAttempts-- > 0) { -- closeAndResendCurrentRequest(); -+ resendCurrentRequest(); - return; - } else { - errorCode = QNetworkReply::RemoteHostClosedError; -@@ -818,24 +840,15 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket - // we can ignore the readbuffersize as the data is already - // in memory and we will not receive more data on the socket. - reply->setReadBufferSize(0); -+ reply->setDownstreamLimited(false); - _q_receiveReply(); --#ifndef QT_NO_SSL -- if (ssl) { -- // QT_NO_OPENSSL. The QSslSocket can still have encrypted bytes in the plainsocket. -- // So we need to check this if the socket is a QSslSocket. When the socket is flushed -- // it will force a decrypt of the encrypted data in the plainsocket. -- QSslSocket *sslSocket = static_cast(socket); -- qint64 beforeFlush = sslSocket->encryptedBytesAvailable(); -- while (sslSocket->encryptedBytesAvailable()) { -- sslSocket->flush(); -- _q_receiveReply(); -- qint64 afterFlush = sslSocket->encryptedBytesAvailable(); -- if (afterFlush == beforeFlush) -- break; -- beforeFlush = afterFlush; -- } -+ if (!reply) { -+ // No more reply assigned after the previous call? Then it had been finished successfully. -+ requeueCurrentlyPipelinedRequests(); -+ state = QHttpNetworkConnectionChannel::IdleState; -+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); -+ return; - } --#endif - } - - errorCode = QNetworkReply::RemoteHostClosedError; -@@ -846,7 +859,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket - case QAbstractSocket::SocketTimeoutError: - // try to reconnect/resend before sending an error. - if (state == QHttpNetworkConnectionChannel::WritingState && (reconnectAttempts-- > 0)) { -- closeAndResendCurrentRequest(); -+ resendCurrentRequest(); - return; - } - errorCode = QNetworkReply::TimeoutError; -@@ -860,7 +873,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket - case QAbstractSocket::ProxyConnectionClosedError: - // try to reconnect/resend before sending an error. - if (reconnectAttempts-- > 0) { -- closeAndResendCurrentRequest(); -+ resendCurrentRequest(); - return; - } - errorCode = QNetworkReply::ProxyConnectionClosedError; -@@ -868,7 +881,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket - case QAbstractSocket::ProxyConnectionTimeoutError: - // try to reconnect/resend before sending an error. - if (reconnectAttempts-- > 0) { -- closeAndResendCurrentRequest(); -+ resendCurrentRequest(); - return; - } - errorCode = QNetworkReply::ProxyTimeoutError; -@@ -916,8 +929,18 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket - // send the next request - QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection); - -- if (that) //signal emission triggered event loop -- close(); -+ if (that) { -+ //signal emission triggered event loop -+ if (!socket) -+ state = QHttpNetworkConnectionChannel::IdleState; -+ else if (socket->state() == QAbstractSocket::UnconnectedState) -+ state = QHttpNetworkConnectionChannel::IdleState; -+ else -+ state = QHttpNetworkConnectionChannel::ClosingState; -+ -+ // pendingEncrypt must only be true in between connected and encrypted states -+ pendingEncrypt = false; -+ } - } - - #ifndef QT_NO_NETWORKPROXY -@@ -941,7 +964,8 @@ void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetwor - - void QHttpNetworkConnectionChannel::_q_uploadDataReadyRead() - { -- sendRequest(); -+ if (reply) -+ sendRequest(); - } - - #ifndef QT_NO_SSL -diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h -index 231fe11..a834b7d 100644 ---- a/src/network/access/qhttpnetworkconnectionchannel_p.h -+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h -@@ -169,6 +169,7 @@ public: - - void handleUnexpectedEOF(); - void closeAndResendCurrentRequest(); -+ void resendCurrentRequest(); - - bool isSocketBusy() const; - bool isSocketWriting() const; -diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp -index 55863a3..8b71bd8 100644 ---- a/src/network/access/qhttpnetworkreply.cpp -+++ b/src/network/access/qhttpnetworkreply.cpp -@@ -191,7 +191,7 @@ QByteArray QHttpNetworkReply::readAny() - return QByteArray(); - - // we'll take the last buffer, so schedule another read from http -- if (d->downstreamLimited && d->responseData.bufferCount() == 1) -+ if (d->downstreamLimited && d->responseData.bufferCount() == 1 && !isFinished()) - d->connection->d_func()->readMoreLater(this); - return d->responseData.read(); - } -diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp -index 3357948..380aaac 100644 ---- a/src/network/access/qhttpprotocolhandler.cpp -+++ b/src/network/access/qhttpprotocolhandler.cpp -@@ -250,7 +250,6 @@ bool QHttpProtocolHandler::sendRequest() - if (!m_reply) { - // heh, how should that happen! - qWarning() << "QAbstractProtocolHandler::sendRequest() called without QHttpNetworkReply"; -- m_channel->state = QHttpNetworkConnectionChannel::IdleState; - return false; - } - -diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp -index 2666771..0e82d4a 100644 ---- a/src/network/socket/qabstractsocket.cpp -+++ b/src/network/socket/qabstractsocket.cpp -@@ -768,6 +768,7 @@ bool QAbstractSocketPrivate::canReadNotification() - void QAbstractSocketPrivate::canCloseNotification() - { - Q_Q(QAbstractSocket); -+ // Note that this method is only called on Windows. Other platforms close in the canReadNotification() - - #if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocketPrivate::canCloseNotification()"); -@@ -777,7 +778,11 @@ void QAbstractSocketPrivate::canCloseNotification() - if (isBuffered) { - // Try to read to the buffer, if the read fail we can close the socket. - newBytes = buffer.size(); -- if (!readFromSocket()) { -+ qint64 oldReadBufferMaxSize = readBufferMaxSize; -+ readBufferMaxSize = 0; // temporarily disable max read buffer, we want to empty the OS buffer -+ bool hadReadFromSocket = readFromSocket(); -+ readBufferMaxSize = oldReadBufferMaxSize; -+ if (!hadReadFromSocket) { - q->disconnectFromHost(); - return; - } -diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp -index c1fab94..2b9e923 100644 ---- a/src/network/ssl/qsslsocket.cpp -+++ b/src/network/ssl/qsslsocket.cpp -@@ -2294,6 +2294,14 @@ void QSslSocketPrivate::_q_errorSlot(QAbstractSocket::SocketError error) - qCDebug(lcSsl) << "\tstate =" << q->state(); - qCDebug(lcSsl) << "\terrorString =" << q->errorString(); - #endif -+ // this moves encrypted bytes from plain socket into our buffer -+ if (plainSocket->bytesAvailable()) { -+ qint64 tmpReadBufferMaxSize = readBufferMaxSize; -+ readBufferMaxSize = 0; // reset temporarily so the plain sockets completely drained drained -+ transmit(); -+ readBufferMaxSize = tmpReadBufferMaxSize; -+ } -+ - q->setSocketError(plainSocket->error()); - q->setErrorString(plainSocket->errorString()); - emit q->error(error); -diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp -index ac4336a..94655fe 100644 ---- a/src/network/ssl/qsslsocket_openssl.cpp -+++ b/src/network/ssl/qsslsocket_openssl.cpp -@@ -1419,6 +1419,13 @@ void QSslSocketBackendPrivate::disconnected() - { - if (plainSocket->bytesAvailable() <= 0) - destroySslContext(); -+ else { -+ // Move all bytes into the plain buffer -+ qint64 tmpReadBufferMaxSize = readBufferMaxSize; -+ readBufferMaxSize = 0; // reset temporarily so the plain socket buffer is completely drained -+ transmit(); -+ readBufferMaxSize = tmpReadBufferMaxSize; -+ } - //if there is still buffered data in the plain socket, don't destroy the ssl context yet. - //it will be destroyed when the socket is deleted. - } -diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp -index d2edf67..138f528 100644 ---- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp -+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp -@@ -1051,7 +1051,7 @@ protected: - // clean up QAbstractSocket's residue: - while (client->bytesToWrite() > 0) { - qDebug() << "Still having" << client->bytesToWrite() << "bytes to write, doing that now"; -- if (!client->waitForBytesWritten(2000)) { -+ if (!client->waitForBytesWritten(10000)) { - qDebug() << "ERROR: FastSender:" << client->error() << "cleaning up residue"; - return; - } -@@ -1071,7 +1071,7 @@ protected: - measuredSentBytes += writeNextData(client, bytesToWrite); - - while (client->bytesToWrite() > 0) { -- if (!client->waitForBytesWritten(2000)) { -+ if (!client->waitForBytesWritten(10000)) { - qDebug() << "ERROR: FastSender:" << client->error() << "during blocking write"; - return; - } -@@ -7946,7 +7946,7 @@ public slots: - m_receivedData += data; - if (!m_parsedHeaders && m_receivedData.contains("\r\n\r\n")) { - m_parsedHeaders = true; -- QTimer::singleShot(qrand()%10, this, SLOT(closeDelayed())); // simulate random network latency -+ QTimer::singleShot(qrand()%60, this, SLOT(closeDelayed())); // simulate random network latency - // This server simulates a web server connection closing, e.g. because of Apaches MaxKeepAliveRequests or KeepAliveTimeout - // In this case QNAM needs to re-send the upload data but it had a bug which then corrupts the upload - // This test catches that. -@@ -8052,11 +8052,12 @@ void tst_QNetworkReply::putWithServerClosingConnectionImmediately() - - // get the request started and the incoming socket connected - QTestEventLoop::instance().enterLoop(10); -+ QVERIFY(!QTestEventLoop::instance().timeout()); - - //qDebug() << "correct=" << server.m_correctUploads << "corrupt=" << server.m_corruptUploads << "expected=" < 5); -+ QVERIFY(server.m_correctUploads > 2); - // Because actually important is that we don't get any corruption: - QCOMPARE(server.m_corruptUploads, 0); - --- -1.9.1 diff --git a/admin/qt/patches/0008-QNAM-Fix-reply-deadlocks-on-server-closing-connectio.patch b/admin/qt/patches/0008-QNAM-Fix-reply-deadlocks-on-server-closing-connectio.patch deleted file mode 100644 index c425118aafb..00000000000 --- a/admin/qt/patches/0008-QNAM-Fix-reply-deadlocks-on-server-closing-connectio.patch +++ /dev/null @@ -1,64 +0,0 @@ -From bc32c0ebc0bc00db84ca2f28eb16ab2e5b53a1b6 Mon Sep 17 00:00:00 2001 -From: Markus Goetz -Date: Fri, 24 Jul 2015 09:53:20 +0200 -Subject: [PATCH] QNAM: Fix reply deadlocks on server closing connection - -The _q_readyRead can also be called from readMoreLater() because we implemented -it so that bandwidth limited reading can be implemented. -This can lead to a race condition if the socket is closing at the specific moment -and then deadlock the channel: It will stay unusable with a zombie request. -The fix in QHttpProtocolaHandler checks if there is actually bytes available to read -from the socket and only then continue. - -The fix in the HTTP channel needs to be done to properly finish the reply in -cases of a server replying with HTTP/1.0 or "Connection: close". -The delayed incovation of _q_receiveReply will properly finish up the reply. - -Change-Id: I19ce2ae595f91d56386cc7406ccacc9935672b6b -Reviewed-by: Richard J. Moore ---- - src/network/access/qhttpnetworkconnectionchannel.cpp | 4 ++++ - src/network/access/qhttpprotocolhandler.cpp | 7 ++++++- - 2 files changed, 10 insertions(+), 1 deletion(-) - -diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp -index 7428f9b..257aa13 100644 ---- a/src/network/access/qhttpnetworkconnectionchannel.cpp -+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp -@@ -829,11 +829,15 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket - - if (!reply->d_func()->expectContent()) { - // No content expected, this is a valid way to have the connection closed by the server -+ // We need to invoke this asynchronously to make sure the state() of the socket is on QAbstractSocket::UnconnectedState -+ QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection); - return; - } - if (reply->contentLength() == -1 && !reply->d_func()->isChunked()) { - // There was no content-length header and it's not chunked encoding, - // so this is a valid way to have the connection closed by the server -+ // We need to invoke this asynchronously to make sure the state() of the socket is on QAbstractSocket::UnconnectedState -+ QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection); - return; - } - // ok, we got a disconnect even though we did not expect it -diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp -index ab2e3da..a208315 100644 ---- a/src/network/access/qhttpprotocolhandler.cpp -+++ b/src/network/access/qhttpprotocolhandler.cpp -@@ -237,7 +237,12 @@ void QHttpProtocolHandler::_q_readyRead() - } - - if (m_channel->isSocketWaiting() || m_channel->isSocketReading()) { -- m_channel->state = QHttpNetworkConnectionChannel::ReadingState; -+ if (m_socket->bytesAvailable()) { -+ // We might get a spurious call from readMoreLater() -+ // call of the QHttpNetworkConnection even while the socket is disconnecting. -+ // Therefore check if there is actually bytes available before changing the channel state. -+ m_channel->state = QHttpNetworkConnectionChannel::ReadingState; -+ } - if (m_reply) - _q_receiveReply(); - } --- -1.9.1 - diff --git a/admin/qt/patches/0009-QNAM-Assign-proper-channel-before-sslErrors-emission.patch b/admin/qt/patches/0009-QNAM-Assign-proper-channel-before-sslErrors-emission.patch deleted file mode 100644 index e66c4c2d5c5..00000000000 --- a/admin/qt/patches/0009-QNAM-Assign-proper-channel-before-sslErrors-emission.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 63cf5d3d26a6f65938c3cdec1734eac9faaaf8cb Mon Sep 17 00:00:00 2001 -From: Markus Goetz -Date: Tue, 22 Sep 2015 14:26:24 -0400 -Subject: [PATCH] QNAM: Assign proper channel before sslErrors() emission - -There can be a race condition where another channel connects -and gets the sslErrors() from the socket first. Then the -QSslConfiguration from the wrong socket (the default -channel 0's socket) was used. - -Task-number: QTBUG-18722 -Change-Id: Ibbfa48c27f181563745daf540fa792a57cc09682 -Reviewed-by: Richard J. Moore ---- - src/network/access/qhttpnetworkconnectionchannel.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp -index 257aa13..477cba2 100644 ---- a/src/network/access/qhttpnetworkconnectionchannel.cpp -+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp -@@ -1066,6 +1066,8 @@ void QHttpNetworkConnectionChannel::_q_sslErrors(const QList &errors) - connection->d_func()->pauseConnection(); - if (pendingEncrypt && !reply) - connection->d_func()->dequeueRequest(socket); -+ if (reply) // a reply was actually dequeued. -+ reply->d_func()->connectionChannel = this; // set correct channel like in sendRequest() and queueRequest(); - if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP) { - if (reply) - emit reply->sslErrors(errors); --- -1.9.1 - diff --git a/admin/qt/patches/0010-Don-t-let-closed-http-sockets-pass-as-valid-connecti.patch b/admin/qt/patches/0010-Don-t-let-closed-http-sockets-pass-as-valid-connecti.patch deleted file mode 100644 index c883e3d952c..00000000000 --- a/admin/qt/patches/0010-Don-t-let-closed-http-sockets-pass-as-valid-connecti.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0df5d079290b4c3b13e58e9397fabdc1dfdba96b Mon Sep 17 00:00:00 2001 -From: Ulf Hermann -Date: Fri, 25 Sep 2015 13:23:46 +0200 -Subject: [PATCH] Don't let closed http sockets pass as valid connections - -A QAbstractSocket can be close()'d at any time, independently of its -current connection state. being closed means that we cannot use it to -read or write data, but internally it might still have some data to -send or receive, for example to an http server. We can even get a -connected() signal after close()'ing the socket. - -We need to catch this condition and mark any pending data not yet -written to the socket for resending. - -Task-number: QTBUG-48326 -Change-Id: I6f61c35f2c567f2a138f8cfe9ade7fd1ec039be6 -Reviewed-by: Simon Hausmann ---- - .../access/qhttpnetworkconnectionchannel.cpp | 7 ++- - .../tst_qhttpnetworkconnection.cpp | 54 ++++++++++++++++++++++ - 2 files changed, 60 insertions(+), 1 deletion(-) - -diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp -index 293909c..b4eda34 100644 ---- a/src/network/access/qhttpnetworkconnectionchannel.cpp -+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp -@@ -272,7 +272,12 @@ bool QHttpNetworkConnectionChannel::ensureConnection() - QAbstractSocket::SocketState socketState = socket->state(); - - // resend this request after we receive the disconnected signal -- if (socketState == QAbstractSocket::ClosingState) { -+ // If !socket->isOpen() then we have already called close() on the socket, but there was still a -+ // pending connectToHost() for which we hadn't seen a connected() signal, yet. The connected() -+ // has now arrived (as indicated by socketState != ClosingState), but we cannot send anything on -+ // such a socket anymore. -+ if (socketState == QAbstractSocket::ClosingState || -+ (socketState != QAbstractSocket::UnconnectedState && !socket->isOpen())) { - if (reply) - resendCurrent = true; - return false; -diff --git a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp -index 5d072af..0d188a8 100644 ---- a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp -+++ b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp -@@ -36,6 +36,7 @@ - #include "private/qhttpnetworkconnection_p.h" - #include "private/qnoncontiguousbytedevice_p.h" - #include -+#include - - #include "../../../network-settings.h" - -@@ -106,6 +107,8 @@ private Q_SLOTS: - - void getAndThenDeleteObject(); - void getAndThenDeleteObject_data(); -+ -+ void overlappingCloseAndWrite(); - }; - - tst_QHttpNetworkConnection::tst_QHttpNetworkConnection() -@@ -1112,6 +1115,57 @@ void tst_QHttpNetworkConnection::getAndThenDeleteObject() - } - } - -+class TestTcpServer : public QTcpServer -+{ -+ Q_OBJECT -+public: -+ TestTcpServer() : errorCodeReports(0) -+ { -+ connect(this, &QTcpServer::newConnection, this, &TestTcpServer::onNewConnection); -+ QVERIFY(listen(QHostAddress::LocalHost)); -+ } -+ -+ int errorCodeReports; -+ -+public slots: -+ void onNewConnection() -+ { -+ QTcpSocket *socket = nextPendingConnection(); -+ if (!socket) -+ return; -+ // close socket instantly! -+ connect(socket, &QTcpSocket::readyRead, socket, &QTcpSocket::close); -+ } -+ -+ void onReply(QNetworkReply::NetworkError code) -+ { -+ QCOMPARE(code, QNetworkReply::RemoteHostClosedError); -+ ++errorCodeReports; -+ } -+}; -+ -+void tst_QHttpNetworkConnection::overlappingCloseAndWrite() -+{ -+ // server accepts connections, but closes the socket instantly -+ TestTcpServer server; -+ QNetworkAccessManager accessManager; -+ -+ // ten requests are scheduled. All should result in an RemoteHostClosed... -+ QUrl url; -+ url.setScheme(QStringLiteral("http")); -+ url.setHost(server.serverAddress().toString()); -+ url.setPort(server.serverPort()); -+ for (int i = 0; i < 10; ++i) { -+ QNetworkRequest request(url); -+ QNetworkReply *reply = accessManager.get(request); -+ // Not using Qt5 connection syntax here because of overly baroque syntax to discern between -+ // different error() methods. -+ QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), -+ &server, SLOT(onReply(QNetworkReply::NetworkError))); -+ } -+ -+ QTRY_COMPARE(server.errorCodeReports, 10); -+} - - - QTEST_MAIN(tst_QHttpNetworkConnection) --- -1.9.1 diff --git a/admin/qt/patches/0011-Make-sure-to-report-correct-NetworkAccessibility.patch b/admin/qt/patches/0011-Make-sure-to-report-correct-NetworkAccessibility.patch deleted file mode 100644 index 9fe366df2f3..00000000000 --- a/admin/qt/patches/0011-Make-sure-to-report-correct-NetworkAccessibility.patch +++ /dev/null @@ -1,113 +0,0 @@ -From c056e63cea1915667997c982f48296ce5acdcc80 Mon Sep 17 00:00:00 2001 -From: Lorn Potter -Date: Tue, 2 Jun 2015 13:22:23 +1000 -Subject: [PATCH] Make sure to report correct NetworkAccessibility - -Task-number: QTBUG-46323 -Change-Id: Ibdeb3280091a97d785d4314340678a63e88fb219 -Reviewed-by: Markus Goetz (Woboq GmbH) -Reviewed-by: Alex Blasche ---- - src/network/access/qnetworkaccessmanager.cpp | 25 +++++++++++++++++-------- - src/network/access/qnetworkaccessmanager_p.h | 2 ++ - 2 files changed, 19 insertions(+), 8 deletions(-) - -diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp -index e878feb..84931cb 100644 ---- a/src/network/access/qnetworkaccessmanager.cpp -+++ b/src/network/access/qnetworkaccessmanager.cpp -@@ -472,11 +472,11 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) - // the QNetworkSession's signals - connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), - SLOT(_q_onlineStateChanged(bool))); -- // we would need all active configurations to check for -- // d->networkConfigurationManager.isOnline(), which is asynchronous -- // and potentially expensive. We can just check the configuration here -- d->online = (d->networkConfiguration.state() & QNetworkConfiguration::Active); - } -+ // we would need all active configurations to check for -+ // d->networkConfigurationManager.isOnline(), which is asynchronous -+ // and potentially expensive. We can just check the configuration here -+ d->online = (d->networkConfiguration.state() & QNetworkConfiguration::Active); - #endif - } - -@@ -946,6 +946,7 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const - void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible) - { - Q_D(QNetworkAccessManager); -+ d->defaultAccessControl = false; - - if (d->networkAccessible != accessible) { - NetworkAccessibility previous = networkAccessible(); -@@ -964,7 +965,6 @@ void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkA - QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const - { - Q_D(const QNetworkAccessManager); -- - if (d->networkSessionRequired) { - QSharedPointer networkSession(d->getNetworkSession()); - if (networkSession) { -@@ -975,7 +975,13 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess - return NotAccessible; - } else { - // Network accessibility is either disabled or unknown. -- return (d->networkAccessible == NotAccessible) ? NotAccessible : UnknownAccessibility; -+ if (d->defaultAccessControl) { -+ if (d->online) -+ return d->networkAccessible; -+ else -+ return NotAccessible; -+ } -+ return (d->networkAccessible); - } - } else { - if (d->online) -@@ -1568,7 +1574,7 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co - if (!networkSessionStrongRef) { - online = false; - -- if (networkAccessible == QNetworkAccessManager::NotAccessible) -+ if (networkAccessible == QNetworkAccessManager::NotAccessible || !online) - emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible); - else - emit q->networkAccessibleChanged(QNetworkAccessManager::UnknownAccessibility); -@@ -1616,11 +1622,14 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession - if (online) { - if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) { - online = false; -- emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible); -+ networkAccessible = QNetworkAccessManager::NotAccessible; -+ emit q->networkAccessibleChanged(networkAccessible); - } - } else { - if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) { - online = true; -+ if (defaultAccessControl) -+ networkAccessible = QNetworkAccessManager::Accessible; - emit q->networkAccessibleChanged(networkAccessible); - } - } -diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h -index f513324..c715da0 100644 ---- a/src/network/access/qnetworkaccessmanager_p.h -+++ b/src/network/access/qnetworkaccessmanager_p.h -@@ -84,6 +84,7 @@ public: - initializeSession(true), - #endif - cookieJarCreated(false), -+ defaultAccessControl(true), - authenticationManager(QSharedPointer::create()) - { } - ~QNetworkAccessManagerPrivate(); -@@ -164,6 +165,7 @@ public: - #endif - - bool cookieJarCreated; -+ bool defaultAccessControl; - - // The cache with authorization data: - QSharedPointer authenticationManager; --- -1.9.1 - diff --git a/admin/qt/patches/0012-Make-sure-networkAccessibilityChanged-is-emitted.patch b/admin/qt/patches/0012-Make-sure-networkAccessibilityChanged-is-emitted.patch deleted file mode 100644 index 5879b538a47..00000000000 --- a/admin/qt/patches/0012-Make-sure-networkAccessibilityChanged-is-emitted.patch +++ /dev/null @@ -1,233 +0,0 @@ -From bb281eea179d50a413f4ec1ff172d27ee48d3a41 Mon Sep 17 00:00:00 2001 -From: Lorn Potter -Date: Fri, 17 Jul 2015 15:32:23 +1000 -Subject: [PATCH] Make sure networkAccessibilityChanged is emitted - -Task-number: QTBUG-46323 -Change-Id: I8297072b62763136f457ca6ae15282d1c22244f4 -Reviewed-by: Timo Jyrinki -Reviewed-by: Alex Blasche ---- - src/network/access/qnetworkaccessmanager.cpp | 70 +++++++++++++++------- - src/network/access/qnetworkaccessmanager_p.h | 14 ++++- - .../tst_qnetworkaccessmanager.cpp | 31 +++++----- - 3 files changed, 77 insertions(+), 38 deletions(-) - -diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp -index 84931cb..f9e9513 100644 ---- a/src/network/access/qnetworkaccessmanager.cpp -+++ b/src/network/access/qnetworkaccessmanager.cpp -@@ -278,7 +278,8 @@ static void ensureInitialized() - - \snippet code/src_network_access_qnetworkaccessmanager.cpp 4 - -- Network requests can be reenabled again by calling -+ Network requests can be re-enabled again, and this property will resume to -+ reflect the actual device state by calling - - \snippet code/src_network_access_qnetworkaccessmanager.cpp 5 - -@@ -467,16 +468,12 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) - qRegisterMetaType >(); - - #ifndef QT_NO_BEARERMANAGEMENT -- if (!d->networkSessionRequired) { -- // if a session is required, we track online state through -- // the QNetworkSession's signals -- connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), -- SLOT(_q_onlineStateChanged(bool))); -- } -- // we would need all active configurations to check for -- // d->networkConfigurationManager.isOnline(), which is asynchronous -- // and potentially expensive. We can just check the configuration here -- d->online = (d->networkConfiguration.state() & QNetworkConfiguration::Active); -+ // if a session is required, we track online state through -+ // the QNetworkSession's signals if a request is already made. -+ // we need to track current accessibility state by default -+ // -+ connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), -+ SLOT(_q_onlineStateChanged(bool))); - #endif - } - -@@ -946,7 +943,8 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const - void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible) - { - Q_D(QNetworkAccessManager); -- d->defaultAccessControl = false; -+ -+ d->defaultAccessControl = accessible == NotAccessible ? false : true; - - if (d->networkAccessible != accessible) { - NetworkAccessibility previous = networkAccessible(); -@@ -965,6 +963,10 @@ void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkA - QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const - { - Q_D(const QNetworkAccessManager); -+ -+ if (d->networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) -+ return UnknownAccessibility; -+ - if (d->networkSessionRequired) { - QSharedPointer networkSession(d->getNetworkSession()); - if (networkSession) { -@@ -1622,32 +1624,56 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession - if (online) { - if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) { - online = false; -- networkAccessible = QNetworkAccessManager::NotAccessible; -- emit q->networkAccessibleChanged(networkAccessible); -+ if (networkAccessible != QNetworkAccessManager::NotAccessible) { -+ networkAccessible = QNetworkAccessManager::NotAccessible; -+ emit q->networkAccessibleChanged(networkAccessible); -+ } - } - } else { - if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) { - online = true; - if (defaultAccessControl) -- networkAccessible = QNetworkAccessManager::Accessible; -- emit q->networkAccessibleChanged(networkAccessible); -+ if (networkAccessible != QNetworkAccessManager::Accessible) { -+ networkAccessible = QNetworkAccessManager::Accessible; -+ emit q->networkAccessibleChanged(networkAccessible); -+ } - } - } - } - - void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) - { -- // if the user set a config, we only care whether this one is active. -+ Q_Q(QNetworkAccessManager); -+ // if the user set a config, we only care whether this one is active. - // Otherwise, this QNAM is online if there is an online config. - if (customNetworkConfiguration) { - online = (networkConfiguration.state() & QNetworkConfiguration::Active); - } else { -- if (isOnline && online != isOnline) { -- networkSessionStrongRef.clear(); -- networkSessionWeakRef.clear(); -+ if (online != isOnline) { -+ if (isOnline) { -+ networkSessionStrongRef.clear(); -+ networkSessionWeakRef.clear(); -+ } -+ online = isOnline; -+ } -+ } -+ if (online) { -+ if (defaultAccessControl) { -+ if (networkAccessible != QNetworkAccessManager::Accessible) { -+ networkAccessible = QNetworkAccessManager::Accessible; -+ emit q->networkAccessibleChanged(networkAccessible); -+ } -+ } -+ } else if (networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) { -+ if (networkAccessible != QNetworkAccessManager::UnknownAccessibility) { -+ networkAccessible = QNetworkAccessManager::UnknownAccessibility; -+ emit q->networkAccessibleChanged(networkAccessible); -+ } -+ } else { -+ if (networkAccessible != QNetworkAccessManager::NotAccessible) { -+ networkAccessible = QNetworkAccessManager::NotAccessible; -+ emit q->networkAccessibleChanged(networkAccessible); - } -- -- online = isOnline; - } - } - -diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h -index c715da0..54ae114 100644 ---- a/src/network/access/qnetworkaccessmanager_p.h -+++ b/src/network/access/qnetworkaccessmanager_p.h -@@ -78,7 +78,6 @@ public: - customNetworkConfiguration(false), - networkSessionRequired(networkConfigurationManager.capabilities() - & QNetworkConfigurationManager::NetworkSessionRequired), -- networkAccessible(QNetworkAccessManager::Accessible), - activeReplyCount(0), - online(false), - initializeSession(true), -@@ -86,7 +85,18 @@ public: - cookieJarCreated(false), - defaultAccessControl(true), - authenticationManager(QSharedPointer::create()) -- { } -+ { -+#ifndef QT_NO_BEARERMANAGEMENT -+ // we would need all active configurations to check for -+ // d->networkConfigurationManager.isOnline(), which is asynchronous -+ // and potentially expensive. We can just check the configuration here -+ online = (networkConfiguration.state().testFlag(QNetworkConfiguration::Active)); -+ if (online) -+ networkAccessible = QNetworkAccessManager::Accessible; -+ else -+ networkAccessible = QNetworkAccessManager::NotAccessible; -+#endif -+ } - ~QNetworkAccessManagerPrivate(); - - void _q_replyFinished(); -diff --git a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp -index b4e4b9c..8ecb57d 100644 ---- a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp -+++ b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp -@@ -74,6 +74,10 @@ void tst_QNetworkAccessManager::networkAccessible() - // if there is no session, we cannot know in which state we are in - QNetworkAccessManager::NetworkAccessibility initialAccessibility = - manager.networkAccessible(); -+ -+ if (initialAccessibility == QNetworkAccessManager::UnknownAccessibility) -+ QSKIP("Unknown accessibility", SkipAll); -+ - QCOMPARE(manager.networkAccessible(), initialAccessibility); - - manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible); -@@ -94,29 +98,28 @@ void tst_QNetworkAccessManager::networkAccessible() - QCOMPARE(manager.networkAccessible(), initialAccessibility); - - QNetworkConfigurationManager configManager; -- bool sessionRequired = (configManager.capabilities() -- & QNetworkConfigurationManager::NetworkSessionRequired); - QNetworkConfiguration defaultConfig = configManager.defaultConfiguration(); - if (defaultConfig.isValid()) { - manager.setConfiguration(defaultConfig); - -- // the accessibility has not changed if no session is required -- if (sessionRequired) { -+ QCOMPARE(spy.count(), 0); -+ -+ if (defaultConfig.state().testFlag(QNetworkConfiguration::Active)) -+ QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::Accessible); -+ else -+ QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible); -+ -+ manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible); -+ -+ if (defaultConfig.state().testFlag(QNetworkConfiguration::Active)) { - QCOMPARE(spy.count(), 1); -- QCOMPARE(spy.takeFirst().at(0).value(), -- QNetworkAccessManager::Accessible); -+ QCOMPARE(QNetworkAccessManager::NetworkAccessibility(spy.takeFirst().at(0).toInt()), -+ QNetworkAccessManager::NotAccessible); - } else { - QCOMPARE(spy.count(), 0); - } -- QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::Accessible); -- -- manager.setNetworkAccessible(QNetworkAccessManager::NotAccessible); -- -- QCOMPARE(spy.count(), 1); -- QCOMPARE(QNetworkAccessManager::NetworkAccessibility(spy.takeFirst().at(0).toInt()), -- QNetworkAccessManager::NotAccessible); -- QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible); - } -+ QCOMPARE(manager.networkAccessible(), QNetworkAccessManager::NotAccessible); - #endif - } - --- -1.9.1 - diff --git a/admin/qt/patches/0013-Make-UnknownAccessibility-not-block-requests.patch b/admin/qt/patches/0013-Make-UnknownAccessibility-not-block-requests.patch deleted file mode 100644 index 7714254eb94..00000000000 --- a/admin/qt/patches/0013-Make-UnknownAccessibility-not-block-requests.patch +++ /dev/null @@ -1,52 +0,0 @@ -From e996d68f6130847637ba287518cff1289cfa48e5 Mon Sep 17 00:00:00 2001 -From: Lorn Potter -Date: Fri, 6 Nov 2015 14:22:44 +1000 -Subject: [PATCH] Make UnknownAccessibility not block requests - -This allows requests to proceed without needing bearer plugins. - -Task-number: QTBUG-49267 -Change-Id: Ie5ce188ddefebd14d666bb5846e8f93ee2925ed1 -Reviewed-by: Markus Goetz (Woboq GmbH) ---- - src/network/access/qnetworkaccessmanager.cpp | 3 +-- - src/network/access/qnetworkaccessmanager_p.h | 2 ++ - 2 files changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp -index 086140f..0e5870a 100644 ---- a/src/network/access/qnetworkaccessmanager.cpp -+++ b/src/network/access/qnetworkaccessmanager.cpp -@@ -976,7 +976,6 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess - else - return NotAccessible; - } else { -- // Network accessibility is either disabled or unknown. - if (d->defaultAccessControl) { - if (d->online) - return d->networkAccessible; -@@ -1161,7 +1160,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera - #ifndef QT_NO_BEARERMANAGEMENT - // Return a disabled network reply if network access is disabled. - // Except if the scheme is empty or file://. -- if (!d->networkAccessible && !isLocalFile) { -+ if (d->networkAccessible == NotAccessible && !isLocalFile) { - return new QDisabledNetworkReply(this, req, op); - } - -diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h -index 54ae114..3fc33b5 100644 ---- a/src/network/access/qnetworkaccessmanager_p.h -+++ b/src/network/access/qnetworkaccessmanager_p.h -@@ -93,6 +93,8 @@ public: - online = (networkConfiguration.state().testFlag(QNetworkConfiguration::Active)); - if (online) - networkAccessible = QNetworkAccessManager::Accessible; -+ else if (networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) -+ networkAccessible = QNetworkAccessManager::UnknownAccessibility; - else - networkAccessible = QNetworkAccessManager::NotAccessible; - #endif --- -1.9.1 - diff --git a/admin/qt/patches/0017-Win32-Re-init-system-proxy-if-internet-settings-chan.patch b/admin/qt/patches/0017-Win32-Re-init-system-proxy-if-internet-settings-chan.patch deleted file mode 100644 index 814c4d1fcd1..00000000000 --- a/admin/qt/patches/0017-Win32-Re-init-system-proxy-if-internet-settings-chan.patch +++ /dev/null @@ -1,152 +0,0 @@ -From ae9d3f4c6c1a732788cd1f24c6a928cee16c3991 Mon Sep 17 00:00:00 2001 -From: Daniel Molkentin -Date: Tue, 27 Jan 2015 16:58:32 +0100 -Subject: [PATCH] Win32: Re-init system proxy if internet settings change - -Because Proxy Auto Configuration performs DNS lookups, -the proxy settings are being cached. For long-running -programs this means that once users switch e.g. from or -to company networks with a proxy, they instantly will -lose connectivity because we cache the old setting. - -To remedy this, we monitor the Registry (locations -courtesy of Chromium's platform support) for changes -in its settings, and requery for the current proxy in -that case. - -Task-number: QTBUG-3470 -Task-number: QTBUG-29990 -Change-Id: Id25a51387bcd232c5f879cea0371038986d0e2de -Reviewed-by: Oliver Wolff ---- - src/network/kernel/qnetworkproxy_win.cpp | 86 +++++++++++++++++++++++++++++++- - 1 file changed, 84 insertions(+), 2 deletions(-) - -diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp -index da2c020..f7741ce 100644 ---- a/src/network/kernel/qnetworkproxy_win.cpp -+++ b/src/network/kernel/qnetworkproxy_win.cpp -@@ -345,12 +345,66 @@ static QList parseServerList(const QNetworkProxyQuery &query, con - return removeDuplicateProxies(result); - } - -+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) -+namespace { -+class QRegistryWatcher { -+public: -+ void addLocation(HKEY hive, const QString& path) -+ { -+ HKEY openedKey; -+ if (RegOpenKeyEx(hive, reinterpret_cast(path.utf16()), 0, KEY_READ, &openedKey) != ERROR_SUCCESS) -+ return; -+ -+ const DWORD filter = REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | -+ REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_SECURITY; -+ -+ // Watch the registry key for a change of value. -+ HANDLE handle = CreateEvent(NULL, true, false, NULL); -+ if (RegNotifyChangeKeyValue(openedKey, true, filter, handle, true) != ERROR_SUCCESS) { -+ CloseHandle(handle); -+ return; -+ } -+ m_watchEvents.append(handle); -+ m_registryHandles.append(openedKey); -+ } -+ -+ bool hasChanged() const { -+ return !isEmpty() && -+ WaitForMultipleObjects(m_watchEvents.size(), m_watchEvents.data(), false, 0) < WAIT_OBJECT_0 + m_watchEvents.size(); -+ } -+ -+ bool isEmpty() const { -+ return m_watchEvents.isEmpty(); -+ } -+ -+ void clear() { -+ foreach (HANDLE event, m_watchEvents) -+ CloseHandle(event); -+ foreach (HKEY key, m_registryHandles) -+ RegCloseKey(key); -+ -+ m_watchEvents.clear(); -+ m_registryHandles.clear(); -+ } -+ -+ ~QRegistryWatcher() { -+ clear(); -+ } -+ -+private: -+ QVector m_watchEvents; -+ QVector m_registryHandles; -+}; -+} // namespace -+#endif // !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) -+ - class QWindowsSystemProxy - { - public: - QWindowsSystemProxy(); - ~QWindowsSystemProxy(); - void init(); -+ void reset(); - - QMutex mutex; - -@@ -361,7 +415,9 @@ public: - QStringList proxyServerList; - QStringList proxyBypass; - QList defaultResult; -- -+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) -+ QRegistryWatcher proxySettingsWatcher; -+#endif - bool initialized; - bool functional; - bool isAutoConfig; -@@ -381,16 +437,42 @@ QWindowsSystemProxy::~QWindowsSystemProxy() - ptrWinHttpCloseHandle(hHttpSession); - } - -+void QWindowsSystemProxy::reset() -+{ -+ autoConfigUrl.clear(); -+ proxyServerList.clear(); -+ proxyBypass.clear(); -+ defaultResult.clear(); -+ defaultResult << QNetworkProxy::NoProxy; -+ functional = false; -+ isAutoConfig = false; -+} -+ - void QWindowsSystemProxy::init() - { -- if (initialized) -+ bool proxySettingsChanged = false; -+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) -+ proxySettingsChanged = proxySettingsWatcher.hasChanged(); -+#endif -+ -+ if (initialized && !proxySettingsChanged) - return; - initialized = true; - -+ reset(); -+ - #ifdef Q_OS_WINCE - // Windows CE does not have any of the following API - return; - #else -+ -+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) -+ proxySettingsWatcher.clear(); // needs reset to trigger a new detection -+ proxySettingsWatcher.addLocation(HKEY_CURRENT_USER, QStringLiteral("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings")); -+ proxySettingsWatcher.addLocation(HKEY_LOCAL_MACHINE, QStringLiteral("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings")); -+ proxySettingsWatcher.addLocation(HKEY_LOCAL_MACHINE, QStringLiteral("Software\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings")); -+#endif -+ - // load the winhttp.dll library - QSystemLibrary lib(L"winhttp"); - if (!lib.load()) --- -1.9.1 diff --git a/admin/qt/patches/0018-Windows-Do-not-crash-if-SSL-context-is-gone-after-ro.patch b/admin/qt/patches/0018-Windows-Do-not-crash-if-SSL-context-is-gone-after-ro.patch deleted file mode 100644 index 6669179aee7..00000000000 --- a/admin/qt/patches/0018-Windows-Do-not-crash-if-SSL-context-is-gone-after-ro.patch +++ /dev/null @@ -1,32 +0,0 @@ -From c1a67e7dc3a6f8876efa32cdbabbfde1c5a37bc6 Mon Sep 17 00:00:00 2001 -From: Daniel Molkentin -Date: Tue, 31 Mar 2015 17:43:44 +0200 -Subject: [PATCH] Windows: Do not crash if SSL context is gone after root cert - lookup - -On Windows, we perform an extra certificate lookup for root CAs that -are not in Windows' (minimal) root store. This check can take up to -15 seconds. The SSL context can already be gone once we return. Hence -we now check for a non-null SSL context on Windows before proceeding. - -Change-Id: I1951569d9b17da33fa604f7c9d8b33255acf200d -Reviewed-by: Richard J. Moore ---- - src/network/ssl/qsslsocket_openssl.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp -index 0e1a3e5..b132aec 100644 ---- a/src/network/ssl/qsslsocket_openssl.cpp -+++ b/src/network/ssl/qsslsocket_openssl.cpp -@@ -1281,7 +1281,7 @@ void QSslSocketBackendPrivate::_q_caRootLoaded(QSslCertificate cert, QSslCertifi - if (plainSocket) - plainSocket->resume(); - paused = false; -- if (checkSslErrors()) -+ if (checkSslErrors() && ssl) - continueHandshake(); - } - --- -1.9.1 diff --git a/admin/qt/patches/0019-Ensure-system-tray-icon-is-prepared-even-when-menu-bar.patch b/admin/qt/patches/0019-Ensure-system-tray-icon-is-prepared-even-when-menu-bar.patch deleted file mode 100644 index afb9ea557ad..00000000000 --- a/admin/qt/patches/0019-Ensure-system-tray-icon-is-prepared-even-when-menu-bar.patch +++ /dev/null @@ -1,39 +0,0 @@ -From cf6881c03d9f08c6ace83defe461423bb87f30d8 Mon Sep 17 00:00:00 2001 -From: =?utf8?q?Tor=20Arne=20Vestb=C3=B8?= -Date: Fri, 15 Jan 2016 14:15:51 +0100 -Subject: [PATCH] OS X: Ensure system tray icon is prepared even when menu bar - is hidden - -On OS X 10.11 (El Capitan) the system menu bar can be automatically -hidden, in which case the menu bar height is reported to be 0 when -using the menuBarHeight API. - -This resulted in failing to prepare an image for the system tray -icon item, making the tray item "invisible". - -Instead we now use the [[NSStatusBar systemStatusBar] thickness] -API, which returns the correct height regardless of the menu bar -being hidden or not. - -Task-number: QTBUG-48960 -Change-Id: I208fb8df13754964a6f254cadfbff06dd56c6bab ---- - src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm -index a3ffb5b..8152c57 100644 ---- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm -+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm -@@ -198,7 +198,7 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) - // current OS X versions is 22 points. Provide some future-proofing - // by deriving the icon height from the menu height. - const int padding = 4; -- const int menuHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; -+ const int menuHeight = [[NSStatusBar systemStatusBar] thickness]; - const int maxImageHeight = menuHeight - padding; - - // Select pixmap based on the device pixel height. Ideally we would use --- -2.6.2.2.g1b5ffa3 - diff --git a/admin/qt/patches/README.md b/admin/qt/patches/README.md index cd68ab06541..1690397e11c 100644 --- a/admin/qt/patches/README.md +++ b/admin/qt/patches/README.md @@ -1,55 +1,20 @@ ## Patches used -There are our patches on top of Qt 5.4.0, which we are currently -using for our binary packages on Windows and Mac OS X. Most of them +There are our patches on top of Qt 5.6.2, which we are currently +using for our binary packages on Windows and macOS. Most of them have been sent upstream and are part of newer Qt releases. -All changes are designed to up upstream, and all those that are +All changes are designed to be upstream, and all those that are special hacks to Qt will bear a NOUPSTREAM in their name -The git-style numeration is ordered by order of creation, their -purpose is outlined in each patches' front matter. +You can apply those patches on a git clone using: -### Part of Qt v5.4.1 and later -* 0001-Fix-crash-on-Mac-OS-if-PAC-URL-contains-non-URL-lega.patch -* 0002-Fix-possible-crash-when-passing-an-invalid-PAC-URL.patch -* 0003-Fix-crash-if-PAC-script-retrieval-returns-a-null-CFD.patch - -### Part of Qt v5.4.2 and later -* 0004-Cocoa-Fix-systray-SVG-icons.patch -* 0005-OSX-Fix-disapearing-tray-icon.patch -* 0007-QNAM-Fix-upload-corruptions-when-server-closes-conne.patch -* 0018-Windows-Do-not-crash-if-SSL-context-is-gone-after-ro.patch - -### Part of Qt v5.5.0 and later -* 0017-Win32-Re-init-system-proxy-if-internet-settings-chan.patch - -### Part of Qt v5.5.1 and later -* 0007-X-Network-Fix-up-previous-corruption-patch.patch -* 0008-QNAM-Fix-reply-deadlocks-on-server-closing-connectio.patch -* 0014-Fix-SNI-for-TlsV1_0OrLater-TlsV1_1OrLater-and-TlsV1_.patch -* 0016-Fix-possible-crash-when-passing-an-invalid-PAC-URL.patch -* 0011-Make-sure-to-report-correct-NetworkAccessibility.patch - -### Part of Qt v5.5.2 (UNRELEASED!) -* 0009-QNAM-Assign-proper-channel-before-sslErrors-emission.patch -* 0010-Don-t-let-closed-http-sockets-pass-as-valid-connecti.patch -* 0012-Make-sure-networkAccessibilityChanged-is-emitted.patch - -### Part of Qt v5.6 and later -* 0009-QNAM-Assign-proper-channel-before-sslErrors-emission.patch -* 0010-Don-t-let-closed-http-sockets-pass-as-valid-connecti.patch -* 0011-Make-sure-to-report-correct-NetworkAccessibility.patch -* 0012-Make-sure-networkAccessibilityChanged-is-emitted.patch -* 0013-Make-UnknownAccessibility-not-block-requests.patch -* 0019-Ensure-system-tray-icon-is-prepared-even-when-menu-bar.patch - -### Part of Qt 5.7 and later -* 0015-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch - -### Not submitted upstream to be part of any release: -* 0006-Fix-force-debug-info-with-macx-clang_NOUPSTREAM.patch -This is only needed if you intent to harvest debugging symbols -for breakpad. +``` +git am /admin/qt/patches/qtbase/*.patch +``` +You can update them using: +``` +git format-patch -N --no-signature -o /admin/qt/patches/qtbase/ +``` diff --git a/admin/qt/patches/0006-Fix-force-debug-info-with-macx-clang_NOUPSTREAM.patch b/admin/qt/patches/qtbase/0001-NOUPSTREAM-Fix-force-debug-info-with-macx-clang.patch similarity index 64% rename from admin/qt/patches/0006-Fix-force-debug-info-with-macx-clang_NOUPSTREAM.patch rename to admin/qt/patches/qtbase/0001-NOUPSTREAM-Fix-force-debug-info-with-macx-clang.patch index ea9c8b875a7..80f40dee505 100644 --- a/admin/qt/patches/0006-Fix-force-debug-info-with-macx-clang_NOUPSTREAM.patch +++ b/admin/qt/patches/qtbase/0001-NOUPSTREAM-Fix-force-debug-info-with-macx-clang.patch @@ -1,30 +1,27 @@ -From f3cd07c11e0b7327ffc629f48a89c8c457cdba75 Mon Sep 17 00:00:00 2001 +From 96c34ce85136cbdc16ef83effa8a13137f7ae4c5 Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Fri, 6 Mar 2015 16:12:37 +0100 -Subject: [PATCH] Fix -force-debug-info with macx-clang +Subject: [PATCH] [NOUPSTREAM] Fix -force-debug-info with macx-clang --- mkspecs/common/clang.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkspecs/common/clang.conf b/mkspecs/common/clang.conf -index 2c29bb8..110d380 100644 +index e003b94..e9b3291 100644 --- a/mkspecs/common/clang.conf +++ b/mkspecs/common/clang.conf -@@ -20,11 +20,13 @@ QMAKE_CFLAGS_ISYSTEM = -isystem - QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} +@@ -21,11 +21,13 @@ QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_ QMAKE_CFLAGS_USE_PRECOMPILE = -Xclang -include-pch -Xclang ${QMAKE_PCH_OUTPUT} QMAKE_CFLAGS_LTCG = -flto + QMAKE_CFLAGS_DISABLE_LTCG = -fno-lto +QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = $$QMAKE_CFLAGS_OPTIMIZE -g QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG - QMAKE_CXXFLAGS_CXX11 = -std=c++11 + QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG +QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO - - QMAKE_LFLAGS_CXX11 = - QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG --- -2.2.0 - + QMAKE_CXXFLAGS_CXX11 = -std=c++11 + QMAKE_CXXFLAGS_CXX14 = -std=c++1y + QMAKE_CXXFLAGS_CXX1Z = -std=c++1z diff --git a/admin/qt/patches/0015-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch b/admin/qt/patches/qtbase/0002-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch similarity index 84% rename from admin/qt/patches/0015-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch rename to admin/qt/patches/qtbase/0002-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch index ce6355ba1e2..3f0c1398e24 100644 --- a/admin/qt/patches/0015-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch +++ b/admin/qt/patches/qtbase/0002-Remove-legacy-platform-code-in-QSslSocket-for-OS-X-1.patch @@ -1,7 +1,7 @@ -From 06818f6d1c602aa3c4f9356324866432d2dd0195 Mon Sep 17 00:00:00 2001 +From e6bccb1f0d8ca59acb1ffdac74a823c06346e7f3 Mon Sep 17 00:00:00 2001 From: Daniel Molkentin Date: Mon, 16 Nov 2015 15:02:37 +0100 -Subject: [PATCH 1/2] Remove legacy platform code in QSslSocket for OS X < 10.5 +Subject: [PATCH] Remove legacy platform code in QSslSocket for OS X < 10.5 This avoids manual symbol lookups and makes the code more readable. Mark identical code. @@ -16,20 +16,18 @@ Reviewed-by: Markus Goetz (Woboq GmbH) Conflicts: src/network/ssl/qsslsocket_openssl.cpp --- - src/network/ssl/qsslsocket_openssl.cpp | 83 +++++++++++----------------------- + src/network/ssl/qsslsocket_openssl.cpp | 81 +++++++++++----------------------- src/network/ssl/qsslsocket_p.h | 6 +-- - 2 files changed, 28 insertions(+), 61 deletions(-) + 2 files changed, 26 insertions(+), 61 deletions(-) diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp -index 13fc534..7d0fe00 100644 +index 82644c1..415f147 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp -@@ -69,14 +69,19 @@ - #include - #include // for loading the security lib for the CA store +@@ -76,14 +76,17 @@ + + #include -+#include -+ +#ifdef Q_OS_DARWIN +# include +#endif @@ -50,7 +48,7 @@ index 13fc534..7d0fe00 100644 PtrCertOpenSystemStoreW QSslSocketPrivate::ptrCertOpenSystemStoreW = 0; PtrCertFindCertificateInStore QSslSocketPrivate::ptrCertFindCertificateInStore = 0; PtrCertCloseStore QSslSocketPrivate::ptrCertCloseStore = 0; -@@ -482,23 +487,7 @@ void QSslSocketPrivate::ensureCiphersAndCertsLoaded() +@@ -509,23 +512,7 @@ void QSslSocketPrivate::ensureCiphersAndCertsLoaded() #ifndef QT_NO_LIBRARY //load symbols needed to receive certificates from system store @@ -59,23 +57,23 @@ index 13fc534..7d0fe00 100644 - if (securityLib.load()) { - ptrSecCertificateCopyData = (PtrSecCertificateCopyData) securityLib.resolve("SecCertificateCopyData"); - if (!ptrSecCertificateCopyData) -- qWarning("could not resolve symbols in security library"); // should never happen +- qCWarning(lcSsl, "could not resolve symbols in security library"); // should never happen - - ptrSecTrustSettingsCopyCertificates = (PtrSecTrustSettingsCopyCertificates) securityLib.resolve("SecTrustSettingsCopyCertificates"); - if (!ptrSecTrustSettingsCopyCertificates) { // method was introduced in Leopard, use legacy method if it's not there - ptrSecTrustCopyAnchorCertificates = (PtrSecTrustCopyAnchorCertificates) securityLib.resolve("SecTrustCopyAnchorCertificates"); - if (!ptrSecTrustCopyAnchorCertificates) -- qWarning("could not resolve symbols in security library"); // should never happen +- qCWarning(lcSsl, "could not resolve symbols in security library"); // should never happen - } - } else { -- qWarning("could not load security library"); +- qCWarning(lcSsl, "could not load security library"); - } -#elif defined(Q_OS_WIN) +#if defined(Q_OS_WIN) HINSTANCE hLib = LoadLibraryW(L"Crypt32"); if (hLib) { #if defined(Q_OS_WINCE) -@@ -635,40 +624,22 @@ QList QSslSocketPrivate::systemCaCertificates() +@@ -693,40 +680,22 @@ QList QSslSocketPrivate::systemCaCertificates() timer.start(); #endif QList systemCerts; @@ -101,7 +99,7 @@ index 13fc534..7d0fe00 100644 - data = ptrSecCertificateCopyData(cfCert); - - if (data == NULL) { -- qWarning("error retrieving a CA certificate from the system store"); +- qCWarning(lcSsl, "error retrieving a CA certificate from the system store"); - } else { - QByteArray rawCert = QByteArray::fromRawData((const char *)CFDataGetBytePtr(data), CFDataGetLength(data)); - systemCerts.append(QSslCertificate::fromData(rawCert, QSsl::Der)); @@ -127,15 +125,15 @@ index 13fc534..7d0fe00 100644 - } - else { - // no detailed error handling here -- qWarning("could not retrieve system CA certificates"); +- qCWarning(lcSsl, "could not retrieve system CA certificates"); } } #elif defined(Q_OS_WIN) diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h -index 6e7a2c5..c1a6f05 100644 +index d651971..17cc7b4 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h -@@ -145,11 +145,7 @@ public: +@@ -151,11 +151,7 @@ public: static bool isMatchingHostname(const QSslCertificate &cert, const QString &peerName); Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QString &cn, const QString &hostname); @@ -148,6 +146,3 @@ index 6e7a2c5..c1a6f05 100644 static PtrCertOpenSystemStoreW ptrCertOpenSystemStoreW; static PtrCertFindCertificateInStore ptrCertFindCertificateInStore; static PtrCertCloseStore ptrCertCloseStore; --- -1.9.1 - diff --git a/admin/qt/patches/0016-QSslSocket-evaluate-CAs-in-all-keychain-categories.patch b/admin/qt/patches/qtbase/0003-QSslSocket-evaluate-CAs-in-all-keychain-categories.patch similarity index 93% rename from admin/qt/patches/0016-QSslSocket-evaluate-CAs-in-all-keychain-categories.patch rename to admin/qt/patches/qtbase/0003-QSslSocket-evaluate-CAs-in-all-keychain-categories.patch index d780fc68d56..6b617a1a323 100644 --- a/admin/qt/patches/0016-QSslSocket-evaluate-CAs-in-all-keychain-categories.patch +++ b/admin/qt/patches/qtbase/0003-QSslSocket-evaluate-CAs-in-all-keychain-categories.patch @@ -1,7 +1,7 @@ -From 6b9366e7748857f14d5b0f92ced70c08ab5235b7 Mon Sep 17 00:00:00 2001 +From 9d1120db0973ea7741b13a6555b20ae61f6d037e Mon Sep 17 00:00:00 2001 From: Daniel Molkentin Date: Wed, 25 Nov 2015 12:37:27 +0100 -Subject: [PATCH 2/2] QSslSocket: evaluate CAs in all keychain categories +Subject: [PATCH] QSslSocket: evaluate CAs in all keychain categories This will make sure that certs in the domainUser (login), and domainAdmin (per machine) keychain are being picked up @@ -15,7 +15,7 @@ it will be accepted. [ChangeLog][Platform Specific Changes] OS X now accepts trusted certificates from the login and system keychains. -(Backport of fe3a84138e266c425f11353f7d8dc28a588af89e to Qt 5.4) +(Backport of fe3a84138e266c425f11353f7d8dc28a588af89e) Task-number: QTBUG-32898 Change-Id: Ia23083d5af74388eeee31ba07239735cbbe64368 @@ -29,10 +29,10 @@ Reviewed-by: Markus Goetz (Woboq GmbH) create mode 100644 src/network/ssl/qsslsocket_mac_shared.cpp diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp -index 8887f47..6347c20 100644 +index 549906a..7b202b0 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp -@@ -1446,6 +1446,10 @@ QList QSslSocket::defaultCaCertificates() +@@ -1508,6 +1508,10 @@ QList QSslSocket::defaultCaCertificates() returned by defaultCaCertificates(). You can replace that database with your own with setDefaultCaCertificates(). @@ -198,10 +198,10 @@ index 0000000..60fea4c + +QT_END_NAMESPACE diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp -index 7d0fe00..7415e32 100644 +index 415f147..7a3cb42 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp -@@ -71,14 +71,6 @@ +@@ -76,14 +76,6 @@ #include @@ -216,15 +216,15 @@ index 7d0fe00..7415e32 100644 QT_BEGIN_NAMESPACE #if defined(Q_OS_WIN) -@@ -616,6 +608,7 @@ void QSslSocketPrivate::resetDefaultCiphers() - setDefaultCiphers(defaultCiphers); +@@ -672,6 +664,7 @@ void QSslSocketPrivate::resetDefaultEllipticCurves() + setDefaultSupportedEllipticCurves(curves); } +#ifndef Q_OS_DARWIN // Apple implementation in qsslsocket_mac_shared.cpp QList QSslSocketPrivate::systemCaCertificates() { ensureInitialized(); -@@ -624,25 +617,7 @@ QList QSslSocketPrivate::systemCaCertificates() +@@ -680,25 +673,7 @@ QList QSslSocketPrivate::systemCaCertificates() timer.start(); #endif QList systemCerts; @@ -251,7 +251,7 @@ index 7d0fe00..7415e32 100644 if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) { HCERTSTORE hSystemStore; #if defined(Q_OS_WINCE) -@@ -719,6 +694,7 @@ QList QSslSocketPrivate::systemCaCertificates() +@@ -775,6 +750,7 @@ QList QSslSocketPrivate::systemCaCertificates() return systemCerts; } @@ -260,10 +260,10 @@ index 7d0fe00..7415e32 100644 void QSslSocketBackendPrivate::startClientEncryption() { diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri -index 384e149..9546f18 100644 +index 29c47cd..8eb605b 100644 --- a/src/network/ssl/ssl.pri +++ b/src/network/ssl/ssl.pri -@@ -45,7 +45,9 @@ contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { +@@ -62,7 +62,9 @@ contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { ssl/qsslsocket_openssl.cpp \ ssl/qsslsocket_openssl_symbols.cpp @@ -274,6 +274,3 @@ index 384e149..9546f18 100644 # Add optional SSL libs # Static linking of OpenSSL with msvc: --- -1.9.1 - From 6dd7ea095472b75a43689b3ed5c42683d979c0ee Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Tue, 6 Dec 2016 14:55:49 +0100 Subject: [PATCH 2/2] Don't try to deploy the mng image format plugin on macOS Qt now only build it if the system library is available since libmng isn't active enough to make its security reliable enough. We don't use that image format ourselves anyway. --- admin/osx/macdeployqt.py | 1 - 1 file changed, 1 deletion(-) diff --git a/admin/osx/macdeployqt.py b/admin/osx/macdeployqt.py index 6c1d241dbfe..f27eead38b6 100755 --- a/admin/osx/macdeployqt.py +++ b/admin/osx/macdeployqt.py @@ -40,7 +40,6 @@ def QueryQMake(attrib): 'imageformats/libqico.dylib', 'imageformats/libqjpeg.dylib', 'imageformats/libqsvg.dylib', - 'imageformats/libqmng.dylib', ] QT_PLUGINS_SEARCH_PATH=[