mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-28 03:20:11 +01:00
Zip64 support added to Poco Zip. I added unit tests CompressTest::testZip64 and ZipTest::testDecompressZip64, but so far I have only run them on Windows. We have built the code on MAC and Linux and will attempt to run the tests there.
This commit is contained in:
@@ -38,9 +38,11 @@ class Zip_API Compress
|
||||
public:
|
||||
Poco::FIFOEvent<const ZipLocalFileHeader> EDone;
|
||||
|
||||
Compress(std::ostream& out, bool seekableOut);
|
||||
Compress(std::ostream& out, bool seekableOut, bool forceZip64 = false);
|
||||
/// seekableOut determines how we write the zip, setting it to true is recommended for local files (smaller zip file),
|
||||
/// if you are compressing directly to a network, you MUST set it to false
|
||||
/// If forceZip64 is set true then the file header is allocated with zip64 extension so that it can be updated after the file data is written
|
||||
/// if seekableOut is true in case the compressed or uncompressed size exceeds 32 bits.
|
||||
|
||||
~Compress();
|
||||
|
||||
@@ -103,16 +105,18 @@ private:
|
||||
/// for directories.
|
||||
|
||||
void addFileRaw(std::istream& in, const ZipLocalFileHeader& hdr, const Poco::Path& fileName);
|
||||
/// Copies an already compressed ZipEntry from in
|
||||
/// copys an already compressed ZipEntry from in
|
||||
|
||||
private:
|
||||
std::set<std::string> _storeExtensions;
|
||||
std::ostream& _out;
|
||||
bool _seekableOut;
|
||||
bool _forceZip64;
|
||||
ZipArchive::FileHeaders _files;
|
||||
ZipArchive::FileInfos _infos;
|
||||
ZipArchive::DirectoryInfos _dirs;
|
||||
Poco::UInt32 _offset;
|
||||
ZipArchive::DirectoryInfos64 _dirs64;
|
||||
Poco::UInt64 _offset;
|
||||
std::string _comment;
|
||||
|
||||
friend class Keep;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "Poco/Zip/ZipLocalFileHeader.h"
|
||||
#include "Poco/Zip/ZipFileInfo.h"
|
||||
#include "Poco/Zip/ZipArchiveInfo.h"
|
||||
|
||||
#include <istream>
|
||||
#include <map>
|
||||
|
||||
@@ -43,6 +44,7 @@ public:
|
||||
typedef std::map<std::string, ZipLocalFileHeader> FileHeaders;
|
||||
typedef std::map<std::string, ZipFileInfo> FileInfos;
|
||||
typedef std::map<Poco::UInt16, ZipArchiveInfo> DirectoryInfos;
|
||||
typedef std::map<Poco::UInt32, ZipArchiveInfo64> DirectoryInfos64;
|
||||
|
||||
ZipArchive(std::istream& in);
|
||||
/// Creates the ZipArchive from a file. Note that the in stream will be in state failed after the constructor is finished
|
||||
@@ -68,7 +70,7 @@ public:
|
||||
private:
|
||||
void parse(std::istream& in, ParseCallback& pc);
|
||||
|
||||
ZipArchive(const FileHeaders& entries, const FileInfos& infos, const DirectoryInfos& dirs );
|
||||
ZipArchive(const FileHeaders& entries, const FileInfos& infos, const DirectoryInfos& dirs, const DirectoryInfos64& dirs64 );
|
||||
|
||||
private:
|
||||
FileHeaders _entries;
|
||||
@@ -77,6 +79,8 @@ private:
|
||||
/// Info generated by parsing the directory block of the zip file
|
||||
DirectoryInfos _disks;
|
||||
/// Stores directory info for all found disks
|
||||
DirectoryInfos64 _disks64;
|
||||
/// Stores directory info for all found disks
|
||||
|
||||
friend class Compress;
|
||||
};
|
||||
|
||||
@@ -70,16 +70,20 @@ public:
|
||||
/// Sets the optional Zip comment.
|
||||
|
||||
void setNumberOfEntries(Poco::UInt16 val);
|
||||
/// Returns the number of entries on this disk
|
||||
/// Sets the number of entries on this disk
|
||||
|
||||
void setTotalNumberOfEntries(Poco::UInt16 val);
|
||||
/// Returns the total number of entries on all disks
|
||||
/// Sets the total number of entries on all disks
|
||||
|
||||
void setCentralDirectorySize(Poco::UInt32 val);
|
||||
/// Returns the size of the central directory in bytes
|
||||
/// Sets the size of the central directory in bytes
|
||||
|
||||
void setHeaderOffset(Poco::UInt32 val);
|
||||
void setCentralDirectoryOffset(Poco::UInt32 val);
|
||||
/// Sets the offset of the central directory from beginning of first disk
|
||||
|
||||
void setHeaderOffset(std::streamoff val);
|
||||
/// Sets the offset of the header in relation to the begin of this disk
|
||||
|
||||
std::string createHeader() const;
|
||||
/// Creates a header
|
||||
|
||||
@@ -181,11 +185,210 @@ inline void ZipArchiveInfo::setCentralDirectorySize(Poco::UInt32 val)
|
||||
}
|
||||
|
||||
|
||||
inline void ZipArchiveInfo::setHeaderOffset(Poco::UInt32 val)
|
||||
inline void ZipArchiveInfo::setCentralDirectoryOffset(Poco::UInt32 val)
|
||||
{
|
||||
ZipUtil::set32BitValue(val, _rawInfo, CENTRALDIRSTARTOFFSET_POS);
|
||||
}
|
||||
|
||||
inline void ZipArchiveInfo::setHeaderOffset(std::streamoff val)
|
||||
{
|
||||
_startPos = val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Zip_API ZipArchiveInfo64
|
||||
/// A ZipArchiveInfo64 stores central directory info
|
||||
{
|
||||
public:
|
||||
static const char HEADER[ZipCommon::HEADER_SIZE];
|
||||
static const char LOCATOR_HEADER[ZipCommon::HEADER_SIZE];
|
||||
|
||||
ZipArchiveInfo64();
|
||||
/// Default constructor, everything set to zero or empty
|
||||
|
||||
ZipArchiveInfo64(std::istream& in, bool assumeHeaderRead);
|
||||
/// Creates the ZipArchiveInfo64 by parsing the input stream.
|
||||
/// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside.
|
||||
|
||||
~ZipArchiveInfo64();
|
||||
/// Destroys the ZipArchiveInfo64.
|
||||
|
||||
void getVersionMadeBy(int& major, int& minor);
|
||||
/// The ZIP version used to create the file
|
||||
|
||||
void getRequiredVersion(int& major, int& minor);
|
||||
/// The minimum version required to extract the data
|
||||
|
||||
Poco::UInt32 getDiskNumber() const;
|
||||
/// Get the number of the disk where this header can be found
|
||||
|
||||
Poco::UInt32 getFirstDiskForDirectoryHeader() const;
|
||||
/// Returns the number of the disk that contains the start of the directory header
|
||||
|
||||
Poco::UInt64 getNumberOfEntries() const;
|
||||
/// Returns the number of entries on this disk
|
||||
|
||||
Poco::UInt64 getTotalNumberOfEntries() const;
|
||||
/// Returns the total number of entries on all disks
|
||||
|
||||
Poco::UInt64 getCentralDirectorySize() const;
|
||||
/// Returns the size of the central directory in bytes
|
||||
|
||||
std::streamoff getCentralDirectoryOffset() const;
|
||||
/// Returns the offset of the central directory from beginning of first disk
|
||||
|
||||
std::streamoff getHeaderOffset() const;
|
||||
/// Returns the offset of the header in relation to the begin of this disk
|
||||
|
||||
void setNumberOfEntries(Poco::UInt64 val);
|
||||
/// Sets the number of entries on this disk
|
||||
|
||||
void setTotalNumberOfEntries(Poco::UInt64 val);
|
||||
/// Sets the total number of entries on all disks
|
||||
|
||||
void setCentralDirectorySize(Poco::UInt64 val);
|
||||
/// Set the size of the central directory in bytes
|
||||
|
||||
void setCentralDirectoryOffset(Poco::UInt64 val);
|
||||
/// Returns the offset of the central directory from beginning of first disk
|
||||
|
||||
void setHeaderOffset(std::streamoff val);
|
||||
/// Sets the offset of the header in relation to the begin of this disk
|
||||
|
||||
void setTotalNumberOfDisks(Poco::UInt32 val);
|
||||
/// Sets the offset of the central directory from beginning of first disk
|
||||
|
||||
std::string createHeader() const;
|
||||
/// Creates a header
|
||||
|
||||
private:
|
||||
void parse(std::istream& inp, bool assumeHeaderRead);
|
||||
|
||||
void setRequiredVersion(int major, int minor);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
HEADER_POS = 0,
|
||||
RECORDSIZE_POS = HEADER_POS + ZipCommon::HEADER_SIZE,
|
||||
RECORDSIZE_SIZE = 8,
|
||||
VERSIONMADEBY_POS = RECORDSIZE_POS + RECORDSIZE_SIZE,
|
||||
VERSIONMADEBY_SIZE = 2,
|
||||
VERSION_NEEDED_POS = VERSIONMADEBY_POS + VERSIONMADEBY_SIZE,
|
||||
VERSION_NEEDED_SIZE = 2,
|
||||
NUMBEROFTHISDISK_POS = VERSION_NEEDED_POS + VERSION_NEEDED_SIZE,
|
||||
NUMBEROFTHISDISK_SIZE = 4,
|
||||
NUMBEROFCENTRALDIRDISK_POS = NUMBEROFTHISDISK_POS + NUMBEROFTHISDISK_SIZE,
|
||||
NUMBEROFCENTRALDIRDISK_SIZE = 4,
|
||||
NUMENTRIESTHISDISK_POS = NUMBEROFCENTRALDIRDISK_POS + NUMBEROFCENTRALDIRDISK_SIZE,
|
||||
NUMENTRIESTHISDISK_SIZE = 8,
|
||||
TOTALNUMENTRIES_POS = NUMENTRIESTHISDISK_POS + NUMENTRIESTHISDISK_SIZE,
|
||||
TOTALNUMENTRIES_SIZE = 8,
|
||||
CENTRALDIRSIZE_POS = TOTALNUMENTRIES_POS + TOTALNUMENTRIES_SIZE,
|
||||
CENTRALDIRSIZE_SIZE = 8,
|
||||
CENTRALDIRSTARTOFFSET_POS = CENTRALDIRSIZE_POS + CENTRALDIRSIZE_SIZE,
|
||||
CENTRALDIRSTARTOFFSET_SIZE = 8,
|
||||
FULL_HEADER_SIZE = 56,
|
||||
|
||||
LOCATOR_HEADER_POS = 0,
|
||||
NUMBEROFENDOFCENTRALDIRDISK_POS = LOCATOR_HEADER_POS + ZipCommon::HEADER_SIZE,
|
||||
NUMBEROFENDOFCENTRALDIRDISK_SIZE = 4,
|
||||
ENDOFCENTRALDIROFFSET_POS = NUMBEROFENDOFCENTRALDIRDISK_POS + NUMBEROFENDOFCENTRALDIRDISK_SIZE,
|
||||
ENDOFCENTRALDIROFFSET_SIZE = 8,
|
||||
TOTALNUMBEROFENDDISKS_POS = ENDOFCENTRALDIROFFSET_POS + ENDOFCENTRALDIROFFSET_SIZE,
|
||||
TOTALNUMBEROFENDDISKS_SIZE = 4,
|
||||
|
||||
FULL_LOCATOR_SIZE = 20
|
||||
};
|
||||
|
||||
char _rawInfo[FULL_HEADER_SIZE];
|
||||
std::string _extraField;
|
||||
char _locInfo[FULL_LOCATOR_SIZE];
|
||||
std::streamoff _startPos;
|
||||
};
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipArchiveInfo64::getDiskNumber() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, NUMBEROFTHISDISK_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipArchiveInfo64::getFirstDiskForDirectoryHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, NUMBEROFCENTRALDIRDISK_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt64 ZipArchiveInfo64::getNumberOfEntries() const
|
||||
{
|
||||
return ZipUtil::get64BitValue(_rawInfo, NUMENTRIESTHISDISK_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt64 ZipArchiveInfo64::getTotalNumberOfEntries() const
|
||||
{
|
||||
return ZipUtil::get64BitValue(_rawInfo, TOTALNUMENTRIES_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt64 ZipArchiveInfo64::getCentralDirectorySize() const
|
||||
{
|
||||
return ZipUtil::get64BitValue(_rawInfo, CENTRALDIRSIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline std::streamoff ZipArchiveInfo64::getCentralDirectoryOffset() const
|
||||
{
|
||||
return _startPos;
|
||||
}
|
||||
|
||||
inline std::streamoff ZipArchiveInfo64::getHeaderOffset() const
|
||||
{
|
||||
return _startPos;
|
||||
}
|
||||
|
||||
inline void ZipArchiveInfo64::setRequiredVersion(int major, int minor)
|
||||
{
|
||||
poco_assert (minor < 10);
|
||||
poco_assert (major < 24);
|
||||
Poco::UInt8 val = static_cast<unsigned char>(major)*10+static_cast<unsigned char>(minor);
|
||||
_rawInfo[VERSIONMADEBY_POS] = static_cast<char>(val);
|
||||
_rawInfo[VERSION_NEEDED_POS] = static_cast<char>(val);
|
||||
}
|
||||
|
||||
inline void ZipArchiveInfo64::setNumberOfEntries(Poco::UInt64 val)
|
||||
{
|
||||
ZipUtil::set64BitValue(val, _rawInfo, NUMENTRIESTHISDISK_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipArchiveInfo64::setTotalNumberOfEntries(Poco::UInt64 val)
|
||||
{
|
||||
ZipUtil::set64BitValue(val, _rawInfo, TOTALNUMENTRIES_POS);
|
||||
}
|
||||
|
||||
inline void ZipArchiveInfo64::setCentralDirectorySize(Poco::UInt64 val)
|
||||
{
|
||||
ZipUtil::set64BitValue(val, _rawInfo, CENTRALDIRSIZE_POS);
|
||||
}
|
||||
|
||||
inline void ZipArchiveInfo64::setCentralDirectoryOffset(Poco::UInt64 val)
|
||||
{
|
||||
ZipUtil::set64BitValue(val, _rawInfo, CENTRALDIRSTARTOFFSET_POS);
|
||||
}
|
||||
|
||||
inline void ZipArchiveInfo64::setHeaderOffset(std::streamoff val)
|
||||
{
|
||||
_startPos = val;
|
||||
ZipUtil::set64BitValue(val, _locInfo, ENDOFCENTRALDIROFFSET_POS);
|
||||
}
|
||||
|
||||
inline void ZipArchiveInfo64::setTotalNumberOfDisks(Poco::UInt32 val)
|
||||
{
|
||||
ZipUtil::set32BitValue(val, _locInfo, TOTALNUMBEROFENDDISKS_POS);
|
||||
}
|
||||
|
||||
} } // namespace Poco::Zip
|
||||
|
||||
|
||||
@@ -33,8 +33,12 @@ class Zip_API ZipCommon
|
||||
public:
|
||||
enum
|
||||
{
|
||||
HEADER_SIZE = 4
|
||||
};
|
||||
HEADER_SIZE = 4,
|
||||
};
|
||||
|
||||
static const Poco::UInt16 ZIP64_EXTRA_ID = 0x1; // Extra data id tag for Zip64 data (in extension for ZipLocalFileHeader and ZipFileInfo)
|
||||
static const Poco::UInt16 ZIP64_MAGIC_SHORT = 0xFFFF;
|
||||
static const Poco::UInt32 ZIP64_MAGIC = 0xFFFFFFFF;
|
||||
|
||||
enum CompressionMethod
|
||||
{
|
||||
|
||||
@@ -134,7 +134,110 @@ inline Poco::UInt32 ZipDataInfo::getFullHeaderSize()
|
||||
}
|
||||
|
||||
|
||||
class Zip_API ZipDataInfo64
|
||||
/// A ZipDataInfo64 stores a Zip data descriptor for a Zip64 file
|
||||
{
|
||||
public:
|
||||
static const char HEADER[ZipCommon::HEADER_SIZE];
|
||||
|
||||
ZipDataInfo64();
|
||||
/// Creates a header with all fields (except the header field) set to 0
|
||||
|
||||
ZipDataInfo64(std::istream& in, bool assumeHeaderRead);
|
||||
/// Creates the ZipDataInfo64.
|
||||
|
||||
~ZipDataInfo64();
|
||||
/// Destroys the ZipDataInfo64.
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
Poco::UInt32 getCRC32() const;
|
||||
|
||||
void setCRC32(Poco::UInt32 crc);
|
||||
|
||||
Poco::UInt64 getCompressedSize() const;
|
||||
|
||||
void setCompressedSize(Poco::UInt64 size);
|
||||
|
||||
Poco::UInt64 getUncompressedSize() const;
|
||||
|
||||
void setUncompressedSize(Poco::UInt64 size);
|
||||
|
||||
static Poco::UInt32 getFullHeaderSize();
|
||||
|
||||
const char* getRawHeader() const;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
HEADER_POS = 0,
|
||||
CRC32_POS = HEADER_POS + ZipCommon::HEADER_SIZE,
|
||||
CRC32_SIZE = 4,
|
||||
COMPRESSED_POS = CRC32_POS + CRC32_SIZE,
|
||||
COMPRESSED_SIZE = 8,
|
||||
UNCOMPRESSED_POS = COMPRESSED_POS + COMPRESSED_SIZE,
|
||||
UNCOMPRESSED_SIZE = 8,
|
||||
FULLHEADER_SIZE = UNCOMPRESSED_POS + UNCOMPRESSED_SIZE
|
||||
};
|
||||
|
||||
char _rawInfo[FULLHEADER_SIZE];
|
||||
bool _valid;
|
||||
};
|
||||
|
||||
|
||||
inline const char* ZipDataInfo64::getRawHeader() const
|
||||
{
|
||||
return _rawInfo;
|
||||
}
|
||||
|
||||
|
||||
inline bool ZipDataInfo64::isValid() const
|
||||
{
|
||||
return _valid;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipDataInfo64::getCRC32() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, CRC32_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipDataInfo64::setCRC32(Poco::UInt32 crc)
|
||||
{
|
||||
return ZipUtil::set32BitValue(crc, _rawInfo, CRC32_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt64 ZipDataInfo64::getCompressedSize() const
|
||||
{
|
||||
return ZipUtil::get64BitValue(_rawInfo, COMPRESSED_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipDataInfo64::setCompressedSize(Poco::UInt64 size)
|
||||
{
|
||||
return ZipUtil::set64BitValue(size, _rawInfo, COMPRESSED_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt64 ZipDataInfo64::getUncompressedSize() const
|
||||
{
|
||||
return ZipUtil::get64BitValue(_rawInfo, UNCOMPRESSED_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipDataInfo64::setUncompressedSize(Poco::UInt64 size)
|
||||
{
|
||||
return ZipUtil::set64BitValue(size, _rawInfo, UNCOMPRESSED_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipDataInfo64::getFullHeaderSize()
|
||||
{
|
||||
return FULLHEADER_SIZE;
|
||||
}
|
||||
|
||||
} } // namespace Poco::Zip
|
||||
|
||||
|
||||
#endif // Zip_ZipDataInfo_INCLUDED
|
||||
|
||||
@@ -48,9 +48,6 @@ public:
|
||||
~ZipFileInfo();
|
||||
/// Destroys the ZipFileInfo.
|
||||
|
||||
Poco::UInt32 getRelativeOffsetOfLocalHeader() const;
|
||||
/// Where on the disk starts the localheader. Combined with the disk number gives the exact location of the header
|
||||
|
||||
ZipCommon::CompressionMethod getCompressionMethod() const;
|
||||
|
||||
bool isEncrypted() const;
|
||||
@@ -62,9 +59,12 @@ public:
|
||||
Poco::UInt32 getHeaderSize() const;
|
||||
/// Returns the total size of the header including filename + other additional fields
|
||||
|
||||
Poco::UInt32 getCompressedSize() const;
|
||||
Poco::UInt64 getCompressedSize() const;
|
||||
|
||||
Poco::UInt32 getUncompressedSize() const;
|
||||
Poco::UInt64 getUncompressedSize() const;
|
||||
|
||||
Poco::UInt64 getOffset() const;
|
||||
/// Where on the disk starts the localheader. Combined with the disk number gives the exact location of the header
|
||||
|
||||
const std::string& getFileName() const;
|
||||
|
||||
@@ -94,14 +94,19 @@ public:
|
||||
|
||||
std::string createHeader() const;
|
||||
|
||||
void setOffset(Poco::UInt32 val);
|
||||
void setOffset(Poco::UInt64 val);
|
||||
|
||||
bool needsZip64() const;
|
||||
|
||||
void setZip64Data();
|
||||
|
||||
private:
|
||||
|
||||
void setCRC(Poco::UInt32 val);
|
||||
|
||||
void setCompressedSize(Poco::UInt32 val);
|
||||
void setCompressedSize(Poco::UInt64 val);
|
||||
|
||||
void setUncompressedSize(Poco::UInt32 val);
|
||||
void setUncompressedSize(Poco::UInt64 val);
|
||||
|
||||
void setCompressionMethod(ZipCommon::CompressionMethod cm);
|
||||
|
||||
@@ -131,6 +136,8 @@ private:
|
||||
|
||||
Poco::UInt32 getUncompressedSizeFromHeader() const;
|
||||
|
||||
Poco::UInt32 getOffsetFromHeader() const;
|
||||
|
||||
Poco::UInt16 getFileNameLength() const;
|
||||
|
||||
Poco::UInt16 getExtraFieldLength() const;
|
||||
@@ -177,7 +184,17 @@ private:
|
||||
EXTERNALFILE_ATTR_SIZE = 4,
|
||||
RELATIVEOFFSETLOCALHEADER_POS = EXTERNALFILE_ATTR_POS + EXTERNALFILE_ATTR_SIZE,
|
||||
RELATIVEOFFSETLOCALHEADER_SIZE = 4,
|
||||
FULLHEADER_SIZE = 46
|
||||
FULLHEADER_SIZE = 46,
|
||||
|
||||
EXTRA_DATA_TAG_SIZE = 2,
|
||||
EXTRA_DATA_TAG_POS = 0,
|
||||
EXTRA_DATA_SIZE_SIZE = 2,
|
||||
EXTRA_DATA_SIZE_POS = EXTRA_DATA_TAG_POS + EXTRA_DATA_TAG_SIZE,
|
||||
EXTRA_DATA_POS = EXTRA_DATA_SIZE_POS + EXTRA_DATA_SIZE_SIZE,
|
||||
EXTRA_DATA_UNCOMPRESSED_SIZE_SIZE = 8,
|
||||
EXTRA_DATA_COMPRESSED_SIZE_SIZE = 8,
|
||||
EXTRA_DATA_OFFSET_SIZE = 8,
|
||||
FULLEXTRA_DATA_SIZE = 28
|
||||
};
|
||||
|
||||
enum
|
||||
@@ -188,8 +205,9 @@ private:
|
||||
|
||||
char _rawInfo[FULLHEADER_SIZE];
|
||||
Poco::UInt32 _crc32;
|
||||
Poco::UInt32 _compressedSize;
|
||||
Poco::UInt32 _uncompressedSize;
|
||||
Poco::UInt64 _compressedSize;
|
||||
Poco::UInt64 _uncompressedSize;
|
||||
Poco::UInt64 _localHeaderOffset;
|
||||
std::string _fileName;
|
||||
Poco::DateTime _lastModifiedAt;
|
||||
std::string _extraField;
|
||||
@@ -197,11 +215,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getRelativeOffsetOfLocalHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getCRCFromHeader() const
|
||||
{
|
||||
@@ -220,6 +233,11 @@ inline Poco::UInt32 ZipFileInfo::getUncompressedSizeFromHeader() const
|
||||
return ZipUtil::get32BitValue(_rawInfo, UNCOMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getOffsetFromHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::parseDateTime()
|
||||
{
|
||||
@@ -245,6 +263,10 @@ inline const Poco::DateTime& ZipFileInfo::lastModifiedAt() const
|
||||
return _lastModifiedAt;
|
||||
}
|
||||
|
||||
inline Poco::UInt64 ZipFileInfo::getOffset() const
|
||||
{
|
||||
return _localHeaderOffset;
|
||||
}
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getCRC() const
|
||||
{
|
||||
@@ -252,13 +274,13 @@ inline Poco::UInt32 ZipFileInfo::getCRC() const
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getCompressedSize() const
|
||||
inline Poco::UInt64 ZipFileInfo::getCompressedSize() const
|
||||
{
|
||||
return _compressedSize;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipFileInfo::getUncompressedSize() const
|
||||
inline Poco::UInt64 ZipFileInfo::getUncompressedSize() const
|
||||
{
|
||||
return _uncompressedSize;
|
||||
}
|
||||
@@ -362,6 +384,30 @@ inline Poco::UInt32 ZipFileInfo::getHeaderSize() const
|
||||
return FULLHEADER_SIZE + getFileNameLength() + getExtraFieldLength() + getFileCommentLength();
|
||||
}
|
||||
|
||||
inline bool ZipFileInfo::needsZip64() const {
|
||||
return _localHeaderOffset >= ZipCommon::ZIP64_MAGIC || _compressedSize >= ZipCommon::ZIP64_MAGIC || _uncompressedSize >= ZipCommon::ZIP64_MAGIC;
|
||||
}
|
||||
|
||||
inline void ZipFileInfo::setZip64Data() {
|
||||
if(needsZip64()) {
|
||||
setRequiredVersion(4, 5);
|
||||
char data[FULLEXTRA_DATA_SIZE];
|
||||
ZipUtil::set16BitValue(ZipCommon::ZIP64_EXTRA_ID, data, EXTRA_DATA_TAG_POS);
|
||||
Poco::UInt16 pos = EXTRA_DATA_POS;
|
||||
if(_uncompressedSize >= ZipCommon::ZIP64_MAGIC) {
|
||||
ZipUtil::set64BitValue(_uncompressedSize, data, pos); pos += 8;
|
||||
}
|
||||
if(_compressedSize >= ZipCommon::ZIP64_MAGIC) {
|
||||
ZipUtil::set64BitValue(_compressedSize, data, pos); pos += 8;
|
||||
}
|
||||
if(_localHeaderOffset >= ZipCommon::ZIP64_MAGIC) {
|
||||
ZipUtil::set64BitValue(_localHeaderOffset, data, pos); pos += 8;
|
||||
}
|
||||
ZipUtil::set16BitValue(pos - EXTRA_DATA_POS, data, EXTRA_DATA_SIZE_POS);
|
||||
_extraField = std::string(data, pos);
|
||||
ZipUtil::set16BitValue(pos, _rawInfo, EXTRAFIELD_LENGTH_POS);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ZipFileInfo::setCRC(Poco::UInt32 val)
|
||||
{
|
||||
@@ -370,23 +416,24 @@ inline void ZipFileInfo::setCRC(Poco::UInt32 val)
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setOffset(Poco::UInt32 val)
|
||||
inline void ZipFileInfo::setOffset(Poco::UInt64 val)
|
||||
{
|
||||
ZipUtil::set32BitValue(val, _rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
|
||||
_localHeaderOffset = val;
|
||||
ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setCompressedSize(Poco::UInt32 val)
|
||||
inline void ZipFileInfo::setCompressedSize(Poco::UInt64 val)
|
||||
{
|
||||
_compressedSize = val;
|
||||
ZipUtil::set32BitValue(val, _rawInfo, COMPRESSED_SIZE_POS);
|
||||
ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawInfo, COMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipFileInfo::setUncompressedSize(Poco::UInt32 val)
|
||||
inline void ZipFileInfo::setUncompressedSize(Poco::UInt64 val)
|
||||
{
|
||||
_uncompressedSize = val;
|
||||
ZipUtil::set32BitValue(val, _rawInfo, UNCOMPRESSED_SIZE_POS);
|
||||
ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawInfo, UNCOMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -41,9 +41,10 @@ class Zip_API ZipLocalFileHeader
|
||||
public:
|
||||
static const char HEADER[ZipCommon::HEADER_SIZE];
|
||||
|
||||
ZipLocalFileHeader(const Poco::Path& fileName, const Poco::DateTime& lastModifiedAt, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl);
|
||||
ZipLocalFileHeader(const Poco::Path& fileName, const Poco::DateTime& lastModifiedAt, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl, bool forceZip64 = false);
|
||||
/// Creates a zip file header from an absoluteFile. fileName is the name of the file in the zip, outputIsSeekable determines if we write
|
||||
/// CRC and file sizes to the LocalFileHeader or after data compression into a ZipDataInfo
|
||||
/// If forceZip64 is set true then the file header is allocated with zip64 extension.
|
||||
|
||||
ZipLocalFileHeader(std::istream& inp, bool assumeHeaderRead, ParseCallback& callback);
|
||||
/// Creates the ZipLocalFileHeader by parsing the input stream.
|
||||
@@ -90,15 +91,15 @@ public:
|
||||
|
||||
Poco::UInt32 getCRC() const;
|
||||
|
||||
Poco::UInt32 getCompressedSize() const;
|
||||
Poco::UInt64 getCompressedSize() const;
|
||||
|
||||
Poco::UInt32 getUncompressedSize() const;
|
||||
Poco::UInt64 getUncompressedSize() const;
|
||||
|
||||
void setCRC(Poco::UInt32 val);
|
||||
|
||||
void setCompressedSize(Poco::UInt32 val);
|
||||
void setCompressedSize(Poco::UInt64 val);
|
||||
|
||||
void setUncompressedSize(Poco::UInt32 val);
|
||||
void setUncompressedSize(Poco::UInt64 val);
|
||||
|
||||
const std::string& getFileName() const;
|
||||
|
||||
@@ -118,6 +119,10 @@ public:
|
||||
|
||||
void setFileName(const std::string& fileName, bool isDirectory);
|
||||
|
||||
bool needsZip64() const;
|
||||
|
||||
void setZip64Data();
|
||||
|
||||
std::string createHeader() const;
|
||||
/// Creates a header
|
||||
|
||||
@@ -170,17 +175,27 @@ private:
|
||||
LASTMODEFILEDATE_POS = LASTMODEFILETIME_POS + LASTMODEFILETIME_SIZE,
|
||||
CRC32_SIZE = 4,
|
||||
CRC32_POS = LASTMODEFILEDATE_POS + LASTMODEFILEDATE_SIZE,
|
||||
COMPRESSEDSIZE_SIZE = 4,
|
||||
COMPRESSEDSIZE_POS = CRC32_POS + CRC32_SIZE,
|
||||
UNCOMPRESSEDSIZE_SIZE = 4,
|
||||
UNCOMPRESSEDSIZE_POS = COMPRESSEDSIZE_POS + COMPRESSEDSIZE_SIZE,
|
||||
FILELENGTH_SIZE = 2,
|
||||
FILELENGTH_POS = UNCOMPRESSEDSIZE_POS + UNCOMPRESSEDSIZE_SIZE,
|
||||
EXTRAFIELD_LENGTH = 2,
|
||||
EXTRAFIELD_POS = FILELENGTH_POS + FILELENGTH_SIZE,
|
||||
FULLHEADER_SIZE = 30
|
||||
COMPRESSED_SIZE_SIZE = 4,
|
||||
COMPRESSED_SIZE_POS = CRC32_POS + CRC32_SIZE,
|
||||
UNCOMPRESSED_SIZE_SIZE = 4,
|
||||
UNCOMPRESSED_SIZE_POS = COMPRESSED_SIZE_POS + COMPRESSED_SIZE_SIZE,
|
||||
FILE_LENGTH_SIZE = 2,
|
||||
FILE_LENGTH_POS = UNCOMPRESSED_SIZE_POS + UNCOMPRESSED_SIZE_SIZE,
|
||||
EXTRA_FIELD_LENGTH = 2,
|
||||
EXTRA_FIELD_POS = FILE_LENGTH_POS + FILE_LENGTH_SIZE,
|
||||
FULLHEADER_SIZE = 30,
|
||||
|
||||
EXTRA_DATA_TAG_SIZE = 2,
|
||||
EXTRA_DATA_TAG_POS = 0,
|
||||
EXTRA_DATA_SIZE_SIZE = 2,
|
||||
EXTRA_DATA_SIZE_POS = EXTRA_DATA_TAG_POS + EXTRA_DATA_TAG_SIZE,
|
||||
EXTRA_DATA_POS = EXTRA_DATA_SIZE_POS + EXTRA_DATA_SIZE_SIZE,
|
||||
EXTRA_DATA_UNCOMPRESSED_SIZE_SIZE = 8,
|
||||
EXTRA_DATA_COMPRESSED_SIZE_SIZE = 8,
|
||||
FULLEXTRA_DATA_SIZE = 20
|
||||
};
|
||||
|
||||
bool _forceZip64;
|
||||
char _rawHeader[FULLHEADER_SIZE];
|
||||
std::streamoff _startPos;
|
||||
std::streamoff _endPos;
|
||||
@@ -188,20 +203,20 @@ private:
|
||||
Poco::DateTime _lastModifiedAt;
|
||||
std::string _extraField;
|
||||
Poco::UInt32 _crc32;
|
||||
Poco::UInt32 _compressedSize;
|
||||
Poco::UInt32 _uncompressedSize;
|
||||
Poco::UInt64 _compressedSize;
|
||||
Poco::UInt64 _uncompressedSize;
|
||||
};
|
||||
|
||||
|
||||
inline void ZipLocalFileHeader::setFileNameLength(Poco::UInt16 size)
|
||||
{
|
||||
ZipUtil::set16BitValue(size, _rawHeader, FILELENGTH_POS);
|
||||
ZipUtil::set16BitValue(size, _rawHeader, FILE_LENGTH_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipLocalFileHeader::setExtraFieldSize(Poco::UInt16 size)
|
||||
{
|
||||
ZipUtil::set16BitValue(size, _rawHeader, EXTRAFIELD_POS);
|
||||
ZipUtil::set16BitValue(size, _rawHeader, EXTRA_FIELD_POS);
|
||||
}
|
||||
|
||||
|
||||
@@ -235,6 +250,23 @@ inline void ZipLocalFileHeader::getRequiredVersion(int& major, int& minor)
|
||||
minor = getMinorVersionNumber();
|
||||
}
|
||||
|
||||
inline bool ZipLocalFileHeader::needsZip64() const {
|
||||
return _forceZip64 || _startPos >= ZipCommon::ZIP64_MAGIC || _compressedSize >= ZipCommon::ZIP64_MAGIC || _uncompressedSize >= ZipCommon::ZIP64_MAGIC;
|
||||
}
|
||||
|
||||
inline void ZipLocalFileHeader::setZip64Data() {
|
||||
setRequiredVersion(4, 5);
|
||||
char data[FULLEXTRA_DATA_SIZE];
|
||||
ZipUtil::set16BitValue(ZipCommon::ZIP64_EXTRA_ID, data, EXTRA_DATA_TAG_POS);
|
||||
Poco::UInt16 pos = EXTRA_DATA_POS;
|
||||
ZipUtil::set64BitValue(_uncompressedSize, data, pos); pos += 8;
|
||||
ZipUtil::set32BitValue(ZipCommon::ZIP64_MAGIC, _rawHeader, UNCOMPRESSED_SIZE_POS);
|
||||
ZipUtil::set64BitValue(_compressedSize, data, pos); pos += 8;
|
||||
ZipUtil::set32BitValue(ZipCommon::ZIP64_MAGIC, _rawHeader, COMPRESSED_SIZE_POS);
|
||||
ZipUtil::set16BitValue(pos - EXTRA_DATA_POS, data, EXTRA_DATA_SIZE_POS);
|
||||
_extraField = std::string(data, pos);
|
||||
ZipUtil::set16BitValue(pos, _rawHeader, EXTRA_FIELD_POS);
|
||||
}
|
||||
|
||||
inline void ZipLocalFileHeader::setRequiredVersion(int major, int minor)
|
||||
{
|
||||
@@ -245,13 +277,13 @@ inline void ZipLocalFileHeader::setRequiredVersion(int major, int minor)
|
||||
|
||||
inline Poco::UInt16 ZipLocalFileHeader::getFileNameLength() const
|
||||
{
|
||||
return ZipUtil::get16BitValue(_rawHeader, FILELENGTH_POS);
|
||||
return ZipUtil::get16BitValue(_rawHeader, FILE_LENGTH_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt16 ZipLocalFileHeader::getExtraFieldLength() const
|
||||
{
|
||||
return ZipUtil::get16BitValue(_rawHeader, EXTRAFIELD_POS);
|
||||
return ZipUtil::get16BitValue(_rawHeader, EXTRA_FIELD_POS);
|
||||
}
|
||||
|
||||
|
||||
@@ -360,13 +392,13 @@ inline Poco::UInt32 ZipLocalFileHeader::getCRC() const
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipLocalFileHeader::getCompressedSize() const
|
||||
inline Poco::UInt64 ZipLocalFileHeader::getCompressedSize() const
|
||||
{
|
||||
return _compressedSize;
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipLocalFileHeader::getUncompressedSize() const
|
||||
inline Poco::UInt64 ZipLocalFileHeader::getUncompressedSize() const
|
||||
{
|
||||
return _uncompressedSize;
|
||||
}
|
||||
@@ -379,17 +411,17 @@ inline void ZipLocalFileHeader::setCRC(Poco::UInt32 val)
|
||||
}
|
||||
|
||||
|
||||
inline void ZipLocalFileHeader::setCompressedSize(Poco::UInt32 val)
|
||||
inline void ZipLocalFileHeader::setCompressedSize(Poco::UInt64 val)
|
||||
{
|
||||
_compressedSize = val;
|
||||
ZipUtil::set32BitValue(val, _rawHeader, COMPRESSEDSIZE_POS);
|
||||
ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawHeader, COMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline void ZipLocalFileHeader::setUncompressedSize(Poco::UInt32 val)
|
||||
inline void ZipLocalFileHeader::setUncompressedSize(Poco::UInt64 val)
|
||||
{
|
||||
_uncompressedSize = val;
|
||||
ZipUtil::set32BitValue(val, _rawHeader, UNCOMPRESSEDSIZE_POS);
|
||||
ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawHeader, UNCOMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
@@ -401,13 +433,13 @@ inline Poco::UInt32 ZipLocalFileHeader::getCRCFromHeader() const
|
||||
|
||||
inline Poco::UInt32 ZipLocalFileHeader::getCompressedSizeFromHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawHeader, COMPRESSEDSIZE_POS);
|
||||
return ZipUtil::get32BitValue(_rawHeader, COMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 ZipLocalFileHeader::getUncompressedSizeFromHeader() const
|
||||
{
|
||||
return ZipUtil::get32BitValue(_rawHeader, UNCOMPRESSEDSIZE_POS);
|
||||
return ZipUtil::get32BitValue(_rawHeader, UNCOMPRESSED_SIZE_POS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
virtual ~ZipStreamBuf();
|
||||
/// Destroys the ZipStreamBuf.
|
||||
|
||||
void close();
|
||||
void close(Poco::UInt64& extraDataSize);
|
||||
/// Informs a writing outputstream that writing is done for this stream
|
||||
|
||||
bool crcValid() const;
|
||||
@@ -79,7 +79,7 @@ private:
|
||||
Poco::UInt32 _expectedCrc32;
|
||||
bool _checkCRC;
|
||||
/// Note: we do not check crc if we decompress a streaming zip file and the crc is stored in the directory header
|
||||
Poco::UInt32 _bytesWritten;
|
||||
Poco::UInt64 _bytesWritten;
|
||||
ZipLocalFileHeader* _pHeader;
|
||||
};
|
||||
|
||||
@@ -140,7 +140,7 @@ public:
|
||||
~ZipOutputStream();
|
||||
/// Destroys the ZipOutputStream.
|
||||
|
||||
void close();
|
||||
void close(Poco::UInt64& extraDataSize);
|
||||
/// Must be called for ZipOutputStreams!
|
||||
};
|
||||
|
||||
|
||||
@@ -39,10 +39,14 @@ public:
|
||||
|
||||
static Poco::UInt32 get32BitValue(const char* pVal, const Poco::UInt32 pos);
|
||||
|
||||
static void set16BitValue(const Poco::UInt16 val, char* pVal, const Poco::UInt32 pos);
|
||||
static Poco::UInt64 get64BitValue(const char* pVal, const Poco::UInt32 pos);
|
||||
|
||||
static void set16BitValue(const Poco::UInt16 val, char* pVal, const Poco::UInt32 pos);
|
||||
|
||||
static void set32BitValue(const Poco::UInt32 val, char* pVal, const Poco::UInt32 pos);
|
||||
|
||||
static void set64BitValue(const Poco::UInt64 val, char* pVal, const Poco::UInt32 pos);
|
||||
|
||||
static Poco::DateTime parseDateTime(const char* pVal, const Poco::UInt32 timePos, const Poco::UInt32 datePos);
|
||||
|
||||
static void setDateTime(const Poco::DateTime& dt, char* pVal, const Poco::UInt32 timePos, const Poco::UInt32 datePos);
|
||||
@@ -77,6 +81,12 @@ inline Poco::UInt32 ZipUtil::get32BitValue(const char* pVal, const Poco::UInt32
|
||||
(static_cast<Poco::UInt32>((unsigned char)pVal[pos+2]) << 16) + (static_cast<Poco::UInt32>((unsigned char)pVal[pos+3]) << 24);
|
||||
}
|
||||
|
||||
inline Poco::UInt64 ZipUtil::get64BitValue(const char* pVal, const Poco::UInt32 pos)
|
||||
{
|
||||
Poco::UInt64 val = ZipUtil::get32BitValue(pVal, pos+4);
|
||||
val = (val << 32) | ZipUtil::get32BitValue(pVal, pos);
|
||||
return val;
|
||||
}
|
||||
|
||||
inline void ZipUtil::set16BitValue(const Poco::UInt16 val, char* pVal, const Poco::UInt32 pos)
|
||||
{
|
||||
@@ -93,6 +103,17 @@ inline void ZipUtil::set32BitValue(const Poco::UInt32 val, char* pVal, const Poc
|
||||
pVal[pos+3] = static_cast<char>(val>>24);
|
||||
}
|
||||
|
||||
inline void ZipUtil::set64BitValue(const Poco::UInt64 val, char* pVal, const Poco::UInt32 pos)
|
||||
{
|
||||
pVal[pos] = static_cast<char>(val);
|
||||
pVal[pos+1] = static_cast<char>(val>>8);
|
||||
pVal[pos+2] = static_cast<char>(val>>16);
|
||||
pVal[pos+3] = static_cast<char>(val>>24);
|
||||
pVal[pos+4] = static_cast<char>(val>>32);
|
||||
pVal[pos+5] = static_cast<char>(val>>40);
|
||||
pVal[pos+6] = static_cast<char>(val>>48);
|
||||
pVal[pos+7] = static_cast<char>(val>>56);
|
||||
}
|
||||
|
||||
} } // namespace Poco::Zip
|
||||
|
||||
|
||||
Reference in New Issue
Block a user