mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Drop gzip support from CZipReader
This allowed reading concatenated gzip-compressed files as if they were an archive. Aside from being generally uncommon we literally don't need this.
This commit is contained in:
parent
ae0f955a0e
commit
785c042f1f
3 changed files with 10 additions and 180 deletions
|
@ -26,12 +26,6 @@ enum E_FILE_ARCHIVE_TYPE
|
|||
//! A PKZIP archive
|
||||
EFAT_ZIP = MAKE_IRR_ID('Z', 'I', 'P', 0),
|
||||
|
||||
//! A gzip archive
|
||||
EFAT_GZIP = MAKE_IRR_ID('g', 'z', 'i', 'p'),
|
||||
|
||||
//! An Android asset file archive
|
||||
EFAT_ANDROID_ASSET = MAKE_IRR_ID('A', 'S', 'S', 'E'),
|
||||
|
||||
//! The type of this archive is unknown
|
||||
EFAT_UNKNOWN = MAKE_IRR_ID('u', 'n', 'k', 'n')
|
||||
};
|
||||
|
@ -73,13 +67,6 @@ public:
|
|||
but checks if file exists will fail.
|
||||
*/
|
||||
virtual void addDirectoryToFileList(const io::path &filename) {}
|
||||
|
||||
//! An optionally used password string
|
||||
/** This variable is publicly accessible from the interface in order to
|
||||
avoid single access patterns to this place, and hence allow some more
|
||||
obscurity.
|
||||
*/
|
||||
core::stringc Password;
|
||||
};
|
||||
|
||||
//! Class which is able to create an archive from a file.
|
||||
|
|
|
@ -29,14 +29,13 @@ CArchiveLoaderZIP::CArchiveLoaderZIP(io::IFileSystem *fs) :
|
|||
//! returns true if the file maybe is able to be loaded by this class
|
||||
bool CArchiveLoaderZIP::isALoadableFileFormat(const io::path &filename) const
|
||||
{
|
||||
return core::hasFileExtension(filename, "zip", "pk3") ||
|
||||
core::hasFileExtension(filename, "gz", "tgz");
|
||||
return core::hasFileExtension(filename, "zip", "pk3");
|
||||
}
|
||||
|
||||
//! Check to see if the loader can create archives of this type.
|
||||
bool CArchiveLoaderZIP::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const
|
||||
{
|
||||
return (fileType == EFAT_ZIP || fileType == EFAT_GZIP);
|
||||
return fileType == EFAT_ZIP;
|
||||
}
|
||||
|
||||
//! Creates an archive from the filename
|
||||
|
@ -63,18 +62,7 @@ IFileArchive *CArchiveLoaderZIP::createArchive(io::IReadFile *file, bool ignoreC
|
|||
if (file) {
|
||||
file->seek(0);
|
||||
|
||||
u16 sig;
|
||||
file->read(&sig, 2);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
sig = os::Byteswap::byteswap(sig);
|
||||
#endif
|
||||
|
||||
file->seek(0);
|
||||
|
||||
bool isGZip = (sig == 0x8b1f);
|
||||
|
||||
archive = new CZipReader(FileSystem, file, ignoreCase, ignorePaths, isGZip);
|
||||
archive = new CZipReader(FileSystem, file, ignoreCase, ignorePaths);
|
||||
}
|
||||
return archive;
|
||||
}
|
||||
|
@ -92,27 +80,21 @@ bool CArchiveLoaderZIP::isALoadableFileFormat(io::IReadFile *file) const
|
|||
header.Sig = os::Byteswap::byteswap(header.Sig);
|
||||
#endif
|
||||
|
||||
return header.Sig == 0x04034b50 || // ZIP
|
||||
(header.Sig & 0xffff) == 0x8b1f; // gzip
|
||||
return header.Sig == 0x04034b50; // ZIP
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// zip archive
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
CZipReader::CZipReader(IFileSystem *fs, IReadFile *file, bool ignoreCase, bool ignorePaths, bool isGZip) :
|
||||
CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), FileSystem(fs), File(file), IsGZip(isGZip)
|
||||
CZipReader::CZipReader(IFileSystem *fs, IReadFile *file, bool ignoreCase, bool ignorePaths) :
|
||||
CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), FileSystem(fs), File(file)
|
||||
{
|
||||
if (File) {
|
||||
File->grab();
|
||||
|
||||
// load file entries
|
||||
if (IsGZip)
|
||||
while (scanGZipHeader()) {
|
||||
}
|
||||
else
|
||||
while (scanZipHeader()) {
|
||||
}
|
||||
while (scanZipHeader()) {}
|
||||
|
||||
sort();
|
||||
}
|
||||
|
@ -127,7 +109,7 @@ CZipReader::~CZipReader()
|
|||
//! get the archive type
|
||||
E_FILE_ARCHIVE_TYPE CZipReader::getType() const
|
||||
{
|
||||
return IsGZip ? EFAT_GZIP : EFAT_ZIP;
|
||||
return EFAT_ZIP;
|
||||
}
|
||||
|
||||
const IFileList *CZipReader::getFileList() const
|
||||
|
@ -135,105 +117,6 @@ const IFileList *CZipReader::getFileList() const
|
|||
return this;
|
||||
}
|
||||
|
||||
//! scans for a local header, returns false if there is no more local file header.
|
||||
//! The gzip file format seems to think that there can be multiple files in a gzip file
|
||||
//! but none
|
||||
bool CZipReader::scanGZipHeader()
|
||||
{
|
||||
SZipFileEntry entry;
|
||||
entry.Offset = 0;
|
||||
memset(&entry.header, 0, sizeof(SZIPFileHeader));
|
||||
|
||||
// read header
|
||||
SGZIPMemberHeader header;
|
||||
if (File->read(&header, sizeof(SGZIPMemberHeader)) == sizeof(SGZIPMemberHeader)) {
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
header.sig = os::Byteswap::byteswap(header.sig);
|
||||
header.time = os::Byteswap::byteswap(header.time);
|
||||
#endif
|
||||
|
||||
// check header value
|
||||
if (header.sig != 0x8b1f)
|
||||
return false;
|
||||
|
||||
// now get the file info
|
||||
if (header.flags & EGZF_EXTRA_FIELDS) {
|
||||
// read lenth of extra data
|
||||
u16 dataLen;
|
||||
|
||||
File->read(&dataLen, 2);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
dataLen = os::Byteswap::byteswap(dataLen);
|
||||
#endif
|
||||
|
||||
// skip it
|
||||
File->seek(dataLen, true);
|
||||
}
|
||||
|
||||
io::path ZipFileName = "";
|
||||
|
||||
if (header.flags & EGZF_FILE_NAME) {
|
||||
c8 c;
|
||||
File->read(&c, 1);
|
||||
while (c) {
|
||||
ZipFileName.append(c);
|
||||
File->read(&c, 1);
|
||||
}
|
||||
} else {
|
||||
// no file name?
|
||||
ZipFileName = core::deletePathFromFilename(Path);
|
||||
|
||||
// rename tgz to tar or remove gz extension
|
||||
if (core::hasFileExtension(ZipFileName, "tgz")) {
|
||||
ZipFileName[ZipFileName.size() - 2] = 'a';
|
||||
ZipFileName[ZipFileName.size() - 1] = 'r';
|
||||
} else if (core::hasFileExtension(ZipFileName, "gz")) {
|
||||
ZipFileName[ZipFileName.size() - 3] = 0;
|
||||
ZipFileName.validate();
|
||||
}
|
||||
}
|
||||
|
||||
if (header.flags & EGZF_COMMENT) {
|
||||
c8 c = 'a';
|
||||
while (c)
|
||||
File->read(&c, 1);
|
||||
}
|
||||
|
||||
if (header.flags & EGZF_CRC16)
|
||||
File->seek(2, true);
|
||||
|
||||
// we are now at the start of the data blocks
|
||||
entry.Offset = File->getPos();
|
||||
|
||||
entry.header.FilenameLength = ZipFileName.size();
|
||||
|
||||
entry.header.CompressionMethod = header.compressionMethod;
|
||||
entry.header.DataDescriptor.CompressedSize = (File->getSize() - 8) - File->getPos();
|
||||
|
||||
// seek to file end
|
||||
File->seek(entry.header.DataDescriptor.CompressedSize, true);
|
||||
|
||||
// read CRC
|
||||
File->read(&entry.header.DataDescriptor.CRC32, 4);
|
||||
// read uncompressed size
|
||||
File->read(&entry.header.DataDescriptor.UncompressedSize, 4);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
entry.header.DataDescriptor.CRC32 = os::Byteswap::byteswap(entry.header.DataDescriptor.CRC32);
|
||||
entry.header.DataDescriptor.UncompressedSize = os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize);
|
||||
#endif
|
||||
|
||||
// now we've filled all the fields, this is just a standard deflate block
|
||||
addItem(ZipFileName, entry.Offset, entry.header.DataDescriptor.UncompressedSize, false, 0);
|
||||
FileInfo.push_back(entry);
|
||||
}
|
||||
|
||||
// there's only one block of data in a gzip file
|
||||
return false;
|
||||
}
|
||||
|
||||
//! scans for a local header, returns false if there is no more local file header.
|
||||
bool CZipReader::scanZipHeader(bool ignoreGPBits)
|
||||
{
|
||||
|
|
|
@ -14,11 +14,9 @@ namespace irr
|
|||
{
|
||||
namespace io
|
||||
{
|
||||
// set if the file is encrypted
|
||||
const s16 ZIP_FILE_ENCRYPTED = 0x0001;
|
||||
// the fields crc-32, compressed size and uncompressed size are set to
|
||||
// zero in the local header
|
||||
const s16 ZIP_INFO_IN_DATA_DESCRIPTOR = 0x0008;
|
||||
static constexpr s16 ZIP_INFO_IN_DATA_DESCRIPTOR = 0x0008;
|
||||
|
||||
// byte-align structures
|
||||
#include "irrpack.h"
|
||||
|
@ -84,39 +82,6 @@ struct SZIPFileCentralDirEnd
|
|||
// zipfile comment (variable size)
|
||||
} PACK_STRUCT;
|
||||
|
||||
struct SZipFileExtraHeader
|
||||
{
|
||||
s16 ID;
|
||||
s16 Size;
|
||||
} PACK_STRUCT;
|
||||
|
||||
struct SZipFileAESExtraData
|
||||
{
|
||||
s16 Version;
|
||||
u8 Vendor[2];
|
||||
u8 EncryptionStrength;
|
||||
s16 CompressionMode;
|
||||
} PACK_STRUCT;
|
||||
|
||||
enum E_GZIP_FLAGS
|
||||
{
|
||||
EGZF_TEXT_DAT = 1,
|
||||
EGZF_CRC16 = 2,
|
||||
EGZF_EXTRA_FIELDS = 4,
|
||||
EGZF_FILE_NAME = 8,
|
||||
EGZF_COMMENT = 16
|
||||
};
|
||||
|
||||
struct SGZIPMemberHeader
|
||||
{
|
||||
u16 sig; // 0x8b1f
|
||||
u8 compressionMethod; // 8 = deflate
|
||||
u8 flags;
|
||||
u32 time;
|
||||
u8 extraFlags; // slow compress = 2, fast compress = 4
|
||||
u8 operatingSystem;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// Default alignment
|
||||
#include "irrunpack.h"
|
||||
|
||||
|
@ -173,7 +138,7 @@ class CZipReader : public virtual IFileArchive, virtual CFileList
|
|||
{
|
||||
public:
|
||||
//! constructor
|
||||
CZipReader(IFileSystem *fs, IReadFile *file, bool ignoreCase, bool ignorePaths, bool isGZip = false);
|
||||
CZipReader(IFileSystem *fs, IReadFile *file, bool ignoreCase, bool ignorePaths);
|
||||
|
||||
//! destructor
|
||||
virtual ~CZipReader();
|
||||
|
@ -200,9 +165,6 @@ protected:
|
|||
directory. */
|
||||
bool scanZipHeader(bool ignoreGPBits = false);
|
||||
|
||||
//! the same but for gzip files
|
||||
bool scanGZipHeader();
|
||||
|
||||
bool scanCentralDirectoryHeader();
|
||||
|
||||
io::IFileSystem *FileSystem;
|
||||
|
@ -210,8 +172,6 @@ protected:
|
|||
|
||||
// holds extended info about files
|
||||
std::vector<SZipFileEntry> FileInfo;
|
||||
|
||||
bool IsGZip;
|
||||
};
|
||||
|
||||
} // end namespace io
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue