1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 // Disable symbol overrides so that we can use zlib.h
24 #define FORBIDDEN_SYMBOL_ALLOW_ALL
25 
26 #include "common/zlib.h"
27 #include "common/ptr.h"
28 #include "common/util.h"
29 #include "common/stream.h"
30 #include "common/debug.h"
31 #include "common/textconsole.h"
32 
33 #if defined(USE_ZLIB)
34   #ifdef __SYMBIAN32__
35 	#include <zlib\zlib.h>
36   #elif defined(__MORPHOS__)
37 	#define _NO_PPCINLINE
38 	#include <zlib.h>
39 	#undef _NO_PPCINLINE
40   #else
41 	#include <zlib.h>
42   #endif
43 
44   #if ZLIB_VERNUM < 0x1204
45   #error Version 1.2.0.4 or newer of zlib is required for this code
46   #endif
47 #endif
48 
49 
50 namespace Common {
51 
52 #if defined(USE_ZLIB)
53 
uncompress(byte * dst,unsigned long * dstLen,const byte * src,unsigned long srcLen)54 bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long srcLen) {
55 	return Z_OK == ::uncompress(dst, dstLen, src, srcLen);
56 }
57 
inflateZlibHeaderless(byte * dst,uint dstLen,const byte * src,uint srcLen,const byte * dict,uint dictLen)58 bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen, const byte *dict, uint dictLen) {
59 	if (!dst || !dstLen || !src || !srcLen)
60 		return false;
61 
62 	// Initialize zlib
63 	z_stream stream;
64 	stream.next_in = const_cast<byte *>(src);
65 	stream.avail_in = srcLen;
66 	stream.next_out = dst;
67 	stream.avail_out = dstLen;
68 	stream.zalloc = Z_NULL;
69 	stream.zfree = Z_NULL;
70 	stream.opaque = Z_NULL;
71 
72 	// Negative MAX_WBITS tells zlib there's no zlib header
73 	int err = inflateInit2(&stream, -MAX_WBITS);
74 	if (err != Z_OK)
75 		return false;
76 
77 	// Set the dictionary, if provided
78 	if (dict != nullptr) {
79 		err = inflateSetDictionary(&stream, const_cast<byte *>(dict), dictLen);
80 		if (err != Z_OK)
81 			return false;
82 	}
83 
84 	err = inflate(&stream, Z_SYNC_FLUSH);
85 	if (err != Z_OK && err != Z_STREAM_END) {
86 		inflateEnd(&stream);
87 		return false;
88 	}
89 
90 	inflateEnd(&stream);
91 	return true;
92 }
93 
94 enum {
95 	kTempBufSize = 65536
96 };
97 
inflateZlibInstallShield(byte * dst,uint dstLen,const byte * src,uint srcLen)98 bool inflateZlibInstallShield(byte *dst, uint dstLen, const byte *src, uint srcLen) {
99 	if (!dst || !dstLen || !src || !srcLen)
100 		return false;
101 
102 	// See if we have sync bytes. If so, just use our function for that.
103 	if (srcLen >= 4 && READ_BE_UINT32(src + srcLen - 4) == 0xFFFF)
104 		return inflateZlibHeaderless(dst, dstLen, src, srcLen);
105 
106 	// Otherwise, we have some custom code we get to use here.
107 
108 	byte *temp = (byte *)malloc(kTempBufSize);
109 
110 	uint32 bytesRead = 0, bytesProcessed = 0;
111 	while (bytesRead < srcLen) {
112 		uint16 chunkSize = READ_LE_UINT16(src + bytesRead);
113 		bytesRead += 2;
114 
115 		// Initialize zlib
116 		z_stream stream;
117 		stream.next_in = const_cast<byte *>(src + bytesRead);
118 		stream.avail_in = chunkSize;
119 		stream.next_out = temp;
120 		stream.avail_out = kTempBufSize;
121 		stream.zalloc = Z_NULL;
122 		stream.zfree = Z_NULL;
123 		stream.opaque = Z_NULL;
124 
125 		// Negative MAX_WBITS tells zlib there's no zlib header
126 		int err = inflateInit2(&stream, -MAX_WBITS);
127 		if (err != Z_OK)
128 			return false;
129 
130 		err = inflate(&stream, Z_FINISH);
131 		if (err != Z_OK && err != Z_STREAM_END) {
132 			inflateEnd(&stream);
133 			free(temp);
134 			return false;
135 		}
136 
137 		memcpy(dst + bytesProcessed, temp, stream.total_out);
138 		bytesProcessed += stream.total_out;
139 
140 		inflateEnd(&stream);
141 		bytesRead += chunkSize;
142 	}
143 
144 	free(temp);
145 	return true;
146 }
147 
inflateZlibHeaderless(Common::WriteStream * dst,Common::SeekableReadStream * src)148 bool inflateZlibHeaderless(Common::WriteStream *dst, Common::SeekableReadStream *src) {
149 	byte *inBuffer, *outBuffer;
150 	z_stream stream;
151 	int status;
152 
153 	// Allocate buffers
154 	inBuffer = new byte[kTempBufSize];
155 	outBuffer = new byte[kTempBufSize];
156 
157 	/* Initialize Zlib inflation functions. */
158 	stream.next_out = outBuffer;
159 	stream.avail_out = kTempBufSize;
160 	stream.next_in = inBuffer;
161 	stream.avail_in = 0;
162 
163 	stream.zalloc = Z_NULL;
164 	stream.zfree = Z_NULL;
165 	stream.opaque = Z_NULL;
166 
167 	status = inflateInit(&stream);
168 	if (status != Z_OK) {
169 		delete[] inBuffer;
170 		delete[] outBuffer;
171 		return false;
172 	}
173 
174 	// Inflate the input buffers. */
175 	for (;;) {
176 		int inBytes, outBytes;
177 
178 		/* If the input buffer is empty, try to obtain more data. */
179 		if (stream.avail_in == 0) {
180 			inBytes = src->read(inBuffer, kTempBufSize);
181 			stream.next_in = inBuffer;
182 			stream.avail_in = inBytes;
183 		}
184 
185 		// Decompress as much stream data as we can. */
186 		status = inflate(&stream, Z_SYNC_FLUSH);
187 		if (status != Z_STREAM_END && status != Z_OK) {
188 			delete[] inBuffer;
189 			delete[] outBuffer;
190 			return false;
191 		}
192 		outBytes = kTempBufSize - stream.avail_out;
193 
194 		// See if decompressed data is available. */
195 		if (outBytes > 0) {
196 			// Add data from the buffer to the output
197 			int consumed = dst->write(outBuffer, outBytes);
198 
199 			// Move unused buffer data to buffer start
200 			memmove(outBuffer, outBuffer + consumed, kTempBufSize - consumed);
201 
202 			// Reset inflation stream for available space
203 			stream.next_out = outBuffer + outBytes - consumed;
204 			stream.avail_out += consumed;
205 		}
206 
207 		// If at inflation stream end and output is empty, leave loop
208 		if (status == Z_STREAM_END && stream.avail_out == kTempBufSize)
209 			break;
210 	}
211 
212 	// End inflation buffers
213 	status = inflateEnd(&stream);
214 	delete[] inBuffer;
215 	delete[] outBuffer;
216 
217 	// Return result
218 	return (status == Z_OK);
219 }
220 
221 #ifndef RELEASE_BUILD
222 static bool _shownBackwardSeekingWarning = false;
223 #endif
224 
225 /**
226  * A simple wrapper class which can be used to wrap around an arbitrary
227  * other SeekableReadStream and will then provide on-the-fly decompression support.
228  * Assumes the compressed data to be in gzip format.
229  */
230 class GZipReadStream : public SeekableReadStream {
231 protected:
232 	enum {
233 		BUFSIZE = 16384		// 1 << MAX_WBITS
234 	};
235 
236 	byte	_buf[BUFSIZE];
237 
238 	ScopedPtr<SeekableReadStream> _wrapped;
239 	z_stream _stream;
240 	int _zlibErr;
241 	uint32 _pos;
242 	uint32 _origSize;
243 	bool _eos;
244 
245 public:
246 
GZipReadStream(SeekableReadStream * w,uint32 knownSize=0)247 	GZipReadStream(SeekableReadStream *w, uint32 knownSize = 0) : _wrapped(w), _stream() {
248 		assert(w != nullptr);
249 
250 		// Verify file header is correct
251 		w->seek(0, SEEK_SET);
252 		uint16 header = w->readUint16BE();
253 		assert(header == 0x1F8B ||
254 		       ((header & 0x0F00) == 0x0800 && header % 31 == 0));
255 
256 		if (header == 0x1F8B) {
257 			// Retrieve the original file size
258 			w->seek(-4, SEEK_END);
259 			_origSize = w->readUint32LE();
260 		} else {
261 			// Original size not available in zlib format
262 			// use an otherwise known size if supplied.
263 			_origSize = knownSize;
264 		}
265 		_pos = 0;
266 		w->seek(0, SEEK_SET);
267 		_eos = false;
268 
269 		// Adding 32 to windowBits indicates to zlib that it is supposed to
270 		// automatically detect whether gzip or zlib headers are used for
271 		// the compressed file. This feature was added in zlib 1.2.0.4,
272 		// released 10 August 2003.
273 		// Note: This is *crucial* for savegame compatibility, do *not* remove!
274 		_zlibErr = inflateInit2(&_stream, MAX_WBITS + 32);
275 		if (_zlibErr != Z_OK)
276 			return;
277 
278 		// Setup input buffer
279 		_stream.next_in = _buf;
280 		_stream.avail_in = 0;
281 	}
282 
~GZipReadStream()283 	~GZipReadStream() {
284 		inflateEnd(&_stream);
285 	}
286 
err() const287 	bool err() const { return (_zlibErr != Z_OK) && (_zlibErr != Z_STREAM_END); }
clearErr()288 	void clearErr() {
289 		// only reset _eos; I/O errors are not recoverable
290 		_eos = false;
291 	}
292 
read(void * dataPtr,uint32 dataSize)293 	uint32 read(void *dataPtr, uint32 dataSize) {
294 		_stream.next_out = (byte *)dataPtr;
295 		_stream.avail_out = dataSize;
296 
297 		// Keep going while we get no error
298 		while (_zlibErr == Z_OK && _stream.avail_out) {
299 			if (_stream.avail_in == 0 && !_wrapped->eos()) {
300 				// If we are out of input data: Read more data, if available.
301 				_stream.next_in = _buf;
302 				_stream.avail_in = _wrapped->read(_buf, BUFSIZE);
303 			}
304 			_zlibErr = inflate(&_stream, Z_NO_FLUSH);
305 		}
306 
307 		// Update the position counter
308 		_pos += dataSize - _stream.avail_out;
309 
310 		if (_zlibErr == Z_STREAM_END && _stream.avail_out > 0)
311 			_eos = true;
312 
313 		return dataSize - _stream.avail_out;
314 	}
315 
eos() const316 	bool eos() const {
317 		return _eos;
318 	}
pos() const319 	int64 pos() const {
320 		return _pos;
321 	}
size() const322 	int64 size() const {
323 		return _origSize;
324 	}
seek(int64 offset,int whence=SEEK_SET)325 	bool seek(int64 offset, int whence = SEEK_SET) {
326 		int32 newPos = 0;
327 		switch (whence) {
328 		default:
329 			// fallthrough intended
330 		case SEEK_SET:
331 			newPos = offset;
332 			break;
333 		case SEEK_CUR:
334 			newPos = _pos + offset;
335 			break;
336 		case SEEK_END:
337 			// NOTE: This can be an expensive operation (see below).
338 			newPos = size() + offset;
339 			break;
340 		}
341 
342 		assert(newPos >= 0);
343 
344 		if ((uint32)newPos < _pos) {
345 			// To search backward, we have to restart the whole decompression
346 			// from the start of the file. A rather wasteful operation, best
347 			// to avoid it. :/
348 
349 #ifndef RELEASE_BUILD
350 			if (!_shownBackwardSeekingWarning) {
351 				// We only throw this warning once per stream, to avoid
352 				// getting the console swarmed with warnings when consecutive
353 				// seeks are made.
354 				debug(1, "Backward seeking in GZipReadStream detected");
355 				_shownBackwardSeekingWarning = true;
356 			}
357 #endif
358 
359 			_pos = 0;
360 			_wrapped->seek(0, SEEK_SET);
361 			_zlibErr = inflateReset(&_stream);
362 			if (_zlibErr != Z_OK)
363 				return false; // FIXME: STREAM REWRITE
364 			_stream.next_in = _buf;
365 			_stream.avail_in = 0;
366 		}
367 
368 		offset = newPos - _pos;
369 
370 		// Skip the given amount of data (very inefficient if one tries to skip
371 		// huge amounts of data, but usually client code will only skip a few
372 		// bytes, so this should be fine.
373 		byte tmpBuf[1024];
374 		while (!err() && offset > 0) {
375 			offset -= read(tmpBuf, MIN((int64)sizeof(tmpBuf), offset));
376 		}
377 
378 		_eos = false;
379 		return true; // FIXME: STREAM REWRITE
380 	}
381 };
382 
383 /**
384  * A simple wrapper class which can be used to wrap around an arbitrary
385  * other WriteStream and will then provide on-the-fly compression support.
386  * The compressed data is written in the gzip format.
387  */
388 class GZipWriteStream : public WriteStream {
389 protected:
390 	enum {
391 		BUFSIZE = 16384		// 1 << MAX_WBITS
392 	};
393 
394 	byte	_buf[BUFSIZE];
395 	ScopedPtr<WriteStream> _wrapped;
396 	z_stream _stream;
397 	int _zlibErr;
398 	uint32 _pos;
399 
processData(int flushType)400 	void processData(int flushType) {
401 		// This function is called by both write() and finalize().
402 		while (_zlibErr == Z_OK && (_stream.avail_in || flushType == Z_FINISH)) {
403 			if (_stream.avail_out == 0) {
404 				if (_wrapped->write(_buf, BUFSIZE) != BUFSIZE) {
405 					_zlibErr = Z_ERRNO;
406 					break;
407 				}
408 				_stream.next_out = _buf;
409 				_stream.avail_out = BUFSIZE;
410 			}
411 			_zlibErr = deflate(&_stream, flushType);
412 		}
413 	}
414 
415 public:
GZipWriteStream(WriteStream * w)416 	GZipWriteStream(WriteStream *w) : _wrapped(w), _stream(), _pos(0) {
417 		assert(w != nullptr);
418 
419 		// Adding 16 to windowBits indicates to zlib that it is supposed to
420 		// write gzip headers. This feature was added in zlib 1.2.0.4,
421 		// released 10 August 2003.
422 		// Note: This is *crucial* for savegame compatibility, do *not* remove!
423 		_zlibErr = deflateInit2(&_stream,
424 		                 Z_DEFAULT_COMPRESSION,
425 		                 Z_DEFLATED,
426 		                 MAX_WBITS + 16,
427 		                 8,
428 				 Z_DEFAULT_STRATEGY);
429 		assert(_zlibErr == Z_OK);
430 
431 		_stream.next_out = _buf;
432 		_stream.avail_out = BUFSIZE;
433 		_stream.avail_in = 0;
434 		_stream.next_in = nullptr;
435 	}
436 
~GZipWriteStream()437 	~GZipWriteStream() {
438 		finalize();
439 		deflateEnd(&_stream);
440 	}
441 
err() const442 	bool err() const {
443 		// CHECKME: does Z_STREAM_END make sense here?
444 		return (_zlibErr != Z_OK && _zlibErr != Z_STREAM_END) || _wrapped->err();
445 	}
446 
clearErr()447 	void clearErr() {
448 		// Note: we don't reset the _zlibErr here, as it is not
449 		// clear in general how
450 		_wrapped->clearErr();
451 	}
452 
finalize()453 	void finalize() {
454 		if (_zlibErr != Z_OK)
455 			return;
456 
457 		// Process whatever remaining data there is.
458 		processData(Z_FINISH);
459 
460 		// Since processData only writes out blocks of size BUFSIZE,
461 		// we may have to flush some stragglers.
462 		uint remainder = BUFSIZE - _stream.avail_out;
463 		if (remainder > 0) {
464 			if (_wrapped->write(_buf, remainder) != remainder) {
465 				_zlibErr = Z_ERRNO;
466 			}
467 		}
468 
469 		// Finalize the wrapped savefile, too
470 		_wrapped->finalize();
471 	}
472 
write(const void * dataPtr,uint32 dataSize)473 	uint32 write(const void *dataPtr, uint32 dataSize) {
474 		if (err())
475 			return 0;
476 
477 		// Hook in the new data ...
478 		// Note: We need to make a const_cast here, as zlib is not aware
479 		// of the const keyword.
480 		_stream.next_in = const_cast<byte *>((const byte *)dataPtr);
481 		_stream.avail_in = dataSize;
482 
483 		// ... and flush it to disk
484 		processData(Z_NO_FLUSH);
485 
486 		_pos += dataSize - _stream.avail_in;
487 		return dataSize - _stream.avail_in;
488 	}
489 
pos() const490 	virtual int64 pos() const { return _pos; }
491 };
492 
493 #endif	// USE_ZLIB
494 
wrapCompressedReadStream(SeekableReadStream * toBeWrapped,uint32 knownSize)495 SeekableReadStream *wrapCompressedReadStream(SeekableReadStream *toBeWrapped, uint32 knownSize) {
496 	if (toBeWrapped) {
497 		if (toBeWrapped->eos() || toBeWrapped->err() || toBeWrapped->size() < 2) {
498 			delete toBeWrapped;
499 			return nullptr;
500 		}
501 		uint16 header = toBeWrapped->readUint16BE();
502 		bool isCompressed = (header == 0x1F8B ||
503 				     ((header & 0x0F00) == 0x0800 &&
504 				      header % 31 == 0));
505 		toBeWrapped->seek(-2, SEEK_CUR);
506 		if (isCompressed) {
507 #if defined(USE_ZLIB)
508 			return new GZipReadStream(toBeWrapped, knownSize);
509 #else
510 			delete toBeWrapped;
511 			return nullptr;
512 #endif
513 		}
514 	}
515 	return toBeWrapped;
516 }
517 
wrapCompressedWriteStream(WriteStream * toBeWrapped)518 WriteStream *wrapCompressedWriteStream(WriteStream *toBeWrapped) {
519 #if defined(USE_ZLIB)
520 	if (toBeWrapped)
521 		return new GZipWriteStream(toBeWrapped);
522 #endif
523 	return toBeWrapped;
524 }
525 
526 
527 } // End of namespace Common
528