25 #include <QtCore/QIODevice>
29 #define ASCII_FLAG 0x01
31 #define EXTRA_FIELD 0x04
32 #define ORIG_NAME 0x08
38 class KGzipFilter::Private
42 : headerWritten(
false), footerWritten(
false), compressed(
false),
mode(0), crc(0), isInitialized(
false)
44 zStream.zalloc = (alloc_func)0;
45 zStream.zfree = (free_func)0;
46 zStream.opaque = (voidpf)0;
76 if (d->isInitialized) {
79 d->zStream.next_in = Z_NULL;
80 d->zStream.avail_in = 0;
81 if ( mode == QIODevice::ReadOnly )
88 const int result = inflateInit2(&d->zStream, windowBits);
89 if ( result != Z_OK ) {
90 qDebug() <<
"inflateInit2 returned " << result;
93 }
else if ( mode == QIODevice::WriteOnly )
95 int result = deflateInit2(&d->zStream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
96 if ( result != Z_OK ) {
97 qDebug() <<
"deflateInit returned " << result;
101 qWarning() <<
"KGzipFilter: Unsupported mode " << mode <<
". Only QIODevice::ReadOnly and QIODevice::WriteOnly supported";
104 d->compressed =
true;
105 d->headerWritten =
false;
106 d->footerWritten =
false;
107 d->isInitialized =
true;
117 if ( d->mode == QIODevice::ReadOnly )
119 int result = inflateEnd(&d->zStream);
120 if ( result != Z_OK ) {
121 qDebug() <<
"inflateEnd returned " << result;
124 }
else if ( d->mode == QIODevice::WriteOnly )
126 int result = deflateEnd(&d->zStream);
127 if ( result != Z_OK ) {
128 qDebug() <<
"deflateEnd returned " << result;
132 d->isInitialized =
false;
138 if ( d->mode == QIODevice::ReadOnly )
140 int result = inflateReset(&d->zStream);
141 if ( result != Z_OK ) {
142 qDebug() <<
"inflateReset returned " << result;
145 }
else if ( d->mode == QIODevice::WriteOnly ) {
146 int result = deflateReset(&d->zStream);
147 if ( result != Z_OK ) {
148 qDebug() <<
"deflateReset returned " << result;
151 d->headerWritten =
false;
152 d->footerWritten =
false;
162 qDebug() <<
"avail=" << d->zStream.avail_in;
165 d->compressed =
false;
166 Bytef *p = d->zStream.next_in;
167 int i = d->zStream.avail_in;
168 if ((i -= 10) < 0)
return false;
172 if (*p++ != 0x1f)
return false;
176 if (*p++ != 0x8b)
return false;
181 if ((method != Z_DEFLATED) || (flags &
RESERVED) != 0)
return false;
185 if ((i -= 2) < 0)
return false;
188 if ((i -= len) < 0)
return false;
194 qDebug() <<
"ORIG_NAME=" << (
char*)p;
196 while( (i > 0) && (*p))
200 if (--i <= 0)
return false;
205 while( (i > 0) && (*p))
209 if (--i <= 0)
return false;
214 if ((i-=2) < 0)
return false;
218 d->zStream.avail_in = i;
219 d->zStream.next_in = p;
222 d->compressed =
true;
224 qDebug() <<
"header OK";
230 #define put_short(w) \
231 *p++ = (uchar) ((w) & 0xff); \
232 *p++ = (uchar) ((ushort)(w) >> 8);
235 #define put_long(n) \
236 put_short((n) & 0xffff); \
237 put_short(((ulong)(n)) >> 16);
241 Bytef *p = d->zStream.next_out;
242 int i = d->zStream.avail_out;
251 uint len = fileName.
length();
252 for ( uint j = 0 ; j < len ; ++j )
255 int headerSize = p - d->zStream.next_out;
258 d->crc = crc32(0L, Z_NULL, 0);
259 d->zStream.next_out = p;
260 d->zStream.avail_out = i;
261 d->headerWritten =
true;
267 Q_ASSERT( d->headerWritten );
268 Q_ASSERT(!d->footerWritten);
269 Bytef *p = d->zStream.next_out;
270 int i = d->zStream.avail_out;
275 i -= p - d->zStream.next_out;
276 d->zStream.next_out = p;
277 d->zStream.avail_out = i;
278 d->footerWritten =
true;
283 d->zStream.avail_out = maxlen;
284 d->zStream.next_out = (Bytef *) data;
289 qDebug() <<
"avail_in=" << size;
291 d->zStream.avail_in = size;
292 d->zStream.next_in = (Bytef*) data;
296 return d->zStream.avail_in;
300 return d->zStream.avail_out;
308 if ( d->zStream.avail_in > 0 )
310 int n = (d->zStream.avail_in < d->zStream.avail_out) ? d->zStream.avail_in : d->zStream.avail_out;
311 memcpy( d->zStream.next_out, d->zStream.next_in, n );
312 d->zStream.avail_out -= n;
313 d->zStream.next_in += n;
314 d->zStream.avail_in -= n;
324 qWarning() <<
"mode==0; KGzipFilter::init was not called!";
326 }
else if (d->mode == QIODevice::WriteOnly) {
327 qWarning() <<
"uncompress called but the filter was opened for writing!";
330 Q_ASSERT ( d->mode == QIODevice::ReadOnly );
337 qDebug() <<
" next_in=" << d->zStream.next_in;
339 int result = inflate(&d->zStream, Z_SYNC_FLUSH);
341 qDebug() <<
" -> inflate returned " << result;
343 qDebug() <<
" next_in=" << d->zStream.next_in;
345 if ( result != Z_OK && result != Z_STREAM_END )
346 qDebug() <<
"Warning: inflate() returned " << result;
350 return uncompress_noop();
355 Q_ASSERT ( d->compressed );
356 Q_ASSERT ( d->mode == QIODevice::WriteOnly );
358 Bytef* p = d->zStream.next_in;
359 ulong len = d->zStream.avail_in;
363 const int result = deflate(&d->zStream, finish ? Z_FINISH : Z_NO_FLUSH);
364 if ( result != Z_OK && result != Z_STREAM_END ) {
365 qDebug() <<
" deflate returned " << result;
367 if ( d->headerWritten )
370 d->crc = crc32(d->crc, p, len - d->zStream.avail_in);
374 if (result == Z_STREAM_END && d->headerWritten && !d->footerWritten) {
375 if (d->zStream.avail_out >= 8 ) {
virtual void setInBuffer(const char *data, uint size)
virtual void setOutBuffer(char *data, uint maxlen)
FilterFlags filterFlags() const
QString number(int n, int base)
virtual Result compress(bool finish)
virtual int outBufferAvailable() const
virtual Result uncompress()
virtual void init(int mode)
virtual int inBufferAvailable() const
virtual bool writeHeader(const QByteArray &fileName)
virtual bool readHeader()