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;
170 qDebug() <<
"first byte is " << QString::number(*p,16);
172 if (*p++ != 0x1f)
return false;
174 qDebug() <<
"second byte is " << QString::number(*p,16);
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
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()