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
|
//! A PKZIP archive
|
||||||
EFAT_ZIP = MAKE_IRR_ID('Z', 'I', 'P', 0),
|
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
|
//! The type of this archive is unknown
|
||||||
EFAT_UNKNOWN = MAKE_IRR_ID('u', 'n', 'k', 'n')
|
EFAT_UNKNOWN = MAKE_IRR_ID('u', 'n', 'k', 'n')
|
||||||
};
|
};
|
||||||
|
@ -73,13 +67,6 @@ public:
|
||||||
but checks if file exists will fail.
|
but checks if file exists will fail.
|
||||||
*/
|
*/
|
||||||
virtual void addDirectoryToFileList(const io::path &filename) {}
|
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.
|
//! 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
|
//! returns true if the file maybe is able to be loaded by this class
|
||||||
bool CArchiveLoaderZIP::isALoadableFileFormat(const io::path &filename) const
|
bool CArchiveLoaderZIP::isALoadableFileFormat(const io::path &filename) const
|
||||||
{
|
{
|
||||||
return core::hasFileExtension(filename, "zip", "pk3") ||
|
return core::hasFileExtension(filename, "zip", "pk3");
|
||||||
core::hasFileExtension(filename, "gz", "tgz");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Check to see if the loader can create archives of this type.
|
//! Check to see if the loader can create archives of this type.
|
||||||
bool CArchiveLoaderZIP::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const
|
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
|
//! Creates an archive from the filename
|
||||||
|
@ -63,18 +62,7 @@ IFileArchive *CArchiveLoaderZIP::createArchive(io::IReadFile *file, bool ignoreC
|
||||||
if (file) {
|
if (file) {
|
||||||
file->seek(0);
|
file->seek(0);
|
||||||
|
|
||||||
u16 sig;
|
archive = new CZipReader(FileSystem, file, ignoreCase, ignorePaths);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
return archive;
|
return archive;
|
||||||
}
|
}
|
||||||
|
@ -92,27 +80,21 @@ bool CArchiveLoaderZIP::isALoadableFileFormat(io::IReadFile *file) const
|
||||||
header.Sig = os::Byteswap::byteswap(header.Sig);
|
header.Sig = os::Byteswap::byteswap(header.Sig);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return header.Sig == 0x04034b50 || // ZIP
|
return header.Sig == 0x04034b50; // ZIP
|
||||||
(header.Sig & 0xffff) == 0x8b1f; // gzip
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// zip archive
|
// zip archive
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
CZipReader::CZipReader(IFileSystem *fs, IReadFile *file, bool ignoreCase, bool ignorePaths, bool isGZip) :
|
CZipReader::CZipReader(IFileSystem *fs, IReadFile *file, bool ignoreCase, bool ignorePaths) :
|
||||||
CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), FileSystem(fs), File(file), IsGZip(isGZip)
|
CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), FileSystem(fs), File(file)
|
||||||
{
|
{
|
||||||
if (File) {
|
if (File) {
|
||||||
File->grab();
|
File->grab();
|
||||||
|
|
||||||
// load file entries
|
// load file entries
|
||||||
if (IsGZip)
|
while (scanZipHeader()) {}
|
||||||
while (scanGZipHeader()) {
|
|
||||||
}
|
|
||||||
else
|
|
||||||
while (scanZipHeader()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
sort();
|
sort();
|
||||||
}
|
}
|
||||||
|
@ -127,7 +109,7 @@ CZipReader::~CZipReader()
|
||||||
//! get the archive type
|
//! get the archive type
|
||||||
E_FILE_ARCHIVE_TYPE CZipReader::getType() const
|
E_FILE_ARCHIVE_TYPE CZipReader::getType() const
|
||||||
{
|
{
|
||||||
return IsGZip ? EFAT_GZIP : EFAT_ZIP;
|
return EFAT_ZIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
const IFileList *CZipReader::getFileList() const
|
const IFileList *CZipReader::getFileList() const
|
||||||
|
@ -135,105 +117,6 @@ const IFileList *CZipReader::getFileList() const
|
||||||
return this;
|
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.
|
//! scans for a local header, returns false if there is no more local file header.
|
||||||
bool CZipReader::scanZipHeader(bool ignoreGPBits)
|
bool CZipReader::scanZipHeader(bool ignoreGPBits)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,11 +14,9 @@ namespace irr
|
||||||
{
|
{
|
||||||
namespace io
|
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
|
// the fields crc-32, compressed size and uncompressed size are set to
|
||||||
// zero in the local header
|
// 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
|
// byte-align structures
|
||||||
#include "irrpack.h"
|
#include "irrpack.h"
|
||||||
|
@ -84,39 +82,6 @@ struct SZIPFileCentralDirEnd
|
||||||
// zipfile comment (variable size)
|
// zipfile comment (variable size)
|
||||||
} PACK_STRUCT;
|
} 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
|
// Default alignment
|
||||||
#include "irrunpack.h"
|
#include "irrunpack.h"
|
||||||
|
|
||||||
|
@ -173,7 +138,7 @@ class CZipReader : public virtual IFileArchive, virtual CFileList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//! constructor
|
//! constructor
|
||||||
CZipReader(IFileSystem *fs, IReadFile *file, bool ignoreCase, bool ignorePaths, bool isGZip = false);
|
CZipReader(IFileSystem *fs, IReadFile *file, bool ignoreCase, bool ignorePaths);
|
||||||
|
|
||||||
//! destructor
|
//! destructor
|
||||||
virtual ~CZipReader();
|
virtual ~CZipReader();
|
||||||
|
@ -200,9 +165,6 @@ protected:
|
||||||
directory. */
|
directory. */
|
||||||
bool scanZipHeader(bool ignoreGPBits = false);
|
bool scanZipHeader(bool ignoreGPBits = false);
|
||||||
|
|
||||||
//! the same but for gzip files
|
|
||||||
bool scanGZipHeader();
|
|
||||||
|
|
||||||
bool scanCentralDirectoryHeader();
|
bool scanCentralDirectoryHeader();
|
||||||
|
|
||||||
io::IFileSystem *FileSystem;
|
io::IFileSystem *FileSystem;
|
||||||
|
@ -210,8 +172,6 @@ protected:
|
||||||
|
|
||||||
// holds extended info about files
|
// holds extended info about files
|
||||||
std::vector<SZipFileEntry> FileInfo;
|
std::vector<SZipFileEntry> FileInfo;
|
||||||
|
|
||||||
bool IsGZip;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace io
|
} // end namespace io
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue