Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
96
Src/external_dependencies/openmpt-trunk/unarchiver/archive.h
Normal file
96
Src/external_dependencies/openmpt-trunk/unarchiver/archive.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* archive.h
|
||||
* ---------
|
||||
* Purpose: archive loader
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "openmpt/all/BuildSettings.hpp"
|
||||
|
||||
#include "../common/FileReader.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
enum class ArchiveFileType
|
||||
{
|
||||
Invalid,
|
||||
Normal,
|
||||
Special,
|
||||
};
|
||||
|
||||
struct ArchiveFileInfo
|
||||
{
|
||||
mpt::PathString name;
|
||||
ArchiveFileType type = ArchiveFileType::Invalid;
|
||||
uint64 size = 0;
|
||||
mpt::ustring comment;
|
||||
uint64 cookie1 = 0;
|
||||
uint64 cookie2 = 0;
|
||||
};
|
||||
|
||||
class IArchive
|
||||
{
|
||||
public:
|
||||
using const_iterator = std::vector<ArchiveFileInfo>::const_iterator;
|
||||
protected:
|
||||
IArchive() {}
|
||||
public:
|
||||
virtual ~IArchive() {}
|
||||
|
||||
public:
|
||||
virtual bool IsArchive() const = 0;
|
||||
virtual mpt::ustring GetComment() const = 0;
|
||||
virtual bool ExtractFile(std::size_t index) = 0;
|
||||
virtual FileReader GetOutputFile() const = 0;
|
||||
virtual std::size_t size() const = 0;
|
||||
virtual IArchive::const_iterator begin() const = 0;
|
||||
virtual IArchive::const_iterator end() const = 0;
|
||||
virtual const ArchiveFileInfo & operator [] (std::size_t index) const = 0;
|
||||
};
|
||||
|
||||
class ArchiveBase
|
||||
: public IArchive
|
||||
{
|
||||
protected:
|
||||
FileReader inFile;
|
||||
mpt::ustring comment;
|
||||
std::vector<ArchiveFileInfo> contents;
|
||||
std::vector<char> data;
|
||||
public:
|
||||
ArchiveBase(const FileReader &inFile)
|
||||
: inFile(inFile)
|
||||
{
|
||||
return;
|
||||
}
|
||||
~ArchiveBase() override
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool ExtractFile(std::size_t index) override { MPT_UNREFERENCED_PARAMETER(index); return false; } // overwrite this
|
||||
public:
|
||||
bool IsArchive() const override
|
||||
{
|
||||
return !contents.empty();
|
||||
}
|
||||
mpt::ustring GetComment() const override
|
||||
{
|
||||
return comment;
|
||||
}
|
||||
FileReader GetOutputFile() const override
|
||||
{
|
||||
return FileReader(mpt::byte_cast<mpt::const_byte_span>(mpt::as_span(data)));
|
||||
}
|
||||
std::size_t size() const override { return contents.size(); }
|
||||
IArchive::const_iterator begin() const override { return contents.begin(); }
|
||||
IArchive::const_iterator end() const override { return contents.end(); }
|
||||
const ArchiveFileInfo & operator [] (std::size_t index) const override { return contents[index]; }
|
||||
};
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* unancient.cpp
|
||||
* -------------
|
||||
* Purpose: Implementation file for extracting modules from compressed files supported by libancient
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "unancient.h"
|
||||
|
||||
#ifdef MPT_WITH_ANCIENT
|
||||
#include <ancient/ancient.hpp>
|
||||
#endif // MPT_WITH_ANCIENT
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
#ifdef MPT_WITH_ANCIENT
|
||||
|
||||
|
||||
CAncientArchive::CAncientArchive(FileReader &file)
|
||||
: ArchiveBase(file)
|
||||
{
|
||||
inFile.Rewind();
|
||||
try
|
||||
{
|
||||
auto dataView = inFile.GetPinnedView();
|
||||
if(!ancient::Decompressor::detect(mpt::byte_cast<const std::uint8_t*>(dataView.data()), dataView.size()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ancient::Decompressor decompressor{mpt::byte_cast<const std::uint8_t*>(dataView.data()), dataView.size(), true, true};
|
||||
if(decompressor.getImageSize() || decompressor.getImageOffset())
|
||||
{
|
||||
// skip disk images
|
||||
return;
|
||||
}
|
||||
ArchiveFileInfo fileInfo;
|
||||
fileInfo.name = inFile.GetOptionalFileName().value_or(P_(""));
|
||||
fileInfo.type = ArchiveFileType::Normal;
|
||||
fileInfo.size = decompressor.getRawSize().value_or(0);
|
||||
contents.push_back(fileInfo);
|
||||
} catch(const ancient::Error &)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CAncientArchive::~CAncientArchive()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool CAncientArchive::ExtractFile(std::size_t index)
|
||||
{
|
||||
if(index >= contents.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
data.clear();
|
||||
inFile.Rewind();
|
||||
try
|
||||
{
|
||||
auto dataView = inFile.GetPinnedView();
|
||||
ancient::Decompressor decompressor{mpt::byte_cast<const std::uint8_t*>(dataView.data()), dataView.size(), true, true};
|
||||
data = mpt::buffer_cast<std::vector<char>>(decompressor.decompress(true));
|
||||
} catch (const ancient::Error &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (data.size() > 0);
|
||||
}
|
||||
|
||||
|
||||
#endif // MPT_WITH_ANCIENT
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* ununancient.h
|
||||
* -------------
|
||||
* Purpose: Header file extracting modules from compressed files supported by libancient
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "openmpt/all/BuildSettings.hpp"
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
#ifdef MPT_WITH_ANCIENT
|
||||
|
||||
class CAncientArchive
|
||||
: public ArchiveBase
|
||||
{
|
||||
public:
|
||||
CAncientArchive(FileReader &file);
|
||||
virtual ~CAncientArchive();
|
||||
public:
|
||||
bool ExtractFile(std::size_t index) override;
|
||||
};
|
||||
|
||||
#endif // MPT_WITH_ANCIENT
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* unarchiver.cpp
|
||||
* --------------
|
||||
* Purpose: archive loader
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "unarchiver.h"
|
||||
#include "../common/FileReader.h"
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
CUnarchiver::CUnarchiver(FileReader &file)
|
||||
: impl(nullptr)
|
||||
, inFile(file)
|
||||
, emptyArchive(inFile)
|
||||
#if (defined(MPT_WITH_ZLIB) && defined(MPT_WITH_MINIZIP)) || defined(MPT_WITH_MINIZ)
|
||||
, zipArchive(inFile)
|
||||
#endif
|
||||
#ifdef MPT_WITH_LHASA
|
||||
, lhaArchive(inFile)
|
||||
#endif
|
||||
#if defined(MPT_WITH_ZLIB) || defined(MPT_WITH_MINIZ)
|
||||
, gzipArchive(inFile)
|
||||
#endif
|
||||
#ifdef MPT_WITH_UNRAR
|
||||
, rarArchive(inFile)
|
||||
#endif
|
||||
#ifdef MPT_WITH_ANCIENT
|
||||
, ancientArchive(inFile)
|
||||
#endif
|
||||
{
|
||||
inFile.Rewind();
|
||||
#if (defined(MPT_WITH_ZLIB) && defined(MPT_WITH_MINIZIP)) || defined(MPT_WITH_MINIZ)
|
||||
if(zipArchive.IsArchive()) { impl = &zipArchive; return; }
|
||||
#endif
|
||||
#ifdef MPT_WITH_LHASA
|
||||
if(lhaArchive.IsArchive()) { impl = &lhaArchive; return; }
|
||||
#endif
|
||||
#if defined(MPT_WITH_ZLIB) || defined(MPT_WITH_MINIZ)
|
||||
if(gzipArchive.IsArchive()) { impl = &gzipArchive; return; }
|
||||
#endif
|
||||
#ifdef MPT_WITH_UNRAR
|
||||
if(rarArchive.IsArchive()) { impl = &rarArchive; return; }
|
||||
#endif
|
||||
#ifdef MPT_WITH_ANCIENT
|
||||
if(ancientArchive.IsArchive()) { impl = &ancientArchive; return; }
|
||||
#endif
|
||||
impl = &emptyArchive;
|
||||
}
|
||||
|
||||
|
||||
CUnarchiver::~CUnarchiver()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static inline std::string GetExtension(const std::string &filename)
|
||||
{
|
||||
if(filename.find_last_of(".") != std::string::npos)
|
||||
{
|
||||
return mpt::ToLowerCaseAscii(filename.substr(filename.find_last_of(".") + 1));
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
std::size_t CUnarchiver::FindBestFile(const std::vector<const char *> &extensions)
|
||||
{
|
||||
if(!IsArchive())
|
||||
{
|
||||
return failIndex;
|
||||
}
|
||||
uint64 biggestSize = 0;
|
||||
std::size_t bestIndex = failIndex;
|
||||
for(std::size_t i = 0; i < size(); ++i)
|
||||
{
|
||||
if(operator[](i).type != ArchiveFileType::Normal)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const std::string ext = GetExtension(operator[](i).name.ToUTF8());
|
||||
|
||||
if(ext == "diz" || ext == "nfo" || ext == "txt")
|
||||
{
|
||||
// we do not want these
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compare with list of preferred extensions
|
||||
if(mpt::contains(extensions, ext))
|
||||
{
|
||||
bestIndex = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if(operator[](i).size >= biggestSize)
|
||||
{
|
||||
biggestSize = operator[](i).size;
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
return bestIndex;
|
||||
}
|
||||
|
||||
|
||||
bool CUnarchiver::ExtractBestFile(const std::vector<const char *> &extensions)
|
||||
{
|
||||
std::size_t bestFile = FindBestFile(extensions);
|
||||
if(bestFile == failIndex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ExtractFile(bestFile);
|
||||
}
|
||||
|
||||
|
||||
bool CUnarchiver::IsArchive() const
|
||||
{
|
||||
return impl->IsArchive();
|
||||
}
|
||||
|
||||
|
||||
mpt::ustring CUnarchiver::GetComment() const
|
||||
{
|
||||
return impl->GetComment();
|
||||
}
|
||||
|
||||
|
||||
bool CUnarchiver::ExtractFile(std::size_t index)
|
||||
{
|
||||
return impl->ExtractFile(index);
|
||||
}
|
||||
|
||||
|
||||
FileReader CUnarchiver::GetOutputFile() const
|
||||
{
|
||||
return impl->GetOutputFile();
|
||||
}
|
||||
|
||||
|
||||
std::size_t CUnarchiver::size() const
|
||||
{
|
||||
return impl->size();
|
||||
}
|
||||
|
||||
|
||||
IArchive::const_iterator CUnarchiver::begin() const
|
||||
{
|
||||
return impl->begin();
|
||||
}
|
||||
|
||||
|
||||
IArchive::const_iterator CUnarchiver::end() const
|
||||
{
|
||||
return impl->end();
|
||||
}
|
||||
|
||||
|
||||
const ArchiveFileInfo & CUnarchiver::operator [] (std::size_t index) const
|
||||
{
|
||||
return impl->operator[](index);
|
||||
}
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* unarchiver.h
|
||||
* ------------
|
||||
* Purpose: archive loader
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "openmpt/all/BuildSettings.hpp"
|
||||
|
||||
#include "../common/FileReader.h"
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
#if (defined(MPT_WITH_ZLIB) && defined(MPT_WITH_MINIZIP)) || defined(MPT_WITH_MINIZ)
|
||||
#include "unzip.h"
|
||||
#endif
|
||||
#ifdef MPT_WITH_LHASA
|
||||
#include "unlha.h"
|
||||
#endif
|
||||
#if defined(MPT_WITH_ZLIB) || defined(MPT_WITH_MINIZ)
|
||||
#include "ungzip.h"
|
||||
#endif
|
||||
#ifdef MPT_WITH_UNRAR
|
||||
#include "unrar.h"
|
||||
#endif
|
||||
#ifdef MPT_WITH_ANCIENT
|
||||
#include "unancient.h"
|
||||
#endif
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
class CUnarchiver : public IArchive
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
IArchive *impl;
|
||||
|
||||
FileReader inFile;
|
||||
|
||||
ArchiveBase emptyArchive;
|
||||
#if (defined(MPT_WITH_ZLIB) && defined(MPT_WITH_MINIZIP)) || defined(MPT_WITH_MINIZ)
|
||||
CZipArchive zipArchive;
|
||||
#endif
|
||||
#ifdef MPT_WITH_LHASA
|
||||
CLhaArchive lhaArchive;
|
||||
#endif
|
||||
#if defined(MPT_WITH_ZLIB) || defined(MPT_WITH_MINIZ)
|
||||
CGzipArchive gzipArchive;
|
||||
#endif
|
||||
#ifdef MPT_WITH_UNRAR
|
||||
CRarArchive rarArchive;
|
||||
#endif
|
||||
#ifdef MPT_WITH_ANCIENT
|
||||
CAncientArchive ancientArchive;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
CUnarchiver(FileReader &file);
|
||||
~CUnarchiver() override;
|
||||
|
||||
bool IsArchive() const override;
|
||||
mpt::ustring GetComment() const override;
|
||||
bool ExtractFile(std::size_t index) override;
|
||||
FileReader GetOutputFile() const override;
|
||||
std::size_t size() const override;
|
||||
IArchive::const_iterator begin() const override;
|
||||
IArchive::const_iterator end() const override;
|
||||
const ArchiveFileInfo & operator [] (std::size_t index) const override;
|
||||
|
||||
public:
|
||||
|
||||
static const std::size_t failIndex = (std::size_t)-1;
|
||||
|
||||
std::size_t FindBestFile(const std::vector<const char *> &extensions);
|
||||
bool ExtractBestFile(const std::vector<const char *> &extensions);
|
||||
|
||||
};
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
147
Src/external_dependencies/openmpt-trunk/unarchiver/ungzip.cpp
Normal file
147
Src/external_dependencies/openmpt-trunk/unarchiver/ungzip.cpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* ungzip.cpp
|
||||
* ----------
|
||||
* Purpose: Implementation file for extracting modules from .gz archives
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "../common/FileReader.h"
|
||||
#include "ungzip.h"
|
||||
|
||||
#if defined(MPT_WITH_ZLIB) || defined(MPT_WITH_MINIZ)
|
||||
|
||||
#if defined(MPT_WITH_ZLIB)
|
||||
#include <zlib.h>
|
||||
#elif defined(MPT_WITH_MINIZ)
|
||||
#include <miniz/miniz.h>
|
||||
#endif
|
||||
|
||||
#endif // MPT_WITH_ZLIB || MPT_WITH_MINIZ
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
#if defined(MPT_WITH_ZLIB) || defined(MPT_WITH_MINIZ)
|
||||
|
||||
|
||||
CGzipArchive::CGzipArchive(const FileReader &file) : ArchiveBase(file)
|
||||
{
|
||||
inFile.Rewind();
|
||||
inFile.ReadStruct(header);
|
||||
|
||||
// Check header data + file size
|
||||
if(header.magic1 != GZ_HMAGIC1 || header.magic2 != GZ_HMAGIC2 || header.method != GZ_HMDEFLATE || (header.flags & GZ_FRESERVED) != 0
|
||||
|| inFile.GetLength() <= sizeof(GZheader) + sizeof(GZtrailer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ArchiveFileInfo info;
|
||||
info.type = ArchiveFileType::Normal;
|
||||
contents.push_back(info);
|
||||
}
|
||||
|
||||
|
||||
CGzipArchive::~CGzipArchive()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool CGzipArchive::ExtractFile(std::size_t index)
|
||||
{
|
||||
if(index >= contents.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read trailer
|
||||
GZtrailer trailer;
|
||||
inFile.Seek(inFile.GetLength() - sizeof(GZtrailer));
|
||||
inFile.ReadStruct(trailer);
|
||||
|
||||
// Continue reading header
|
||||
inFile.Seek(sizeof(GZheader));
|
||||
|
||||
// Extra block present? (skip the extra data)
|
||||
if(header.flags & GZ_FEXTRA)
|
||||
{
|
||||
inFile.Skip(inFile.ReadUint16LE());
|
||||
}
|
||||
|
||||
// Filename present? (ignore)
|
||||
if(header.flags & GZ_FNAME)
|
||||
{
|
||||
while(inFile.ReadUint8() != 0);
|
||||
}
|
||||
|
||||
// Comment present? (ignore)
|
||||
if(header.flags & GZ_FCOMMENT)
|
||||
{
|
||||
while(inFile.ReadUint8() != 0);
|
||||
}
|
||||
|
||||
// CRC16 present? (ignore)
|
||||
if(header.flags & GZ_FHCRC)
|
||||
{
|
||||
inFile.Skip(2);
|
||||
}
|
||||
|
||||
// Well, this is a bit small when deflated.
|
||||
if(!inFile.CanRead(sizeof(GZtrailer)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
data.reserve(inFile.BytesLeft());
|
||||
} catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Inflate!
|
||||
z_stream strm{};
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = 0;
|
||||
strm.next_in = Z_NULL;
|
||||
if(inflateInit2(&strm, -15) != Z_OK)
|
||||
return false;
|
||||
int retVal = Z_OK;
|
||||
uint32 crc = 0;
|
||||
auto bytesLeft = inFile.BytesLeft() - sizeof(GZtrailer);
|
||||
do
|
||||
{
|
||||
std::array<char, mpt::IO::BUFFERSIZE_SMALL> inBuffer, outBuffer;
|
||||
strm.avail_in = static_cast<uInt>(std::min(static_cast<FileReader::pos_type>(inBuffer.size()), bytesLeft));
|
||||
inFile.ReadStructPartial(inBuffer, strm.avail_in);
|
||||
strm.next_in = reinterpret_cast<Bytef *>(inBuffer.data());
|
||||
bytesLeft -= strm.avail_in;
|
||||
do
|
||||
{
|
||||
strm.avail_out = static_cast<uInt>(outBuffer.size());
|
||||
strm.next_out = reinterpret_cast<Bytef *>(outBuffer.data());
|
||||
retVal = inflate(&strm, Z_NO_FLUSH);
|
||||
const auto output = mpt::as_span(outBuffer.data(), outBuffer.data() + outBuffer.size() - strm.avail_out);
|
||||
crc = crc32(crc, reinterpret_cast<Bytef *>(output.data()), static_cast<uInt>(output.size()));
|
||||
data.insert(data.end(), output.begin(), output.end());
|
||||
} while(strm.avail_out == 0);
|
||||
} while(retVal == Z_OK && bytesLeft);
|
||||
inflateEnd(&strm);
|
||||
|
||||
// Everything went OK? Check return code, number of written bytes and CRC32.
|
||||
return retVal == Z_STREAM_END && trailer.isize == static_cast<uint32>(strm.total_out) && trailer.crc32_ == crc;
|
||||
}
|
||||
|
||||
|
||||
#endif // MPT_WITH_ZLIB || MPT_WITH_MINIZ
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
74
Src/external_dependencies/openmpt-trunk/unarchiver/ungzip.h
Normal file
74
Src/external_dependencies/openmpt-trunk/unarchiver/ungzip.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* ungzip.h
|
||||
* --------
|
||||
* Purpose: Header file for .gz loader
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "openmpt/all/BuildSettings.hpp"
|
||||
#include "openmpt/base/Endian.hpp"
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
#if defined(MPT_WITH_ZLIB) || defined(MPT_WITH_MINIZ)
|
||||
|
||||
class CGzipArchive : public ArchiveBase
|
||||
{
|
||||
public:
|
||||
struct GZheader
|
||||
{
|
||||
uint8le magic1; // 0x1F
|
||||
uint8le magic2; // 0x8B
|
||||
uint8le method; // 0-7 = reserved, 8 = deflate
|
||||
uint8le flags; // See GZ_F* constants
|
||||
uint32le mtime; // UNIX time
|
||||
uint8le xflags; // Available for use by specific compression methods. We ignore this.
|
||||
uint8le os; // Which OS was used to compress the file? We also ignore this.
|
||||
};
|
||||
|
||||
struct GZtrailer
|
||||
{
|
||||
uint32le crc32_; // CRC32 of decompressed data
|
||||
uint32le isize; // Size of decompressed data modulo 2^32
|
||||
};
|
||||
|
||||
protected:
|
||||
enum MagicBytes
|
||||
{
|
||||
GZ_HMAGIC1 = 0x1F,
|
||||
GZ_HMAGIC2 = 0x8B,
|
||||
GZ_HMDEFLATE = 0x08,
|
||||
};
|
||||
|
||||
enum HeaderFlags
|
||||
{
|
||||
GZ_FTEXT = 0x01, // File is probably ASCII text (who cares)
|
||||
GZ_FHCRC = 0x02, // CRC16 present
|
||||
GZ_FEXTRA = 0x04, // Extra fields present
|
||||
GZ_FNAME = 0x08, // Original filename present
|
||||
GZ_FCOMMENT = 0x10, // Comment is present
|
||||
GZ_FRESERVED = (~(GZ_FTEXT | GZ_FHCRC | GZ_FEXTRA | GZ_FNAME | GZ_FCOMMENT))
|
||||
};
|
||||
|
||||
GZheader header;
|
||||
|
||||
public:
|
||||
|
||||
bool ExtractFile(std::size_t index) override;
|
||||
|
||||
CGzipArchive(const FileReader &file);
|
||||
~CGzipArchive() override;
|
||||
};
|
||||
|
||||
MPT_BINARY_STRUCT(CGzipArchive::GZheader, 10)
|
||||
MPT_BINARY_STRUCT(CGzipArchive::GZtrailer, 8)
|
||||
|
||||
#endif // MPT_WITH_ZLIB || MPT_WITH_MINIZ
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
162
Src/external_dependencies/openmpt-trunk/unarchiver/unlha.cpp
Normal file
162
Src/external_dependencies/openmpt-trunk/unarchiver/unlha.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* unlha.cpp
|
||||
* ---------
|
||||
* Purpose: Implementation file for extracting modules from .lha archives, making use of lhasa
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "unlha.h"
|
||||
|
||||
#ifdef MPT_WITH_LHASA
|
||||
#include "lhasa.h"
|
||||
#endif // MPT_WITH_LHASA
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
#ifdef MPT_WITH_LHASA
|
||||
|
||||
|
||||
static int LHAreadFileReader(void *handle, void *buf, size_t buf_len)
|
||||
{
|
||||
FileReader *f = reinterpret_cast<FileReader*>(handle);
|
||||
int read_len = mpt::saturate_cast<int>(buf_len);
|
||||
int result = mpt::saturate_cast<int>(f->ReadRaw(mpt::span(mpt::void_cast<std::byte*>(buf), read_len)).size());
|
||||
if(result == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int LHAskipFileReader(void *handle, size_t bytes)
|
||||
{
|
||||
FileReader *f = reinterpret_cast<FileReader*>(handle);
|
||||
if(f->CanRead(bytes))
|
||||
{
|
||||
f->Skip(bytes);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void LHAcloseFileReader(void * /*handle*/)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static LHAInputStreamType vtable =
|
||||
{
|
||||
LHAreadFileReader,
|
||||
LHAskipFileReader,
|
||||
LHAcloseFileReader
|
||||
};
|
||||
|
||||
|
||||
CLhaArchive::CLhaArchive(FileReader &file) : ArchiveBase(file), inputstream(nullptr), reader(nullptr), firstfile(nullptr)
|
||||
{
|
||||
OpenArchive();
|
||||
for(LHAFileHeader *fileheader = firstfile; fileheader; fileheader = lha_reader_next_file(reader))
|
||||
{
|
||||
ArchiveFileInfo info;
|
||||
info.name = mpt::PathString::FromUnicode(mpt::ToUnicode(mpt::Charset::Amiga_no_C1, fileheader->filename));
|
||||
info.size = fileheader->length;
|
||||
info.type = ArchiveFileType::Normal;
|
||||
contents.push_back(info);
|
||||
}
|
||||
CloseArchive();
|
||||
}
|
||||
|
||||
|
||||
CLhaArchive::~CLhaArchive()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void CLhaArchive::OpenArchive()
|
||||
{
|
||||
inFile.Rewind();
|
||||
inputstream = lha_input_stream_new(&vtable, &inFile);
|
||||
if(inputstream)
|
||||
{
|
||||
reader = lha_reader_new(inputstream);
|
||||
}
|
||||
if(reader)
|
||||
{
|
||||
lha_reader_set_dir_policy(reader, LHA_READER_DIR_END_OF_DIR);
|
||||
firstfile = lha_reader_next_file(reader);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CLhaArchive::CloseArchive()
|
||||
{
|
||||
if(reader)
|
||||
{
|
||||
lha_reader_free(reader);
|
||||
reader = nullptr;
|
||||
}
|
||||
if(inputstream)
|
||||
{
|
||||
lha_input_stream_free(inputstream);
|
||||
inputstream = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CLhaArchive::ExtractFile(std::size_t index)
|
||||
{
|
||||
if(index >= contents.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
data.clear();
|
||||
OpenArchive();
|
||||
const std::size_t bufSize = 4096;
|
||||
std::size_t i = 0;
|
||||
for(LHAFileHeader *fileheader = firstfile; fileheader; fileheader = lha_reader_next_file(reader))
|
||||
{
|
||||
if(index == i)
|
||||
{
|
||||
data.clear();
|
||||
std::size_t countRead = 0;
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
data.resize(data.size() + bufSize);
|
||||
} catch(...)
|
||||
{
|
||||
CloseArchive();
|
||||
return false;
|
||||
}
|
||||
countRead = lha_reader_read(reader, &data[data.size() - bufSize], bufSize);
|
||||
if(countRead < bufSize)
|
||||
{
|
||||
try
|
||||
{
|
||||
data.resize(data.size() - (bufSize - countRead));
|
||||
} catch(...)
|
||||
{
|
||||
CloseArchive();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} while(countRead > 0);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
CloseArchive();
|
||||
return data.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
#endif // MPT_WITH_LHASA
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
46
Src/external_dependencies/openmpt-trunk/unarchiver/unlha.h
Normal file
46
Src/external_dependencies/openmpt-trunk/unarchiver/unlha.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* unlha.h
|
||||
* -------
|
||||
* Purpose: Header file for .lha loader
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "openmpt/all/BuildSettings.hpp"
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
|
||||
#ifdef MPT_WITH_LHASA
|
||||
|
||||
typedef struct _LHAInputStream LHAInputStream;
|
||||
typedef struct _LHAReader LHAReader;
|
||||
typedef struct _LHAFileHeader LHAFileHeader;
|
||||
|
||||
#endif // MPT_WITH_LHASA
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
#ifdef MPT_WITH_LHASA
|
||||
|
||||
class CLhaArchive : public ArchiveBase
|
||||
{
|
||||
private:
|
||||
LHAInputStream *inputstream;
|
||||
LHAReader *reader;
|
||||
LHAFileHeader *firstfile;
|
||||
void OpenArchive();
|
||||
void CloseArchive();
|
||||
public:
|
||||
CLhaArchive(FileReader &file);
|
||||
virtual ~CLhaArchive();
|
||||
public:
|
||||
bool ExtractFile(std::size_t index) override;
|
||||
};
|
||||
|
||||
#endif // MPT_WITH_LHASA
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
279
Src/external_dependencies/openmpt-trunk/unarchiver/unrar.cpp
Normal file
279
Src/external_dependencies/openmpt-trunk/unarchiver/unrar.cpp
Normal file
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* unrar.cpp
|
||||
* ---------
|
||||
* Purpose: Implementation file for extracting modules from .rar archives
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "unrar.h"
|
||||
|
||||
#ifdef MPT_WITH_UNRAR
|
||||
|
||||
#include "../common/mptFileIO.h"
|
||||
|
||||
#if MPT_OS_WINDOWS
|
||||
#include <windows.h>
|
||||
#else // !MPT_OS_WINDOWS
|
||||
#ifdef _UNIX
|
||||
#define MPT_UNRAR_UNIX_WAS_DEFINED
|
||||
#else
|
||||
#define _UNIX
|
||||
#endif
|
||||
#endif // MPT_OS_WINDOWS
|
||||
|
||||
#include "unrar/dll.hpp"
|
||||
|
||||
#if !MPT_OS_WINDOWS
|
||||
#ifndef MPT_UNRAR_UNIX_WAS_DEFINED
|
||||
#undef _UNIX
|
||||
#undef MPT_UNRAR_UNIX_WAS_DEFINED
|
||||
#endif
|
||||
#endif // !MPT_OS_WINDOWS
|
||||
|
||||
#endif // MPT_WITH_UNRAR
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
#ifdef MPT_WITH_UNRAR
|
||||
|
||||
|
||||
struct RARHandle // RAII
|
||||
{
|
||||
HANDLE rar = nullptr;
|
||||
explicit RARHandle(HANDLE rar_) : rar(rar_) { return; }
|
||||
RARHandle(const RARHandle &) = delete;
|
||||
~RARHandle() { if(rar) RARCloseArchive(rar); }
|
||||
|
||||
operator HANDLE () const { return rar; }
|
||||
};
|
||||
|
||||
|
||||
static int CALLBACK RARCallback(unsigned int msg, LPARAM userData, LPARAM p1, LPARAM p2)
|
||||
{
|
||||
int result = 0;
|
||||
CRarArchive *that = reinterpret_cast<CRarArchive *>(userData);
|
||||
switch(msg)
|
||||
{
|
||||
case UCM_PROCESSDATA:
|
||||
// Receive extracted data
|
||||
that->RARCallbackProcessData(reinterpret_cast<const char *>(p1), p2);
|
||||
result = 1;
|
||||
break;
|
||||
default:
|
||||
// No support for passwords or volumes
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void CRarArchive::RARCallbackProcessData(const char * buf, std::size_t size)
|
||||
{
|
||||
if(!captureCurrentFile)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mpt::append(data, buf, buf + size);
|
||||
}
|
||||
|
||||
|
||||
CRarArchive::CRarArchive(FileReader &file)
|
||||
: ArchiveBase(file)
|
||||
{
|
||||
// NOTE:
|
||||
// We open the archive twice, once for listing the contents in the
|
||||
// constructor and once for actual decompression in ExtractFile.
|
||||
// For solid archives, listing the contents via RAR_OM_LIST is way faster.
|
||||
// The overhead of opening twice for non-solid archives is negligable if the
|
||||
// archive does not contain a lot of files (and archives with large amount of
|
||||
// files are pretty useless for OpenMPT anyway).
|
||||
|
||||
// Early reject files with no Rar! magic
|
||||
// so that we do not have to instantiate OnDiskFileWrapper.
|
||||
inFile.Rewind();
|
||||
if(!inFile.ReadMagic("Rar!\x1A"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
inFile.Rewind();
|
||||
|
||||
diskFile = std::make_unique<OnDiskFileWrapper>(inFile);
|
||||
if(!diskFile->IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring ArcName = diskFile->GetFilename().ToWide();
|
||||
std::vector<wchar_t> ArcNameBuf(ArcName.c_str(), ArcName.c_str() + ArcName.length() + 1);
|
||||
std::vector<wchar_t> CmtBuf(65536);
|
||||
RAROpenArchiveDataEx ArchiveData = {};
|
||||
ArchiveData.OpenMode = RAR_OM_LIST;
|
||||
ArchiveData.ArcNameW = ArcNameBuf.data();
|
||||
ArchiveData.CmtBufW = CmtBuf.data();
|
||||
ArchiveData.CmtBufSize = static_cast<unsigned int>(CmtBuf.size());
|
||||
RARHandle rar(RAROpenArchiveEx(&ArchiveData));
|
||||
if(!rar)
|
||||
{
|
||||
Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ArchiveData.CmtState)
|
||||
{
|
||||
case 1:
|
||||
if(ArchiveData.CmtSize)
|
||||
{
|
||||
comment = mpt::ToUnicode(std::wstring(ArchiveData.CmtBufW, ArchiveData.CmtBufW + ArchiveData.CmtSize - 1));
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case 0:
|
||||
comment = mpt::ustring();
|
||||
break;
|
||||
default:
|
||||
Reset();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
bool eof = false;
|
||||
int RARResult = 0;
|
||||
while(!eof)
|
||||
{
|
||||
RARHeaderDataEx HeaderData = {};
|
||||
RARResult = RARReadHeaderEx(rar, &HeaderData);
|
||||
switch(RARResult)
|
||||
{
|
||||
case ERAR_SUCCESS:
|
||||
break;
|
||||
case ERAR_END_ARCHIVE:
|
||||
eof = true;
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
Reset();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
ArchiveFileInfo fileInfo;
|
||||
fileInfo.name = mpt::PathString::FromWide(HeaderData.FileNameW);
|
||||
fileInfo.type = ArchiveFileType::Normal;
|
||||
fileInfo.size = HeaderData.UnpSize;
|
||||
contents.push_back(fileInfo);
|
||||
RARResult = RARProcessFileW(rar, RAR_SKIP, NULL, NULL);
|
||||
switch(RARResult)
|
||||
{
|
||||
case ERAR_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
Reset();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
CRarArchive::~CRarArchive()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool CRarArchive::ExtractFile(std::size_t index)
|
||||
{
|
||||
|
||||
if(!diskFile || !diskFile->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(index >= contents.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring ArcName = diskFile->GetFilename().ToWide();
|
||||
std::vector<wchar_t> ArcNameBuf(ArcName.c_str(), ArcName.c_str() + ArcName.length() + 1);
|
||||
RAROpenArchiveDataEx ArchiveData = {};
|
||||
ArchiveData.OpenMode = RAR_OM_EXTRACT;
|
||||
ArchiveData.ArcNameW = ArcNameBuf.data();
|
||||
ArchiveData.Callback = RARCallback;
|
||||
ArchiveData.UserData = reinterpret_cast<LPARAM>(this);
|
||||
RARHandle rar(RAROpenArchiveEx(&ArchiveData));
|
||||
if(!rar)
|
||||
{
|
||||
ResetFile();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t i = 0;
|
||||
int RARResult = 0;
|
||||
bool eof = false;
|
||||
while(!eof)
|
||||
{
|
||||
RARHeaderDataEx HeaderData = {};
|
||||
RARResult = RARReadHeaderEx(rar, &HeaderData);
|
||||
switch(RARResult)
|
||||
{
|
||||
case ERAR_SUCCESS:
|
||||
break;
|
||||
case ERAR_END_ARCHIVE:
|
||||
eof = true;
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
ResetFile();
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
captureCurrentFile = (i == index);
|
||||
RARResult = RARProcessFileW(rar, captureCurrentFile ? RAR_TEST : RAR_SKIP, NULL, NULL);
|
||||
switch(RARResult)
|
||||
{
|
||||
case ERAR_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
ResetFile();
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
if(captureCurrentFile)
|
||||
{ // done
|
||||
return true;
|
||||
}
|
||||
captureCurrentFile = false;
|
||||
++i;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CRarArchive::Reset()
|
||||
{
|
||||
captureCurrentFile = false;
|
||||
comment = mpt::ustring();
|
||||
contents = std::vector<ArchiveFileInfo>();
|
||||
data = std::vector<char>();
|
||||
}
|
||||
|
||||
|
||||
void CRarArchive::ResetFile()
|
||||
{
|
||||
captureCurrentFile = false;
|
||||
data = std::vector<char>();
|
||||
}
|
||||
|
||||
|
||||
#endif // MPT_WITH_UNRAR
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
48
Src/external_dependencies/openmpt-trunk/unarchiver/unrar.h
Normal file
48
Src/external_dependencies/openmpt-trunk/unarchiver/unrar.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* unrar.h
|
||||
* -------
|
||||
* Purpose: Header file for .rar loader
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "openmpt/all/BuildSettings.hpp"
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
#ifdef MPT_WITH_UNRAR
|
||||
|
||||
class CRarArchive
|
||||
: public ArchiveBase
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
std::unique_ptr<OnDiskFileWrapper> diskFile;
|
||||
bool captureCurrentFile = false;
|
||||
|
||||
public:
|
||||
CRarArchive(FileReader &file);
|
||||
~CRarArchive() override;
|
||||
|
||||
bool ExtractFile(std::size_t index) override;
|
||||
|
||||
public:
|
||||
|
||||
void RARCallbackProcessData(const char * data, std::size_t size);
|
||||
|
||||
private:
|
||||
|
||||
void Reset();
|
||||
void ResetFile();
|
||||
|
||||
};
|
||||
|
||||
#endif // MPT_WITH_UNRAR
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
315
Src/external_dependencies/openmpt-trunk/unarchiver/unzip.cpp
Normal file
315
Src/external_dependencies/openmpt-trunk/unarchiver/unzip.cpp
Normal file
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
* unzip.cpp
|
||||
* ---------
|
||||
* Purpose: Implementation file for extracting modules from .zip archives, making use of MiniZip (from the zlib contrib package)
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "../common/FileReader.h"
|
||||
#include "unzip.h"
|
||||
#include "../common/misc_util.h"
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#if defined(MPT_WITH_ZLIB) && defined(MPT_WITH_MINIZIP)
|
||||
#include <contrib/minizip/unzip.h>
|
||||
#elif defined(MPT_WITH_MINIZ)
|
||||
#include <miniz/miniz.h>
|
||||
#endif
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
#if defined(MPT_WITH_ZLIB) && defined(MPT_WITH_MINIZIP)
|
||||
|
||||
|
||||
// Low-level file abstractions for in-memory file handling
|
||||
struct ZipFileAbstraction
|
||||
{
|
||||
static voidpf ZCALLBACK fopen64_mem(voidpf opaque, const void *, int mode)
|
||||
{
|
||||
FileReader &file = *static_cast<FileReader *>(opaque);
|
||||
if((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_WRITE)
|
||||
{
|
||||
return nullptr;
|
||||
} else
|
||||
{
|
||||
file.Rewind();
|
||||
return opaque;
|
||||
}
|
||||
}
|
||||
|
||||
static uLong ZCALLBACK fread_mem(voidpf opaque, voidpf, void *buf, uLong size)
|
||||
{
|
||||
FileReader &file = *static_cast<FileReader *>(opaque);
|
||||
return mpt::saturate_cast<uLong>(file.ReadRaw(mpt::span(mpt::void_cast<std::byte*>(buf), size)).size());
|
||||
}
|
||||
|
||||
static uLong ZCALLBACK fwrite_mem(voidpf, voidpf, const void *, uLong)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ZPOS64_T ZCALLBACK ftell64_mem(voidpf opaque, voidpf)
|
||||
{
|
||||
FileReader &file = *static_cast<FileReader *>(opaque);
|
||||
return file.GetPosition();
|
||||
}
|
||||
|
||||
static long ZCALLBACK fseek64_mem(voidpf opaque, voidpf, ZPOS64_T offset, int origin)
|
||||
{
|
||||
FileReader &file = *static_cast<FileReader *>(opaque);
|
||||
ZPOS64_T destination = 0;
|
||||
switch(origin)
|
||||
{
|
||||
case ZLIB_FILEFUNC_SEEK_CUR:
|
||||
destination = static_cast<ZPOS64_T>(file.GetPosition()) + offset;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_END:
|
||||
destination = static_cast<ZPOS64_T>(file.GetLength()) + offset;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_SET:
|
||||
destination = offset;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if(!mpt::in_range<FileReader::off_t>(destination))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return (file.Seek(static_cast<FileReader::off_t>(destination)) ? 0 : 1);
|
||||
}
|
||||
|
||||
static int ZCALLBACK fclose_mem(voidpf, voidpf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ZCALLBACK ferror_mem(voidpf, voidpf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
CZipArchive::CZipArchive(FileReader &file)
|
||||
: ArchiveBase(file)
|
||||
, zipFile(nullptr)
|
||||
{
|
||||
zlib_filefunc64_def functions =
|
||||
{
|
||||
ZipFileAbstraction::fopen64_mem,
|
||||
ZipFileAbstraction::fread_mem,
|
||||
ZipFileAbstraction::fwrite_mem,
|
||||
ZipFileAbstraction::ftell64_mem,
|
||||
ZipFileAbstraction::fseek64_mem,
|
||||
ZipFileAbstraction::fclose_mem,
|
||||
ZipFileAbstraction::ferror_mem,
|
||||
&inFile
|
||||
};
|
||||
|
||||
zipFile = unzOpen2_64(nullptr, &functions);
|
||||
|
||||
if(zipFile == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// read comment
|
||||
{
|
||||
unz_global_info info;
|
||||
if(unzGetGlobalInfo(zipFile, &info) == UNZ_OK)
|
||||
{
|
||||
if(info.size_comment > 0)
|
||||
{
|
||||
if(info.size_comment < Util::MaxValueOfType(info.size_comment))
|
||||
{
|
||||
info.size_comment++;
|
||||
}
|
||||
std::vector<char> commentData(info.size_comment);
|
||||
if(unzGetGlobalComment(zipFile, commentData.data(), info.size_comment) >= 0)
|
||||
{
|
||||
commentData[info.size_comment - 1] = '\0';
|
||||
comment = mpt::ToUnicode(mpt::IsUTF8(commentData.data()) ? mpt::Charset::UTF8 : mpt::Charset::CP437, commentData.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// read contents
|
||||
unz_file_pos curFile;
|
||||
int status = unzGoToFirstFile(zipFile);
|
||||
unzGetFilePos(zipFile, &curFile);
|
||||
|
||||
while(status == UNZ_OK)
|
||||
{
|
||||
ArchiveFileInfo fileinfo;
|
||||
|
||||
fileinfo.type = ArchiveFileType::Normal;
|
||||
|
||||
unz_file_info info;
|
||||
char name[256];
|
||||
unzGetCurrentFileInfo(zipFile, &info, name, sizeof(name), nullptr, 0, nullptr, 0);
|
||||
fileinfo.name = mpt::PathString::FromUnicode(mpt::ToUnicode((info.flag & (1<<11)) ? mpt::Charset::UTF8 : mpt::Charset::CP437, std::string(name)));
|
||||
fileinfo.size = info.uncompressed_size;
|
||||
|
||||
unzGetFilePos(zipFile, &curFile);
|
||||
fileinfo.cookie1 = curFile.pos_in_zip_directory;
|
||||
fileinfo.cookie2 = curFile.num_of_file;
|
||||
|
||||
contents.push_back(fileinfo);
|
||||
|
||||
status = unzGoToNextFile(zipFile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
CZipArchive::~CZipArchive()
|
||||
{
|
||||
unzClose(zipFile);
|
||||
}
|
||||
|
||||
|
||||
bool CZipArchive::ExtractFile(std::size_t index)
|
||||
{
|
||||
if(index >= contents.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
data.clear();
|
||||
|
||||
unz_file_pos bestFile;
|
||||
unz_file_info info;
|
||||
|
||||
bestFile.pos_in_zip_directory = static_cast<uLong>(contents[index].cookie1);
|
||||
bestFile.num_of_file = static_cast<uLong>(contents[index].cookie2);
|
||||
|
||||
if(unzGoToFilePos(zipFile, &bestFile) == UNZ_OK && unzOpenCurrentFile(zipFile) == UNZ_OK)
|
||||
{
|
||||
unzGetCurrentFileInfo(zipFile, &info, nullptr, 0, nullptr, 0, nullptr, 0);
|
||||
|
||||
try
|
||||
{
|
||||
data.resize(info.uncompressed_size);
|
||||
} catch(...)
|
||||
{
|
||||
unzCloseCurrentFile(zipFile);
|
||||
return false;
|
||||
}
|
||||
unzReadCurrentFile(zipFile, data.data(), info.uncompressed_size);
|
||||
unzCloseCurrentFile(zipFile);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#elif defined(MPT_WITH_MINIZ)
|
||||
|
||||
|
||||
CZipArchive::CZipArchive(FileReader &file) : ArchiveBase(file)
|
||||
{
|
||||
zipFile = new mz_zip_archive();
|
||||
|
||||
mz_zip_archive *zip = static_cast<mz_zip_archive*>(zipFile);
|
||||
|
||||
(*zip) = {};
|
||||
const auto fileData = file.GetRawData();
|
||||
if(!mz_zip_reader_init_mem(zip, fileData.data(), fileData.size(), 0))
|
||||
{
|
||||
delete zip;
|
||||
zip = nullptr;
|
||||
zipFile = nullptr;
|
||||
}
|
||||
|
||||
if(!zip)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(mz_uint i = 0; i < mz_zip_reader_get_num_files(zip); ++i)
|
||||
{
|
||||
ArchiveFileInfo info;
|
||||
info.type = ArchiveFileType::Invalid;
|
||||
mz_zip_archive_file_stat stat = {};
|
||||
if(mz_zip_reader_file_stat(zip, i, &stat))
|
||||
{
|
||||
info.type = ArchiveFileType::Normal;
|
||||
info.name = mpt::PathString::FromUnicode(mpt::ToUnicode((stat.m_bit_flag & (1<<11)) ? mpt::Charset::UTF8 : mpt::Charset::CP437, stat.m_filename));
|
||||
info.size = stat.m_uncomp_size;
|
||||
}
|
||||
if(mz_zip_reader_is_file_a_directory(zip, i))
|
||||
{
|
||||
info.type = ArchiveFileType::Special;
|
||||
} else if(mz_zip_reader_is_file_encrypted(zip, i))
|
||||
{
|
||||
info.type = ArchiveFileType::Special;
|
||||
}
|
||||
contents.push_back(info);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
CZipArchive::~CZipArchive()
|
||||
{
|
||||
mz_zip_archive *zip = static_cast<mz_zip_archive*>(zipFile);
|
||||
|
||||
if(zip)
|
||||
{
|
||||
mz_zip_reader_end(zip);
|
||||
|
||||
delete zip;
|
||||
zipFile = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool CZipArchive::ExtractFile(std::size_t index)
|
||||
{
|
||||
mz_zip_archive *zip = static_cast<mz_zip_archive*>(zipFile);
|
||||
|
||||
if(index >= contents.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mz_uint bestFile = index;
|
||||
|
||||
mz_zip_archive_file_stat stat = {};
|
||||
mz_zip_reader_file_stat(zip, bestFile, &stat);
|
||||
if(stat.m_uncomp_size >= std::numeric_limits<std::size_t>::max())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
data.resize(static_cast<std::size_t>(stat.m_uncomp_size));
|
||||
} catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(!mz_zip_reader_extract_to_mem(zip, bestFile, data.data(), static_cast<std::size_t>(stat.m_uncomp_size), 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
comment = mpt::ToUnicode(mpt::Charset::CP437, std::string(stat.m_comment, stat.m_comment + stat.m_comment_size));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif // MPT_WITH_ZLIB || MPT_WITH_MINIZ
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
29
Src/external_dependencies/openmpt-trunk/unarchiver/unzip.h
Normal file
29
Src/external_dependencies/openmpt-trunk/unarchiver/unzip.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* unzip.h
|
||||
* -------
|
||||
* Purpose: Header file for .zip loader
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "openmpt/all/BuildSettings.hpp"
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
class CZipArchive : public ArchiveBase
|
||||
{
|
||||
protected:
|
||||
void *zipFile;
|
||||
public:
|
||||
CZipArchive(FileReader &file);
|
||||
~CZipArchive() override;
|
||||
public:
|
||||
bool ExtractFile(std::size_t index) override;
|
||||
};
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
Loading…
Add table
Add a link
Reference in a new issue