1
0
Fork 0
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:
sfan5 2025-03-29 11:55:40 +01:00
parent ae0f955a0e
commit 785c042f1f
3 changed files with 10 additions and 180 deletions

View file

@ -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.

View 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)
{

View file

@ -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