Merge "Merge remote-tracking branch 'origin/5.4' into 5.5" into refs/staging/5.5
commit
a47cd2cc82
|
|
@ -2605,6 +2605,7 @@
|
|||
(checked if all children are checked, unchecked if all children are unchecked,
|
||||
or partially checked if only some children are checked).
|
||||
\value ItemNeverHasChildren The item never has child items.
|
||||
This is used for optimization purposes only.
|
||||
\value ItemIsUserTristate The user can cycle through three separate states.
|
||||
This value has been added in Qt 5.5.
|
||||
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ QString QProcessEnvironment::value(const QString &name, const QString &defaultVa
|
|||
Use with the QProcess::setEnvironment function is not recommended due to
|
||||
potential encoding problems under Unix, and worse performance.
|
||||
|
||||
\sa systemEnvironment(), QProcess::systemEnvironment(), QProcess::environment(),
|
||||
QProcess::setEnvironment()
|
||||
\sa systemEnvironment(), QProcess::systemEnvironment(),
|
||||
QProcess::setProcessEnvironment()
|
||||
*/
|
||||
QStringList QProcessEnvironment::toStringList() const
|
||||
{
|
||||
|
|
@ -539,7 +539,7 @@ void QProcessPrivate::Channel::clear()
|
|||
|
||||
Certain processes need special environment settings in order to
|
||||
operate. You can set environment variables for your process by
|
||||
calling setEnvironment(). To set a working directory, call
|
||||
calling setProcessEnvironment(). To set a working directory, call
|
||||
setWorkingDirectory(). By default, processes are run in the
|
||||
current working directory of the calling process.
|
||||
|
||||
|
|
@ -2514,7 +2514,7 @@ QT_END_INCLUDE_NAMESPACE
|
|||
|
||||
\note For new code, it is recommended to use QProcessEnvironment::systemEnvironment()
|
||||
|
||||
\sa QProcessEnvironment::systemEnvironment(), environment(), setEnvironment()
|
||||
\sa QProcessEnvironment::systemEnvironment(), setProcessEnvironment()
|
||||
*/
|
||||
QStringList QProcess::systemEnvironment()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -506,9 +506,9 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
|
|||
valid = true;
|
||||
ready = true;
|
||||
|
||||
bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize;
|
||||
bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize;
|
||||
bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize;
|
||||
bytesTotal = statfs_buf.f_blocks * statfs_buf.f_frsize;
|
||||
bytesFree = statfs_buf.f_bfree * statfs_buf.f_frsize;
|
||||
bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize;
|
||||
#if defined(Q_OS_ANDROID) || defined (Q_OS_BSD4)
|
||||
#if defined(_STATFS_F_FLAGS)
|
||||
readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ int qFindByteArray(
|
|||
int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW
|
||||
{
|
||||
Q_ASSERT(alloc >= 0 && extra >= 0);
|
||||
Q_ASSERT_X(uint(alloc) < QByteArray::MaxSize, "qAllocMore", "Requested size is too large!");
|
||||
Q_ASSERT_X(alloc <= MaxAllocSize - extra, "qAllocMore", "Requested size is too large!");
|
||||
|
||||
unsigned nalloc = qNextPowerOfTwo(alloc + extra);
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,16 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline bool qSafeFromBigEndian(const uchar *source, const uchar *end, T *output)
|
||||
{
|
||||
if (source + sizeof(T) > end)
|
||||
return false;
|
||||
|
||||
*output = qFromBigEndian<T>(source);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Harfbuzz helper functions
|
||||
|
||||
#ifdef QT_ENABLE_HARFBUZZ_NG
|
||||
|
|
@ -1039,26 +1049,38 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
|
|||
return;
|
||||
|
||||
const uchar *table = reinterpret_cast<const uchar *>(tab.constData());
|
||||
const uchar *end = table + tab.size();
|
||||
|
||||
quint16 version;
|
||||
if (!qSafeFromBigEndian(table, end, &version))
|
||||
return;
|
||||
|
||||
unsigned short version = qFromBigEndian<quint16>(table);
|
||||
if (version != 0) {
|
||||
// qDebug("wrong version");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned short numTables = qFromBigEndian<quint16>(table + 2);
|
||||
quint16 numTables;
|
||||
if (!qSafeFromBigEndian(table + 2, end, &numTables))
|
||||
return;
|
||||
|
||||
{
|
||||
int offset = 4;
|
||||
for(int i = 0; i < numTables; ++i) {
|
||||
if (offset + 6 > tab.size()) {
|
||||
// qDebug("offset out of bounds");
|
||||
goto end;
|
||||
}
|
||||
const uchar *header = table + offset;
|
||||
|
||||
ushort version = qFromBigEndian<quint16>(header);
|
||||
ushort length = qFromBigEndian<quint16>(header+2);
|
||||
ushort coverage = qFromBigEndian<quint16>(header+4);
|
||||
quint16 version;
|
||||
if (!qSafeFromBigEndian(header, end, &version))
|
||||
goto end;
|
||||
|
||||
quint16 length;
|
||||
if (!qSafeFromBigEndian(header + 2, end, &length))
|
||||
goto end;
|
||||
|
||||
quint16 coverage;
|
||||
if (!qSafeFromBigEndian(header + 4, end, &coverage))
|
||||
goto end;
|
||||
|
||||
// qDebug("subtable: version=%d, coverage=%x",version, coverage);
|
||||
if(version == 0 && coverage == 0x0001) {
|
||||
if (offset + length > tab.size()) {
|
||||
|
|
@ -1067,7 +1089,10 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
|
|||
}
|
||||
const uchar *data = table + offset + 6;
|
||||
|
||||
ushort nPairs = qFromBigEndian<quint16>(data);
|
||||
quint16 nPairs;
|
||||
if (!qSafeFromBigEndian(data, end, &nPairs))
|
||||
goto end;
|
||||
|
||||
if(nPairs * 6 + 8 > length - 6) {
|
||||
// qDebug("corrupt table!");
|
||||
// corrupt table
|
||||
|
|
@ -1077,8 +1102,21 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
|
|||
int off = 8;
|
||||
for(int i = 0; i < nPairs; ++i) {
|
||||
QFontEngine::KernPair p;
|
||||
p.left_right = (((uint)qFromBigEndian<quint16>(data+off)) << 16) + qFromBigEndian<quint16>(data+off+2);
|
||||
p.adjust = QFixed(((int)(short)qFromBigEndian<quint16>(data+off+4))) / scalingFactor;
|
||||
|
||||
quint16 tmp;
|
||||
if (!qSafeFromBigEndian(data + off, end, &tmp))
|
||||
goto end;
|
||||
|
||||
p.left_right = uint(tmp) << 16;
|
||||
if (!qSafeFromBigEndian(data + off + 2, end, &tmp))
|
||||
goto end;
|
||||
|
||||
p.left_right |= tmp;
|
||||
|
||||
if (!qSafeFromBigEndian(data + off + 4, end, &tmp))
|
||||
goto end;
|
||||
|
||||
p.adjust = QFixed(int(short(tmp))) / scalingFactor;
|
||||
kerning_pairs.append(p);
|
||||
off += 6;
|
||||
}
|
||||
|
|
@ -1098,26 +1136,31 @@ int QFontEngine::glyphCount() const
|
|||
QByteArray maxpTable = getSfntTable(MAKE_TAG('m', 'a', 'x', 'p'));
|
||||
if (maxpTable.size() < 6)
|
||||
return 0;
|
||||
return qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(maxpTable.constData() + 4));
|
||||
|
||||
const uchar *source = reinterpret_cast<const uchar *>(maxpTable.constData() + 4);
|
||||
const uchar *end = source + maxpTable.size();
|
||||
|
||||
quint16 count = 0;
|
||||
qSafeFromBigEndian(source, end, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize)
|
||||
{
|
||||
const uchar *header = table;
|
||||
if (tableSize < 4)
|
||||
return 0;
|
||||
|
||||
const uchar *endPtr = table + tableSize;
|
||||
|
||||
// version check
|
||||
if (qFromBigEndian<quint16>(header) != 0)
|
||||
quint16 version;
|
||||
if (!qSafeFromBigEndian(header, endPtr, &version) || version != 0)
|
||||
return 0;
|
||||
|
||||
unsigned short numTables = qFromBigEndian<quint16>(header + 2);
|
||||
const uchar *maps = table + 4;
|
||||
if (maps + 8 * numTables > endPtr)
|
||||
quint16 numTables;
|
||||
if (!qSafeFromBigEndian(header + 2, endPtr, &numTables))
|
||||
return 0;
|
||||
|
||||
const uchar *maps = table + 4;
|
||||
|
||||
enum {
|
||||
Invalid,
|
||||
AppleRoman,
|
||||
|
|
@ -1132,8 +1175,14 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
|
|||
int tableToUse = -1;
|
||||
int score = Invalid;
|
||||
for (int n = 0; n < numTables; ++n) {
|
||||
const quint16 platformId = qFromBigEndian<quint16>(maps + 8 * n);
|
||||
const quint16 platformSpecificId = qFromBigEndian<quint16>(maps + 8 * n + 2);
|
||||
quint16 platformId;
|
||||
if (!qSafeFromBigEndian(maps + 8 * n, endPtr, &platformId))
|
||||
return 0;
|
||||
|
||||
quint16 platformSpecificId;
|
||||
if (!qSafeFromBigEndian(maps + 8 * n + 2, endPtr, &platformSpecificId))
|
||||
return 0;
|
||||
|
||||
switch (platformId) {
|
||||
case 0: // Unicode
|
||||
if (score < Unicode &&
|
||||
|
|
@ -1187,20 +1236,30 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
|
|||
resolveTable:
|
||||
*isSymbolFont = (symbolTable > -1);
|
||||
|
||||
unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8*tableToUse + 4);
|
||||
quint32 unicode_table;
|
||||
if (!qSafeFromBigEndian(maps + 8 * tableToUse + 4, endPtr, &unicode_table))
|
||||
return 0;
|
||||
|
||||
if (!unicode_table || unicode_table + 8 > tableSize)
|
||||
if (!unicode_table)
|
||||
return 0;
|
||||
|
||||
// get the header of the unicode table
|
||||
header = table + unicode_table;
|
||||
|
||||
unsigned short format = qFromBigEndian<quint16>(header);
|
||||
unsigned int length;
|
||||
if(format < 8)
|
||||
length = qFromBigEndian<quint16>(header + 2);
|
||||
else
|
||||
length = qFromBigEndian<quint32>(header + 4);
|
||||
quint16 format;
|
||||
if (!qSafeFromBigEndian(header, endPtr, &format))
|
||||
return 0;
|
||||
|
||||
quint32 length;
|
||||
if (format < 8) {
|
||||
quint16 tmp;
|
||||
if (!qSafeFromBigEndian(header + 2, endPtr, &tmp))
|
||||
return 0;
|
||||
length = tmp;
|
||||
} else {
|
||||
if (!qSafeFromBigEndian(header + 4, endPtr, &length))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (table + unicode_table + length > endPtr)
|
||||
return 0;
|
||||
|
|
@ -1215,7 +1274,7 @@ resolveTable:
|
|||
// Check that none of the latin1 range are in the unicode table
|
||||
bool unicodeTableHasLatin1 = false;
|
||||
for (int uc=0x00; uc<0x100; ++uc) {
|
||||
if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) {
|
||||
if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) {
|
||||
unicodeTableHasLatin1 = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1225,7 +1284,7 @@ resolveTable:
|
|||
bool unicodeTableHasSymbols = false;
|
||||
if (!unicodeTableHasLatin1) {
|
||||
for (int uc=0xf000; uc<0xf100; ++uc) {
|
||||
if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) {
|
||||
if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) {
|
||||
unicodeTableHasSymbols = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1243,12 +1302,17 @@ resolveTable:
|
|||
return table + unicode_table;
|
||||
}
|
||||
|
||||
quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
|
||||
quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode)
|
||||
{
|
||||
unsigned short format = qFromBigEndian<quint16>(cmap);
|
||||
const uchar *end = cmap + cmapSize;
|
||||
quint16 format;
|
||||
if (!qSafeFromBigEndian(cmap, end, &format))
|
||||
return 0;
|
||||
|
||||
if (format == 0) {
|
||||
if (unicode < 256)
|
||||
return (int) *(cmap+6+unicode);
|
||||
const uchar *ptr = cmap + 6 + unicode;
|
||||
if (unicode < 256 && ptr < end)
|
||||
return quint32(*ptr);
|
||||
} else if (format == 4) {
|
||||
/* some fonts come with invalid cmap tables, where the last segment
|
||||
specified end = start = rangeoffset = 0xffff, delta = 0x0001
|
||||
|
|
@ -1257,25 +1321,49 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
|
|||
*/
|
||||
if(unicode >= 0xffff)
|
||||
return 0;
|
||||
quint16 segCountX2 = qFromBigEndian<quint16>(cmap + 6);
|
||||
|
||||
quint16 segCountX2;
|
||||
if (!qSafeFromBigEndian(cmap + 6, end, &segCountX2))
|
||||
return 0;
|
||||
|
||||
const unsigned char *ends = cmap + 14;
|
||||
|
||||
int i = 0;
|
||||
for (; i < segCountX2/2 && qFromBigEndian<quint16>(ends + 2*i) < unicode; i++) {}
|
||||
for (; i < segCountX2/2; ++i) {
|
||||
quint16 codePoint;
|
||||
if (!qSafeFromBigEndian(ends + 2 * i, end, &codePoint))
|
||||
return 0;
|
||||
if (codePoint >= unicode)
|
||||
break;
|
||||
}
|
||||
|
||||
const unsigned char *idx = ends + segCountX2 + 2 + 2*i;
|
||||
quint16 startIndex = qFromBigEndian<quint16>(idx);
|
||||
|
||||
quint16 startIndex;
|
||||
if (!qSafeFromBigEndian(idx, end, &startIndex))
|
||||
return 0;
|
||||
if (startIndex > unicode)
|
||||
return 0;
|
||||
|
||||
idx += segCountX2;
|
||||
qint16 idDelta = (qint16)qFromBigEndian<quint16>(idx);
|
||||
|
||||
quint16 tmp;
|
||||
if (!qSafeFromBigEndian(idx, end, &tmp))
|
||||
return 0;
|
||||
qint16 idDelta = qint16(tmp);
|
||||
|
||||
idx += segCountX2;
|
||||
quint16 idRangeoffset_t = (quint16)qFromBigEndian<quint16>(idx);
|
||||
|
||||
quint16 idRangeoffset_t;
|
||||
if (!qSafeFromBigEndian(idx, end, &idRangeoffset_t))
|
||||
return 0;
|
||||
|
||||
quint16 glyphIndex;
|
||||
if (idRangeoffset_t) {
|
||||
quint16 id = qFromBigEndian<quint16>(idRangeoffset_t + 2*(unicode - startIndex) + idx);
|
||||
quint16 id;
|
||||
if (!qSafeFromBigEndian(idRangeoffset_t + 2 * (unicode - startIndex) + idx, end, &id))
|
||||
return 0;
|
||||
|
||||
if (id)
|
||||
glyphIndex = (idDelta + id) % 0x10000;
|
||||
else
|
||||
|
|
@ -1285,13 +1373,19 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
|
|||
}
|
||||
return glyphIndex;
|
||||
} else if (format == 6) {
|
||||
quint16 tableSize = qFromBigEndian<quint16>(cmap + 2);
|
||||
quint16 tableSize;
|
||||
if (!qSafeFromBigEndian(cmap + 2, end, &tableSize))
|
||||
return 0;
|
||||
|
||||
quint16 firstCode6 = qFromBigEndian<quint16>(cmap + 6);
|
||||
quint16 firstCode6;
|
||||
if (!qSafeFromBigEndian(cmap + 6, end, &firstCode6))
|
||||
return 0;
|
||||
if (unicode < firstCode6)
|
||||
return 0;
|
||||
|
||||
quint16 entryCount6 = qFromBigEndian<quint16>(cmap + 8);
|
||||
quint16 entryCount6;
|
||||
if (!qSafeFromBigEndian(cmap + 8, end, &entryCount6))
|
||||
return 0;
|
||||
if (entryCount6 * 2 + 10 > tableSize)
|
||||
return 0;
|
||||
|
||||
|
|
@ -1300,9 +1394,14 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
|
|||
return 0;
|
||||
|
||||
quint16 entryIndex6 = unicode - firstCode6;
|
||||
return qFromBigEndian<quint16>(cmap + 10 + (entryIndex6 * 2));
|
||||
|
||||
quint16 index = 0;
|
||||
qSafeFromBigEndian(cmap + 10 + (entryIndex6 * 2), end, &index);
|
||||
return index;
|
||||
} else if (format == 12) {
|
||||
quint32 nGroups = qFromBigEndian<quint32>(cmap + 12);
|
||||
quint32 nGroups;
|
||||
if (!qSafeFromBigEndian(cmap + 12, end, &nGroups))
|
||||
return 0;
|
||||
|
||||
cmap += 16; // move to start of groups
|
||||
|
||||
|
|
@ -1310,13 +1409,24 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
|
|||
while (left <= right) {
|
||||
int middle = left + ( ( right - left ) >> 1 );
|
||||
|
||||
quint32 startCharCode = qFromBigEndian<quint32>(cmap + 12*middle);
|
||||
quint32 startCharCode;
|
||||
if (!qSafeFromBigEndian(cmap + 12 * middle, end, &startCharCode))
|
||||
return 0;
|
||||
|
||||
if(unicode < startCharCode)
|
||||
right = middle - 1;
|
||||
else {
|
||||
quint32 endCharCode = qFromBigEndian<quint32>(cmap + 12*middle + 4);
|
||||
if(unicode <= endCharCode)
|
||||
return qFromBigEndian<quint32>(cmap + 12*middle + 8) + unicode - startCharCode;
|
||||
quint32 endCharCode;
|
||||
if (!qSafeFromBigEndian(cmap + 12 * middle + 4, end, &endCharCode))
|
||||
return 0;
|
||||
|
||||
if (unicode <= endCharCode) {
|
||||
quint32 index;
|
||||
if (!qSafeFromBigEndian(cmap + 12 * middle + 8, end, &index))
|
||||
return 0;
|
||||
|
||||
return index + unicode - startCharCode;
|
||||
}
|
||||
left = middle + 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ public:
|
|||
QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform) const;
|
||||
|
||||
static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize);
|
||||
static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode);
|
||||
static quint32 getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode);
|
||||
|
||||
static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily);
|
||||
|
||||
|
|
|
|||
|
|
@ -322,9 +322,9 @@ bool QFontEngineQPF2::getSfntTableData(uint tag, uchar *buffer, uint *length) co
|
|||
|
||||
glyph_t QFontEngineQPF2::glyphIndex(uint ucs4) const
|
||||
{
|
||||
glyph_t glyph = getTrueTypeGlyphIndex(cmap, ucs4);
|
||||
glyph_t glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
|
||||
if (glyph == 0 && symbol && ucs4 < 0x100)
|
||||
glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000);
|
||||
glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000);
|
||||
if (!findGlyph(glyph))
|
||||
glyph = 0;
|
||||
|
||||
|
|
@ -348,16 +348,16 @@ bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyp
|
|||
QStringIterator it(str, str + len);
|
||||
while (it.hasNext()) {
|
||||
const uint uc = it.next();
|
||||
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
|
||||
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
|
||||
if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
|
||||
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
|
||||
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
|
||||
++glyph_pos;
|
||||
}
|
||||
} else {
|
||||
QStringIterator it(str, str + len);
|
||||
while (it.hasNext()) {
|
||||
const uint uc = it.next();
|
||||
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
|
||||
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
|
||||
#if 0 && defined(DEBUG_FONTENGINE)
|
||||
QChar c(uc);
|
||||
if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c))
|
||||
|
|
|
|||
|
|
@ -918,7 +918,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())
|
||||
|
|
|
|||
|
|
@ -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<QAbstractSocket::SocketError>();
|
||||
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,7 +151,7 @@ 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<QSslError>)),
|
||||
this, SLOT(_q_sslErrors(QList<QSslError>)),
|
||||
Qt::DirectConnection);
|
||||
|
|
@ -156,7 +160,7 @@ void QHttpNetworkConnectionChannel::init()
|
|||
Qt::DirectConnection);
|
||||
QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)),
|
||||
this, SLOT(_q_encryptedBytesWritten(qint64)),
|
||||
Qt::QueuedConnection);
|
||||
Qt::DirectConnection);
|
||||
|
||||
if (ignoreAllSslErrors)
|
||||
sslSocket->ignoreSslErrors();
|
||||
|
|
@ -400,7 +404,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)
|
||||
|
|
@ -654,6 +658,15 @@ void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest()
|
|||
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void QHttpNetworkConnectionChannel::resendCurrentRequest()
|
||||
{
|
||||
requeueCurrentlyPipelinedRequests();
|
||||
if (reply)
|
||||
resendCurrent = true;
|
||||
if (qobject_cast<QHttpNetworkConnection*>(connection))
|
||||
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
bool QHttpNetworkConnectionChannel::isSocketBusy() const
|
||||
{
|
||||
return (state & QHttpNetworkConnectionChannel::BusyState);
|
||||
|
|
@ -697,8 +710,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();
|
||||
|
|
@ -710,7 +723,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
|
|||
state = QHttpNetworkConnectionChannel::IdleState;
|
||||
|
||||
requeueCurrentlyPipelinedRequests();
|
||||
close();
|
||||
|
||||
pendingEncrypt = false;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -792,11 +806,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;
|
||||
|
|
@ -821,24 +843,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<QSslSocket*>(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;
|
||||
|
|
@ -849,7 +862,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;
|
||||
|
|
@ -863,7 +876,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;
|
||||
|
|
@ -871,7 +884,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;
|
||||
|
|
@ -919,8 +932,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
|
||||
|
|
@ -944,7 +967,8 @@ void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetwor
|
|||
|
||||
void QHttpNetworkConnectionChannel::_q_uploadDataReadyRead()
|
||||
{
|
||||
sendRequest();
|
||||
if (reply)
|
||||
sendRequest();
|
||||
}
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ public:
|
|||
|
||||
void handleUnexpectedEOF();
|
||||
void closeAndResendCurrentRequest();
|
||||
void resendCurrentRequest();
|
||||
|
||||
bool isSocketBusy() const;
|
||||
bool isSocketWriting() const;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -767,6 +767,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()");
|
||||
|
|
@ -776,7 +777,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2408,6 +2408,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);
|
||||
|
|
|
|||
|
|
@ -1527,6 +1527,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.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,9 +181,8 @@ void QWindowsFontEngine::getCMap()
|
|||
bool symb = false;
|
||||
if (ttf) {
|
||||
cmapTable = getSfntTable(qbswap<quint32>(MAKE_TAG('c', 'm', 'a', 'p')));
|
||||
int size = 0;
|
||||
cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()),
|
||||
cmapTable.size(), &symb, &size);
|
||||
cmapTable.size(), &symb, &cmapSize);
|
||||
}
|
||||
if (!cmap) {
|
||||
ttf = false;
|
||||
|
|
@ -218,16 +217,16 @@ int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLa
|
|||
QStringIterator it(str, str + numChars);
|
||||
while (it.hasNext()) {
|
||||
const uint uc = it.next();
|
||||
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
|
||||
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
|
||||
if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
|
||||
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
|
||||
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
|
||||
++glyph_pos;
|
||||
}
|
||||
} else if (ttf) {
|
||||
QStringIterator it(str, str + numChars);
|
||||
while (it.hasNext()) {
|
||||
const uint uc = it.next();
|
||||
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
|
||||
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
|
||||
++glyph_pos;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -275,6 +274,7 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name,
|
|||
hasOutline(0),
|
||||
lw(0),
|
||||
cmap(0),
|
||||
cmapSize(0),
|
||||
lbearing(SHRT_MIN),
|
||||
rbearing(SHRT_MIN),
|
||||
x_height(-1),
|
||||
|
|
@ -346,11 +346,11 @@ glyph_t QWindowsFontEngine::glyphIndex(uint ucs4) const
|
|||
|
||||
#if !defined(Q_OS_WINCE)
|
||||
if (symbol) {
|
||||
glyph = getTrueTypeGlyphIndex(cmap, ucs4);
|
||||
glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
|
||||
if (glyph == 0 && ucs4 < 0x100)
|
||||
glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000);
|
||||
glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000);
|
||||
} else if (ttf) {
|
||||
glyph = getTrueTypeGlyphIndex(cmap, ucs4);
|
||||
glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
|
||||
#else
|
||||
if (tm.tmFirstChar > 60000) {
|
||||
glyph = ucs4;
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ private:
|
|||
TEXTMETRIC tm;
|
||||
int lw;
|
||||
const unsigned char *cmap;
|
||||
int cmapSize;
|
||||
QByteArray cmapTable;
|
||||
mutable qreal lbearing;
|
||||
mutable qreal rbearing;
|
||||
|
|
|
|||
|
|
@ -1332,6 +1332,9 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
|
|||
if (r.isEmpty())
|
||||
r = QSqlDriver::formatValue(field, trimStrings);
|
||||
break;
|
||||
case QVariant::Uuid:
|
||||
r = QLatin1Char('\'') + field.value().toString() + QLatin1Char('\'');
|
||||
break;
|
||||
default:
|
||||
r = QSqlDriver::formatValue(field, trimStrings);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -541,17 +541,21 @@ QRect QStyle::itemPixmapRect(const QRect &rect, int alignment, const QPixmap &pi
|
|||
QRect result;
|
||||
int x, y, w, h;
|
||||
rect.getRect(&x, &y, &w, &h);
|
||||
|
||||
const int pixmapWidth = pixmap.width()/pixmap.devicePixelRatio();
|
||||
const int pixmapHeight = pixmap.height()/pixmap.devicePixelRatio();
|
||||
|
||||
if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter)
|
||||
y += h/2 - pixmap.height()/2;
|
||||
y += h/2 - pixmapHeight/2;
|
||||
else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom)
|
||||
y += h - pixmap.height();
|
||||
y += h - pixmapHeight;
|
||||
if ((alignment & Qt::AlignRight) == Qt::AlignRight)
|
||||
x += w - pixmap.width();
|
||||
x += w - pixmapWidth;
|
||||
else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter)
|
||||
x += w/2 - pixmap.width()/2;
|
||||
x += w/2 - pixmapWidth/2;
|
||||
else if ((alignment & Qt::AlignLeft) != Qt::AlignLeft && QApplication::isRightToLeft())
|
||||
x += w - pixmap.width();
|
||||
result = QRect(x, y, pixmap.width(), pixmap.height());
|
||||
x += w - pixmapWidth;
|
||||
result = QRect(x, y, pixmapWidth, pixmapHeight);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1058,7 +1058,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;
|
||||
}
|
||||
|
|
@ -1078,7 +1078,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;
|
||||
}
|
||||
|
|
@ -8012,7 +8012,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.
|
||||
|
|
@ -8118,11 +8118,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=" <<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);
|
||||
QVERIFY(server.m_correctUploads > 2);
|
||||
// Because actually important is that we don't get any corruption:
|
||||
QCOMPARE(server.m_corruptUploads, 0);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue