From: <man...@us...> - 2013-10-19 13:42:10
|
Revision: 2930 http://sourceforge.net/p/modplug/code/2930 Author: manxorist Date: 2013-10-19 13:42:04 +0000 (Sat, 19 Oct 2013) Log Message: ----------- [Ref] unarchiver: Add support for using miniz instead of zlib and minizip to decompress .zip and .gz files. The only missing feature is the zip file global comment, so use zlib+minizip by default for now. [Ref] unarchiver: Cleanup GetComments() interface. [Fix] unarchiver: Fix memleak in CZipArchive::GetComments() . Modified Paths: -------------- trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/unarchiver/unarchiver.cpp trunk/OpenMPT/unarchiver/unarchiver.h trunk/OpenMPT/unarchiver/ungzip.cpp trunk/OpenMPT/unarchiver/ungzip.h trunk/OpenMPT/unarchiver/unzip.cpp trunk/OpenMPT/unarchiver/unzip.h Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2013-10-19 13:31:36 UTC (rev 2929) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2013-10-19 13:42:04 UTC (rev 2930) @@ -742,9 +742,9 @@ #ifndef NO_ARCHIVE_SUPPORT // Read archive comment if there is no song comment - if(songMessage.empty() && unarchiver.GetComments(false)) + if(songMessage.empty()) { - songMessage.assign(unarchiver.GetComments(true)); + songMessage.assign(unarchiver.GetComments()); } #endif Modified: trunk/OpenMPT/unarchiver/unarchiver.cpp =================================================================== --- trunk/OpenMPT/unarchiver/unarchiver.cpp 2013-10-19 13:31:36 UTC (rev 2929) +++ trunk/OpenMPT/unarchiver/unarchiver.cpp 2013-10-19 13:42:04 UTC (rev 2930) @@ -93,12 +93,14 @@ } -const char *CUnarchiver::GetComments(bool get) +std::string CUnarchiver::GetComments() +//------------------------------------ { #ifdef ZIPPED_MOD_SUPPORT - if(!zipArchive.IsArchive()) return nullptr; - return zipArchive.GetComments(get); -#else - return nullptr; + if(zipArchive.IsArchive()) + { + return zipArchive.GetComments(); + } #endif + return ""; } Modified: trunk/OpenMPT/unarchiver/unarchiver.h =================================================================== --- trunk/OpenMPT/unarchiver/unarchiver.h 2013-10-19 13:31:36 UTC (rev 2929) +++ trunk/OpenMPT/unarchiver/unarchiver.h 2013-10-19 13:42:04 UTC (rev 2930) @@ -51,7 +51,7 @@ FileReader GetOutputFile() const { return outFile; } bool IsArchive() const; bool ExtractFile(); - const char *GetComments(bool get); + std::string GetComments(); CUnarchiver(FileReader &file, const std::vector<const char *> &extensions); ~CUnarchiver(); Modified: trunk/OpenMPT/unarchiver/ungzip.cpp =================================================================== --- trunk/OpenMPT/unarchiver/ungzip.cpp 2013-10-19 13:31:36 UTC (rev 2929) +++ trunk/OpenMPT/unarchiver/ungzip.cpp 2013-10-19 13:42:04 UTC (rev 2930) @@ -12,7 +12,12 @@ #include "../soundlib/FileReader.h" #include "ungzip.h" +#if !defined(NO_ZLIB) #include <zlib/zlib.h> +#elif !defined(NO_MINIZ) +#define MINIZ_HEADER_FILE_ONLY +#include <miniz/miniz.c> +#endif CGzipArchive::CGzipArchive(FileReader &file) : inFile(file) @@ -115,7 +120,7 @@ inflateEnd(&strm); // Everything went OK? Check return code, number of written bytes and CRC32. - if(retVal == Z_STREAM_END && trailer.isize == strm.total_out && trailer.crc32 == crc32(0, (Bytef *)data, trailer.isize)) + if(retVal == Z_STREAM_END && trailer.isize == strm.total_out && trailer.crc32_ == crc32(0, (Bytef *)data, trailer.isize)) { // Success! :) outFile = FileReader(data, trailer.isize); Modified: trunk/OpenMPT/unarchiver/ungzip.h =================================================================== --- trunk/OpenMPT/unarchiver/ungzip.h 2013-10-19 13:31:36 UTC (rev 2929) +++ trunk/OpenMPT/unarchiver/ungzip.h 2013-10-19 13:42:04 UTC (rev 2930) @@ -35,12 +35,12 @@ struct PACKED GZtrailer { - uint32 crc32; // CRC32 of decompressed data + uint32 crc32_; // CRC32 of decompressed data uint32 isize; // Size of decompressed data void ConvertEndianness() { - SwapBytesLE(crc32); + SwapBytesLE(crc32_); SwapBytesLE(isize); } }; Modified: trunk/OpenMPT/unarchiver/unzip.cpp =================================================================== --- trunk/OpenMPT/unarchiver/unzip.cpp 2013-10-19 13:31:36 UTC (rev 2929) +++ trunk/OpenMPT/unarchiver/unzip.cpp 2013-10-19 13:42:04 UTC (rev 2930) @@ -15,9 +15,17 @@ #include "../common/misc_util.h" #include <algorithm> +#if !defined(NO_ZLIB) #include <contrib/minizip/unzip.h> +#elif !defined(NO_MINIZ) +#define MINIZ_HEADER_FILE_ONLY +#include <miniz/miniz.c> +#endif +#if !defined(NO_ZLIB) + + // Low-level file abstractions for in-memory file handling struct ZipFileAbstraction { @@ -204,20 +212,17 @@ } -const char *CZipArchive::GetComments(bool get) -//-------------------------------------------- +std::string CZipArchive::GetComments() +//------------------------------------ { unz_global_info info; if(zipFile == nullptr || unzGetGlobalInfo(zipFile, &info) != UNZ_OK) { - return nullptr; + return ""; } - if(!get) + if(info.size_comment > 0) { - return reinterpret_cast<char *>((info.size_comment > 0) ? 1 : 0); - } else if(info.size_comment > 0) - { if(info.size_comment < Util::MaxValueOfType(info.size_comment)) { info.size_comment++; @@ -226,11 +231,151 @@ if(comment != nullptr && unzGetGlobalComment(zipFile, comment, info.size_comment) >= 0) { comment[info.size_comment - 1] = '\0'; - return comment; + std::string result = comment; + delete[] comment; + return result; } else { delete[] comment; } } - return nullptr; + return ""; } + + +#elif !defined(NO_MINIZ) + + +CZipArchive::CZipArchive(FileReader &file, const std::vector<const char *> &ext) : inFile(file), extensions(ext) +//-------------------------------------------------------------------------------------------------------------- +{ + zipFile = new mz_zip_archive(); + + mz_zip_archive *zip = static_cast<mz_zip_archive*>(zipFile); + + MemsetZero(*zip); + if(!mz_zip_reader_init_mem(zip, file.GetRawData(), file.GetLength(), 0)) + { + delete zip; + zipFile = nullptr; + } + +} + + +CZipArchive::~CZipArchive() +//------------------------- +{ + mz_zip_archive *zip = static_cast<mz_zip_archive*>(zipFile); + + if(zip) + { + mz_zip_reader_end(zip); + + delete zip; + zipFile = nullptr; + } + + delete[] outFile.GetRawData(); +} + + +bool CZipArchive::IsArchive() const +//--------------------------------- +{ + return (zipFile != nullptr); +} + + +static inline std::string GetExtension(const std::string &filename) +//----------------------------------------------------------------- +{ + if(filename.find_last_of(".") != std::string::npos) + { + return filename.substr(filename.find_last_of(".") + 1); + } + return std::string(); +} + + +bool CZipArchive::ExtractFile() +//----------------------------- +{ + mz_zip_archive *zip = static_cast<mz_zip_archive*>(zipFile); + + if(!zip) + { + return false; + } + + mz_uint bestFile = (mz_uint)-1; + mz_uint64 biggestFile = 0; + for(mz_uint i = 0; i < mz_zip_reader_get_num_files(zip); ++i) + { + mz_zip_archive_file_stat stat; + MemsetZero(stat); + if(!mz_zip_reader_file_stat(zip, i, &stat)) + { + continue; + } + if(mz_zip_reader_is_file_a_directory(zip, i)) + { + continue; + } + if(mz_zip_reader_is_file_encrypted(zip, i)) + { + continue; + } + std::string ext = GetExtension(stat.m_filename); + if(std::find(extensions.begin(), extensions.end(), ext) != extensions.end()) + { + // File has a preferred extension: use it. + bestFile = i; + break; + } + if(ext != "diz" && ext != "nfo" && ext != "txt" && stat.m_uncomp_size >= biggestFile) + { + // If this isn't some kind of info file, we should maybe pick it. + bestFile = i; + biggestFile = stat.m_uncomp_size; + } + } + if(bestFile == (mz_uint)-1) + { + return false; + } + delete [] outFile.GetRawData(); + mz_zip_archive_file_stat stat; + MemsetZero(stat); + mz_zip_reader_file_stat(zip, bestFile, &stat); + char *data = new (std::nothrow) char[stat.m_uncomp_size]; + if(data != nullptr) + { + if(!mz_zip_reader_extract_to_mem(zip, bestFile, data, stat.m_uncomp_size, 0)) + { + delete [] data; + return false; + } + outFile = FileReader(data, stat.m_uncomp_size); + comment = std::string(stat.m_comment, stat.m_comment + stat.m_comment_size); + } + + return true; +} + + +std::string CZipArchive::GetComments() +//------------------------------------ +{ + mz_zip_archive *zip = static_cast<mz_zip_archive*>(zipFile); + + if(!zip) + { + return ""; + } + + return comment; +} + + +#endif // NO_ZLIB || NO_MINIZ Modified: trunk/OpenMPT/unarchiver/unzip.h =================================================================== --- trunk/OpenMPT/unarchiver/unzip.h 2013-10-19 13:31:36 UTC (rev 2929) +++ trunk/OpenMPT/unarchiver/unzip.h 2013-10-19 13:42:04 UTC (rev 2930) @@ -17,13 +17,14 @@ FileReader inFile, outFile; void *zipFile; const std::vector<const char *> &extensions; + std::string comment; public: FileReader GetOutputFile() const { return outFile; } bool IsArchive() const; bool ExtractFile(); - const char *GetComments(bool get); + std::string GetComments(); CZipArchive(FileReader &file, const std::vector<const char *> &ext); ~CZipArchive(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |