Namespace the bundled zlib symbols, to avoid clash with user zlib

When Qt is being compiled and is using the bundled zlib, QtCore needs
to export the zlib symbols, since zlib is needed in other Qt
libraries as well. That gives a danger of a potentially disastrous
symbol clash if the user later on links with both Qt and an external
zlib (ref. e.g. QTBUG-15071).

This commit enables a zlib compilation flag that causes all zlib
symbols to be redefined with a prefix. Hence, they will not clash
with a standard zlib.

A minor drawback is that zlib.h will now have #defines for a few
semi-normal identifiers. Hence, a couple of more changes are done:
In the private qzip code, the identifer crc32 had to be renamed.
QHttpNetworkReplyPrivate needed no change, but as a defensive measure
the #include <zlib.h> is moved from the _p.h file to the .cpp file,
to avoid surprising compilation errors later in code that include
that header.

This commit does not in itself solve the issue of how to let Qt
libraries outside of qtbase use the same bundled zlib, but it is
a prerequisite for that.

Change-Id: If84105901a8c90d35009faffe660c85a6bd2fee5
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
aavit 2012-06-06 15:16:49 +02:00 committed by Qt by Nokia
parent 02191b6e4b
commit 1f461ac45b
5 changed files with 59 additions and 39 deletions

View File

@ -8,6 +8,9 @@
#ifndef ZCONF_H #ifndef ZCONF_H
#define ZCONF_H #define ZCONF_H
/* Since QtCore must export these symbols, define Z_PREFIX to avoid clashes system zlib */
#define Z_PREFIX
/* /*
* If you *really* need a unique prefix for all types and library functions, * If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.

View File

@ -358,7 +358,7 @@ struct FileHeader
}; };
QZipReader::FileInfo::FileInfo() QZipReader::FileInfo::FileInfo()
: isDir(false), isFile(false), isSymLink(false), crc32(0), size(0) : isDir(false), isFile(false), isSymLink(false), crc(0), size(0)
{ {
} }
@ -378,7 +378,7 @@ QZipReader::FileInfo& QZipReader::FileInfo::operator=(const FileInfo &other)
isFile = other.isFile; isFile = other.isFile;
isSymLink = other.isSymLink; isSymLink = other.isSymLink;
permissions = other.permissions; permissions = other.permissions;
crc32 = other.crc32; crc = other.crc;
size = other.size; size = other.size;
lastModified = other.lastModified; lastModified = other.lastModified;
return *this; return *this;
@ -424,7 +424,7 @@ void QZipPrivate::fillFileInfo(int index, QZipReader::FileInfo &fileInfo) const
fileInfo.isFile = S_ISREG(mode); fileInfo.isFile = S_ISREG(mode);
fileInfo.isSymLink = S_ISLNK(mode); fileInfo.isSymLink = S_ISLNK(mode);
fileInfo.permissions = modeToPermissions(mode); fileInfo.permissions = modeToPermissions(mode);
fileInfo.crc32 = readUInt(header.h.crc_32); fileInfo.crc = readUInt(header.h.crc_32);
fileInfo.size = readUInt(header.h.uncompressed_size); fileInfo.size = readUInt(header.h.uncompressed_size);
fileInfo.lastModified = readMSDosDate(header.h.last_mod_file); fileInfo.lastModified = readMSDosDate(header.h.last_mod_file);
} }
@ -701,8 +701,8 @@ void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const
*/ */
/*! /*!
\variable FileInfo::crc32 \variable FileInfo::crc
The calculated checksum as a crc32 type. The calculated checksum as a crc type.
*/ */
/*! /*!

View File

@ -88,7 +88,7 @@ public:
uint isFile : 1; uint isFile : 1;
uint isSymLink : 1; uint isSymLink : 1;
QFile::Permissions permissions; QFile::Permissions permissions;
uint crc32; uint crc;
qint64 size; qint64 size;
QDateTime lastModified; QDateTime lastModified;
void *d; void *d;

View File

@ -52,6 +52,10 @@
# include <QtNetwork/qsslconfiguration.h> # include <QtNetwork/qsslconfiguration.h>
#endif #endif
#ifndef QT_NO_COMPRESS
#include <zlib.h>
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QHttpNetworkReply::QHttpNetworkReply(const QUrl &url, QObject *parent) QHttpNetworkReply::QHttpNetworkReply(const QUrl &url, QObject *parent)
@ -67,8 +71,8 @@ QHttpNetworkReply::~QHttpNetworkReply()
} }
#ifndef QT_NO_COMPRESS #ifndef QT_NO_COMPRESS
if (d->autoDecompress && d->isCompressed()) if (d->autoDecompress && d->isCompressed() && d->inflateStrm)
inflateEnd(&d->inflateStrm); inflateEnd(d->inflateStrm);
#endif #endif
} }
@ -281,11 +285,19 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
autoDecompress(false), responseData(), requestIsPrepared(false) autoDecompress(false), responseData(), requestIsPrepared(false)
,pipeliningUsed(false), downstreamLimited(false) ,pipeliningUsed(false), downstreamLimited(false)
,userProvidedDownloadBuffer(0) ,userProvidedDownloadBuffer(0)
#ifndef QT_NO_COMPRESS
,inflateStrm(0)
#endif
{ {
} }
QHttpNetworkReplyPrivate::~QHttpNetworkReplyPrivate() QHttpNetworkReplyPrivate::~QHttpNetworkReplyPrivate()
{ {
#ifndef QT_NO_COMPRESS
if (inflateStrm)
delete inflateStrm;
#endif
} }
void QHttpNetworkReplyPrivate::clearHttpLayerInformation() void QHttpNetworkReplyPrivate::clearHttpLayerInformation()
@ -300,8 +312,8 @@ void QHttpNetworkReplyPrivate::clearHttpLayerInformation()
lastChunkRead = false; lastChunkRead = false;
connectionCloseEnabled = true; connectionCloseEnabled = true;
#ifndef QT_NO_COMPRESS #ifndef QT_NO_COMPRESS
if (autoDecompress) if (autoDecompress && inflateStrm)
inflateEnd(&inflateStrm); inflateEnd(inflateStrm);
#endif #endif
fields.clear(); fields.clear();
} }
@ -530,15 +542,17 @@ qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket)
#ifndef QT_NO_COMPRESS #ifndef QT_NO_COMPRESS
if (autoDecompress && isCompressed()) { if (autoDecompress && isCompressed()) {
// allocate inflate state // allocate inflate state
inflateStrm.zalloc = Z_NULL; if (!inflateStrm)
inflateStrm.zfree = Z_NULL; inflateStrm = new z_stream;
inflateStrm.opaque = Z_NULL; inflateStrm->zalloc = Z_NULL;
inflateStrm.avail_in = 0; inflateStrm->zfree = Z_NULL;
inflateStrm.next_in = 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. // "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" // Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection"
// http://www.zlib.net/manual.html // http://www.zlib.net/manual.html
int ret = inflateInit2(&inflateStrm, MAX_WBITS+32); int ret = inflateInit2(inflateStrm, MAX_WBITS+32);
if (ret != Z_OK) if (ret != Z_OK)
return -1; return -1;
} }
@ -685,47 +699,50 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QByteDataBuff
#ifndef QT_NO_COMPRESS #ifndef QT_NO_COMPRESS
qint64 QHttpNetworkReplyPrivate::uncompressBodyData(QByteDataBuffer *in, QByteDataBuffer *out) qint64 QHttpNetworkReplyPrivate::uncompressBodyData(QByteDataBuffer *in, QByteDataBuffer *out)
{ {
if (!inflateStrm)
return -1;
bool triedRawDeflate = false; bool triedRawDeflate = false;
for (int i = 0; i < in->bufferCount(); i++) { for (int i = 0; i < in->bufferCount(); i++) {
QByteArray &bIn = (*in)[i]; QByteArray &bIn = (*in)[i];
inflateStrm.avail_in = bIn.size(); inflateStrm->avail_in = bIn.size();
inflateStrm.next_in = reinterpret_cast<Bytef*>(bIn.data()); inflateStrm->next_in = reinterpret_cast<Bytef*>(bIn.data());
do { do {
QByteArray bOut; QByteArray bOut;
// make a wild guess about the uncompressed size. // make a wild guess about the uncompressed size.
bOut.reserve(inflateStrm.avail_in * 3 + 512); bOut.reserve(inflateStrm->avail_in * 3 + 512);
inflateStrm.avail_out = bOut.capacity(); inflateStrm->avail_out = bOut.capacity();
inflateStrm.next_out = reinterpret_cast<Bytef*>(bOut.data()); inflateStrm->next_out = reinterpret_cast<Bytef*>(bOut.data());
int ret = inflate(&inflateStrm, Z_NO_FLUSH); int ret = inflate(inflateStrm, Z_NO_FLUSH);
//All negative return codes are errors, in the context of HTTP compression, Z_NEED_DICT is also an error. //All negative return codes are errors, in the context of HTTP compression, Z_NEED_DICT is also an error.
// in the case where we get Z_DATA_ERROR this could be because we recieved raw deflate compressed data. // in the case where we get Z_DATA_ERROR this could be because we recieved raw deflate compressed data.
if (ret == Z_DATA_ERROR && !triedRawDeflate) { if (ret == Z_DATA_ERROR && !triedRawDeflate) {
inflateEnd(&inflateStrm); inflateEnd(inflateStrm);
triedRawDeflate = true; triedRawDeflate = true;
inflateStrm.zalloc = Z_NULL; inflateStrm->zalloc = Z_NULL;
inflateStrm.zfree = Z_NULL; inflateStrm->zfree = Z_NULL;
inflateStrm.opaque = Z_NULL; inflateStrm->opaque = Z_NULL;
inflateStrm.avail_in = 0; inflateStrm->avail_in = 0;
inflateStrm.next_in = Z_NULL; inflateStrm->next_in = Z_NULL;
int ret = inflateInit2(&inflateStrm, -MAX_WBITS); int ret = inflateInit2(inflateStrm, -MAX_WBITS);
if (ret != Z_OK) { if (ret != Z_OK) {
return -1; return -1;
} else { } else {
inflateStrm.avail_in = bIn.size(); inflateStrm->avail_in = bIn.size();
inflateStrm.next_in = reinterpret_cast<Bytef*>(bIn.data()); inflateStrm->next_in = reinterpret_cast<Bytef*>(bIn.data());
continue; continue;
} }
} else if (ret < 0 || ret == Z_NEED_DICT) { } else if (ret < 0 || ret == Z_NEED_DICT) {
return -1; return -1;
} }
bOut.resize(bOut.capacity() - inflateStrm.avail_out); bOut.resize(bOut.capacity() - inflateStrm->avail_out);
out->append(bOut); out->append(bOut);
if (ret == Z_STREAM_END) if (ret == Z_STREAM_END)
return out->byteAmount(); return out->byteAmount();
} while (inflateStrm.avail_in > 0); } while (inflateStrm->avail_in > 0);
} }
return out->byteAmount(); return out->byteAmount();

View File

@ -56,7 +56,7 @@
#ifndef QT_NO_HTTP #ifndef QT_NO_HTTP
#ifndef QT_NO_COMPRESS #ifndef QT_NO_COMPRESS
#include <zlib.h> struct z_stream_s;
#endif #endif
#include <QtNetwork/qtcpsocket.h> #include <QtNetwork/qtcpsocket.h>
@ -227,11 +227,6 @@ public:
QPointer<QHttpNetworkConnection> connection; QPointer<QHttpNetworkConnection> connection;
QPointer<QHttpNetworkConnectionChannel> connectionChannel; QPointer<QHttpNetworkConnectionChannel> connectionChannel;
#ifndef QT_NO_COMPRESS
z_stream inflateStrm;
qint64 uncompressBodyData(QByteDataBuffer *in, QByteDataBuffer *out);
#endif
bool autoDecompress; bool autoDecompress;
QByteDataBuffer responseData; // uncompressed body QByteDataBuffer responseData; // uncompressed body
@ -242,6 +237,11 @@ public:
bool downstreamLimited; bool downstreamLimited;
char* userProvidedDownloadBuffer; char* userProvidedDownloadBuffer;
#ifndef QT_NO_COMPRESS
z_stream_s *inflateStrm;
qint64 uncompressBodyData(QByteDataBuffer *in, QByteDataBuffer *out);
#endif
}; };