mirror of
https://github.com/archlinuxarm/PKGBUILDs.git
synced 2025-02-16 23:57:11 +00:00
extra/qt5 to 5.4.2-1
This commit is contained in:
parent
4c95ad9655
commit
eecf9a0d83
14 changed files with 108 additions and 1755 deletions
|
@ -1,44 +0,0 @@
|
|||
From 3eca75de67b3fd2c890715b30c7899cebc096fe9 Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Macieira <thiago.macieira@intel.com>
|
||||
Date: Mon, 11 May 2015 18:30:00 +0900
|
||||
Subject: [PATCH] Make qglobal.h complain if you use -fPIE
|
||||
|
||||
Prior to Qt 5.4.2 (commit 36d6eb721e7d5997ade75e289d4088dc48678d0d), we
|
||||
allowed it, but now we need to enforce that it is not used. Note that
|
||||
-fPIE does define __PIC__, so we need this to catch the use of -fPIE.
|
||||
|
||||
[ChangeLog][Important Behavior Changes] On x86 and x86-64 systems with
|
||||
ELF binaries (especially Linux), due to a new optimization in GCC 5.x in
|
||||
combination with a recent version of GNU binutils, compiling Qt
|
||||
applications with -fPIE is no longer enough. Applications now need to be
|
||||
compiled with the -fPIC option if Qt's option "reduce relocations" is
|
||||
active. Note that Clang is known to generate incompatible code even with
|
||||
-fPIC if the -flto option is active.
|
||||
|
||||
Task-number: QTBUG-45755
|
||||
Change-Id: I66a35ce5f88941f29aa6ffff13dd210e0aa2728f
|
||||
Reviewed-by: Dmitry Shachnev <mitya57@gmail.com>
|
||||
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
|
||||
---
|
||||
src/corelib/global/qglobal.h | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
|
||||
index ef84662..4547877 100644
|
||||
--- a/src/corelib/global/qglobal.h
|
||||
+++ b/src/corelib/global/qglobal.h
|
||||
@@ -1047,9 +1047,9 @@ Q_CORE_EXPORT int qrand();
|
||||
# define QT_NO_SHAREDMEMORY
|
||||
#endif
|
||||
|
||||
-#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && !defined(__PIC__)
|
||||
+#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && (!defined(__PIC__) || defined(__PIE__))
|
||||
# error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\
|
||||
- "Compile your code with -fPIC."
|
||||
+ "Compile your code with -fPIC (-fPIE is not enough)."
|
||||
#endif
|
||||
|
||||
namespace QtPrivate {
|
||||
--
|
||||
2.4.0
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
From 36d6eb721e7d5997ade75e289d4088dc48678d0d Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Macieira <thiago.macieira@intel.com>
|
||||
Date: Tue, 5 May 2015 08:43:42 -0700
|
||||
Subject: [PATCH] Require -fPIC instead of just -fPIE for -reduce-relocations
|
||||
|
||||
GCC 5 combined with a recent binutils have a new optimization that
|
||||
allows them to generate copy relocations even in -fPIE code. Clang has
|
||||
the same functionality when compiling an executable with -flto. We need
|
||||
to let the compilers know that they cannot use copy relocations, so they
|
||||
need to use really position-independent code.
|
||||
|
||||
Position independent code throughout is not really required. We just
|
||||
need the compilers to use position-independent access to symbols coming
|
||||
from the Qt libraries, but there's currently no other way of doing that.
|
||||
|
||||
Task-number: QTBUG-45755
|
||||
Change-Id: I0d4913955e3745b69672ffff13db5df7377398c5
|
||||
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
|
||||
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
|
||||
---
|
||||
mkspecs/common/gcc-base.conf | 2 +-
|
||||
mkspecs/common/qcc-base.conf | 2 +-
|
||||
mkspecs/linux-icc/qmake.conf | 2 +-
|
||||
src/corelib/Qt5CoreConfigExtras.cmake.in | 2 +-
|
||||
src/corelib/global/qglobal.h | 4 ++--
|
||||
tests/auto/tools/moc/tst_moc.cpp | 6 +++---
|
||||
6 files changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf
|
||||
index a149f4d..e4ccbd7 100644
|
||||
--- a/mkspecs/common/gcc-base.conf
|
||||
+++ b/mkspecs/common/gcc-base.conf
|
||||
@@ -42,7 +42,7 @@ QMAKE_CFLAGS_RELEASE += $$QMAKE_CFLAGS_OPTIMIZE
|
||||
QMAKE_CFLAGS_DEBUG += -g
|
||||
QMAKE_CFLAGS_SHLIB += -fPIC
|
||||
QMAKE_CFLAGS_STATIC_LIB += -fPIC
|
||||
-QMAKE_CFLAGS_APP += -fPIE
|
||||
+QMAKE_CFLAGS_APP += -fPIC
|
||||
QMAKE_CFLAGS_ISYSTEM = -isystem
|
||||
QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses
|
||||
QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden
|
||||
diff --git a/mkspecs/common/qcc-base.conf b/mkspecs/common/qcc-base.conf
|
||||
index f529d7f..8276316 100644
|
||||
--- a/mkspecs/common/qcc-base.conf
|
||||
+++ b/mkspecs/common/qcc-base.conf
|
||||
@@ -23,7 +23,7 @@ QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -g
|
||||
QMAKE_CFLAGS_DEBUG += -g
|
||||
QMAKE_CFLAGS_SHLIB += -fPIC -shared
|
||||
QMAKE_CFLAGS_STATIC_LIB += -fPIC
|
||||
-QMAKE_CFLAGS_APP += -fPIE
|
||||
+QMAKE_CFLAGS_APP += -fPIC
|
||||
QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses
|
||||
QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden
|
||||
QMAKE_CFLAGS_SSE2 += -msse2
|
||||
diff --git a/mkspecs/linux-icc/qmake.conf b/mkspecs/linux-icc/qmake.conf
|
||||
index 8119c8a..9190aa9 100644
|
||||
--- a/mkspecs/linux-icc/qmake.conf
|
||||
+++ b/mkspecs/linux-icc/qmake.conf
|
||||
@@ -12,7 +12,7 @@ QMAKE_LEXFLAGS =
|
||||
QMAKE_YACC = yacc
|
||||
QMAKE_YACCFLAGS = -d
|
||||
QMAKE_CFLAGS =
|
||||
-QMAKE_CFLAGS_APP = -fPIE
|
||||
+QMAKE_CFLAGS_APP = -fPIC
|
||||
QMAKE_CFLAGS_DEPS = -M
|
||||
QMAKE_CFLAGS_WARN_ON = -w1 -Wall -Wcheck -wd1572,873,2259,2261
|
||||
QMAKE_CFLAGS_WARN_OFF = -w
|
||||
diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in
|
||||
index 7213a84..48d5f21 100644
|
||||
--- a/src/corelib/Qt5CoreConfigExtras.cmake.in
|
||||
+++ b/src/corelib/Qt5CoreConfigExtras.cmake.in
|
||||
@@ -71,7 +71,7 @@ set(_qt5_corelib_extra_includes)
|
||||
# macro to add it.
|
||||
set(Qt5_POSITION_INDEPENDENT_CODE True)
|
||||
set_property(TARGET Qt5::Core PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE \"ON\")
|
||||
-set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"-fPIE\")
|
||||
+set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"-fPIC\")
|
||||
!!ENDIF
|
||||
|
||||
!!IF !isEmpty(QT_NAMESPACE)
|
||||
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
|
||||
index 455582e..ef84662 100644
|
||||
--- a/src/corelib/global/qglobal.h
|
||||
+++ b/src/corelib/global/qglobal.h
|
||||
@@ -1047,9 +1047,9 @@ Q_CORE_EXPORT int qrand();
|
||||
# define QT_NO_SHAREDMEMORY
|
||||
#endif
|
||||
|
||||
-#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && !defined(__PIC__) && !defined(__PIE__)
|
||||
+#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && !defined(__PIC__)
|
||||
# error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\
|
||||
- "Compile your code with -fPIC or -fPIE."
|
||||
+ "Compile your code with -fPIC."
|
||||
#endif
|
||||
|
||||
namespace QtPrivate {
|
||||
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
|
||||
index edb6488..748cb82 100644
|
||||
--- a/tests/auto/tools/moc/tst_moc.cpp
|
||||
+++ b/tests/auto/tools/moc/tst_moc.cpp
|
||||
@@ -662,7 +662,7 @@ void tst_Moc::oldStyleCasts()
|
||||
|
||||
QStringList args;
|
||||
args << "-c" << "-x" << "c++" << "-Wold-style-cast" << "-I" << "."
|
||||
- << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIE" << "-";
|
||||
+ << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-";
|
||||
proc.start("gcc", args);
|
||||
QVERIFY(proc.waitForStarted());
|
||||
proc.write(mocOut);
|
||||
@@ -732,7 +732,7 @@ void tst_Moc::inputFileNameWithDotsButNoExtension()
|
||||
|
||||
QStringList args;
|
||||
args << "-c" << "-x" << "c++" << "-I" << ".."
|
||||
- << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIE" << "-";
|
||||
+ << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-";
|
||||
proc.start("gcc", args);
|
||||
QVERIFY(proc.waitForStarted());
|
||||
proc.write(mocOut);
|
||||
@@ -1011,7 +1011,7 @@ void tst_Moc::ignoreOptionClashes()
|
||||
// If -pthread wasn't ignored, it was parsed as a prefix of "thread/", which breaks compilation.
|
||||
QStringList gccArgs;
|
||||
gccArgs << "-c" << "-x" << "c++" << "-I" << ".."
|
||||
- << "-I" << qtIncludePath << "-I" << includeDir << "-o" << "/dev/null" << "-fPIE" << "-";
|
||||
+ << "-I" << qtIncludePath << "-I" << includeDir << "-o" << "/dev/null" << "-fPIC" << "-";
|
||||
proc.start("gcc", gccArgs);
|
||||
QVERIFY(proc.waitForStarted());
|
||||
proc.write(mocOut);
|
||||
--
|
||||
2.3.6
|
||||
|
|
@ -1,290 +0,0 @@
|
|||
From 518f886b6128331ce47932edd637471d58d0d877 Mon Sep 17 00:00:00 2001
|
||||
From: Rainer Keller <rainer.keller@theqtcompany.com>
|
||||
Date: Fri, 17 Apr 2015 10:43:19 +0200
|
||||
Subject: [PATCH] Revert "Rotate images according to Exif orientation"
|
||||
|
||||
Due to a behavior change.
|
||||
|
||||
This reverts commit 9157087334186ff3ef811f2ec234a3bf5d4a4889.
|
||||
This reverts commit 16c32c6dfbca03a46d1a2bb87b6c1c365e6179d5.
|
||||
|
||||
Task-number: QTBUG-37946
|
||||
Task-number: QTBUG-45552
|
||||
Task-number: QTBUG-43563
|
||||
Change-Id: Idf8df7d8f22465e8f6b51acb68993ac97208b184
|
||||
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
|
||||
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
|
||||
---
|
||||
src/gui/image/qjpeghandler.cpp | 150 +----------------------------
|
||||
tests/auto/gui/image/qimage/tst_qimage.cpp | 33 -------
|
||||
2 files changed, 1 insertion(+), 182 deletions(-)
|
||||
|
||||
diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp
|
||||
index 9cf9947..14c8b4c 100644
|
||||
--- a/src/gui/image/qjpeghandler.cpp
|
||||
+++ b/src/gui/image/qjpeghandler.cpp
|
||||
@@ -726,7 +726,7 @@ public:
|
||||
};
|
||||
|
||||
QJpegHandlerPrivate(QJpegHandler *qq)
|
||||
- : quality(75), exifOrientation(1), iod_src(0), state(Ready), q(qq)
|
||||
+ : quality(75), iod_src(0), state(Ready), q(qq)
|
||||
{}
|
||||
|
||||
~QJpegHandlerPrivate()
|
||||
@@ -741,10 +741,8 @@ public:
|
||||
|
||||
bool readJpegHeader(QIODevice*);
|
||||
bool read(QImage *image);
|
||||
- void applyExifOrientation(QImage *image);
|
||||
|
||||
int quality;
|
||||
- int exifOrientation;
|
||||
QVariant size;
|
||||
QImage::Format format;
|
||||
QSize scaledSize;
|
||||
@@ -762,97 +760,6 @@ public:
|
||||
QJpegHandler *q;
|
||||
};
|
||||
|
||||
-static bool readExifHeader(QDataStream &stream)
|
||||
-{
|
||||
- char prefix[6];
|
||||
- if (stream.readRawData(prefix, sizeof(prefix)) != sizeof(prefix))
|
||||
- return false;
|
||||
- if (prefix[0] != 'E' || prefix[1] != 'x' || prefix[2] != 'i' || prefix[3] != 'f' || prefix[4] != 0 || prefix[5] != 0)
|
||||
- return false;
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * Returns -1 on error
|
||||
- * Returns 0 if no Exif orientation was found
|
||||
- * Returns 1 orientation is horizontal (normal)
|
||||
- * Returns 2 mirror horizontal
|
||||
- * Returns 3 rotate 180
|
||||
- * Returns 4 mirror vertical
|
||||
- * Returns 5 mirror horizontal and rotate 270 CCW
|
||||
- * Returns 6 rotate 90 CW
|
||||
- * Returns 7 mirror horizontal and rotate 90 CW
|
||||
- * Returns 8 rotate 270 CW
|
||||
- */
|
||||
-static int getExifOrientation(QByteArray &exifData)
|
||||
-{
|
||||
- QDataStream stream(&exifData, QIODevice::ReadOnly);
|
||||
-
|
||||
- if (!readExifHeader(stream))
|
||||
- return -1;
|
||||
-
|
||||
- quint16 val;
|
||||
- quint32 offset;
|
||||
-
|
||||
- // read byte order marker
|
||||
- stream >> val;
|
||||
- if (val == 0x4949) // 'II' == Intel
|
||||
- stream.setByteOrder(QDataStream::LittleEndian);
|
||||
- else if (val == 0x4d4d) // 'MM' == Motorola
|
||||
- stream.setByteOrder(QDataStream::BigEndian);
|
||||
- else
|
||||
- return -1; // unknown byte order
|
||||
-
|
||||
- // read size
|
||||
- stream >> val;
|
||||
- if (val != 0x2a)
|
||||
- return -1;
|
||||
-
|
||||
- stream >> offset;
|
||||
- // we have already used 8 bytes of TIFF header
|
||||
- offset -= 8;
|
||||
-
|
||||
- // read IFD
|
||||
- while (!stream.atEnd()) {
|
||||
- quint16 numEntries;
|
||||
-
|
||||
- // skip offset bytes to get the next IFD
|
||||
- if (stream.skipRawData(offset) != (qint32)offset)
|
||||
- return -1;
|
||||
-
|
||||
- stream >> numEntries;
|
||||
-
|
||||
- for (;numEntries > 0; --numEntries) {
|
||||
- quint16 tag;
|
||||
- quint16 type;
|
||||
- quint32 components;
|
||||
- quint16 value;
|
||||
- quint16 dummy;
|
||||
-
|
||||
- stream >> tag >> type >> components >> value >> dummy;
|
||||
- if (tag == 0x0112) { // Tag Exif.Image.Orientation
|
||||
- if (components !=1)
|
||||
- return -1;
|
||||
- if (type != 3) // we are expecting it to be an unsigned short
|
||||
- return -1;
|
||||
- if (value < 1 || value > 8) // check for valid range
|
||||
- return -1;
|
||||
-
|
||||
- // It is possible to include the orientation multiple times.
|
||||
- // Right now the first value is returned.
|
||||
- return value;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // read offset to next IFD
|
||||
- stream >> offset;
|
||||
- if (offset == 0) // this is the last IFD
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- // No Exif orientation was found
|
||||
- return 0;
|
||||
-}
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
@@ -872,7 +779,6 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
|
||||
|
||||
if (!setjmp(err.setjmp_buffer)) {
|
||||
jpeg_save_markers(&info, JPEG_COM, 0xFFFF);
|
||||
- jpeg_save_markers(&info, JPEG_APP0+1, 0xFFFF); // Exif uses APP1 marker
|
||||
|
||||
(void) jpeg_read_header(&info, TRUE);
|
||||
|
||||
@@ -884,8 +790,6 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
|
||||
format = QImage::Format_Invalid;
|
||||
read_jpeg_format(format, &info);
|
||||
|
||||
- QByteArray exifData;
|
||||
-
|
||||
for (jpeg_saved_marker_ptr marker = info.marker_list; marker != NULL; marker = marker->next) {
|
||||
if (marker->marker == JPEG_COM) {
|
||||
QString key, value;
|
||||
@@ -903,18 +807,9 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
|
||||
description += key + QLatin1String(": ") + value.simplified();
|
||||
readTexts.append(key);
|
||||
readTexts.append(value);
|
||||
- } else if (marker->marker == JPEG_APP0+1) {
|
||||
- exifData.append((const char*)marker->data, marker->data_length);
|
||||
}
|
||||
}
|
||||
|
||||
- if (exifData.size()) {
|
||||
- // Exif data present
|
||||
- int orientation = getExifOrientation(exifData);
|
||||
- if (orientation > 0)
|
||||
- exifOrientation = orientation;
|
||||
- }
|
||||
-
|
||||
state = ReadHeader;
|
||||
return true;
|
||||
}
|
||||
@@ -928,48 +823,6 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
|
||||
return true;
|
||||
}
|
||||
|
||||
-void QJpegHandlerPrivate::applyExifOrientation(QImage *image)
|
||||
-{
|
||||
- // This is not an optimized implementation, but easiest to maintain
|
||||
- QTransform transform;
|
||||
-
|
||||
- switch (exifOrientation) {
|
||||
- case 1: // normal
|
||||
- break;
|
||||
- case 2: // mirror horizontal
|
||||
- *image = image->mirrored(true, false);
|
||||
- break;
|
||||
- case 3: // rotate 180
|
||||
- transform.rotate(180);
|
||||
- *image = image->transformed(transform);
|
||||
- break;
|
||||
- case 4: // mirror vertical
|
||||
- *image = image->mirrored(false, true);
|
||||
- break;
|
||||
- case 5: // mirror horizontal and rotate 270 CCW
|
||||
- *image = image->mirrored(true, false);
|
||||
- transform.rotate(270);
|
||||
- *image = image->transformed(transform);
|
||||
- break;
|
||||
- case 6: // rotate 90 CW
|
||||
- transform.rotate(90);
|
||||
- *image = image->transformed(transform);
|
||||
- break;
|
||||
- case 7: // mirror horizontal and rotate 90 CW
|
||||
- *image = image->mirrored(true, false);
|
||||
- transform.rotate(90);
|
||||
- *image = image->transformed(transform);
|
||||
- break;
|
||||
- case 8: // rotate 270 CW
|
||||
- transform.rotate(-90);
|
||||
- *image = image->transformed(transform);
|
||||
- break;
|
||||
- default:
|
||||
- qWarning("This should never happen");
|
||||
- }
|
||||
- exifOrientation = 1;
|
||||
-}
|
||||
-
|
||||
bool QJpegHandlerPrivate::read(QImage *image)
|
||||
{
|
||||
if(state == Ready)
|
||||
@@ -981,7 +834,6 @@ bool QJpegHandlerPrivate::read(QImage *image)
|
||||
if (success) {
|
||||
for (int i = 0; i < readTexts.size()-1; i+=2)
|
||||
image->setText(readTexts.at(i), readTexts.at(i+1));
|
||||
- applyExifOrientation(image);
|
||||
|
||||
state = Ready;
|
||||
return true;
|
||||
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
|
||||
index 309d3a8..33302ed 100644
|
||||
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
|
||||
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
|
||||
@@ -173,9 +173,6 @@ private slots:
|
||||
void invertPixelsRGB_data();
|
||||
void invertPixelsRGB();
|
||||
|
||||
- void exifOrientation_data();
|
||||
- void exifOrientation();
|
||||
-
|
||||
void cleanupFunctions();
|
||||
|
||||
private:
|
||||
@@ -2649,36 +2646,6 @@ void tst_QImage::invertPixelsRGB()
|
||||
QCOMPARE(qBlue(pixel) >> 4, (255 - 96) >> 4);
|
||||
}
|
||||
|
||||
-void tst_QImage::exifOrientation_data()
|
||||
-{
|
||||
- QTest::addColumn<QString>("fileName");
|
||||
- QTest::newRow("Orientation 1, Intel format") << m_prefix + "jpeg_exif_orientation_value_1.jpg";
|
||||
- QTest::newRow("Orientation 2, Intel format") << m_prefix + "jpeg_exif_orientation_value_2.jpg";
|
||||
- QTest::newRow("Orientation 3, Intel format") << m_prefix + "jpeg_exif_orientation_value_3.jpg";
|
||||
- QTest::newRow("Orientation 4, Intel format") << m_prefix + "jpeg_exif_orientation_value_4.jpg";
|
||||
- QTest::newRow("Orientation 5, Intel format") << m_prefix + "jpeg_exif_orientation_value_5.jpg";
|
||||
- QTest::newRow("Orientation 6, Intel format") << m_prefix + "jpeg_exif_orientation_value_6.jpg";
|
||||
- QTest::newRow("Orientation 6, Motorola format") << m_prefix + "jpeg_exif_orientation_value_6_motorola.jpg";
|
||||
- QTest::newRow("Orientation 7, Intel format") << m_prefix + "jpeg_exif_orientation_value_7.jpg";
|
||||
- QTest::newRow("Orientation 8, Intel format") << m_prefix + "jpeg_exif_orientation_value_8.jpg";
|
||||
-}
|
||||
-
|
||||
-void tst_QImage::exifOrientation()
|
||||
-{
|
||||
- QFETCH(QString, fileName);
|
||||
-
|
||||
- QImage img;
|
||||
- QRgb px;
|
||||
-
|
||||
- QVERIFY(img.load(fileName));
|
||||
-
|
||||
- px = img.pixel(0, 0);
|
||||
- QVERIFY(qRed(px) > 250 && qGreen(px) < 5 && qBlue(px) < 5);
|
||||
-
|
||||
- px = img.pixel(img.width() - 1, 0);
|
||||
- QVERIFY(qRed(px) < 5 && qGreen(px) < 5 && qBlue(px) > 250);
|
||||
-}
|
||||
-
|
||||
static void cleanupFunction(void* info)
|
||||
{
|
||||
bool *called = static_cast<bool*>(info);
|
||||
--
|
||||
2.3.6
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
From 083c9269ed73e8771e1dbe10812696b45b7389f3 Mon Sep 17 00:00:00 2001
|
||||
From: Evangelos Foutras <evangelos@foutrelis.com>
|
||||
Date: Mon, 11 May 2015 12:20:57 +0300
|
||||
Subject: [PATCH] Try to ensure that -fPIC is used in CMake builds
|
||||
|
||||
In commit 36d6eb721e7d5997ade75e289d4088dc48678d0d the -fPIE switch was
|
||||
replaced with -fPIC in an effort to avoid generating copy relocations
|
||||
which are incompatible with Qt5 when built with -reduce-relocations.
|
||||
|
||||
Task-number: QTBUG-45755
|
||||
Change-Id: I59a55ea15052f498104848c5fd867e563ddc2290
|
||||
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
||||
---
|
||||
src/corelib/Qt5CoreConfigExtras.cmake.in | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in
|
||||
index 48d5f21..d4abc5f 100644
|
||||
--- a/src/corelib/Qt5CoreConfigExtras.cmake.in
|
||||
+++ b/src/corelib/Qt5CoreConfigExtras.cmake.in
|
||||
@@ -70,8 +70,9 @@ set(_qt5_corelib_extra_includes)
|
||||
# Qt5_POSITION_INDEPENDENT_CODE variable is used in the # qt5_use_module
|
||||
# macro to add it.
|
||||
set(Qt5_POSITION_INDEPENDENT_CODE True)
|
||||
-set_property(TARGET Qt5::Core PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE \"ON\")
|
||||
set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"-fPIC\")
|
||||
+set_property(TARGET Qt5::Core PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE \"ON\")
|
||||
+set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_COMPILE_OPTIONS ${Qt5Core_EXECUTABLE_COMPILE_FLAGS})
|
||||
!!ENDIF
|
||||
|
||||
!!IF !isEmpty(QT_NAMESPACE)
|
||||
--
|
||||
2.4.0
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
From 661f6bfd032dacc62841037732816a583640e187 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard J. Moore" <rich@kde.org>
|
||||
Date: Sat, 21 Feb 2015 17:43:21 +0000
|
||||
Subject: Fix a division by zero when processing malformed BMP files.
|
||||
|
||||
This fixes a division by 0 when processing a maliciously crafted BMP
|
||||
file. No impact beyond DoS.
|
||||
|
||||
Task-number: QTBUG-44547
|
||||
Change-Id: Ifcded2c0aa712e90d23e6b3969af0ec3add53973
|
||||
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
||||
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
|
||||
---
|
||||
src/gui/image/qbmphandler.cpp | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
|
||||
index 21c1a2f..df66499 100644
|
||||
--- a/src/gui/image/qbmphandler.cpp
|
||||
+++ b/src/gui/image/qbmphandler.cpp
|
||||
@@ -314,12 +314,20 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
|
||||
}
|
||||
} else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) {
|
||||
red_shift = calc_shift(red_mask);
|
||||
+ if (((red_mask >> red_shift) + 1) == 0)
|
||||
+ return false;
|
||||
red_scale = 256 / ((red_mask >> red_shift) + 1);
|
||||
green_shift = calc_shift(green_mask);
|
||||
+ if (((green_mask >> green_shift) + 1) == 0)
|
||||
+ return false;
|
||||
green_scale = 256 / ((green_mask >> green_shift) + 1);
|
||||
blue_shift = calc_shift(blue_mask);
|
||||
+ if (((blue_mask >> blue_shift) + 1) == 0)
|
||||
+ return false;
|
||||
blue_scale = 256 / ((blue_mask >> blue_shift) + 1);
|
||||
alpha_shift = calc_shift(alpha_mask);
|
||||
+ if (((alpha_mask >> alpha_shift) + 1) == 0)
|
||||
+ return false;
|
||||
alpha_scale = 256 / ((alpha_mask >> alpha_shift) + 1);
|
||||
} else if (comp == BMP_RGB && (nbits == 24 || nbits == 32)) {
|
||||
blue_mask = 0x000000ff;
|
||||
--
|
||||
cgit v0.11.0
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
From 51ec7ebfe5f45d1c0a03d992e97053cac66e25fe Mon Sep 17 00:00:00 2001
|
||||
From: Eirik Aavitsland <eirik.aavitsland@theqtcompany.com>
|
||||
Date: Wed, 11 Mar 2015 13:34:01 +0100
|
||||
Subject: Fixes crash in bmp and ico image decoding
|
||||
|
||||
Fuzzing test revealed that for certain malformed bmp and ico files,
|
||||
the handler would segfault.
|
||||
|
||||
Change-Id: I19d45145f31e7f808f7f6a1a1610270ea4159cbe
|
||||
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
|
||||
---
|
||||
src/gui/image/qbmphandler.cpp | 13 +++++++------
|
||||
src/plugins/imageformats/ico/qicohandler.cpp | 2 +-
|
||||
2 files changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
|
||||
index df66499..8acc593 100644
|
||||
--- a/src/gui/image/qbmphandler.cpp
|
||||
+++ b/src/gui/image/qbmphandler.cpp
|
||||
@@ -484,12 +484,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
|
||||
p = data + (h-y-1)*bpl;
|
||||
break;
|
||||
case 2: // delta (jump)
|
||||
- // Protection
|
||||
- if ((uint)x >= (uint)w)
|
||||
- x = w-1;
|
||||
- if ((uint)y >= (uint)h)
|
||||
- y = h-1;
|
||||
-
|
||||
{
|
||||
quint8 tmp;
|
||||
d->getChar((char *)&tmp);
|
||||
@@ -497,6 +491,13 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
|
||||
d->getChar((char *)&tmp);
|
||||
y += tmp;
|
||||
}
|
||||
+
|
||||
+ // Protection
|
||||
+ if ((uint)x >= (uint)w)
|
||||
+ x = w-1;
|
||||
+ if ((uint)y >= (uint)h)
|
||||
+ y = h-1;
|
||||
+
|
||||
p = data + (h-y-1)*bpl + x;
|
||||
break;
|
||||
default: // absolute mode
|
||||
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
|
||||
index 00de0c8..ec1654e 100644
|
||||
--- a/src/plugins/imageformats/ico/qicohandler.cpp
|
||||
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
|
||||
@@ -567,7 +567,7 @@ QImage ICOReader::iconAt(int index)
|
||||
QImage::Format format = QImage::Format_ARGB32;
|
||||
if (icoAttrib.nbits == 24)
|
||||
format = QImage::Format_RGB32;
|
||||
- else if (icoAttrib.ncolors == 2)
|
||||
+ else if (icoAttrib.ncolors == 2 && icoAttrib.depth == 1)
|
||||
format = QImage::Format_Mono;
|
||||
else if (icoAttrib.ncolors > 0)
|
||||
format = QImage::Format_Indexed8;
|
||||
--
|
||||
cgit v0.11.0
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
From d3048a29797ee2d80d84bbda26bb3c954584f332 Mon Sep 17 00:00:00 2001
|
||||
From: Eirik Aavitsland <eirik.aavitsland@theqtcompany.com>
|
||||
Date: Wed, 11 Mar 2015 09:00:41 +0100
|
||||
Subject: Fixes crash in gif image decoder
|
||||
|
||||
Fuzzing test revealed that for certain malformed gif files,
|
||||
qgifhandler would segfault.
|
||||
|
||||
Change-Id: I5bb6f60e1c61849e0d8c735edc3869945e5331c1
|
||||
Reviewed-by: Richard J. Moore <rich@kde.org>
|
||||
---
|
||||
src/gui/image/qgifhandler.cpp | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/gui/image/qgifhandler.cpp b/src/gui/image/qgifhandler.cpp
|
||||
index 03e46ab..8d8c4ae 100644
|
||||
--- a/src/gui/image/qgifhandler.cpp
|
||||
+++ b/src/gui/image/qgifhandler.cpp
|
||||
@@ -936,6 +936,8 @@ void QGIFFormat::fillRect(QImage *image, int col, int row, int w, int h, QRgb co
|
||||
|
||||
void QGIFFormat::nextY(unsigned char *bits, int bpl)
|
||||
{
|
||||
+ if (out_of_bounds)
|
||||
+ return;
|
||||
int my;
|
||||
switch (interlace) {
|
||||
case 0: // Non-interlaced
|
||||
--
|
||||
cgit v0.11.0
|
||||
|
|
@ -38,8 +38,8 @@ pkgname=('qt5-base'
|
|||
'qt5-websockets'
|
||||
'qt5-x11extras'
|
||||
'qt5-xmlpatterns')
|
||||
pkgver=5.4.1
|
||||
pkgrel=9
|
||||
pkgver=5.4.2
|
||||
pkgrel=1
|
||||
arch=('i686' 'x86_64')
|
||||
url='http://qt-project.org/'
|
||||
license=('GPL3' 'LGPL' 'FDL' 'custom')
|
||||
|
@ -53,62 +53,33 @@ makedepends=('libxcb' 'xcb-proto' 'xcb-util' 'xcb-util-image' 'xcb-util-wm' 'xcb
|
|||
groups=('qt' 'qt5')
|
||||
_pkgfqn="qt-everywhere-opensource-src-${pkgver}"
|
||||
source=("http://download.qt-project.org/official_releases/qt/${pkgver%.*}/${pkgver}/single/${_pkgfqn}.tar.xz"
|
||||
'0001-Revert-Rotate-images-according-to-Exif-orientation.patch'
|
||||
'0001-Require-fPIC-instead-of-just-fPIE-for-reduce-relocat.patch'
|
||||
'0001-Make-qglobal.h-complain-if-you-use-fPIE.patch'
|
||||
'0001-Try-to-ensure-that-fPIC-is-used-in-CMake-builds.patch'
|
||||
'assistant.desktop' 'designer.desktop' 'linguist.desktop' 'qdbusviewer.desktop' 'glib-2.43.patch'
|
||||
'qlockfile-deadlock.patch' 'qnam-corruption.patch' 'keypad-shortcuts.patch'
|
||||
'CVE-2015-0295.patch' 'CVE-2015-1858_1859.patch' 'CVE-2015-1860.patch'
|
||||
'assistant.desktop' 'designer.desktop' 'linguist.desktop' 'qdbusviewer.desktop'
|
||||
'keypad-shortcuts.patch' 'avoid-calling-potentially-pure-virtual-method.patch'
|
||||
'ibus-get-display-number-when-screen-number-is-omitted.patch'
|
||||
'rpi.patch'
|
||||
'qt5webkit-0002-Fix-QtWebKit-build-on-ARM-softfp.patch')
|
||||
md5sums=('7afb5f9235d8d42b5b6e832442a32a5d'
|
||||
'fb1459f325a15b15b18afeac51173a1d'
|
||||
'ac8fa252868161c676d876b614e24436'
|
||||
'913a5931d33110b8e698bc9ce733075e'
|
||||
'fb18ddd022422cd42721d6fb2a994e6a'
|
||||
md5sums=('c23bd0f14d66e7901d24906a1edce9b0'
|
||||
'b2897dd6a2967bccf8f10e397aafee55'
|
||||
'76e150b20178d2d43801f7367232e5f7'
|
||||
'188da8f4c87316e730ebf1c6217bf5a0'
|
||||
'322b419b16c75d4de0ee7ad0a246caa1'
|
||||
'bf756a3061e1b30b28df85dcf0c90df3'
|
||||
'30d219401f77e536d215addc420b634c'
|
||||
'd0b070d6f211948ef4842b46542b9e4f'
|
||||
'665439088fc7de52a97455c5eaf87889'
|
||||
'871ab111d03a640b4d0250388a4307cc'
|
||||
'b799130014294cb3c73fc46e7e8889db'
|
||||
'64bc4f7d5097438eb6c6f8042378b3a3'
|
||||
'cab3284d52ea700b8761f4d71d68baf0'
|
||||
'39e285d08b4951de095c2f6d6acdc925'
|
||||
'9fe115d2c1d4778b8cb8e7f1b2e2bca6'
|
||||
'd55ad1f1c90725834b44eada5db4e401')
|
||||
|
||||
prepare() {
|
||||
cd ${_pkgfqn}
|
||||
|
||||
# https://bugreports.qt.io/browse/QTBUG-37946
|
||||
(cd qtbase; patch -p1 -i "$srcdir/0001-Revert-Rotate-images-according-to-Exif-orientation.patch")
|
||||
|
||||
# https://bugreports.qt.io/browse/QTBUG-45755
|
||||
(cd qtbase; patch -p1 -i "$srcdir/0001-Require-fPIC-instead-of-just-fPIE-for-reduce-relocat.patch")
|
||||
(cd qtbase; patch -p1 -i "$srcdir/0001-Make-qglobal.h-complain-if-you-use-fPIE.patch")
|
||||
(cd qtbase; patch -p1 -i "$srcdir/0001-Try-to-ensure-that-fPIC-is-used-in-CMake-builds.patch")
|
||||
|
||||
# for glib 2.43+ https://bugreports.qt.io/browse/QTBUG-44714
|
||||
(cd qtwebkit; patch -p1 -i "$srcdir/glib-2.43.patch")
|
||||
|
||||
# https://bugs.kde.org/show_bug.cgi?id=345901
|
||||
(cd qtbase; patch -p1 -i "$srcdir/qlockfile-deadlock.patch")
|
||||
|
||||
# https://codereview.qt-project.org/#/c/110150/
|
||||
(cd qtbase; patch -p1 -i "$srcdir/qnam-corruption.patch")
|
||||
|
||||
# https://bugs.archlinux.org/task/44676
|
||||
(cd qtbase; patch -p1 -i "$srcdir/keypad-shortcuts.patch")
|
||||
|
||||
# http://lists.qt-project.org/pipermail/announce/2015-February/000059.html
|
||||
(cd qtbase; patch -p1 -i "$srcdir/CVE-2015-0295.patch")
|
||||
# https://bugs.archlinux.org/task/43986
|
||||
(cd qtdeclarative; patch -p1 -i "$srcdir/avoid-calling-potentially-pure-virtual-method.patch")
|
||||
|
||||
# http://lists.qt-project.org/pipermail/announce/2015-April/000067.html
|
||||
(cd qtbase; patch -p1 -i "$srcdir/CVE-2015-1858_1859.patch"; patch -p1 -i "$srcdir/CVE-2015-1860.patch")
|
||||
# https://bugs.archlinux.org/task/45180
|
||||
(cd qtbase; patch -p1 -i "$srcdir/ibus-get-display-number-when-screen-number-is-omitted.patch")
|
||||
|
||||
MAKEFLAGS="-j3"
|
||||
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
From 0d31aa1617c96ed3e3624d77332ea6f13aba1492 Mon Sep 17 00:00:00 2001
|
||||
From: David Edmundson <davidedmundson@kde.org>
|
||||
Date: Thu, 23 Apr 2015 15:01:24 +0200
|
||||
Subject: [PATCH 67/68] Avoid calling potentially pure virtual method
|
||||
|
||||
In Qt 5.4 screenChanged is called indirectly from the destructor of
|
||||
QPlatformScreen. By comparing new values against the oldScreen we call
|
||||
call virtual methods of QPlatformScreen from it's own destructor which
|
||||
results in a crash.
|
||||
|
||||
This patch simply emits change signals whenever a screen change regardless
|
||||
of whether the value differs from the previous screen. Arguably less
|
||||
efficient, but better than crashing.
|
||||
|
||||
This fix is not needed in Qt 5.5 where the QPA architecture has changed.
|
||||
|
||||
Task-number: QTBUG-45753
|
||||
Change-Id: Ic155906928855a377add9b21bff9e72b31f4667e
|
||||
Reviewed-by: Alan Alpert <aalpert@blackberry.com>
|
||||
---
|
||||
src/quick/items/qquickscreen.cpp | 27 +++++++++------------------
|
||||
1 file changed, 9 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp
|
||||
index c4d1407..0900adb 100644
|
||||
--- a/src/quick/items/qquickscreen.cpp
|
||||
+++ b/src/quick/items/qquickscreen.cpp
|
||||
@@ -347,24 +347,15 @@ void QQuickScreenAttached::screenChanged(QScreen *screen)
|
||||
emit orientationUpdateMaskChanged();
|
||||
}
|
||||
|
||||
- if (!oldScreen || screen->size() != oldScreen->size()) {
|
||||
- emit widthChanged();
|
||||
- emit heightChanged();
|
||||
- }
|
||||
- if (!oldScreen || screen->name() != oldScreen->name())
|
||||
- emit nameChanged();
|
||||
- if (!oldScreen || screen->orientation() != oldScreen->orientation())
|
||||
- emit orientationChanged();
|
||||
- if (!oldScreen || screen->primaryOrientation() != oldScreen->primaryOrientation())
|
||||
- emit primaryOrientationChanged();
|
||||
- if (!oldScreen || screen->availableVirtualGeometry() != oldScreen->availableVirtualGeometry())
|
||||
- emit desktopGeometryChanged();
|
||||
- if (!oldScreen || screen->logicalDotsPerInch() != oldScreen->logicalDotsPerInch())
|
||||
- emit logicalPixelDensityChanged();
|
||||
- if (!oldScreen || screen->physicalDotsPerInch() != oldScreen->physicalDotsPerInch())
|
||||
- emit pixelDensityChanged();
|
||||
- if (!oldScreen || screen->devicePixelRatio() != oldScreen->devicePixelRatio())
|
||||
- emit devicePixelRatioChanged();
|
||||
+ emit widthChanged();
|
||||
+ emit heightChanged();
|
||||
+ emit nameChanged();
|
||||
+ emit orientationChanged();
|
||||
+ emit primaryOrientationChanged();
|
||||
+ emit desktopGeometryChanged();
|
||||
+ emit logicalPixelDensityChanged();
|
||||
+ emit pixelDensityChanged();
|
||||
+ emit devicePixelRatioChanged();
|
||||
|
||||
connect(screen, SIGNAL(geometryChanged(QRect)),
|
||||
this, SIGNAL(widthChanged()));
|
||||
--
|
||||
2.3.7
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
From ed5d6c93f7cf902e58aaf3f0abd54b3b258172ed Mon Sep 17 00:00:00 2001
|
||||
From: Allan Sandfeld Jensen <allan.jensen@theqtcompany.com>
|
||||
Date: Fri, 27 Feb 2015 14:14:44 +0100
|
||||
Subject: Fix building with glib 2.43+
|
||||
|
||||
The newest version of glib have introduced their own GMutexLocker
|
||||
conflicting with the one defined in WebCore.
|
||||
|
||||
Task-number: QTBUG-44714
|
||||
Change-Id: Ibdd1646e129eaed84c65dc0d96bebe80f2a61f4b
|
||||
Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
|
||||
---
|
||||
.../gstreamer/WebKitWebSourceGStreamer.cpp | 48 +++++++++++-----------
|
||||
1 file changed, 24 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
|
||||
index 5625873..a6d961f 100644
|
||||
--- a/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
|
||||
+++ b/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
|
||||
@@ -354,7 +354,7 @@ static void webKitWebSrcSetProperty(GObject* object, guint propID, const GValue*
|
||||
|
||||
switch (propID) {
|
||||
case PROP_IRADIO_MODE: {
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
priv->iradioMode = g_value_get_boolean(value);
|
||||
break;
|
||||
}
|
||||
@@ -376,7 +376,7 @@ static void webKitWebSrcGetProperty(GObject* object, guint propID, GValue* value
|
||||
WebKitWebSrc* src = WEBKIT_WEB_SRC(object);
|
||||
WebKitWebSrcPrivate* priv = src->priv;
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
switch (propID) {
|
||||
case PROP_IRADIO_MODE:
|
||||
g_value_set_boolean(value, priv->iradioMode);
|
||||
@@ -429,7 +429,7 @@ static gboolean webKitWebSrcStop(WebKitWebSrc* src)
|
||||
|
||||
ASSERT(isMainThread());
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
|
||||
bool seeking = priv->seekID;
|
||||
|
||||
@@ -493,7 +493,7 @@ static gboolean webKitWebSrcStart(WebKitWebSrc* src)
|
||||
|
||||
ASSERT(isMainThread());
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
|
||||
priv->startID = 0;
|
||||
|
||||
@@ -584,7 +584,7 @@ static GstStateChangeReturn webKitWebSrcChangeState(GstElement* element, GstStat
|
||||
return ret;
|
||||
}
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
GST_DEBUG_OBJECT(src, "READY->PAUSED");
|
||||
@@ -615,7 +615,7 @@ static gboolean webKitWebSrcQueryWithParent(GstPad* pad, GstObject* parent, GstQ
|
||||
gst_query_parse_duration(query, &format, NULL);
|
||||
|
||||
GST_DEBUG_OBJECT(src, "duration query in format %s", gst_format_get_name(format));
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
if (format == GST_FORMAT_BYTES && src->priv->size > 0) {
|
||||
gst_query_set_duration(query, format, src->priv->size);
|
||||
result = TRUE;
|
||||
@@ -623,7 +623,7 @@ static gboolean webKitWebSrcQueryWithParent(GstPad* pad, GstObject* parent, GstQ
|
||||
break;
|
||||
}
|
||||
case GST_QUERY_URI: {
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
gst_query_set_uri(query, src->priv->uri);
|
||||
result = TRUE;
|
||||
break;
|
||||
@@ -668,7 +668,7 @@ static gchar* webKitWebSrcGetUri(GstURIHandler* handler)
|
||||
WebKitWebSrc* src = WEBKIT_WEB_SRC(handler);
|
||||
gchar* ret;
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
ret = g_strdup(src->priv->uri);
|
||||
return ret;
|
||||
}
|
||||
@@ -683,7 +683,7 @@ static gboolean webKitWebSrcSetUri(GstURIHandler* handler, const gchar* uri, GEr
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
|
||||
g_free(priv->uri);
|
||||
priv->uri = 0;
|
||||
@@ -719,7 +719,7 @@ static const gchar* webKitWebSrcGetUri(GstURIHandler* handler)
|
||||
WebKitWebSrc* src = WEBKIT_WEB_SRC(handler);
|
||||
gchar* ret;
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
ret = g_strdup(src->priv->uri);
|
||||
return ret;
|
||||
}
|
||||
@@ -734,7 +734,7 @@ static gboolean webKitWebSrcSetUri(GstURIHandler* handler, const gchar* uri)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
|
||||
g_free(priv->uri);
|
||||
priv->uri = 0;
|
||||
@@ -772,7 +772,7 @@ static gboolean webKitWebSrcNeedDataMainCb(WebKitWebSrc* src)
|
||||
|
||||
ASSERT(isMainThread());
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
// already stopped
|
||||
if (!priv->needDataID)
|
||||
return FALSE;
|
||||
@@ -793,7 +793,7 @@ static void webKitWebSrcNeedDataCb(GstAppSrc*, guint length, gpointer userData)
|
||||
|
||||
GST_DEBUG_OBJECT(src, "Need more data: %u", length);
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
if (priv->needDataID || !priv->paused) {
|
||||
return;
|
||||
}
|
||||
@@ -807,7 +807,7 @@ static gboolean webKitWebSrcEnoughDataMainCb(WebKitWebSrc* src)
|
||||
|
||||
ASSERT(isMainThread());
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
// already stopped
|
||||
if (!priv->enoughDataID)
|
||||
return FALSE;
|
||||
@@ -828,7 +828,7 @@ static void webKitWebSrcEnoughDataCb(GstAppSrc*, gpointer userData)
|
||||
|
||||
GST_DEBUG_OBJECT(src, "Have enough data");
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
if (priv->enoughDataID || priv->paused) {
|
||||
return;
|
||||
}
|
||||
@@ -842,7 +842,7 @@ static gboolean webKitWebSrcSeekMainCb(WebKitWebSrc* src)
|
||||
|
||||
ASSERT(isMainThread());
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
// already stopped
|
||||
if (!priv->seekID)
|
||||
return FALSE;
|
||||
@@ -860,7 +860,7 @@ static gboolean webKitWebSrcSeekDataCb(GstAppSrc*, guint64 offset, gpointer user
|
||||
WebKitWebSrcPrivate* priv = src->priv;
|
||||
|
||||
GST_DEBUG_OBJECT(src, "Seeking to offset: %" G_GUINT64_FORMAT, offset);
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
if (offset == priv->offset && priv->requestedOffset == priv->offset)
|
||||
return TRUE;
|
||||
|
||||
@@ -879,7 +879,7 @@ static gboolean webKitWebSrcSeekDataCb(GstAppSrc*, guint64 offset, gpointer user
|
||||
void webKitWebSrcSetMediaPlayer(WebKitWebSrc* src, WebCore::MediaPlayer* player)
|
||||
{
|
||||
ASSERT(player);
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
src->priv->player = player;
|
||||
s_cachedResourceLoader = player->cachedResourceLoader();
|
||||
}
|
||||
@@ -906,7 +906,7 @@ char* StreamingClient::createReadBuffer(size_t requestedSize, size_t& actualSize
|
||||
mapGstBuffer(buffer);
|
||||
#endif
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
priv->buffer = adoptGRef(buffer);
|
||||
locker.unlock();
|
||||
|
||||
@@ -921,7 +921,7 @@ void StreamingClient::handleResponseReceived(const ResourceResponse& response)
|
||||
|
||||
GST_DEBUG_OBJECT(src, "Received response: %d", response.httpStatusCode());
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
|
||||
// If we seeked we need 206 == PARTIAL_CONTENT
|
||||
if (priv->requestedOffset && response.httpStatusCode() != 206) {
|
||||
@@ -1020,7 +1020,7 @@ void StreamingClient::handleDataReceived(const char* data, int length)
|
||||
WebKitWebSrc* src = WEBKIT_WEB_SRC(m_src.get());
|
||||
WebKitWebSrcPrivate* priv = src->priv;
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
|
||||
GST_LOG_OBJECT(src, "Have %d bytes of data", priv->buffer ? getGstBufferSize(priv->buffer.get()) : length);
|
||||
|
||||
@@ -1074,7 +1074,7 @@ void StreamingClient::handleNotifyFinished()
|
||||
|
||||
GST_DEBUG_OBJECT(src, "Have EOS");
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
if (!priv->seekID) {
|
||||
locker.unlock();
|
||||
gst_app_src_end_of_stream(priv->appsrc);
|
||||
@@ -1210,7 +1210,7 @@ void ResourceHandleStreamingClient::wasBlocked(ResourceHandle*)
|
||||
|
||||
GST_ERROR_OBJECT(src, "Request was blocked");
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
uri.set(g_strdup(src->priv->uri));
|
||||
locker.unlock();
|
||||
|
||||
@@ -1224,7 +1224,7 @@ void ResourceHandleStreamingClient::cannotShowURL(ResourceHandle*)
|
||||
|
||||
GST_ERROR_OBJECT(src, "Cannot show URL");
|
||||
|
||||
- GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
+ WebCore::GMutexLocker locker(GST_OBJECT_GET_LOCK(src));
|
||||
uri.set(g_strdup(src->priv->uri));
|
||||
locker.unlock();
|
||||
|
||||
--
|
||||
cgit v0.11.0
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From c72325d52575cb8a46cc8595c592c27581089dec Mon Sep 17 00:00:00 2001
|
||||
From: Takao Fujiwara <tfujiwar@redhat.com>
|
||||
Date: Tue, 24 Mar 2015 19:08:34 +0900
|
||||
Subject: [PATCH] ibus: Get display number when screen number is omitted.
|
||||
|
||||
QIBusPlatformInputContextPrivate::createConnection() parses DISPLAY
|
||||
variable and it does not get the display number when the screen number
|
||||
is omitted. E.g. DISPLAY=":1".
|
||||
|
||||
Change-Id: I9f81d8114d4e0f654a27ada67c5dc110eb34cd64
|
||||
Reviewed-by: Gatis Paeglis <gatis.paeglis@digia.com>
|
||||
---
|
||||
.../ibus/qibusplatforminputcontext.cpp | 2 ++
|
||||
1 files changed, 2 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
|
||||
index d00435b..673942b 100644
|
||||
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
|
||||
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
|
||||
@@ -351,6 +351,8 @@ QDBusConnection *QIBusPlatformInputContextPrivate::createConnection()
|
||||
int pos2 = display.indexOf('.', pos);
|
||||
if (pos2 > 0)
|
||||
displayNumber = display.mid(pos, pos2 - pos);
|
||||
+ else
|
||||
+ displayNumber = display.right(pos);
|
||||
if (debug)
|
||||
qDebug() << "host=" << host << "displayNumber" << displayNumber;
|
||||
|
||||
--
|
||||
1.7.1
|
||||
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
From 6a7ee92b3958e3a3ebc16be15f8bd34217ec7bd2 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= <mgraesslin@kde.org>
|
||||
Date: Wed, 10 Dec 2014 07:27:23 +0100
|
||||
Subject: [PATCH] Handle SelectionClientClose in QXcbClipboard
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
QXcbClipboard listens for subtype SelectionClientClose of Xfixes
|
||||
SelectionNotify event, but doesn't handle it. When the client holding
|
||||
the clipboard selection closes the Clipboard becomes empty and thus the
|
||||
change should be emitted.
|
||||
|
||||
This fixes downstream KDE Bug #329174.
|
||||
|
||||
Change-Id: I19fb8cfd7bd3b249c0bc6ca2a724a9aeeb05ac7e
|
||||
Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
|
||||
Reviewed-by: Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
---
|
||||
src/plugins/platforms/xcb/qxcbclipboard.cpp | 3 ++-
|
||||
1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
|
||||
index 8b3893e..f56a29d 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
|
||||
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
|
||||
@@ -742,7 +742,8 @@ void QXcbClipboard::handleXFixesSelectionRequest(xcb_xfixes_selection_notify_eve
|
||||
m_xClipboard[mode]->reset();
|
||||
}
|
||||
emitChanged(mode);
|
||||
- }
|
||||
+ } else if (event->subtype == XCB_XFIXES_SELECTION_EVENT_SELECTION_CLIENT_CLOSE)
|
||||
+ emitChanged(mode);
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
1.7.1
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
From f58e882b7594c59b6050d3c87562fcf836d10f60 Mon Sep 17 00:00:00 2001
|
||||
From: Olivier Goffart <ogoffart@woboq.com>
|
||||
Date: Tue, 14 Apr 2015 10:58:26 +0200
|
||||
Subject: QLockFile: fix deadlock when the lock file is corrupted
|
||||
|
||||
[ChangeLog][QtCore][QLockFile] Fixed a deadlock when the lock file
|
||||
is corrupted.
|
||||
|
||||
Task-number: QTBUG-44771
|
||||
Change-Id: Ic490b09d70ff1cc1733b64949889a73720b2d0f3
|
||||
Reviewed-by: David Faure <david.faure@kdab.com>
|
||||
---
|
||||
src/corelib/io/qlockfile_unix.cpp | 10 +++++-----
|
||||
src/corelib/io/qlockfile_win.cpp | 22 +++++++++++-----------
|
||||
tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp | 17 +++++++++++++++++
|
||||
3 files changed, 33 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
|
||||
index bf1015a..dc9f8f7 100644
|
||||
--- a/src/corelib/io/qlockfile_unix.cpp
|
||||
+++ b/src/corelib/io/qlockfile_unix.cpp
|
||||
@@ -181,11 +181,11 @@ bool QLockFilePrivate::isApparentlyStale() const
|
||||
{
|
||||
qint64 pid;
|
||||
QString hostname, appname;
|
||||
- if (!getLockInfo(&pid, &hostname, &appname))
|
||||
- return false;
|
||||
- if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
|
||||
- if (::kill(pid, 0) == -1 && errno == ESRCH)
|
||||
- return true; // PID doesn't exist anymore
|
||||
+ if (getLockInfo(&pid, &hostname, &appname)) {
|
||||
+ if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
|
||||
+ if (::kill(pid, 0) == -1 && errno == ESRCH)
|
||||
+ return true; // PID doesn't exist anymore
|
||||
+ }
|
||||
}
|
||||
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
|
||||
return staleLockTime > 0 && age > staleLockTime;
|
||||
diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp
|
||||
index f9f2909..3587c7b 100644
|
||||
--- a/src/corelib/io/qlockfile_win.cpp
|
||||
+++ b/src/corelib/io/qlockfile_win.cpp
|
||||
@@ -115,21 +115,21 @@ bool QLockFilePrivate::isApparentlyStale() const
|
||||
{
|
||||
qint64 pid;
|
||||
QString hostname, appname;
|
||||
- if (!getLockInfo(&pid, &hostname, &appname))
|
||||
- return false;
|
||||
|
||||
// On WinRT there seems to be no way of obtaining information about other
|
||||
// processes due to sandboxing
|
||||
#ifndef Q_OS_WINRT
|
||||
- if (hostname == QString::fromLocal8Bit(localHostName())) {
|
||||
- HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
||||
- if (!procHandle)
|
||||
- return true;
|
||||
- // We got a handle but check if process is still alive
|
||||
- DWORD dwR = ::WaitForSingleObject(procHandle, 0);
|
||||
- ::CloseHandle(procHandle);
|
||||
- if (dwR == WAIT_TIMEOUT)
|
||||
- return true;
|
||||
+ if (getLockInfo(&pid, &hostname, &appname)) {
|
||||
+ if (hostname == QString::fromLocal8Bit(localHostName())) {
|
||||
+ HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
||||
+ if (!procHandle)
|
||||
+ return true;
|
||||
+ // We got a handle but check if process is still alive
|
||||
+ DWORD dwR = ::WaitForSingleObject(procHandle, 0);
|
||||
+ ::CloseHandle(procHandle);
|
||||
+ if (dwR == WAIT_TIMEOUT)
|
||||
+ return true;
|
||||
+ }
|
||||
}
|
||||
#endif // !Q_OS_WINRT
|
||||
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
|
||||
diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
|
||||
index 77bef94..12bea67 100644
|
||||
--- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
|
||||
+++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
|
||||
@@ -58,6 +58,7 @@ private slots:
|
||||
void staleLongLockFromBusyProcess();
|
||||
void staleLockRace();
|
||||
void noPermissions();
|
||||
+ void corruptedLockFile();
|
||||
|
||||
public:
|
||||
QString m_helperApp;
|
||||
@@ -415,5 +416,21 @@ void tst_QLockFile::noPermissions()
|
||||
QCOMPARE(int(lockFile.error()), int(QLockFile::PermissionError));
|
||||
}
|
||||
|
||||
+void tst_QLockFile::corruptedLockFile()
|
||||
+{
|
||||
+ const QString fileName = dir.path() + "/corruptedLockFile";
|
||||
+
|
||||
+ {
|
||||
+ // Create a empty file. Typically the result of a computer crash or hard disk full.
|
||||
+ QFile file(fileName);
|
||||
+ QVERIFY(file.open(QFile::WriteOnly));
|
||||
+ }
|
||||
+
|
||||
+ QLockFile secondLock(fileName);
|
||||
+ secondLock.setStaleLockTime(100);
|
||||
+ QVERIFY(secondLock.tryLock(10000));
|
||||
+ QCOMPARE(int(secondLock.error()), int(QLockFile::NoError));
|
||||
+}
|
||||
+
|
||||
QTEST_MAIN(tst_QLockFile)
|
||||
#include "tst_qlockfile.moc"
|
||||
--
|
||||
cgit v0.11.0
|
||||
|
|
@ -1,691 +0,0 @@
|
|||
From cff39fba10ffc10ee4dcfdc66ff6528eb26462d3 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Goetz <markus@woboq.com>
|
||||
Date: Fri, 10 Apr 2015 14:09:53 +0200
|
||||
Subject: 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 <peter-qt@hartmann.tk>
|
||||
---
|
||||
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<QRingBuffer> 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<QRingBuffer> 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<QSslError>)),
|
||||
this, SLOT(_q_sslErrors(QList<QSslError>)),
|
||||
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<QHttpNetworkRequest, QHttpNetworkReply*> 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<QNonContiguousByteDevice> uploadByteDevice;
|
||||
+ qint64 uploadByteDevicePosition;
|
||||
bool uploadDeviceChoking; // if we couldn't readPointer() any data at the moment
|
||||
QIODevice *outgoingData;
|
||||
QSharedPointer<QRingBuffer> 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<QSslError>)), 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<QSslError>)), 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<QSslError>)), 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=" <<numUploads;
|
||||
+
|
||||
+ // Sanity check because ecause of 9c2ecf89 most replies will error out but we want to make sure at least some of them worked
|
||||
+ QVERIFY(server.m_correctUploads > 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()
|
||||
--
|
||||
cgit v0.11.0
|
||||
|
Loading…
Reference in a new issue