#include "CompressionUtility.h" #include "malloc.h" #include #include "zlib.h" #include "minizip/unzip.h" #define dir_delimter '/' #define MAX_FILENAME 512 #define READ_SIZE 8192 /// /// Compress given buffer as GZIP. /// Dont forget to free out buffer!!!! /// /// /// /// /// /// int CompressionUtility::CompressAsGZip(const void* input, size_t input_size, void** ppvOut, size_t& out_size) { z_stream zlib_stream; zlib_stream.next_in = (Bytef*)input; zlib_stream.avail_in = (uInt)input_size; zlib_stream.next_out = Z_NULL; zlib_stream.avail_out = Z_NULL; zlib_stream.zalloc = (alloc_func)0; zlib_stream.zfree = (free_func)0; zlib_stream.opaque = 0; int ret = deflateInit2(&zlib_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (16 + MAX_WBITS), 8, Z_DEFAULT_STRATEGY); unsigned full_length = 2000; unsigned half_length = input_size / 2; unsigned compLength = full_length; unsigned char* comp = (unsigned char*)malloc(compLength); bool done = false; while (!done) { if (zlib_stream.total_out >= compLength) { // Increase size of output buffer unsigned char* uncomp2 = (unsigned char*)malloc(compLength + half_length); memcpy(uncomp2, comp, compLength); compLength += half_length; free(comp); comp = uncomp2; } zlib_stream.next_out = (Bytef*)(comp + zlib_stream.total_out); zlib_stream.avail_out = compLength - zlib_stream.total_out; // Deflate another chunk. ret = deflate(&zlib_stream, Z_FINISH); if (Z_STREAM_END == ret) { done = true; } else if (Z_OK != ret) { break; } } if (Z_OK != deflateEnd(&zlib_stream)) { free(comp); return ret; } *ppvOut = (void*)comp; out_size = zlib_stream.total_out; return ret; } /// /// Decompress given buffer. /// Dont forget to free out buffer!!!! /// /// /// /// /// /// int CompressionUtility::DecompressGZip(const void* input, size_t input_size, void** ppvOut, size_t& out_size) { z_stream zlib_stream; zlib_stream.next_in = (Bytef*)input; zlib_stream.avail_in = (uInt)input_size; zlib_stream.next_out = Z_NULL; zlib_stream.avail_out = Z_NULL; zlib_stream.zalloc = (alloc_func)0; zlib_stream.zfree = (free_func)0; zlib_stream.opaque = Z_NULL; int ret = inflateInit2(&zlib_stream, (16 + MAX_WBITS)); if (Z_OK != ret) { return ret; } unsigned full_length = input_size; unsigned half_length = input_size / 2; unsigned uncompLength = full_length; unsigned char* uncomp = (unsigned char*)malloc(uncompLength); bool done = false; while (!done) { if (zlib_stream.total_out >= uncompLength) { // Increase size of output buffer unsigned char* uncomp2 = (unsigned char*)malloc(uncompLength + half_length); memcpy(uncomp2, uncomp, uncompLength); uncompLength += half_length; free(uncomp); uncomp = uncomp2; } zlib_stream.next_out = (Bytef*)(uncomp + zlib_stream.total_out); zlib_stream.avail_out = uncompLength - zlib_stream.total_out; // Inflate another chunk. ret = inflate(&zlib_stream, Z_SYNC_FLUSH); if (Z_STREAM_END == ret) { done = true; } else if (Z_OK != ret) { break; } } if (Z_OK != inflateEnd(&zlib_stream)) { free(uncomp); return ret; } *ppvOut = (void*)uncomp; out_size = zlib_stream.total_out; return ret; } /// /// Returns inflated first file inside the ZIP container, /// rest are ignored!!!!! /// /// /// /// /// /// int CompressionUtility::DecompressPKZip(const char* fn, void** ppvOut, size_t& out_size) { // Open the zip file unzFile zipfile = unzOpen(fn); if (nullptr == zipfile) { // file not found return -1; } // Get info about the zip file unz_global_info global_info; if (UNZ_OK != unzGetGlobalInfo(zipfile, &global_info)) { // could not read file global info unzClose(zipfile); return -1; } // Buffer to hold data read from the zip file. //char read_buffer[READ_SIZE]; // Loop to extract all files for (uLong i = 0; i < global_info.number_entry; ++i) { // Get info about current file. unz_file_info file_info; char filename[MAX_FILENAME]; if (unzGetCurrentFileInfo( zipfile, &file_info, filename, MAX_FILENAME, NULL, 0, NULL, 0) != UNZ_OK) { // could not read file info unzClose(zipfile); return -1; } // Check if this entry is a directory or file. const size_t filename_length = strlen(filename); if (filename[filename_length - 1] == dir_delimter) { // Entry is a directory, skip it } else { // Entry is a file, so extract it. if (unzOpenCurrentFile(zipfile) != UNZ_OK) { // could not open file unzClose(zipfile); return -1; } unsigned full_length = READ_SIZE * 2; unsigned half_length = READ_SIZE; unsigned uncompLength = full_length; unsigned char* uncomp = (unsigned char*)malloc(uncompLength); size_t total_out = 0; int error = UNZ_OK; do { if (total_out >= uncompLength) { // Increase size of output buffer unsigned char* uncomp2 = (unsigned char*)malloc(uncompLength + half_length); memcpy(uncomp2, uncomp, uncompLength); uncompLength += half_length; free(uncomp); uncomp = uncomp2; } error = unzReadCurrentFile(zipfile, uncomp + total_out, uncompLength - total_out); if (error < 0) { // something happened unzCloseCurrentFile(zipfile); unzClose(zipfile); return -1; } // Write data to buffer. if (error > 0) { total_out += error; } } while (error > 0); *ppvOut = (void*)uncomp; out_size = total_out; } unzCloseCurrentFile(zipfile); // Go the the next entry listed in the zip file. //if ((i + 1) < global_info.number_entry) //{ // if (unzGoToNextFile(zipfile) != UNZ_OK) // { // printf("cound not read next file\n"); // unzClose(zipfile); // return -1; // } //} } unzClose(zipfile); return UNZ_OK; }