Merge remote-tracking branch 'origin/master' into refactor

Change-Id: I53c78056abde99198ffe1c67f7f9e90b4b08051d
bb10
Lars Knoll 2011-07-13 12:22:12 +02:00
commit a81093b915
31 changed files with 1039 additions and 502 deletions

View File

@ -540,6 +540,7 @@ namespace QT_NAMESPACE {}
# define Q_COMPILER_DEFAULT_DELETE_MEMBERS
# define Q_COMPILER_CLASS_ENUM
# define Q_COMPILER_INITIALIZER_LISTS
# define Q_COMPILER_ATOMICS
# endif
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
/* C++0x features supported in GCC 4.5: */
@ -547,7 +548,10 @@ namespace QT_NAMESPACE {}
# endif
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
/* C++0x features supported in GCC 4.6: */
# define Q_COMPILER_NULLPTR
# define Q_COMPILER_CONSTEXPR
# define Q_COMPILER_UNRESTRICTED_UNIONS
# define Q_COMPILER_RANGE_FOR
# endif
# endif
@ -799,11 +803,10 @@ namespace QT_NAMESPACE {}
# define Q_NO_TEMPLATE_FRIENDS
# endif
# if defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__)
# if __INTEL_COMPILER >= 1100
# if __INTEL_COMPILER >= 1200
# define Q_COMPILER_RVALUE_REFS
# define Q_COMPILER_EXTERN_TEMPLATES
# define Q_COMPILER_DECLTYPE
# elif __INTEL_COMPILER >= 1200
# define Q_COMPILER_VARIADIC_TEMPLATES
# define Q_COMPILER_AUTO_TYPE
# define Q_COMPILER_DEFAULT_DELETE_MEMBERS
@ -1114,6 +1117,12 @@ redefine to built-in booleans to make autotests work properly */
# define QT_FASTCALL
#endif
#ifdef Q_COMPILER_NULLPTR
# define Q_NULLPTR nullptr
#else
# define Q_NULLPTR 0
#endif
#ifdef Q_COMPILER_CONSTEXPR
# define Q_DECL_CONSTEXPR constexpr
#else

View File

@ -57,7 +57,7 @@
#include <string.h>
#include <stdlib.h>
#define IS_RAW_DATA(d) ((d)->data != (d)->array)
#define IS_RAW_DATA(d) ((d)->offset != 0)
QT_BEGIN_NAMESPACE
@ -546,7 +546,7 @@ QByteArray qUncompress(const uchar* data, int nbytes)
qWarning("qUncompress: Input data is corrupted");
return QByteArray();
}
QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + alloc));
QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + alloc + 1));
if (!p) {
// we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
qWarning("qUncompress: could not allocate enough memory to uncompress data");
@ -554,8 +554,9 @@ QByteArray qUncompress(const uchar* data, int nbytes)
}
d.take(); // realloc was successful
d.reset(p);
d->offset = 0;
int res = ::uncompress((uchar*)d->array, &len,
int res = ::uncompress((uchar*)d->data(), &len,
(uchar*)data+4, nbytes-4);
switch (res) {
@ -566,7 +567,7 @@ QByteArray qUncompress(const uchar* data, int nbytes)
qWarning("qUncompress: Input data is corrupted");
return QByteArray();
}
QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + len));
QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + len + 1));
if (!p) {
// we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
qWarning("qUncompress: could not allocate enough memory to uncompress data");
@ -576,9 +577,11 @@ QByteArray qUncompress(const uchar* data, int nbytes)
d.reset(p);
}
d->ref = 1;
d->alloc = d->size = len;
d->data = d->array;
d->array[len] = 0;
d->size = len;
d->alloc = len;
d->capacityReserved = false;
d->offset = 0;
d->data()[len] = 0;
return QByteArray(d.take(), 0, 0);
@ -611,10 +614,10 @@ static inline char qToLower(char c)
return c;
}
QByteArray::Data QByteArray::shared_null = {Q_BASIC_ATOMIC_INITIALIZER(1),
0, 0, shared_null.array, {0} };
QByteArray::Data QByteArray::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1),
0, 0, shared_empty.array, {0} };
QConstByteArrayData<1> QByteArray::shared_null = { { Q_REFCOUNT_INITIALIZER(-1),
0, 0, 0, { 0 } }, { 0 } };
QConstByteArrayData<1> QByteArray::shared_empty = { { Q_REFCOUNT_INITIALIZER(-1),
0, 0, 0, { 0 } }, { 0 } };
/*!
\class QByteArray
@ -896,15 +899,15 @@ QByteArray &QByteArray::operator=(const char *str)
{
Data *x;
if (!str) {
x = &shared_null;
x = const_cast<Data *>(&shared_null.ba);
} else if (!*str) {
x = &shared_empty;
x = const_cast<Data *>(&shared_empty.ba);
} else {
int len = qstrlen(str);
if (d->ref != 1 || len > d->alloc || (len < d->size && len < d->alloc >> 1))
realloc(len);
x = d;
memcpy(x->data, str, len + 1); // include null terminator
memcpy(x->data(), str, len + 1); // include null terminator
x->size = len;
}
x->ref.ref();
@ -1294,19 +1297,20 @@ void QByteArray::chop(int n)
QByteArray::QByteArray(const char *str)
{
if (!str) {
d = &shared_null;
d = const_cast<Data *>(&shared_null.ba);
} else if (!*str) {
d = &shared_empty;
d = const_cast<Data *>(&shared_empty.ba);
} else {
int len = qstrlen(str);
d = static_cast<Data *>(qMalloc(sizeof(Data)+len));
d = static_cast<Data *>(qMalloc(sizeof(Data) + len + 1));
Q_CHECK_PTR(d);
d->ref = 0;;
d->alloc = d->size = len;
d->data = d->array;
memcpy(d->array, str, len+1); // include null terminator
d->ref = 1;
d->size = len;
d->alloc = len;
d->capacityReserved = false;
d->offset = 0;
memcpy(d->data(), str, len+1); // include null terminator
}
d->ref.ref();
}
/*!
@ -1323,19 +1327,20 @@ QByteArray::QByteArray(const char *str)
QByteArray::QByteArray(const char *data, int size)
{
if (!data) {
d = &shared_null;
d = const_cast<Data *>(&shared_null.ba);
} else if (size <= 0) {
d = &shared_empty;
d = const_cast<Data *>(&shared_empty.ba);
} else {
d = static_cast<Data *>(qMalloc(sizeof(Data) + size));
d = static_cast<Data *>(qMalloc(sizeof(Data) + size + 1));
Q_CHECK_PTR(d);
d->ref = 0;
d->alloc = d->size = size;
d->data = d->array;
memcpy(d->array, data, size);
d->array[size] = '\0';
d->ref = 1;
d->size = size;
d->alloc = size;
d->capacityReserved = false;
d->offset = 0;
memcpy(d->data(), data, size);
d->data()[size] = '\0';
}
d->ref.ref();
}
/*!
@ -1348,17 +1353,18 @@ QByteArray::QByteArray(const char *data, int size)
QByteArray::QByteArray(int size, char ch)
{
if (size <= 0) {
d = &shared_null;
d = const_cast<Data *>(&shared_null.ba);
} else {
d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
d = static_cast<Data *>(qMalloc(sizeof(Data) + size + 1));
Q_CHECK_PTR(d);
d->ref = 0;
d->alloc = d->size = size;
d->data = d->array;
d->array[size] = '\0';
memset(d->array, ch, size);
d->ref = 1;
d->size = size;
d->alloc = size;
d->capacityReserved = false;
d->offset = 0;
memset(d->data(), ch, size);
d->data()[size] = '\0';
}
d->ref.ref();
}
/*!
@ -1369,12 +1375,14 @@ QByteArray::QByteArray(int size, char ch)
QByteArray::QByteArray(int size, Qt::Initialization)
{
d = static_cast<Data *>(qMalloc(sizeof(Data)+size));
d = static_cast<Data *>(qMalloc(sizeof(Data) + size + 1));
Q_CHECK_PTR(d);
d->ref = 1;
d->alloc = d->size = size;
d->data = d->array;
d->array[size] = '\0';
d->size = size;
d->alloc = size;
d->capacityReserved = false;
d->offset = 0;
d->data()[size] = '\0';
}
/*!
@ -1392,13 +1400,20 @@ QByteArray::QByteArray(int size, Qt::Initialization)
void QByteArray::resize(int size)
{
if (size <= 0) {
Data *x = &shared_empty;
x->ref.ref();
if (size < 0)
size = 0;
if (d->offset && d->ref == 1 && size < d->size) {
d->size = size;
return;
}
if (size == 0 && !d->capacityReserved) {
Data *x = const_cast<Data *>(&shared_empty.ba);
if (!d->ref.deref())
qFree(d);
d = x;
} else if (d == &shared_null) {
} else if (d == &shared_null.ba || d == &shared_empty.ba) {
//
// Optimize the idiom:
// QByteArray a;
@ -1407,22 +1422,21 @@ void QByteArray::resize(int size)
// which is used in place of the Qt 3 idiom:
// QByteArray a(sz);
//
Data *x = static_cast<Data *>(qMalloc(sizeof(Data)+size));
Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + size + 1));
Q_CHECK_PTR(x);
x->ref = 1;
x->alloc = x->size = size;
x->data = x->array;
x->array[size] = '\0';
(void) d->ref.deref(); // cannot be 0, x points to shared_null
x->size = size;
x->alloc = size;
x->capacityReserved = false;
x->offset = 0;
x->data()[size] = '\0';
d = x;
} else {
if (d->ref != 1 || size > d->alloc || (size < d->size && size < d->alloc >> 1))
if (d->ref != 1 || size > d->alloc || (!d->capacityReserved && size < d->size && size < d->alloc >> 1))
realloc(qAllocMore(size, sizeof(Data)));
if (d->alloc >= size) {
d->size = size;
if (d->data == d->array) {
d->array[size] = '\0';
}
d->data()[size] = '\0';
}
}
}
@ -1442,29 +1456,30 @@ QByteArray &QByteArray::fill(char ch, int size)
{
resize(size < 0 ? d->size : size);
if (d->size)
memset(d->data, ch, d->size);
memset(d->data(), ch, d->size);
return *this;
}
void QByteArray::realloc(int alloc)
{
if (d->ref != 1 || d->data != d->array) {
Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc));
if (d->ref != 1 || d->offset) {
Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc + 1));
Q_CHECK_PTR(x);
x->size = qMin(alloc, d->size);
::memcpy(x->array, d->data, x->size);
x->array[x->size] = '\0';
x->ref = 1;
x->size = qMin(alloc, d->size);
x->alloc = alloc;
x->data = x->array;
x->capacityReserved = d->capacityReserved;
x->offset = 0;
::memcpy(x->data(), d->data(), x->size);
x->data()[x->size] = '\0';
if (!d->ref.deref())
qFree(d);
d = x;
} else {
Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc));
Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc + 1));
Q_CHECK_PTR(x);
x->alloc = alloc;
x->data = x->array;
x->offset = 0;
d = x;
}
}
@ -1486,7 +1501,7 @@ void QByteArray::expand(int i)
QByteArray QByteArray::nulTerminated() const
{
// is this fromRawData?
if (d->data == d->array)
if (!d->offset)
return *this; // no, then we're sure we're zero terminated
QByteArray copy(*this);
@ -1517,9 +1532,9 @@ QByteArray QByteArray::nulTerminated() const
QByteArray &QByteArray::prepend(const QByteArray &ba)
{
if ((d == &shared_null || d == &shared_empty) && !IS_RAW_DATA(ba.d)) {
if ((d == &shared_null.ba || d == &shared_empty.ba) && !IS_RAW_DATA(ba.d)) {
*this = ba;
} else if (ba.d != &shared_null) {
} else if (ba.d != &shared_null.ba) {
QByteArray tmp = *this;
*this = ba;
append(tmp);
@ -1550,10 +1565,10 @@ QByteArray &QByteArray::prepend(const char *str, int len)
if (str) {
if (d->ref != 1 || d->size + len > d->alloc)
realloc(qAllocMore(d->size + len, sizeof(Data)));
memmove(d->data+len, d->data, d->size);
memcpy(d->data, str, len);
memmove(d->data()+len, d->data(), d->size);
memcpy(d->data(), str, len);
d->size += len;
d->data[d->size] = '\0';
d->data()[d->size] = '\0';
}
return *this;
}
@ -1568,10 +1583,10 @@ QByteArray &QByteArray::prepend(char ch)
{
if (d->ref != 1 || d->size + 1 > d->alloc)
realloc(qAllocMore(d->size + 1, sizeof(Data)));
memmove(d->data+1, d->data, d->size);
d->data[0] = ch;
memmove(d->data()+1, d->data(), d->size);
d->data()[0] = ch;
++d->size;
d->data[d->size] = '\0';
d->data()[d->size] = '\0';
return *this;
}
@ -1601,14 +1616,14 @@ QByteArray &QByteArray::prepend(char ch)
QByteArray &QByteArray::append(const QByteArray &ba)
{
if ((d == &shared_null || d == &shared_empty) && !IS_RAW_DATA(ba.d)) {
if ((d == &shared_null.ba || d == &shared_empty.ba) && !IS_RAW_DATA(ba.d)) {
*this = ba;
} else if (ba.d != &shared_null) {
} else if (ba.d != &shared_null.ba) {
if (d->ref != 1 || d->size + ba.d->size > d->alloc)
realloc(qAllocMore(d->size + ba.d->size, sizeof(Data)));
memcpy(d->data + d->size, ba.d->data, ba.d->size);
memcpy(d->data() + d->size, ba.d->data(), ba.d->size);
d->size += ba.d->size;
d->data[d->size] = '\0';
d->data()[d->size] = '\0';
}
return *this;
}
@ -1640,7 +1655,7 @@ QByteArray& QByteArray::append(const char *str)
int len = qstrlen(str);
if (d->ref != 1 || d->size + len > d->alloc)
realloc(qAllocMore(d->size + len, sizeof(Data)));
memcpy(d->data + d->size, str, len + 1); // include null terminator
memcpy(d->data() + d->size, str, len + 1); // include null terminator
d->size += len;
}
return *this;
@ -1665,9 +1680,9 @@ QByteArray &QByteArray::append(const char *str, int len)
if (str && len) {
if (d->ref != 1 || d->size + len > d->alloc)
realloc(qAllocMore(d->size + len, sizeof(Data)));
memcpy(d->data + d->size, str, len); // include null terminator
memcpy(d->data() + d->size, str, len); // include null terminator
d->size += len;
d->data[d->size] = '\0';
d->data()[d->size] = '\0';
}
return *this;
}
@ -1682,8 +1697,8 @@ QByteArray& QByteArray::append(char ch)
{
if (d->ref != 1 || d->size + 1 > d->alloc)
realloc(qAllocMore(d->size + 1, sizeof(Data)));
d->data[d->size++] = ch;
d->data[d->size] = '\0';
d->data()[d->size++] = ch;
d->data()[d->size] = '\0';
return *this;
}
@ -1724,7 +1739,7 @@ static inline QByteArray &qbytearray_insert(QByteArray *ba,
QByteArray &QByteArray::insert(int i, const QByteArray &ba)
{
QByteArray copy(ba);
return qbytearray_insert(this, i, copy.d->data, copy.d->size);
return qbytearray_insert(this, i, copy.d->data(), copy.d->size);
}
/*!
@ -1812,7 +1827,7 @@ QByteArray &QByteArray::remove(int pos, int len)
if (pos + len >= d->size) {
resize(pos);
} else {
memmove(d->data + pos, d->data + pos + len, d->size - pos - len);
memmove(d->data() + pos, d->data() + pos + len, d->size - pos - len);
resize(d->size - len);
}
return *this;
@ -1832,7 +1847,7 @@ QByteArray &QByteArray::replace(int pos, int len, const QByteArray &after)
{
if (len == after.d->size && (pos + len <= d->size)) {
detach();
memmove(d->data + pos, after.d->data, len*sizeof(char));
memmove(d->data() + pos, after.d->data(), len*sizeof(char));
return *this;
} else {
QByteArray copy(after);
@ -1869,7 +1884,7 @@ QByteArray &QByteArray::replace(int pos, int len, const char *after, int alen)
{
if (len == alen && (pos + len <= d->size)) {
detach();
memcpy(d->data + pos, after, len*sizeof(char));
memcpy(d->data() + pos, after, len*sizeof(char));
return *this;
} else {
remove(pos, len);
@ -1936,13 +1951,13 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
// protect against before or after being part of this
const char *a = after;
const char *b = before;
if (after >= d->data && after < d->data + d->size) {
if (after >= d->data() && after < d->data() + d->size) {
char *copy = (char *)malloc(asize);
Q_CHECK_PTR(copy);
memcpy(copy, after, asize);
a = copy;
}
if (before >= d->data && before < d->data + d->size) {
if (before >= d->data() && before < d->data() + d->size) {
char *copy = (char *)malloc(bsize);
Q_CHECK_PTR(copy);
memcpy(copy, before, bsize);
@ -2019,7 +2034,7 @@ QByteArray &QByteArray::replace(const char *before, int bsize, const char *after
resize(newlen);
len = newlen;
}
d = this->d->data;
d = this->d->data();
while(pos) {
pos--;
@ -2192,19 +2207,19 @@ QByteArray QByteArray::repeated(int times) const
if (result.d->alloc != resultSize)
return QByteArray(); // not enough memory
memcpy(result.d->data, d->data, d->size);
memcpy(result.d->data(), d->data(), d->size);
int sizeSoFar = d->size;
char *end = result.d->data + sizeSoFar;
char *end = result.d->data() + sizeSoFar;
const int halfResultSize = resultSize >> 1;
while (sizeSoFar <= halfResultSize) {
memcpy(end, result.d->data, sizeSoFar);
memcpy(end, result.d->data(), sizeSoFar);
end += sizeSoFar;
sizeSoFar <<= 1;
}
memcpy(end, result.d->data, resultSize - sizeSoFar);
result.d->data[resultSize] = '\0';
memcpy(end, result.d->data(), resultSize - sizeSoFar);
result.d->data()[resultSize] = '\0';
result.d->size = resultSize;
return result;
}
@ -2231,13 +2246,13 @@ int QByteArray::indexOf(const QByteArray &ba, int from) const
if (ol == 0)
return from;
if (ol == 1)
return indexOf(*ba.d->data, from);
return indexOf(*ba.d->data(), from);
const int l = d->size;
if (from > d->size || ol + from > l)
return -1;
return qFindByteArray(d->data, d->size, from, ba.d->data, ol);
return qFindByteArray(d->data(), d->size, from, ba.d->data(), ol);
}
/*! \fn int QByteArray::indexOf(const QString &str, int from) const
@ -2279,7 +2294,7 @@ int QByteArray::indexOf(const char *c, int from) const
if (ol == 0)
return from;
return qFindByteArray(d->data, d->size, from, c, ol);
return qFindByteArray(d->data(), d->size, from, c, ol);
}
/*!
@ -2300,11 +2315,11 @@ int QByteArray::indexOf(char ch, int from) const
if (from < 0)
from = qMax(from + d->size, 0);
if (from < d->size) {
const char *n = d->data + from - 1;
const char *e = d->data + d->size;
const char *n = d->data() + from - 1;
const char *e = d->data() + d->size;
while (++n != e)
if (*n == ch)
return n - d->data;
return n - d->data();
}
return -1;
}
@ -2361,9 +2376,9 @@ int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
{
const int ol = ba.d->size;
if (ol == 1)
return lastIndexOf(*ba.d->data, from);
return lastIndexOf(*ba.d->data(), from);
return lastIndexOfHelper(d->data, d->size, ba.d->data, ol, from);
return lastIndexOfHelper(d->data(), d->size, ba.d->data(), ol, from);
}
/*! \fn int QByteArray::lastIndexOf(const QString &str, int from) const
@ -2400,7 +2415,7 @@ int QByteArray::lastIndexOf(const char *str, int from) const
if (ol == 1)
return lastIndexOf(*str, from);
return lastIndexOfHelper(d->data, d->size, str, ol, from);
return lastIndexOfHelper(d->data(), d->size, str, ol, from);
}
/*!
@ -2424,8 +2439,8 @@ int QByteArray::lastIndexOf(char ch, int from) const
else if (from > d->size)
from = d->size-1;
if (from >= 0) {
const char *b = d->data;
const char *n = d->data + from + 1;
const char *b = d->data();
const char *n = d->data() + from + 1;
while (n-- != b)
if (*n == ch)
return n - b;
@ -2479,8 +2494,8 @@ int QByteArray::count(const char *str) const
int QByteArray::count(char ch) const
{
int num = 0;
const char *i = d->data + d->size;
const char *b = d->data;
const char *i = d->data() + d->size;
const char *b = d->data();
while (i != b)
if (*--i == ch)
++num;
@ -2509,7 +2524,7 @@ bool QByteArray::startsWith(const QByteArray &ba) const
return true;
if (d->size < ba.d->size)
return false;
return memcmp(d->data, ba.d->data, ba.d->size) == 0;
return memcmp(d->data(), ba.d->data(), ba.d->size) == 0;
}
/*! \overload
@ -2524,7 +2539,7 @@ bool QByteArray::startsWith(const char *str) const
int len = qstrlen(str);
if (d->size < len)
return false;
return qstrncmp(d->data, str, len) == 0;
return qstrncmp(d->data(), str, len) == 0;
}
/*! \overload
@ -2536,7 +2551,7 @@ bool QByteArray::startsWith(char ch) const
{
if (d->size == 0)
return false;
return d->data[0] == ch;
return d->data()[0] == ch;
}
/*!
@ -2554,7 +2569,7 @@ bool QByteArray::endsWith(const QByteArray &ba) const
return true;
if (d->size < ba.d->size)
return false;
return memcmp(d->data + d->size - ba.d->size, ba.d->data, ba.d->size) == 0;
return memcmp(d->data() + d->size - ba.d->size, ba.d->data(), ba.d->size) == 0;
}
/*! \overload
@ -2569,7 +2584,7 @@ bool QByteArray::endsWith(const char *str) const
int len = qstrlen(str);
if (d->size < len)
return false;
return qstrncmp(d->data + d->size - len, str, len) == 0;
return qstrncmp(d->data() + d->size - len, str, len) == 0;
}
/*! \overload
@ -2581,7 +2596,7 @@ bool QByteArray::endsWith(char ch) const
{
if (d->size == 0)
return false;
return d->data[d->size - 1] == ch;
return d->data()[d->size - 1] == ch;
}
/*!
@ -2603,7 +2618,7 @@ QByteArray QByteArray::left(int len) const
return *this;
if (len < 0)
len = 0;
return QByteArray(d->data, len);
return QByteArray(d->data(), len);
}
/*!
@ -2625,7 +2640,7 @@ QByteArray QByteArray::right(int len) const
return *this;
if (len < 0)
len = 0;
return QByteArray(d->data + d->size - len, len);
return QByteArray(d->data() + d->size - len, len);
}
/*!
@ -2644,7 +2659,7 @@ QByteArray QByteArray::right(int len) const
QByteArray QByteArray::mid(int pos, int len) const
{
if (d == &shared_null || d == &shared_empty || pos >= d->size)
if (d == &shared_null.ba || d == &shared_empty.ba || pos >= d->size)
return QByteArray();
if (len < 0)
len = d->size - pos;
@ -2656,7 +2671,7 @@ QByteArray QByteArray::mid(int pos, int len) const
len = d->size - pos;
if (pos == 0 && len == d->size)
return *this;
return QByteArray(d->data + pos, len);
return QByteArray(d->data() + pos, len);
}
/*!
@ -2715,7 +2730,7 @@ void QByteArray::clear()
{
if (!d->ref.deref())
qFree(d);
d = &shared_null;
d = const_cast<Data *>(&shared_null.ba);
d->ref.ref();
}
@ -3106,10 +3121,10 @@ QByteArray QByteArray::simplified() const
if (d->size == 0)
return *this;
QByteArray result(d->size, Qt::Uninitialized);
const char *from = d->data;
const char *from = d->data();
const char *fromend = from + d->size;
int outc=0;
char *to = result.d->data;
char *to = result.d->data();
for (;;) {
while (from!=fromend && isspace(uchar(*from)))
from++;
@ -3145,7 +3160,7 @@ QByteArray QByteArray::trimmed() const
{
if (d->size == 0)
return *this;
const char *s = d->data;
const char *s = d->data();
if (!isspace(uchar(*s)) && !isspace(uchar(s[d->size-1])))
return *this;
int start = 0;
@ -3158,8 +3173,7 @@ QByteArray QByteArray::trimmed() const
}
int l = end - start + 1;
if (l <= 0) {
shared_empty.ref.ref();
return QByteArray(&shared_empty, 0, 0);
return QByteArray(const_cast<Data *>(&shared_empty.ba), 0, 0);
}
return QByteArray(s+start, l);
}
@ -3190,8 +3204,8 @@ QByteArray QByteArray::leftJustified(int width, char fill, bool truncate) const
if (padlen > 0) {
result.resize(len+padlen);
if (len)
memcpy(result.d->data, d->data, len);
memset(result.d->data+len, fill, padlen);
memcpy(result.d->data(), d->data(), len);
memset(result.d->data()+len, fill, padlen);
} else {
if (truncate)
result = left(width);
@ -3227,8 +3241,8 @@ QByteArray QByteArray::rightJustified(int width, char fill, bool truncate) const
if (padlen > 0) {
result.resize(len+padlen);
if (len)
memcpy(result.d->data+padlen, data(), len);
memset(result.d->data, fill, padlen);
memcpy(result.d->data()+padlen, data(), len);
memset(result.d->data(), fill, padlen);
} else {
if (truncate)
result = left(width);
@ -3238,7 +3252,7 @@ QByteArray QByteArray::rightJustified(int width, char fill, bool truncate) const
return result;
}
bool QByteArray::isNull() const { return d == &shared_null; }
bool QByteArray::isNull() const { return d == &shared_null.ba; }
/*!
@ -3562,13 +3576,13 @@ QByteArray QByteArray::toBase64() const
char *out = tmp.data();
while (i < d->size) {
int chunk = 0;
chunk |= int(uchar(d->data[i++])) << 16;
chunk |= int(uchar(d->data()[i++])) << 16;
if (i == d->size) {
padlen = 2;
} else {
chunk |= int(uchar(d->data[i++])) << 8;
chunk |= int(uchar(d->data()[i++])) << 8;
if (i == d->size) padlen = 1;
else chunk |= int(uchar(d->data[i++]));
else chunk |= int(uchar(d->data()[i++]));
}
int j = (chunk & 0x00fc0000) >> 18;
@ -3864,17 +3878,20 @@ QByteArray QByteArray::number(double n, char f, int prec)
QByteArray QByteArray::fromRawData(const char *data, int size)
{
Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
Q_CHECK_PTR(x);
if (data) {
x->data = const_cast<char *>(data);
Data *x;
if (!data) {
x = const_cast<Data *>(&shared_null.ba);
} else if (!size) {
x = const_cast<Data *>(&shared_empty.ba);
} else {
x->data = x->array;
size = 0;
x = static_cast<Data *>(qMalloc(sizeof(Data) + 1));
Q_CHECK_PTR(x);
x->ref = 1;
x->size = size;
x->alloc = 0;
x->capacityReserved = false;
x->offset = data - (x->d + sizeof(qptrdiff));
}
x->ref = 1;
x->alloc = x->size = size;
*x->array = '\0';
return QByteArray(x, 0, 0);
}
@ -3898,13 +3915,13 @@ QByteArray &QByteArray::setRawData(const char *data, uint size)
*this = fromRawData(data, size);
} else {
if (data) {
d->data = const_cast<char *>(data);
d->size = size;
d->offset = data - (d->d + sizeof(qptrdiff));
} else {
d->data = d->array;
size = 0;
d->offset = 0;
d->size = 0;
*d->data() = 0;
}
d->alloc = d->size = size;
*d->array = '\0';
}
return *this;
}
@ -4013,7 +4030,7 @@ QByteArray QByteArray::toHex() const
{
QByteArray hex(d->size * 2, Qt::Uninitialized);
char *hexData = hex.data();
const uchar *data = (const uchar *)d->data;
const uchar *data = (const uchar *)d->data();
for (int i = 0; i < d->size; ++i) {
int j = (data[i] >> 4) & 0xf;
if (j <= 9)

View File

@ -42,7 +42,7 @@
#ifndef QBYTEARRAY_H
#define QBYTEARRAY_H
#include <QtCore/qatomic.h>
#include <QtCore/qrefcount.h>
#include <QtCore/qnamespace.h>
#include <string.h>
@ -119,18 +119,65 @@ class QString;
class QDataStream;
template <typename T> class QList;
struct QByteArrayData
{
QtPrivate::RefCount ref;
int size;
uint alloc : 31;
uint capacityReserved : 1;
union {
qptrdiff offset; // will always work as we add/subtract from a ushort ptr
char d[sizeof(qptrdiff)];
};
inline char *data() { return d + sizeof(qptrdiff) + offset; }
inline const char *data() const { return d + sizeof(qptrdiff) + offset; }
};
template<int n> struct QConstByteArrayData
{
const QByteArrayData ba;
const char data[n];
};
template<int N> struct QConstByteArrayDataPtr
{
const QConstByteArrayData<N> *ptr;
};
#if defined(Q_COMPILER_LAMBDA)
# define QByteArrayLiteral(str) ([]() { \
enum { Size = sizeof(str) }; \
static const QConstByteArrayData<Size> qbytearray_literal = \
{ { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, str }; \
QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
return holder; }())
#elif defined(Q_CC_GNU)
// We need to create a QByteArrayData in the .rodata section of memory
// and the only way to do that is to create a "static const" variable.
// To do that, we need the __extension__ {( )} trick which only GCC supports
# define QByteArrayLiteral(str) \
__extension__ ({ \
enum { Size = sizeof(str) }; \
static const QConstByteArrayData<Size> qbytearray_literal = \
{ { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, str }; \
QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
holder; })
#endif
#ifndef QByteArrayLiteral
// no lambdas, not GCC, use const char * instead
# define QByteArrayLiteral(str) (str)
#endif
class Q_CORE_EXPORT QByteArray
{
private:
struct Data {
QBasicAtomicInt ref;
int alloc, size;
// ### Qt 5.0: We need to add the missing capacity bit
// (like other tool classes have), to maintain the
// reserved memory on resize.
char *data;
char array[1];
};
typedef QByteArrayData Data;
public:
inline QByteArray();
@ -330,10 +377,17 @@ public:
int length() const { return d->size; }
bool isNull() const;
template <int n>
inline QByteArray(const QConstByteArrayData<n> &dd)
: d(const_cast<QByteArrayData *>(&dd.str)) {}
template <int N>
Q_DECL_CONSTEXPR inline QByteArray(QConstByteArrayDataPtr<N> dd)
: d(const_cast<QByteArrayData *>(&dd.ptr->ba)) {}
private:
operator QNoImplicitBoolCast() const;
static Data shared_null;
static Data shared_empty;
static QConstByteArrayData<1> shared_null;
static QConstByteArrayData<1> shared_empty;
Data *d;
QByteArray(Data *dd, int /*dummy*/, int /*dummy*/) : d(dd) {}
void realloc(int alloc);
@ -348,34 +402,34 @@ public:
inline DataPtr &data_ptr() { return d; }
};
inline QByteArray::QByteArray(): d(&shared_null) { d->ref.ref(); }
inline QByteArray::QByteArray(): d(const_cast<Data *>(&shared_null.ba)) { d->ref.ref(); }
inline QByteArray::~QByteArray() { if (!d->ref.deref()) qFree(d); }
inline int QByteArray::size() const
{ return d->size; }
inline char QByteArray::at(int i) const
{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
{ Q_ASSERT(i >= 0 && i < size()); return d->data()[i]; }
inline char QByteArray::operator[](int i) const
{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
{ Q_ASSERT(i >= 0 && i < size()); return d->data()[i]; }
inline char QByteArray::operator[](uint i) const
{ Q_ASSERT(i < uint(size())); return d->data[i]; }
{ Q_ASSERT(i < uint(size())); return d->data()[i]; }
inline bool QByteArray::isEmpty() const
{ return d->size == 0; }
#ifndef QT_NO_CAST_FROM_BYTEARRAY
inline QByteArray::operator const char *() const
{ return d->data; }
{ return d->data(); }
inline QByteArray::operator const void *() const
{ return d->data; }
{ return d->data(); }
#endif
inline char *QByteArray::data()
{ detach(); return d->data; }
{ detach(); return d->data(); }
inline const char *QByteArray::data() const
{ return d->data; }
{ return d->data(); }
inline const char *QByteArray::constData() const
{ return d->data; }
{ return d->data(); }
inline void QByteArray::detach()
{ if (d->ref != 1 || d->data != d->array) realloc(d->size); }
{ if (d->ref != 1 || d->offset) realloc(d->size); }
inline bool QByteArray::isDetached() const
{ return d->ref == 1; }
inline QByteArray::QByteArray(const QByteArray &a) : d(a.d)
@ -385,10 +439,10 @@ inline int QByteArray::capacity() const
{ return d->alloc; }
inline void QByteArray::reserve(int asize)
{ if (d->ref != 1 || asize > d->alloc) realloc(asize); }
{ if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacityReserved = true; }
inline void QByteArray::squeeze()
{ if (d->size < d->alloc) realloc(d->size); }
{ if (d->size < d->alloc) realloc(d->size); d->capacityReserved = false; }
class Q_CORE_EXPORT QByteRef {
QByteArray &a;
@ -398,25 +452,25 @@ class Q_CORE_EXPORT QByteRef {
friend class QByteArray;
public:
inline operator char() const
{ return i < a.d->size ? a.d->data[i] : char(0); }
{ return i < a.d->size ? a.d->data()[i] : char(0); }
inline QByteRef &operator=(char c)
{ if (i >= a.d->size) a.expand(i); else a.detach();
a.d->data[i] = c; return *this; }
a.d->data()[i] = c; return *this; }
inline QByteRef &operator=(const QByteRef &c)
{ if (i >= a.d->size) a.expand(i); else a.detach();
a.d->data[i] = c.a.d->data[c.i]; return *this; }
a.d->data()[i] = c.a.d->data()[c.i]; return *this; }
inline bool operator==(char c) const
{ return a.d->data[i] == c; }
{ return a.d->data()[i] == c; }
inline bool operator!=(char c) const
{ return a.d->data[i] != c; }
{ return a.d->data()[i] != c; }
inline bool operator>(char c) const
{ return a.d->data[i] > c; }
{ return a.d->data()[i] > c; }
inline bool operator>=(char c) const
{ return a.d->data[i] >= c; }
{ return a.d->data()[i] >= c; }
inline bool operator<(char c) const
{ return a.d->data[i] < c; }
{ return a.d->data()[i] < c; }
inline bool operator<=(char c) const
{ return a.d->data[i] <= c; }
{ return a.d->data()[i] <= c; }
};
inline QByteRef QByteArray::operator[](int i)
@ -424,17 +478,17 @@ inline QByteRef QByteArray::operator[](int i)
inline QByteRef QByteArray::operator[](uint i)
{ return QByteRef(*this, i); }
inline QByteArray::iterator QByteArray::begin()
{ detach(); return d->data; }
{ detach(); return d->data(); }
inline QByteArray::const_iterator QByteArray::begin() const
{ return d->data; }
{ return d->data(); }
inline QByteArray::const_iterator QByteArray::constBegin() const
{ return d->data; }
{ return d->data(); }
inline QByteArray::iterator QByteArray::end()
{ detach(); return d->data + d->size; }
{ detach(); return d->data() + d->size; }
inline QByteArray::const_iterator QByteArray::end() const
{ return d->data + d->size; }
{ return d->data() + d->size; }
inline QByteArray::const_iterator QByteArray::constEnd() const
{ return d->data + d->size; }
{ return d->data() + d->size; }
inline QByteArray &QByteArray::operator+=(char c)
{ return append(c); }
inline QByteArray &QByteArray::operator+=(const char *s)

View File

@ -76,17 +76,16 @@
QT_BEGIN_NAMESPACE
class QDateTimePrivate
class QDateTimePrivate : public QSharedData
{
public:
enum Spec { LocalUnknown = -1, LocalStandard = 0, LocalDST = 1, UTC = 2, OffsetFromUTC = 3};
QDateTimePrivate() : spec(LocalUnknown), utcOffset(0) {}
QDateTimePrivate(const QDateTimePrivate &other)
: date(other.date), time(other.time), spec(other.spec), utcOffset(other.utcOffset)
: QSharedData(other), date(other.date), time(other.time), spec(other.spec), utcOffset(other.utcOffset)
{}
QAtomicInt ref;
QDate date;
QTime time;
Spec spec;

View File

@ -1051,7 +1051,11 @@ QString::QString(const QChar *unicode, int size)
} else {
d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
*d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
d->ref = 1;
d->size = size;
d->alloc = (uint) size;
d->capacityReserved = false;
d->offset = 0;
memcpy(d->data(), unicode, size * sizeof(QChar));
d->data()[size] = '\0';
}
@ -1079,7 +1083,11 @@ QString::QString(const QChar *unicode)
} else {
d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
*d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
d->ref = 1;
d->size = size;
d->alloc = (uint) size;
d->capacityReserved = false;
d->offset = 0;
memcpy(d->data(), unicode, size * sizeof(QChar));
d->data()[size] = '\0';
}
@ -1100,7 +1108,11 @@ QString::QString(int size, QChar ch)
} else {
d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
*d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
d->ref = 1;
d->size = size;
d->alloc = (uint) size;
d->capacityReserved = false;
d->offset = 0;
d->data()[size] = '\0';
ushort *i = d->data() + size;
ushort *b = d->data();
@ -1120,7 +1132,11 @@ QString::QString(int size, Qt::Initialization)
{
d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar));
Q_CHECK_PTR(d);
*d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
d->ref = 1;
d->size = size;
d->alloc = (uint) size;
d->capacityReserved = false;
d->offset = 0;
d->data()[size] = '\0';
}
@ -1138,7 +1154,11 @@ QString::QString(QChar ch)
{
d = (Data *) qMalloc(sizeof(Data) + 2*sizeof(QChar));
Q_CHECK_PTR(d);
*d = (Data) { Q_REFCOUNT_INITIALIZER(1), 1, 1, false, { 0 } };
d->ref = 1;
d->size = 1;
d->alloc = 1;
d->capacityReserved = false;
d->offset = 0;
d->data()[0] = ch.unicode();
d->data()[1] = '\0';
}
@ -1313,7 +1333,11 @@ void QString::realloc(int alloc)
if (d->ref != 1 || d->offset) {
Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + (alloc+1) * sizeof(QChar)));
Q_CHECK_PTR(x);
*x = (Data){ Q_REFCOUNT_INITIALIZER(1), qMin(alloc, d->size), alloc, d->capacityReserved, { 0 } };
x->ref = 1;
x->size = qMin(alloc, d->size);
x->alloc = (uint) alloc;
x->capacityReserved = d->capacityReserved;
x->offset =0;
::memcpy(x->data(), d->data(), x->size * sizeof(QChar));
x->data()[x->size] = 0;
if (!d->ref.deref())
@ -3747,7 +3771,11 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size)
size = qstrlen(str);
d = static_cast<Data *>(qMalloc(sizeof(Data) + (size+1) * sizeof(QChar)));
Q_CHECK_PTR(d);
*d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } };
d->ref = 1;
d->size = size;
d->alloc = (uint) size;
d->capacityReserved = false;
d->offset = 0;
d->data()[size] = '\0';
ushort *dst = d->data();
/* SIMD:
@ -7071,13 +7099,19 @@ bool QString::isRightToLeft() const
*/
QString QString::fromRawData(const QChar *unicode, int size)
{
Data *x = static_cast<Data *>(qMalloc(sizeof(Data)));
*x = (Data){ Q_REFCOUNT_INITIALIZER(1), size, 0, false, { 0 } };
Q_CHECK_PTR(x);
if (unicode) {
x->offset = (const ushort *)unicode - (x->d + sizeof(qptrdiff)/sizeof(ushort));
Data *x;
if (!unicode) {
x = const_cast<Data *>(&shared_null.str);
} else if (!size) {
x = const_cast<Data *>(&shared_empty.str);
} else {
size = 0;
x = static_cast<Data *>(qMalloc(sizeof(Data) + sizeof(ushort)));
Q_CHECK_PTR(x);
x->ref = 1;
x->size = size;
x->alloc = 0;
x->capacityReserved = false;
x->offset = (const ushort *)unicode - (x->d + sizeof(qptrdiff)/sizeof(ushort));
}
return QString(x, 0);
}

View File

@ -185,7 +185,7 @@ public:
int capacity() const;
inline void reserve(int size);
inline void squeeze() { if (d->size < d->alloc || d->ref != 1) realloc(); d->capacityReserved = false;}
inline void squeeze() { if (d->size < (int)d->alloc || d->ref != 1) realloc(); d->capacityReserved = false;}
inline const QChar *unicode() const;
inline QChar *data();
@ -337,7 +337,7 @@ public:
inline QString &prepend(const QLatin1String &s) { return insert(0, s); }
inline QString &operator+=(QChar c) {
if (d->ref != 1 || d->size + 1 > d->alloc)
if (d->ref != 1 || d->size + 1 > (int)d->alloc)
realloc(grow(d->size + 1));
d->data()[d->size++] = c.unicode();
d->data()[d->size] = '\0';
@ -633,7 +633,7 @@ public:
class Q_CORE_EXPORT QLatin1String
{
public:
inline explicit QLatin1String(const char *s) : m_size(s ? strlen(s) : 0), m_data(s) {}
inline explicit QLatin1String(const char *s) : m_size(s ? (int)strlen(s) : 0), m_data(s) {}
inline const char *latin1() const { return m_data; }
inline int size() const { return m_size; }
@ -842,7 +842,7 @@ inline void QCharRef::setCell(uchar acell) { QChar(*this).setCell(acell); }
inline QString::QString() : d(const_cast<Data *>(&shared_null.str)) {}
inline QString::~QString() { if (!d->ref.deref()) free(d); }
inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacityReserved = true;}
inline void QString::reserve(int asize) { if (d->ref != 1 || asize > (int)d->alloc) realloc(asize); d->capacityReserved = true;}
inline QString &QString::setUtf16(const ushort *autf16, int asize)
{ return setUnicode(reinterpret_cast<const QChar *>(autf16), asize); }
inline QCharRef QString::operator[](int i)

View File

@ -1644,7 +1644,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
overall.y = qMin(overall.y, y);
xmax = qMax(xmax, x + g->width);
ymax = qMax(ymax, y + g->height);
overall.xoff += qRound(g->advance);
overall.xoff += g->advance;
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
@ -1657,7 +1657,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
overall.y = qMin(overall.y, y);
xmax = qMax(xmax, x + TRUNC(right - left));
ymax = qMax(ymax, y + TRUNC(top - bottom));
overall.xoff += qRound(TRUNC(ROUND(face->glyph->advance.x)));
overall.xoff += int(TRUNC(ROUND(face->glyph->advance.x)));
}
}
overall.height = qMax(overall.height, ymax - overall.y);

View File

@ -271,7 +271,7 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair)
value = request.headerField("accept-encoding");
if (value.isEmpty()) {
#ifndef QT_NO_COMPRESS
request.setHeaderField("Accept-Encoding", "gzip");
request.setHeaderField("Accept-Encoding", "gzip, deflate");
request.d->autoDecompress = true;
#else
// if zlib is not available set this to false always

View File

@ -202,9 +202,6 @@ public:
QString errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket,
const QString &extraDetail = QString());
#ifndef QT_NO_COMPRESS
bool expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete);
#endif
void removeReply(QHttpNetworkReply *reply);
QString hostName;

View File

@ -403,7 +403,7 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
bytes += headerBytes;
// If headers were parsed successfully now it is the ReadingDataState
if (replyPrivate->state == QHttpNetworkReplyPrivate::ReadingDataState) {
if (replyPrivate->isGzipped() && replyPrivate->autoDecompress) {
if (replyPrivate->isCompressed() && replyPrivate->autoDecompress) {
// remove the Content-Length from header
replyPrivate->removeAutoDecompressHeader();
} else {
@ -448,12 +448,17 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
// the buffer in that size.
// note that this call will read only from the still buffered data
qint64 haveRead = replyPrivate->readBodyVeryFast(socket, replyPrivate->userProvidedDownloadBuffer + replyPrivate->totalProgress);
bytes += haveRead;
replyPrivate->totalProgress += haveRead;
// the user will get notified of it via progress signal
if (haveRead > 0)
if (haveRead > 0) {
bytes += haveRead;
replyPrivate->totalProgress += haveRead;
// the user will get notified of it via progress signal
emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength);
} else if (haveRead == 0) {
// Happens since this called in a loop. Currently no bytes available.
} else if (haveRead < 0) {
connection->d_func()->emitReplyError(socket, reply, QNetworkReply::RemoteHostClosedError);
break;
}
} else if (!replyPrivate->isChunked() && !replyPrivate->autoDecompress
&& replyPrivate->bodyLength > 0) {
// bulk files like images should fulfill these properties and
@ -470,30 +475,18 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
{
// use the traditional slower reading (for compressed encoding, chunked encoding,
// no content-length etc)
QByteDataBuffer byteDatas;
qint64 haveRead = replyPrivate->readBody(socket, &byteDatas);
if (haveRead) {
qint64 haveRead = replyPrivate->readBody(socket, &replyPrivate->responseData);
if (haveRead > 0) {
bytes += haveRead;
if (replyPrivate->autoDecompress)
replyPrivate->appendCompressedReplyData(byteDatas);
else
replyPrivate->appendUncompressedReplyData(byteDatas);
if (!replyPrivate->autoDecompress) {
replyPrivate->totalProgress += bytes;
if (replyPrivate->shouldEmitSignals()) {
// important: At the point of this readyRead(), the byteDatas list must be empty,
// else implicit sharing will trigger memcpy when the user is reading data!
emit reply->readyRead();
emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength);
}
replyPrivate->totalProgress += haveRead;
if (replyPrivate->shouldEmitSignals()) {
emit reply->readyRead();
emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength);
}
#ifndef QT_NO_COMPRESS
else if (!expand(false)) { // expand a chunk if possible
// If expand() failed we can just return, it had already called connection->emitReplyError()
return;
}
#endif
} else if (haveRead == -1) {
// Some error occured
connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ProtocolFailure);
break;
}
}
// still in ReadingDataState? This function will be called again by the socket's readyRead
@ -633,57 +626,9 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
return true;
}
#ifndef QT_NO_COMPRESS
bool QHttpNetworkConnectionChannel::expand(bool dataComplete)
{
Q_ASSERT(socket);
Q_ASSERT(reply);
qint64 total = reply->d_func()->compressedData.size();
if (total >= CHUNK || dataComplete) {
// uncompress the data
QByteArray content, inflated;
content = reply->d_func()->compressedData;
reply->d_func()->compressedData.clear();
int ret = Z_OK;
if (content.size())
ret = reply->d_func()->gunzipBodyPartially(content, inflated);
int retCheck = (dataComplete) ? Z_STREAM_END : Z_OK;
if (ret >= retCheck) {
if (inflated.size()) {
reply->d_func()->totalProgress += inflated.size();
reply->d_func()->appendUncompressedReplyData(inflated);
if (reply->d_func()->shouldEmitSignals()) {
// important: At the point of this readyRead(), inflated must be cleared,
// else implicit sharing will trigger memcpy when the user is reading data!
emit reply->readyRead();
emit reply->dataReadProgress(reply->d_func()->totalProgress, 0);
}
}
} else {
connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ProtocolFailure);
return false;
}
}
return true;
}
#endif
void QHttpNetworkConnectionChannel::allDone()
{
Q_ASSERT(reply);
#ifndef QT_NO_COMPRESS
// expand the whole data.
if (reply->d_func()->expectContent() && reply->d_func()->autoDecompress && !reply->d_func()->streamEnd) {
bool expandResult = expand(true);
// If expand() failed we can just return, it had already called connection->emitReplyError()
if (!expandResult)
return;
}
#endif
if (!reply) {
qWarning() << "QHttpNetworkConnectionChannel::allDone() called without reply. Please report at http://bugreports.qt.nokia.com/";

View File

@ -149,7 +149,6 @@ public:
bool ensureConnection();
bool expand(bool dataComplete);
void allDone(); // reply header + body have been read
void handleStatus(); // called from allDone()

View File

@ -65,6 +65,11 @@ QHttpNetworkReply::~QHttpNetworkReply()
if (d->connection) {
d->connection->d_func()->removeReply(this);
}
#ifndef QT_NO_COMPRESS
if (d->autoDecompress && d->isCompressed())
inflateEnd(&d->inflateStrm);
#endif
}
QUrl QHttpNetworkReply::url() const
@ -211,7 +216,7 @@ void QHttpNetworkReply::setDownstreamLimited(bool dsl)
bool QHttpNetworkReply::supportsUserProvidedDownloadBuffer()
{
Q_D(QHttpNetworkReply);
return (!d->isChunked() && !d->autoDecompress && d->bodyLength > 0);
return (!d->isChunked() && !d->autoDecompress && d->bodyLength > 0 && d->statusCode == 200);
}
void QHttpNetworkReply::setUserProvidedDownloadBuffer(char* b)
@ -252,7 +257,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
chunkedTransferEncoding(false),
connectionCloseEnabled(true),
forceConnectionCloseEnabled(false),
currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false),
currentChunkSize(0), currentChunkRead(0), connection(0),
autoDecompress(false), responseData(), requestIsPrepared(false)
,pipeliningUsed(false), downstreamLimited(false)
,userProvidedDownloadBuffer(0)
@ -274,11 +279,9 @@ void QHttpNetworkReplyPrivate::clearHttpLayerInformation()
currentChunkRead = 0;
connectionCloseEnabled = true;
#ifndef QT_NO_COMPRESS
if (initInflate)
if (autoDecompress)
inflateEnd(&inflateStrm);
#endif
initInflate = false;
streamEnd = false;
fields.clear();
}
@ -297,10 +300,10 @@ qint64 QHttpNetworkReplyPrivate::bytesAvailable() const
return (state != ReadingDataState ? 0 : fragment.size());
}
bool QHttpNetworkReplyPrivate::isGzipped()
bool QHttpNetworkReplyPrivate::isCompressed()
{
QByteArray encoding = headerField("content-encoding");
return qstricmp(encoding.constData(), "gzip") == 0;
return qstricmp(encoding.constData(), "gzip") == 0 || qstricmp(encoding.constData(), "deflate") == 0;
}
void QHttpNetworkReplyPrivate::removeAutoDecompressHeader()
@ -358,120 +361,6 @@ QAuthenticatorPrivate::Method QHttpNetworkReplyPrivate::authenticationMethod(boo
return method;
}
#ifndef QT_NO_COMPRESS
bool QHttpNetworkReplyPrivate::gzipCheckHeader(QByteArray &content, int &pos)
{
int method = 0; // method byte
int flags = 0; // flags byte
bool ret = false;
// Assure two bytes in the buffer so we can peek ahead -- handle case
// where first byte of header is at the end of the buffer after the last
// gzip segment
pos = -1;
QByteArray &body = content;
int maxPos = body.size()-1;
if (maxPos < 1) {
return ret;
}
// Peek ahead to check the gzip magic header
if (body[0] != char(gz_magic[0]) ||
body[1] != char(gz_magic[1])) {
return ret;
}
pos += 2;
// Check the rest of the gzip header
if (++pos <= maxPos)
method = body[pos];
if (pos++ <= maxPos)
flags = body[pos];
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
return ret;
}
// Discard time, xflags and OS code:
pos += 6;
if (pos > maxPos)
return ret;
if ((flags & EXTRA_FIELD) && ((pos+2) <= maxPos)) { // skip the extra field
unsigned len = (unsigned)body[++pos];
len += ((unsigned)body[++pos])<<8;
pos += len;
if (pos > maxPos)
return ret;
}
if ((flags & ORIG_NAME) != 0) { // skip the original file name
while(++pos <= maxPos && body[pos]) {}
}
if ((flags & COMMENT) != 0) { // skip the .gz file comment
while(++pos <= maxPos && body[pos]) {}
}
if ((flags & HEAD_CRC) != 0) { // skip the header crc
pos += 2;
if (pos > maxPos)
return ret;
}
ret = (pos < maxPos); // return failed, if no more bytes left
return ret;
}
int QHttpNetworkReplyPrivate::gunzipBodyPartially(QByteArray &compressed, QByteArray &inflated)
{
int ret = Z_DATA_ERROR;
unsigned have;
unsigned char out[CHUNK];
int pos = -1;
if (!initInflate) {
// check the header
if (!gzipCheckHeader(compressed, pos))
return ret;
// allocate inflate state
inflateStrm.zalloc = Z_NULL;
inflateStrm.zfree = Z_NULL;
inflateStrm.opaque = Z_NULL;
inflateStrm.avail_in = 0;
inflateStrm.next_in = Z_NULL;
ret = inflateInit2(&inflateStrm, -MAX_WBITS);
if (ret != Z_OK)
return ret;
initInflate = true;
streamEnd = false;
}
//remove the header.
compressed.remove(0, pos+1);
// expand until deflate stream ends
inflateStrm.next_in = (unsigned char *)compressed.data();
inflateStrm.avail_in = compressed.size();
do {
inflateStrm.avail_out = sizeof(out);
inflateStrm.next_out = out;
ret = inflate(&inflateStrm, Z_NO_FLUSH);
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR;
// and fall through
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&inflateStrm);
initInflate = false;
return ret;
}
have = sizeof(out) - inflateStrm.avail_out;
inflated.append(QByteArray((const char *)out, have));
} while (inflateStrm.avail_out == 0);
// clean up and return
if (ret <= Z_ERRNO || ret == Z_STREAM_END) {
inflateEnd(&inflateStrm);
initInflate = false;
}
streamEnd = (ret == Z_STREAM_END);
return ret;
}
#endif
qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
{
if (fragment.isEmpty()) {
@ -616,6 +505,24 @@ qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket)
connectionCloseEnabled = (connectionHeaderField.toLower().contains("close") ||
headerField("proxy-connection").toLower().contains("close")) ||
(majorVersion == 1 && minorVersion == 0 && connectionHeaderField.isEmpty());
#ifndef QT_NO_COMPRESS
if (autoDecompress && isCompressed()) {
// allocate inflate state
inflateStrm.zalloc = Z_NULL;
inflateStrm.zfree = Z_NULL;
inflateStrm.opaque = Z_NULL;
inflateStrm.avail_in = 0;
inflateStrm.next_in = Z_NULL;
// "windowBits can also be greater than 15 for optional gzip decoding.
// Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection"
// http://www.zlib.net/manual.html
int ret = inflateInit2(&inflateStrm, MAX_WBITS+32);
if (ret != Z_OK)
return -1;
}
#endif
}
return bytes;
}
@ -672,7 +579,7 @@ qint64 QHttpNetworkReplyPrivate::readBodyVeryFast(QAbstractSocket *socket, char
qint64 haveRead = 0;
haveRead = socket->read(b, bodyLength - contentRead);
if (haveRead == -1) {
return 0; // ### error checking here;
return -1;
}
contentRead += haveRead;
@ -712,22 +619,74 @@ qint64 QHttpNetworkReplyPrivate::readBodyFast(QAbstractSocket *socket, QByteData
qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QByteDataBuffer *out)
{
qint64 bytes = 0;
#ifndef QT_NO_COMPRESS
// for gzip we'll allocate a temporary one that we then decompress
QByteDataBuffer *tempOutDataBuffer = (autoDecompress ? new QByteDataBuffer : out);
#else
QByteDataBuffer *tempOutDataBuffer = out;
#endif
if (isChunked()) {
// chunked transfer encoding (rfc 2616, sec 3.6)
bytes += readReplyBodyChunked(socket, out);
bytes += readReplyBodyChunked(socket, tempOutDataBuffer);
} else if (bodyLength > 0) {
// we have a Content-Length
bytes += readReplyBodyRaw(socket, out, bodyLength - contentRead);
bytes += readReplyBodyRaw(socket, tempOutDataBuffer, bodyLength - contentRead);
if (contentRead + bytes == bodyLength)
state = AllDoneState;
} else {
// no content length. just read what's possible
bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable());
bytes += readReplyBodyRaw(socket, tempOutDataBuffer, socket->bytesAvailable());
}
#ifndef QT_NO_COMPRESS
// This is true if there is compressed encoding and we're supposed to use it.
if (autoDecompress) {
qint64 uncompressRet = uncompressBodyData(tempOutDataBuffer, out);
delete tempOutDataBuffer;
if (uncompressRet < 0)
return -1;
}
#endif
contentRead += bytes;
return bytes;
}
#ifndef QT_NO_COMPRESS
qint64 QHttpNetworkReplyPrivate::uncompressBodyData(QByteDataBuffer *in, QByteDataBuffer *out)
{
for (int i = 0; i < in->bufferCount(); i++) {
QByteArray &bIn = (*in)[i];
inflateStrm.avail_in = bIn.size();
inflateStrm.next_in = reinterpret_cast<Bytef*>(bIn.data());
do {
QByteArray bOut;
// make a wild guess about the uncompressed size.
bOut.reserve(inflateStrm.avail_in * 3 + 512);
inflateStrm.avail_out = bOut.capacity();
inflateStrm.next_out = reinterpret_cast<Bytef*>(bOut.data());
int ret = inflate(&inflateStrm, Z_NO_FLUSH);
switch (ret) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
return -1;
}
bOut.resize(bOut.capacity() - inflateStrm.avail_out);
out->append(bOut);
} while (inflateStrm.avail_in > 0);
}
return out->byteAmount();
}
#endif
qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QAbstractSocket *socket, QByteDataBuffer *out, qint64 size)
{
// FIXME get rid of this function and just use readBodyFast and give it socket->bytesAvailable()
@ -841,36 +800,6 @@ qint64 QHttpNetworkReplyPrivate::getChunkSize(QAbstractSocket *socket, qint64 *c
return bytes;
}
void QHttpNetworkReplyPrivate::appendUncompressedReplyData(QByteArray &qba)
{
responseData.append(qba);
// clear the original! helps with implicit sharing and
// avoiding memcpy when the user is reading the data
qba.clear();
}
void QHttpNetworkReplyPrivate::appendUncompressedReplyData(QByteDataBuffer &data)
{
responseData.append(data);
// clear the original! helps with implicit sharing and
// avoiding memcpy when the user is reading the data
data.clear();
}
void QHttpNetworkReplyPrivate::appendCompressedReplyData(QByteDataBuffer &data)
{
// Work in progress: Later we will directly use a list of QByteArray or a QRingBuffer
// instead of one QByteArray.
for(int i = 0; i < data.bufferCount(); i++) {
QByteArray &byteData = data[i];
compressedData.append(byteData.constData(), byteData.size());
}
data.clear();
}
bool QHttpNetworkReplyPrivate::shouldEmitSignals()
{
// for 401 & 407 don't emit the data signals. Content along with these

View File

@ -56,15 +56,7 @@
#ifndef QT_NO_HTTP
#ifndef QT_NO_COMPRESS
# include <zlib.h>
static const unsigned char gz_magic[2] = {0x1f, 0x8b}; // gzip magic header
// gzip flag byte
#define HEAD_CRC 0x02 // bit 1 set: header CRC present
#define EXTRA_FIELD 0x04 // bit 2 set: extra field present
#define ORIG_NAME 0x08 // bit 3 set: original file name present
#define COMMENT 0x10 // bit 4 set: file comment present
#define RESERVED 0xE0 // bits 5..7: reserved
#define CHUNK 16384
#include <zlib.h>
#endif
#include <QtNetwork/qtcpsocket.h>
@ -192,10 +184,6 @@ public:
qint64 readReplyBodyChunked(QAbstractSocket *in, QByteDataBuffer *out);
qint64 getChunkSize(QAbstractSocket *in, qint64 *chunkSize);
void appendUncompressedReplyData(QByteArray &qba);
void appendUncompressedReplyData(QByteDataBuffer &data);
void appendCompressedReplyData(QByteDataBuffer &data);
bool shouldEmitSignals();
bool expectContent();
void eraseData();
@ -203,11 +191,8 @@ public:
qint64 bytesAvailable() const;
bool isChunked();
bool isConnectionCloseEnabled();
bool isGzipped();
#ifndef QT_NO_COMPRESS
bool gzipCheckHeader(QByteArray &content, int &pos);
int gunzipBodyPartially(QByteArray &compressed, QByteArray &inflated);
#endif
bool isCompressed();
void removeAutoDecompressHeader();
enum ReplyState {
@ -236,11 +221,12 @@ public:
qint64 currentChunkRead;
QPointer<QHttpNetworkConnection> connection;
QPointer<QHttpNetworkConnectionChannel> connectionChannel;
bool initInflate;
bool streamEnd;
#ifndef QT_NO_COMPRESS
z_stream inflateStrm;
qint64 uncompressBodyData(QByteDataBuffer *in, QByteDataBuffer *out);
#endif
bool autoDecompress;
QByteDataBuffer responseData; // uncompressed body

View File

@ -777,8 +777,16 @@ void QNetworkReplyHttpImplPrivate::postRequest()
if (!synchronous) {
// Tell our zerocopy policy to the delegate
delegate->downloadBufferMaximumSize =
request.attribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute).toLongLong();
QVariant downloadBufferMaximumSizeAttribute = request.attribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute);
if (downloadBufferMaximumSizeAttribute.isValid()) {
delegate->downloadBufferMaximumSize = downloadBufferMaximumSizeAttribute.toLongLong();
} else {
// If there is no MaximumDownloadBufferSizeAttribute set (which is for the majority
// of QNetworkRequest) then we can assume we'll do it anyway for small HTTP replies.
// This helps with performance and memory fragmentation.
delegate->downloadBufferMaximumSize = 128*1024;
}
// These atomic integers are used for signal compression
delegate->pendingDownloadData = pendingDownloadDataEmissions;

View File

@ -121,6 +121,7 @@
#include <QtCore/qfile.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qmap.h>
#include <QtCore/qmutex.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qvarlengtharray.h>
@ -666,6 +667,21 @@ QList<QSslCertificate> QSslCertificate::fromData(const QByteArray &data, QSsl::E
: QSslCertificatePrivate::certificatesFromDer(data);
}
/*!
Verifies a certificate chain. If \a hostName is specified then the certificate is
also checked to see if it is valid for the specified host name.
Note that the first certificate in the list should be the leaf certificate of
the chain to be verified.
The root (CA) certificate should not be included in the list to be verified,
this will be looked up automatically either using the CA list specified by
QSslSocket::defaultCaCertificates() or, if possible, it will be loaded on demand
on Unix.
*/
QList<QSslError> QSslCertificate::verify(QList<QSslCertificate> certificateChain, const QString &hostName)
{
return QSslSocketBackendPrivate::verify(certificateChain, hostName);
}
void QSslCertificatePrivate::init(const QByteArray &data, QSsl::EncodingFormat format)
{
if (!data.isEmpty()) {

View File

@ -62,6 +62,7 @@ QT_MODULE(Network)
class QDateTime;
class QIODevice;
class QSslError;
class QSslKey;
class QStringList;
template <typename T, typename U> class QMultiMap;
@ -122,6 +123,8 @@ public:
static QList<QSslCertificate> fromData(
const QByteArray &data, QSsl::EncodingFormat format = QSsl::Pem);
static QList<QSslError> verify(QList<QSslCertificate> certificateChain, const QString &hostName = QString());
Qt::HANDLE handle() const;
private:

View File

@ -1283,33 +1283,14 @@ bool QSslSocketBackendPrivate::startHandshake()
// if we're the server, don't check CN
if (mode == QSslSocket::SslClientMode) {
QString peerName = (verificationPeerName.isEmpty () ? q->peerName() : verificationPeerName);
QStringList commonNameList = configuration.peerCertificate.subjectInfo(QSslCertificate::CommonName);
bool matched = false;
foreach (const QString &commonName, commonNameList) {
if (isMatchingHostname(commonName.toLower(), peerName.toLower())) {
matched = true;
break;
}
}
if (!matched) {
foreach (const QString &altName, configuration.peerCertificate
.alternateSubjectNames().values(QSsl::DnsEntry)) {
if (isMatchingHostname(altName.toLower(), peerName.toLower())) {
matched = true;
break;
}
}
}
if (!matched) {
// No matches in common names or alternate names.
QSslError error(QSslError::HostNameMismatch, configuration.peerCertificate);
errors << error;
emit q->peerVerifyError(error);
if (q->state() != QAbstractSocket::ConnectedState)
return false;
if (!isMatchingHostname(configuration.peerCertificate, peerName)) {
// No matches in common names or alternate names.
QSslError error(QSslError::HostNameMismatch, configuration.peerCertificate);
errors << error;
emit q->peerVerifyError(error);
if (q->state() != QAbstractSocket::ConnectedState)
return false;
}
}
} else {
@ -1444,6 +1425,25 @@ QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
return errorString;
}
bool QSslSocketBackendPrivate::isMatchingHostname(const QSslCertificate &cert, const QString &peerName)
{
QStringList commonNameList = cert.subjectInfo(QSslCertificate::CommonName);
foreach (const QString &commonName, commonNameList) {
if (isMatchingHostname(commonName.toLower(), peerName.toLower())) {
return true;
}
}
foreach (const QString &altName, cert.alternateSubjectNames().values(QSsl::DnsEntry)) {
if (isMatchingHostname(altName.toLower(), peerName.toLower())) {
return true;
}
}
return false;
}
bool QSslSocketBackendPrivate::isMatchingHostname(const QString &cn, const QString &hostname)
{
int wildcard = cn.indexOf(QLatin1Char('*'));
@ -1484,4 +1484,133 @@ bool QSslSocketBackendPrivate::isMatchingHostname(const QString &cn, const QStri
return true;
}
QList<QSslError> QSslSocketBackendPrivate::verify(QList<QSslCertificate> certificateChain, const QString &hostName)
{
QList<QSslError> errors;
if (certificateChain.count() <= 0) {
errors << QSslError(QSslError::UnspecifiedError);
return errors;
}
// Setup the store with the default CA certificates
X509_STORE *certStore = q_X509_STORE_new();
if (!certStore) {
qWarning() << "Unable to create certificate store";
errors << QSslError(QSslError::UnspecifiedError);
return errors;
}
QList<QSslCertificate> expiredCerts;
foreach (const QSslCertificate &caCertificate, QSslSocket::defaultCaCertificates()) {
// add expired certs later, so that the
// valid ones are used before the expired ones
if (!caCertificate.isValid()) {
expiredCerts.append(caCertificate);
} else {
q_X509_STORE_add_cert(certStore, (X509 *)caCertificate.handle());
}
}
bool addExpiredCerts = true;
#if defined(Q_OS_MAC) && (MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5)
//On Leopard SSL does not work if we add the expired certificates.
if (QSysInfo::MacintoshVersion == QSysInfo::MV_10_5)
addExpiredCerts = false;
#endif
// now add the expired certs
if (addExpiredCerts) {
foreach (const QSslCertificate &caCertificate, expiredCerts) {
q_X509_STORE_add_cert(certStore, (X509 *)caCertificate.handle());
}
}
_q_sslErrorList()->mutex.lock();
// Register a custom callback to get all verification errors.
X509_STORE_set_verify_cb_func(certStore, q_X509Callback);
// Build the chain of intermediate certificates
STACK_OF(X509) *intermediates = 0;
if (certificateChain.length() > 1) {
intermediates = (STACK_OF(X509) *) q_sk_new_null();
if (!intermediates) {
q_X509_STORE_free(certStore);
errors << QSslError(QSslError::UnspecifiedError);
return errors;
}
bool first = true;
foreach (const QSslCertificate &cert, certificateChain) {
if (first) {
first = false;
continue;
}
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
q_sk_push( (_STACK *)intermediates, (X509 *)cert.handle());
#else
q_sk_push( (STACK *)intermediates, (X509 *)cert.handle());
#endif
}
}
X509_STORE_CTX *storeContext = q_X509_STORE_CTX_new();
if (!storeContext) {
q_X509_STORE_free(certStore);
errors << QSslError(QSslError::UnspecifiedError);
return errors;
}
if (!q_X509_STORE_CTX_init(storeContext, certStore, (X509 *)certificateChain[0].handle(), intermediates)) {
q_X509_STORE_CTX_free(storeContext);
q_X509_STORE_free(certStore);
errors << QSslError(QSslError::UnspecifiedError);
return errors;
}
// Now we can actually perform the verification of the chain we have built.
// We ignore the result of this function since we process errors via the
// callback.
(void) q_X509_verify_cert(storeContext);
q_X509_STORE_CTX_free(storeContext);
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
q_sk_free( (_STACK *) intermediates);
#else
q_sk_free( (STACK *) intermediates);
#endif
// Now process the errors
const QList<QPair<int, int> > errorList = _q_sslErrorList()->errors;
_q_sslErrorList()->errors.clear();
_q_sslErrorList()->mutex.unlock();
// Translate the errors
if (QSslCertificatePrivate::isBlacklisted(certificateChain[0])) {
QSslError error(QSslError::CertificateBlacklisted, certificateChain[0]);
errors << error;
}
// Check the certificate name against the hostname if one was specified
if ((!hostName.isEmpty()) && (!isMatchingHostname(certificateChain[0], hostName))) {
// No matches in common names or alternate names.
QSslError error(QSslError::HostNameMismatch, certificateChain[0]);
errors << error;
}
// Translate errors from the error list into QSslErrors.
for (int i = 0; i < errorList.size(); ++i) {
const QPair<int, int> &errorAndDepth = errorList.at(i);
int err = errorAndDepth.first;
int depth = errorAndDepth.second;
errors << _q_OpenSSL_to_QSslError(err, certificateChain.value(depth));
}
q_X509_STORE_free(certStore);
return errors;
}
QT_END_NAMESPACE

View File

@ -120,7 +120,9 @@ public:
static QSslCipher QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher);
static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
static bool isMatchingHostname(const QSslCertificate &cert, const QString &peerName);
Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QString &cn, const QString &hostname);
static QList<QSslError> verify(QList<QSslCertificate> certificateChain, const QString &hostName);
static QString getErrorsFromOpenSsl();
};

View File

@ -157,9 +157,13 @@ DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG)
DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG)
DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
#else
DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC2(void, sk_push, STACK *a, a, void *b, b, return, DUMMYARG)
DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
#endif
@ -710,6 +714,8 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(RAND_seed)
RESOLVEFUNC(RAND_status)
RESOLVEFUNC(RSA_free)
RESOLVEFUNC(sk_new_null)
RESOLVEFUNC(sk_push)
RESOLVEFUNC(sk_free)
RESOLVEFUNC(sk_num)
RESOLVEFUNC(sk_pop_free)

View File

@ -263,9 +263,13 @@ void q_RSA_free(RSA *a);
int q_sk_num(STACK *a);
void q_sk_pop_free(STACK *a, void (*b)(void *));
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
_STACK *q_sk_new_null();
void q_sk_push(_STACK *st, void *data);
void q_sk_free(_STACK *a);
void * q_sk_value(STACK *a, int b);
#else
STACK *q_sk_new_null();
void q_sk_push(STACK *st, void *data);
void q_sk_free(STACK *a);
char * q_sk_value(STACK *a, int b);
#endif

View File

@ -1638,7 +1638,8 @@ QGraphicsScene::~QGraphicsScene()
Q_D(QGraphicsScene);
// Remove this scene from qApp's global scene list.
qApp->d_func()->scene_list.removeAll(this);
if (!QApplicationPrivate::is_app_closing)
qApp->d_func()->scene_list.removeAll(this);
clear();

View File

@ -64,6 +64,13 @@ static void my_terminate_handler()
#ifdef __GLIBC__
/* Use glibc's memory allocation hooks */
// From glibc 2.14, the malloc hook variables are declared volatile.
// Note: The malloc hook implementation is marked as deprecated.
#if !defined(__MALLOC_HOOK_VOLATILE)
# define __MALLOC_HOOK_VOLATILE
#endif
/* our hooks */
static void *my_malloc_hook(size_t, const void *);
static void *my_realloc_hook(void *, size_t, const void *);
@ -71,16 +78,17 @@ static void *my_memalign_hook(size_t, size_t, const void *);
static void my_free_hook(void *, const void *);
/* original hooks. */
static void *(*old_malloc_hook)(size_t, const void *);
static void *(*old_realloc_hook)(void *, size_t, const void *);
static void *(*old_memalign_hook)(size_t, size_t, const void *);
static void (*old_free_hook)(void *, const void *);
static void *(*__MALLOC_HOOK_VOLATILE old_malloc_hook)(size_t, const void *);
static void *(*__MALLOC_HOOK_VOLATILE old_realloc_hook)(void *, size_t, const void *);
static void *(*__MALLOC_HOOK_VOLATILE old_memalign_hook)(size_t, size_t, const void *);
static void (*__MALLOC_HOOK_VOLATILE old_free_hook)(void *, const void *);
/* initializer function */
static void my_init_hook();
/* Override initialising hook from the C library. */
void (*__malloc_initialize_hook) (void) = my_init_hook;
void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) = my_init_hook;
static void disableHooks()
{

View File

@ -145,6 +145,8 @@ private slots:
void byteRefDetaching() const;
void reserve();
void literals();
};
tst_QByteArray::tst_QByteArray()
@ -1527,14 +1529,38 @@ void tst_QByteArray::reserve()
QVERIFY(qba.capacity() == capacity);
char *data = qba.data();
// FIXME count from 0 to make it fail
for (int i = 1; i < capacity; i++) {
for (int i = 0; i < capacity; i++) {
qba.resize(i);
QVERIFY(capacity == qba.capacity());
QVERIFY(data == qba.data());
}
}
void tst_QByteArray::literals()
{
#if defined(Q_COMPILER_LAMBDA) || defined(Q_CC_GNU)
QByteArray str(QByteArrayLiteral("abcd"));
QVERIFY(str.length() == 4);
QVERIFY(str == "abcd");
QVERIFY(str.data_ptr()->ref == -1);
QVERIFY(str.data_ptr()->offset == 0);
const char *s = str.constData();
QByteArray str2 = str;
QVERIFY(str2.constData() == s);
// detach on non const access
QVERIFY(str.data() != s);
QVERIFY(str2.constData() == s);
QVERIFY(str2.data() != s);
#else
QSKIP("Only tested on c++0x compliant compiler or gcc", SkipAll);
#endif
}
const char globalChar = '1';
QTEST_APPLESS_MAIN(tst_QByteArray)

View File

@ -116,6 +116,7 @@ private slots:
void toText();
void multipleCommonNames();
void subjectAndIssuerAttributes();
void verify();
// ### add tests for certificate bundles (multiple certificates concatenated into a single
// structure); both PEM and DER formatted
@ -901,6 +902,71 @@ void tst_QSslCertificate::subjectAndIssuerAttributes()
QVERIFY(attributes.contains(QByteArray("1.3.6.1.4.1.311.60.2.1.3")));
}
void tst_QSslCertificate::verify()
{
QList<QSslError> errors;
QList<QSslCertificate> toVerify;
// Empty chain is unspecified error
errors = QSslCertificate::verify(toVerify);
QVERIFY(errors.count() == 1);
QVERIFY(errors[0] == QSslError(QSslError::UnspecifiedError));
errors.clear();
// Verify a valid cert signed by a CA
QList<QSslCertificate> caCerts = QSslCertificate::fromPath(SRCDIR "verify-certs/cacert.pem");
QSslSocket::addDefaultCaCertificate(caCerts.first());
toVerify = QSslCertificate::fromPath(SRCDIR "verify-certs/test-ocsp-good-cert.pem");
errors = QSslCertificate::verify(toVerify);
QVERIFY(errors.count() == 0);
errors.clear();
// Test a blacklisted certificate
toVerify = QSslCertificate::fromPath(SRCDIR "verify-certs/test-addons-mozilla-org-cert.pem");
errors = QSslCertificate::verify(toVerify);
bool foundBlack = false;
foreach (const QSslError &error, errors) {
if (error.error() == QSslError::CertificateBlacklisted) {
foundBlack = true;
break;
}
}
QVERIFY(foundBlack);
errors.clear();
// This one is expired and untrusted
toVerify = QSslCertificate::fromPath(SRCDIR "more-certificates/cert-large-serial-number.pem");
errors = QSslCertificate::verify(toVerify);
QVERIFY(errors.contains(QSslError(QSslError::SelfSignedCertificate, toVerify[0])));
QVERIFY(errors.contains(QSslError(QSslError::CertificateExpired, toVerify[0])));
errors.clear();
toVerify.clear();
// This one is signed by a valid cert, but the signer is not a valid CA
toVerify << QSslCertificate::fromPath(SRCDIR "verify-certs/test-intermediate-not-ca-cert.pem").first();
toVerify << QSslCertificate::fromPath(SRCDIR "verify-certs/test-ocsp-good-cert.pem").first();
errors = QSslCertificate::verify(toVerify);
QVERIFY(errors.contains(QSslError(QSslError::InvalidCaCertificate, toVerify[1])));
toVerify.clear();
// This one is signed by a valid cert, and the signer is a valid CA
toVerify << QSslCertificate::fromPath(SRCDIR "verify-certs/test-intermediate-is-ca-cert.pem").first();
toVerify << QSslCertificate::fromPath(SRCDIR "verify-certs/test-intermediate-ca-cert.pem").first();
errors = QSslCertificate::verify(toVerify);
QVERIFY(errors.length() == 0);
// Recheck the above with hostname validation
errors = QSslCertificate::verify(toVerify, QLatin1String("example.com"));
QVERIFY(errors.length() == 0);
// Recheck the above with a bad hostname
errors = QSslCertificate::verify(toVerify, QLatin1String("fail.example.com"));
QVERIFY(errors.contains(QSslError(QSslError::HostNameMismatch, toVerify[0])));
toVerify.clear();
}
#endif // QT_NO_OPENSSL
QTEST_MAIN(tst_QSslCertificate)

View File

@ -0,0 +1,2 @@
openssl verify -CAfile cacert.pem -untrusted test-intermediate-ca-cert.pem test-intermediate-is-ca-cert.pem
openssl verify -CAfile cacert.pem -untrusted test-ocsp-good-cert.pem test-intermediate-not-ca-cert.pem

View File

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID6zCCAtOgAwIBAgIJALIOhqebAhS9MA0GCSqGSIb3DQEBBQUAMIGrMSYwJAYD
VQQDEx1XZXN0cG9pbnQgQ2VydGlmaWNhdGUgVGVzdCBDQTETMBEGA1UECBMKTGFu
Y2FzaGlyZTELMAkGA1UEBhMCVUsxHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUu
Y29tMUAwPgYDVQQKEzdXZXN0cG9pbnQgQ2VydGlmaWNhdGUgVGVzdCBSb290IENl
cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTExMDYyNjE5MzYzOVoXDTExMDcyNjE5
MzYzOVowgasxJjAkBgNVBAMTHVdlc3Rwb2ludCBDZXJ0aWZpY2F0ZSBUZXN0IENB
MRMwEQYDVQQIEwpMYW5jYXNoaXJlMQswCQYDVQQGEwJVSzEdMBsGCSqGSIb3DQEJ
ARYOY2FAZXhhbXBsZS5jb20xQDA+BgNVBAoTN1dlc3Rwb2ludCBDZXJ0aWZpY2F0
ZSBUZXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQCoP3znXuxcIAWkyu51aPWwXYX0kSPnBO1gcJj6
xQa4ycOHv9Cs9XTVTGvpj4aoc6lP+6/jUe14cVCR7018zHRe7u5g4ozO1aZqISqS
Y4hdWkTSFPmFoiyXkACl0ZGwcfv6QdFhNnK4COBrff4D6lndfQUZu8CnRYxlKGuR
1vGiUcJ88t0dDmMEFEdYNtlDnYlxXHbTS4VdRb2u3EGFzV24ENJwgqYuFrBAG/+N
TRXahWMsdfP0whCYJOsaNBwXaoeoxGlYz35gMU8A8AFmYOJLohsWqHcHmMV3X6hn
aKGnL3nOa8zlNKNr948Dwenucaggf5KquDCHVf2Ms+ROxlfTAgMBAAGjEDAOMAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGmY4+AeMyx+FkpPxeNY3DAH
Jys0WfndLZFABARYfKdJE1dqQi3uXaRkKMkV7npb46cw92jmwFT+v9rHd88UmgMs
KGJNWjARD6Ai1dzenMNYBJz9GFkDJ0Pr4Gqj2tR9JuzEOdxss+nZ4r6vhC+/yeAB
4jGT4QMuYU+14Rfsv5Aw0HjbcH955zTy1pJ6ck9OWWyzET8ALxz+RTFOok/4r4++
yhE5Hh8+2aE52AcZqKa4hKXdVBCb9oewl93h3rmYcA/Yz36w+GRkSnOPZUgDDL5D
HKnICDidtf9ZZBZ4iJxaBg4iCraeuei20V+0g+9/1aoIWJ5TrelVYVCx8O0x+E0=
-----END CERTIFICATE-----

View File

@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
MIIF+DCCBOCgAwIBAgIRAJI51TSPQNFpWnRUcOHyP0MwDQYJKoZIhvcNAQEFBQAw
gZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtl
IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMY
aHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR8wHQYDVQQDExZVVE4tVVNFUkZpcnN0
LUhhcmR3YXJlMB4XDTExMDMxNTAwMDAwMFoXDTE0MDMxNDIzNTk1OVowgeIxCzAJ
BgNVBAYTAlVTMQ4wDAYDVQQREwUzODQ3NzEQMA4GA1UECBMHRmxvcmlkYTEQMA4G
A1UEBxMHRW5nbGlzaDEXMBUGA1UECRMOU2VhIFZpbGxhZ2UgMTAxFDASBgNVBAoT
C0dvb2dsZSBMdGQuMRMwEQYDVQQLEwpUZWNoIERlcHQuMSgwJgYDVQQLEx9Ib3N0
ZWQgYnkgR1RJIEdyb3VwIENvcnBvcmF0aW9uMRQwEgYDVQQLEwtQbGF0aW51bVNT
TDEbMBkGA1UEAxMSYWRkb25zLm1vemlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAq8ZtNvMVc3iDc850hdWu7LLw4CQfE4O4IKy7mv6Iu6uh
HQsfRQCqSbc1Nwxq70dMudG+41cSBI2Sx7bsAby22seBOCCtcoXmDvyBbAetaHY4
xUTXzMZKxZc+ZPRR5vB+suxW9yWCTUmYyxaY3SPxiZHRF5dAmSbW4qIrXt+9ifIb
GlMtzFBBetA9KgxVcBQB6VhJEHoLk4KL4R7tOoAQgs6WijTwzNfTubRQh1VUCbid
QihVAOWMNVS/3SWRRrcN5V2DqOWL+4TkPK522sRDK1t0C/i+XWjxeFu1zn3xXZlA
2sruOIFQvpihbLgkrfOvjA/XESgshBhMfbXZjzC1GwIDAQABo4IB8DCCAewwHwYD
VR0jBBgwFoAUoXJfJhsomEOVXQc31YWWnUvSw0UwHQYDVR0OBBYEFN2A0lQ990xw
yqOw3TR6MuToO1o7MA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1Ud
JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBGBgNVHSAEPzA9MDsGDCsGAQQBsjEB
AgEDBDArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQ
UzB7BgNVHR8EdDByMDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9VVE4t
VVNFUkZpcnN0LUhhcmR3YXJlLmNybDA2oDSgMoYwaHR0cDovL2NybC5jb21vZG8u
bmV0L1VUTi1VU0VSRmlyc3QtSGFyZHdhcmUuY3JsMHEGCCsGAQUFBwEBBGUwYzA7
BggrBgEFBQcwAoYvaHR0cDovL2NydC5jb21vZG9jYS5jb20vVVROQWRkVHJ1c3RT
ZXJ2ZXJDQS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNv
bTA1BgNVHREELjAsghJhZGRvbnMubW96aWxsYS5vcmeCFnd3dy5hZGRvbnMubW96
aWxsYS5vcmcwDQYJKoZIhvcNAQEFBQADggEBADM7YxX8sewULJPddZTegVrZTpm+
+0qkOVVNoUB63hMqh6k3z+jV+63Re21vjCCHglTmV0m8ICiEzdYB2ZOLF24jZuWE
yIA/xqFwgOTsTR35/JFac2IpmvcgHGHgizmfyrx+jd282bHjn57fFVORIVIL2Roj
D2Y226yTlkqjpSLPKfeimaj2ttlArtl+tvZYLpusNspkj2VS3IacgqtuUEvaX/oF
AIgwDt6NVr+BR409BuKyYpJnj57ImrLlBrhwJLh3fCMKOMN5CNixUZ2slRHHQBee
oxyP8hGnaCfaSQWEGHxYLQFnXOWfoSm7SjlFL78Rqnmi7bTUtWVDt5NGitM=
-----END CERTIFICATE-----

View File

@ -0,0 +1,66 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 28 (0x1c)
Signature Algorithm: sha1WithRSAEncryption
Issuer: CN=Westpoint Certificate Test CA, ST=Lancashire, C=UK/emailAddress=ca@example.com, O=Westpoint Certificate Test Root Certification Authority
Validity
Not Before: Jun 26 19:36:42 2011 GMT
Not After : Jun 23 19:36:42 2021 GMT
Subject: ST=Lancashire, C=UK/emailAddress=test@example.com, O=Test intermediate CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:a7:ed:3f:86:ee:ad:f8:b7:60:44:63:fc:1b:2c:
79:3c:90:8b:47:b8:51:b5:3e:96:6d:5d:f1:97:b3:
de:90:b2:9a:aa:9e:54:7e:2b:b1:6d:91:ae:20:29:
b6:69:7b:8a:e5:6c:41:10:b6:d3:73:4c:20:30:38:
57:c9:c8:ef:67:7e:76:39:c4:1c:df:6b:73:4e:2b:
21:2d:79:5a:c5:60:5e:85:11:52:3b:8e:ef:b0:e5:
2f:0c:e8:a3:fc:05:27:91:08:64:ea:2e:5a:f2:82:
0c:08:48:bc:bc:ca:60:02:1c:6a:38:eb:c8:02:a6:
f7:e8:c8:31:20:29:e6:e4:8d
Exponent: 65537 (0x10001)
X509v3 extensions:
Authority Information Access:
OCSP - URI:http://ocsp.example.com:8888/
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: sha1WithRSAEncryption
94:1a:91:6a:05:41:0c:40:f9:46:35:e9:46:15:f1:3e:e4:d9:
50:d6:0e:14:d8:1f:85:9e:a6:98:a2:db:db:ee:ff:56:55:6c:
46:fd:0e:b0:03:79:a6:96:0f:c1:85:c3:3e:68:e0:17:10:a6:
9c:10:34:88:96:f7:c8:ef:32:31:24:f4:3c:2d:eb:51:08:d6:
87:83:f7:db:68:43:ed:d9:af:46:a2:48:74:d2:9d:c9:af:0f:
29:42:ad:a2:cf:1e:ab:50:6f:ef:33:18:d3:07:ef:13:13:10:
50:db:a9:56:db:f4:38:c1:db:05:fa:5a:67:92:72:69:fb:7a:
5b:ec:d4:dd:fd:a2:21:06:59:b0:0d:48:5f:53:c1:65:94:aa:
d4:4e:1c:e8:9f:b4:7d:9b:10:85:4a:b6:be:df:d8:33:b5:72:
b0:ac:46:a9:67:55:1e:3e:58:a5:52:ed:b6:4a:cb:e9:d2:e5:
f8:fe:56:b4:2c:5e:9f:3c:d1:7f:b4:eb:05:8d:46:1f:47:32:
2b:4f:2e:ac:8d:c3:3c:eb:f1:0c:2f:3a:e0:fa:46:0b:e4:c5:
f2:03:24:70:fc:ef:1a:fd:7b:a9:9c:d9:b6:4f:0e:74:07:52:
23:eb:cd:66:61:67:a1:91:7f:76:a2:9d:42:54:d4:c6:5e:10:
26:eb:37:e7
-----BEGIN CERTIFICATE-----
MIIDUDCCAjigAwIBAgIBHDANBgkqhkiG9w0BAQUFADCBqzEmMCQGA1UEAxMdV2Vz
dHBvaW50IENlcnRpZmljYXRlIFRlc3QgQ0ExEzARBgNVBAgTCkxhbmNhc2hpcmUx
CzAJBgNVBAYTAlVLMR0wGwYJKoZIhvcNAQkBFg5jYUBleGFtcGxlLmNvbTFAMD4G
A1UEChM3V2VzdHBvaW50IENlcnRpZmljYXRlIFRlc3QgUm9vdCBDZXJ0aWZpY2F0
aW9uIEF1dGhvcml0eTAeFw0xMTA2MjYxOTM2NDJaFw0yMTA2MjMxOTM2NDJaMGIx
EzARBgNVBAgTCkxhbmNhc2hpcmUxCzAJBgNVBAYTAlVLMR8wHQYJKoZIhvcNAQkB
FhB0ZXN0QGV4YW1wbGUuY29tMR0wGwYDVQQKExRUZXN0IGludGVybWVkaWF0ZSBD
QTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAp+0/hu6t+LdgRGP8Gyx5PJCL
R7hRtT6WbV3xl7PekLKaqp5UfiuxbZGuICm2aXuK5WxBELbTc0wgMDhXycjvZ352
OcQc32tzTishLXlaxWBehRFSO47vsOUvDOij/AUnkQhk6i5a8oIMCEi8vMpgAhxq
OOvIAqb36MgxICnm5I0CAwEAAaNLMEkwOQYIKwYBBQUHAQEELTArMCkGCCsGAQUF
BzABhh1odHRwOi8vb2NzcC5leGFtcGxlLmNvbTo4ODg4LzAMBgNVHRMEBTADAQH/
MA0GCSqGSIb3DQEBBQUAA4IBAQCUGpFqBUEMQPlGNelGFfE+5NlQ1g4U2B+FnqaY
otvb7v9WVWxG/Q6wA3mmlg/BhcM+aOAXEKacEDSIlvfI7zIxJPQ8LetRCNaHg/fb
aEPt2a9Gokh00p3Jrw8pQq2izx6rUG/vMxjTB+8TExBQ26lW2/Q4wdsF+lpnknJp
+3pb7NTd/aIhBlmwDUhfU8FllKrUThzon7R9mxCFSra+39gztXKwrEapZ1UePlil
Uu22Ssvp0uX4/la0LF6fPNF/tOsFjUYfRzIrTy6sjcM86/EMLzrg+kYL5MXyAyRw
/O8a/XupnNm2Tw50B1Ij681mYWehkX92op1CVNTGXhAm6zfn
-----END CERTIFICATE-----

View File

@ -0,0 +1,53 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 29 (0x1d)
Signature Algorithm: sha1WithRSAEncryption
Issuer: ST=Lancashire, C=UK/emailAddress=test@example.com, O=Test intermediate CA
Validity
Not Before: Jun 26 19:36:42 2011 GMT
Not After : Jun 23 19:36:42 2021 GMT
Subject: CN=example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:ba:f2:dc:f9:77:b0:ad:fd:9d:42:4f:22:15:6d:
87:40:ed:30:8a:04:ad:ac:7a:0b:d4:7a:a4:a7:ef:
e0:e7:9b:f2:5e:62:56:24:ed:88:bd:bd:e3:64:d2:
d4:b4:01:39:b8:9e:6f:c7:b0:fc:b9:fd:a8:4d:46:
c8:9e:6a:43:82:ca:56:83:d4:4b:ea:63:d5:56:d1:
99:46:4f:8b:28:d0:2f:db:bf:04:65:64:82:c2:61:
aa:66:50:27:e5:7a:57:e3:72:e3:ae:22:8d:92:7e:
25:90:a2:7c:0c:04:79:c5:ab:64:58:a9:83:79:67:
7f:72:33:cc:5f:5b:cd:74:bb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Authority Information Access:
OCSP - URI:http://ocsp.example.com:8888/
Signature Algorithm: sha1WithRSAEncryption
19:e8:ce:9d:4d:ef:cc:4f:6c:e5:ab:df:aa:e2:3c:d8:6b:a8:
dd:b8:fa:50:e4:b6:04:fc:66:92:fb:e8:11:73:81:60:1a:88:
b2:18:0b:8c:89:05:47:16:50:09:be:bc:a6:3c:fe:2e:45:01:
00:e3:27:30:72:f6:93:49:7f:d0:3b:a8:0e:cb:e7:01:95:28:
8b:40:95:f7:b1:5b:c9:ff:26:ff:ad:4a:c4:e4:99:f7:65:fc:
e4:5e:d2:56:ea:98:42:dc:93:62:46:1a:33:53:0d:43:9d:ef:
14:03:35:a7:13:fa:27:24:92:2f:9a:f9:0a:62:99:cc:c0:80:
79:10
-----BEGIN CERTIFICATE-----
MIICNjCCAZ+gAwIBAgIBHTANBgkqhkiG9w0BAQUFADBiMRMwEQYDVQQIEwpMYW5j
YXNoaXJlMQswCQYDVQQGEwJVSzEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxl
LmNvbTEdMBsGA1UEChMUVGVzdCBpbnRlcm1lZGlhdGUgQ0EwHhcNMTEwNjI2MTkz
NjQyWhcNMjEwNjIzMTkzNjQyWjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCBnzAN
BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuvLc+Xewrf2dQk8iFW2HQO0wigStrHoL
1Hqkp+/g55vyXmJWJO2Ivb3jZNLUtAE5uJ5vx7D8uf2oTUbInmpDgspWg9RL6mPV
VtGZRk+LKNAv278EZWSCwmGqZlAn5XpX43LjriKNkn4lkKJ8DAR5xatkWKmDeWd/
cjPMX1vNdLsCAwEAAaNIMEYwCQYDVR0TBAIwADA5BggrBgEFBQcBAQQtMCswKQYI
KwYBBQUHMAGGHWh0dHA6Ly9vY3NwLmV4YW1wbGUuY29tOjg4ODgvMA0GCSqGSIb3
DQEBBQUAA4GBABnozp1N78xPbOWr36riPNhrqN24+lDktgT8ZpL76BFzgWAaiLIY
C4yJBUcWUAm+vKY8/i5FAQDjJzBy9pNJf9A7qA7L5wGVKItAlfexW8n/Jv+tSsTk
mfdl/ORe0lbqmELck2JGGjNTDUOd7xQDNacT+ickki+a+QpimczAgHkQ
-----END CERTIFICATE-----

View File

@ -0,0 +1,54 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 27 (0x1b)
Signature Algorithm: sha1WithRSAEncryption
Issuer: CN=example.com, ST=Lancashire, C=UK/emailAddress=test@example.com, O=Some organisation
Validity
Not Before: Jun 26 19:36:42 2011 GMT
Not After : Jun 23 19:36:42 2021 GMT
Subject: CN=example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:d7:b6:a8:07:83:27:b8:72:da:85:ad:50:bf:c2:
3f:cc:d4:e7:97:55:b5:45:aa:d2:cb:df:b6:34:6f:
c2:8f:86:e2:15:8a:cd:3e:af:f5:c0:f9:2e:61:80:
70:17:d3:db:0f:8a:e6:2c:a8:e3:12:2d:92:e1:8d:
10:e0:e7:30:94:98:ec:b0:21:c3:86:f7:ff:29:58:
2b:ab:b1:23:e4:ca:66:66:6a:18:b5:73:dc:c7:44:
04:30:55:bf:f9:3b:74:f6:de:bd:d9:ef:46:b0:15:
56:3b:43:cc:55:c2:cc:2e:5d:17:f8:04:dc:3d:bf:
1b:cc:0a:41:61:c8:35:02:1b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Authority Information Access:
OCSP - URI:http://ocsp.example.com:8888/
Signature Algorithm: sha1WithRSAEncryption
18:e2:06:f3:4b:42:46:b6:29:d1:8d:50:ef:5b:8b:e5:33:24:
f3:f1:3e:58:4d:7f:3e:51:e9:c4:a2:cb:64:5f:d1:51:ce:8d:
b6:15:63:23:30:4b:7c:70:30:61:ce:1f:70:bb:99:63:5b:15:
d9:ce:aa:da:65:87:66:ab:ad:64:e8:09:37:ea:79:d0:3a:a2:
e0:cf:0b:1b:a7:35:3d:f8:45:4c:4b:96:15:ec:fe:64:9f:e0:
1d:04:52:35:a1:b4:7e:31:34:84:7e:e6:e0:58:1e:14:02:df:
68:f6:b6:eb:dc:10:eb:da:fe:8e:06:ab:52:b7:ca:15:c3:8d:
5a:8a
-----BEGIN CERTIFICATE-----
MIICSTCCAbKgAwIBAgIBGzANBgkqhkiG9w0BAQUFADB1MRQwEgYDVQQDEwtleGFt
cGxlLmNvbTETMBEGA1UECBMKTGFuY2FzaGlyZTELMAkGA1UEBhMCVUsxHzAdBgkq
hkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20xGjAYBgNVBAoTEVNvbWUgb3JnYW5p
c2F0aW9uMB4XDTExMDYyNjE5MzY0MloXDTIxMDYyMzE5MzY0MlowFjEUMBIGA1UE
AxMLZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANe2qAeD
J7hy2oWtUL/CP8zU55dVtUWq0svftjRvwo+G4hWKzT6v9cD5LmGAcBfT2w+K5iyo
4xItkuGNEODnMJSY7LAhw4b3/ylYK6uxI+TKZmZqGLVz3MdEBDBVv/k7dPbevdnv
RrAVVjtDzFXCzC5dF/gE3D2/G8wKQWHINQIbAgMBAAGjSDBGMAkGA1UdEwQCMAAw
OQYIKwYBBQUHAQEELTArMCkGCCsGAQUFBzABhh1odHRwOi8vb2NzcC5leGFtcGxl
LmNvbTo4ODg4LzANBgkqhkiG9w0BAQUFAAOBgQAY4gbzS0JGtinRjVDvW4vlMyTz
8T5YTX8+UenEostkX9FRzo22FWMjMEt8cDBhzh9wu5ljWxXZzqraZYdmq61k6Ak3
6nnQOqLgzwsbpzU9+EVMS5YV7P5kn+AdBFI1obR+MTSEfubgWB4UAt9o9rbr3BDr
2v6OBqtSt8oVw41aig==
-----END CERTIFICATE-----

View File

@ -0,0 +1,67 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: sha1WithRSAEncryption
Issuer: CN=Westpoint Certificate Test CA, ST=Lancashire, C=UK/emailAddress=ca@example.com, O=Westpoint Certificate Test Root Certification Authority
Validity
Not Before: Jun 26 19:36:39 2011 GMT
Not After : Jun 23 19:36:39 2021 GMT
Subject: CN=example.com, ST=Lancashire, C=UK/emailAddress=test@example.com, O=Some organisation
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:c7:d8:d4:a7:c0:a0:e7:82:b4:ec:67:52:bf:50:
bf:b9:a6:f2:10:19:67:53:8c:99:5e:c8:fc:03:07:
71:24:a3:a9:c4:49:f8:15:34:4a:45:ee:92:81:aa:
3c:5a:1a:42:2b:db:d7:30:9e:85:e6:b8:74:bc:ae:
f0:ae:7d:05:4e:c9:0f:00:33:b2:86:ba:b6:49:9a:
07:18:92:f9:35:69:d2:ac:39:b9:85:ac:78:99:81:
06:f5:fa:2e:5b:18:f7:6a:16:d0:e6:f9:71:0f:b0:
05:c4:f0:5f:ed:90:81:3c:96:f5:e3:45:73:72:5f:
ce:dc:ce:0b:56:2e:be:d2:eb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Authority Information Access:
OCSP - URI:http://ocsp.example.com:8888/
Signature Algorithm: sha1WithRSAEncryption
76:84:40:52:b8:1d:6c:64:58:f1:10:30:03:db:16:91:da:b1:
70:28:54:6f:0f:32:1c:84:65:b3:14:99:c6:59:f9:ec:f9:3f:
46:1f:12:77:4e:f1:26:ad:46:4b:ee:48:78:bd:bf:2a:11:01:
5b:02:cd:d2:6e:2d:8c:08:ea:a7:5a:18:16:71:e8:5d:c8:e7:
7d:f2:4f:23:6c:59:3c:17:93:02:60:c0:d0:62:09:d2:a3:7d:
90:77:6c:f7:0c:b2:e4:9e:73:d2:f8:dd:a3:0c:70:36:2f:5a:
58:2b:2d:3e:0e:71:43:b2:14:00:e2:eb:2d:0e:09:91:47:83:
e8:02:d4:7d:5c:1f:ce:d8:f5:ad:1f:ee:82:4f:23:47:db:f4:
71:48:1b:e1:82:f1:d1:86:db:0f:b6:bb:3a:8f:40:05:48:b7:
f2:a8:c7:c9:46:e1:ea:28:b2:02:00:90:04:00:19:32:6f:8d:
3e:c2:67:ca:b0:80:3a:32:e3:35:92:18:a2:62:30:9d:7a:f5:
13:3b:c7:00:3f:4e:17:a9:01:5d:a1:2c:71:76:d7:37:c8:16:
92:f8:82:69:15:5f:7d:5e:b0:ba:0b:9f:bd:53:ad:e5:a6:b3:
bc:6b:e4:1a:79:29:31:ff:ff:a1:2d:0b:30:46:d3:a5:2d:62:
e6:be:68:df
-----BEGIN CERTIFICATE-----
MIIDYDCCAkigAwIBAgIBATANBgkqhkiG9w0BAQUFADCBqzEmMCQGA1UEAxMdV2Vz
dHBvaW50IENlcnRpZmljYXRlIFRlc3QgQ0ExEzARBgNVBAgTCkxhbmNhc2hpcmUx
CzAJBgNVBAYTAlVLMR0wGwYJKoZIhvcNAQkBFg5jYUBleGFtcGxlLmNvbTFAMD4G
A1UEChM3V2VzdHBvaW50IENlcnRpZmljYXRlIFRlc3QgUm9vdCBDZXJ0aWZpY2F0
aW9uIEF1dGhvcml0eTAeFw0xMTA2MjYxOTM2MzlaFw0yMTA2MjMxOTM2MzlaMHUx
FDASBgNVBAMTC2V4YW1wbGUuY29tMRMwEQYDVQQIEwpMYW5jYXNoaXJlMQswCQYD
VQQGEwJVSzEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbTEaMBgGA1UE
ChMRU29tZSBvcmdhbmlzYXRpb24wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
AMfY1KfAoOeCtOxnUr9Qv7mm8hAZZ1OMmV7I/AMHcSSjqcRJ+BU0SkXukoGqPFoa
Qivb1zCehea4dLyu8K59BU7JDwAzsoa6tkmaBxiS+TVp0qw5uYWseJmBBvX6LlsY
92oW0Ob5cQ+wBcTwX+2QgTyW9eNFc3JfztzOC1YuvtLrAgMBAAGjSDBGMAkGA1Ud
EwQCMAAwOQYIKwYBBQUHAQEELTArMCkGCCsGAQUFBzABhh1odHRwOi8vb2NzcC5l
eGFtcGxlLmNvbTo4ODg4LzANBgkqhkiG9w0BAQUFAAOCAQEAdoRAUrgdbGRY8RAw
A9sWkdqxcChUbw8yHIRlsxSZxln57Pk/Rh8Sd07xJq1GS+5IeL2/KhEBWwLN0m4t
jAjqp1oYFnHoXcjnffJPI2xZPBeTAmDA0GIJ0qN9kHds9wyy5J5z0vjdowxwNi9a
WCstPg5xQ7IUAOLrLQ4JkUeD6ALUfVwfztj1rR/ugk8jR9v0cUgb4YLx0YbbD7a7
Oo9ABUi38qjHyUbh6iiyAgCQBAAZMm+NPsJnyrCAOjLjNZIYomIwnXr1EzvHAD9O
F6kBXaEscXbXN8gWkviCaRVffV6wugufvVOt5aazvGvkGnkpMf//oS0LMEbTpS1i
5r5o3w==
-----END CERTIFICATE-----