/**************************************************************************/ /* */ /* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ /* Copyright (c) 2008-2014 Oleksandr Shneyder */ /* Copyright (c) 2014-2016 Ulrich Sibiller */ /* Copyright (c) 2014-2016 Mihai Moldovan */ /* Copyright (c) 2011-2016 Mike Gabriel */ /* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ /* */ /* NXCOMPEXT, NX protocol compression and NX extensions to this software */ /* are copyright of the aforementioned persons and companies. */ /* */ /* Redistribution and use of the present software is allowed according */ /* to terms specified in the file LICENSE which comes in the source */ /* distribution. */ /* */ /* All rights reserved. */ /* */ /* NOTE: This software has received contributions from various other */ /* contributors, only the core maintainers and supporters are listed as */ /* copyright holders. Please contact us, if you feel you should be listed */ /* as copyright holder, as well. */ /* */ /**************************************************************************/ #include #include #include #include #include "Compext.h" #include "Z.h" #include "../Utils.h" #define PANIC #define WARNING #undef TEST #undef DEBUG #define Z_COMPRESSION_LEVEL 4 #define Z_COMPRESSION_THRESHOLD 32 #define Z_COMPRESSION_STRATEGY Z_DEFAULT_STRATEGY static int zCompressionLevel = Z_COMPRESSION_LEVEL; static int zCompressionStrategy = Z_COMPRESSION_STRATEGY; static z_stream *zStream; static int zInitialized; static int ZConfigure(int level, int strategy); static int ZDeflate(char *dest, unsigned int *destLen, const char *source, unsigned int sourceLen); char *ZCompressData(const char *plainData, unsigned int plainSize, int threshold, int level, int strategy, unsigned int *compressedSize) { char *compressedData; /* * Determine the size of the source image * data and make sure there is enough * space in the destination buffer. */ *compressedSize = plainSize + (plainSize / 1000) + 12 + 1; compressedData = malloc(*compressedSize); if (compressedData == NULL) { #ifdef PANIC fprintf(stderr, "******ZCompressData: PANIC! Failed to allocate [%d] bytes for the destination.\n", *compressedSize); #endif *compressedSize = 0; return NULL; } if (level == Z_NO_COMPRESSION || plainSize < threshold) { #ifdef TEST fprintf(stderr, "******ZCompressData: Not compressing [%d] bytes with level [%d] and " "threshold [%d].\n", plainSize, level, threshold); #endif /* * Tell in the first byte of the buffer * if the remaining data is compressed * or not. This same byte can be used * in future to store some other flag. */ *compressedData = 0; memcpy(compressedData + 1, plainData, plainSize); *compressedSize = plainSize + 1; return compressedData; } else { int result; /* * Reconfigure the stream if needed. */ if (zCompressionLevel != level || zCompressionStrategy != strategy) { ZConfigure(level, strategy); zCompressionLevel = level; zCompressionStrategy = strategy; } result = ZDeflate(compressedData + 1, compressedSize, plainData, plainSize); if (result != Z_OK) { #ifdef PANIC fprintf(stderr, "******ZCompressData: PANIC! Failed to compress [%d] bytes with error [%s].\n", plainSize, zError(result)); #endif SAFE_free(compressedData); *compressedSize = 0; return NULL; } #ifdef TEST fprintf(stderr, "******ZCompressData: Source data of [%d] bytes compressed to [%d].\n", plainSize, *compressedSize); #endif *compressedData = 1; *compressedSize = *compressedSize + 1; return compressedData; } } int ZConfigure(int level, int strategy) { /* * ZLIB wants the avail_out to be * non zero, even if the stream was * already flushed. */ unsigned char dest[1]; zStream -> next_out = dest; zStream -> avail_out = 1; if (deflateParams(zStream, level, strategy) != Z_OK) { #ifdef PANIC fprintf(stderr, "******ZConfigure: PANIC! Failed to set level to [%d] and strategy to [%d].\n", level, strategy); #endif return -1; } #ifdef TEST else { fprintf(stderr, "******ZConfigure: Reconfigured the stream with level [%d] and strategy [%d].\n", level, strategy); } #endif return 1; } int ZDeflate(char *dest, unsigned int *destLen, const char *source, unsigned int sourceLen) { int saveOut; int result; /* * Deal with the possible overflow. */ if (zStream -> total_out & 0x80000000) { #ifdef TEST fprintf(stderr, "******ZDeflate: Reset Z stream counters with total in [%ld] total out [%ld].\n", zStream -> total_in, zStream -> total_out); #endif zStream -> total_in = 0; zStream -> total_out = 0; } saveOut = zStream -> total_out; zStream -> next_in = (Bytef *) source; zStream -> avail_in = (uInt) sourceLen; #ifdef MAXSEG_64K /* * Check if the source is greater * than 64K on a 16-bit machine. */ if ((uLong) zStream -> avail_in != sourceLen) return Z_BUF_ERROR; #endif zStream -> next_out = (unsigned char *) dest; zStream -> avail_out = (uInt) *destLen; if ((uLong) zStream -> avail_out != *destLen) return Z_BUF_ERROR; result = deflate(zStream, Z_FINISH); if (result != Z_STREAM_END) { deflateReset(zStream); return (result == Z_OK ? Z_BUF_ERROR : result); } *destLen = zStream -> total_out - saveOut; result = deflateReset(zStream); return result; } int ZInitEncoder(void) { if (zInitialized == 0) { int result; zStream = malloc(sizeof(z_stream)); if (zStream == NULL) { #ifdef PANIC fprintf(stderr, "******ZInitEncoder: PANIC! Failed to allocate memory for the stream.\n"); #endif return -1; } zStream -> zalloc = (alloc_func) 0; zStream -> zfree = (free_func) 0; zStream -> opaque = (voidpf) 0; #ifdef TEST fprintf(stderr, "******ZInitEncoder: Initializing compressor with level [%d] and strategy [%d].\n", zCompressionLevel, zCompressionStrategy); #endif result = deflateInit2(zStream, zCompressionLevel, Z_DEFLATED, 15, 9, zCompressionStrategy); if (result != Z_OK) { #ifdef PANIC fprintf(stderr, "******ZInitEncoder: Failed to initialize the compressor with error [%s].\n", zError(result)); #endif return -1; } zInitialized = 1; } return zInitialized; } int ZResetEncoder(void) { int result; if (zInitialized == 1) { result = deflateEnd(zStream); if (result != Z_OK) { #ifdef WARNING fprintf(stderr, "******ZResetEncoder: WARNING! Failed to deinitialize the compressor with error [%s].\n", zError(result)); #endif } SAFE_free(zStream); } zInitialized = 0; return 1; }