mirror of
				https://github.com/pocoproject/poco.git
				synced 2025-10-27 11:06:50 +01:00 
			
		
		
		
	| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -30,9 +30,10 @@ namespace Poco { | ||||
| namespace Zip { | ||||
|  | ||||
|  | ||||
| Compress::Compress(std::ostream& out, bool seekableOut): | ||||
| Compress::Compress(std::ostream& out, bool seekableOut, bool forceZip64): | ||||
| 	_out(out), | ||||
| 	_seekableOut(seekableOut), | ||||
|     _forceZip64(forceZip64), | ||||
| 	_files(), | ||||
| 	_infos(), | ||||
| 	_dirs(), | ||||
| @@ -63,26 +64,24 @@ void Compress::addEntry(std::istream& in, const Poco::DateTime& lastModifiedAt, | ||||
|  | ||||
| 	std::string fn = ZipUtil::validZipEntryFileName(fileName); | ||||
|  | ||||
| 	if (_files.size() >= 65535) | ||||
| 		throw ZipException("Maximum number of entries for a ZIP file reached: 65535"); | ||||
| 	if (!in.good()) | ||||
| 		throw ZipException("Invalid input stream"); | ||||
|  | ||||
| 	std::streamoff localHeaderOffset = _offset; | ||||
| 	ZipLocalFileHeader hdr(fileName, lastModifiedAt, cm, cl); | ||||
| 	ZipLocalFileHeader hdr(fileName, lastModifiedAt, cm, cl, _forceZip64); | ||||
| 	hdr.setStartPos(localHeaderOffset); | ||||
|  | ||||
| 	ZipOutputStream zipOut(_out, hdr, _seekableOut); | ||||
| 	Poco::StreamCopier::copyStream(in, zipOut); | ||||
| 	zipOut.close(); | ||||
| 	hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known | ||||
|     Poco::UInt64 extraDataSize; | ||||
| 	zipOut.close(extraDataSize); | ||||
| 	_offset = hdr.getEndPos(); | ||||
| 	if (hdr.searchCRCAndSizesAfterData()) | ||||
| 		_offset += ZipDataInfo::getFullHeaderSize(); | ||||
|     _offset += extraDataSize; | ||||
| 	_files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr)); | ||||
| 	poco_assert (_out); | ||||
| 	ZipFileInfo nfo(hdr); | ||||
| 	nfo.setOffset(localHeaderOffset); | ||||
|     nfo.setZip64Data(); | ||||
| 	_infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo)); | ||||
| 	EDone.notify(this, hdr); | ||||
| } | ||||
| @@ -94,8 +93,6 @@ void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const P | ||||
| 	//bypass the header of the input stream and point to the first byte of the data payload | ||||
| 	in.seekg(h.getDataStartPos(), std::ios_base::beg); | ||||
|  | ||||
| 	if (_files.size() >= 65535) | ||||
| 		throw ZipException("Maximum number of entries for a ZIP file reached: 65535"); | ||||
| 	if (!in.good()) | ||||
| 		throw ZipException("Invalid input stream"); | ||||
|  | ||||
| @@ -103,16 +100,18 @@ void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const P | ||||
| 	ZipLocalFileHeader hdr(h); | ||||
| 	hdr.setFileName(fn, h.isDirectory()); | ||||
| 	hdr.setStartPos(localHeaderOffset); | ||||
|     if(hdr.needsZip64()) | ||||
|         hdr.setZip64Data(); | ||||
| 	//bypass zipoutputstream | ||||
| 	//write the header directly | ||||
| 	std::string header = hdr.createHeader(); | ||||
| 	_out.write(header.c_str(), static_cast<std::streamsize>(header.size())); | ||||
| 	// now fwd the payload to _out in chunks of size CHUNKSIZE | ||||
| 	Poco::UInt32 totalSize = hdr.getCompressedSize(); | ||||
| 	Poco::UInt64 totalSize = hdr.getCompressedSize(); | ||||
| 	if (totalSize > 0) | ||||
| 	{ | ||||
| 		Poco::Buffer<char> buffer(COMPRESS_CHUNK_SIZE); | ||||
| 		Poco::UInt32 remaining = totalSize; | ||||
| 		Poco::UInt64 remaining = totalSize; | ||||
| 		while(remaining > 0) | ||||
| 		{ | ||||
| 			if (remaining > COMPRESS_CHUNK_SIZE) | ||||
| @@ -133,20 +132,33 @@ void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const P | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	//write optional block afterwards | ||||
| 	if (hdr.searchCRCAndSizesAfterData()) | ||||
| 	{ | ||||
| 		ZipDataInfo info(in, false); | ||||
| 		_out.write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize())); | ||||
| 	} | ||||
| 	hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known | ||||
| 	hdr.setStartPos(localHeaderOffset); // This resets EndPos now that compressed Size is known | ||||
| 	_offset = hdr.getEndPos(); | ||||
| 	if (hdr.searchCRCAndSizesAfterData()) | ||||
| 		_offset += ZipDataInfo::getFullHeaderSize(); | ||||
| 	//write optional block afterwards | ||||
| 	if (hdr.searchCRCAndSizesAfterData()) { | ||||
|         if(hdr.needsZip64()) { | ||||
|     		ZipDataInfo64 info(in, false); | ||||
| 	    	_out.write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize())); | ||||
| 		    _offset += ZipDataInfo::getFullHeaderSize(); | ||||
|         } else { | ||||
|     		ZipDataInfo info(in, false); | ||||
| 	    	_out.write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize())); | ||||
| 		    _offset += ZipDataInfo::getFullHeaderSize(); | ||||
|         } | ||||
| 	} else { | ||||
|         if(hdr.hasExtraField())  // Update sizes in header extension. | ||||
|             hdr.setZip64Data(); | ||||
|     	_out.seekp(hdr.getStartPos(), std::ios_base::beg); | ||||
|     	std::string header = hdr.createHeader(); | ||||
| 		_out.write(header.c_str(), static_cast<std::streamsize>(header.size())); | ||||
|     	_out.seekp(0, std::ios_base::end); | ||||
|     } | ||||
|  | ||||
| 	_files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr)); | ||||
| 	poco_assert (_out); | ||||
| 	ZipFileInfo nfo(hdr); | ||||
| 	nfo.setOffset(localHeaderOffset); | ||||
|     nfo.setZip64Data(); | ||||
| 	_infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo)); | ||||
| 	EDone.notify(this, hdr); | ||||
| } | ||||
| @@ -186,8 +198,6 @@ void Compress::addDirectory(const Poco::Path& entryName, const Poco::DateTime& l | ||||
| 	std::string fileStr = entryName.toString(Poco::Path::PATH_UNIX); | ||||
| 	if (_files.find(fileStr) != _files.end()) | ||||
| 		return; // ignore duplicate add | ||||
| 	if (_files.size() >= 65535) | ||||
| 		throw ZipException("Maximum number of entries for a ZIP file reached: 65535"); | ||||
| 	if (fileStr == "/") | ||||
| 		throw ZipException("Illegal entry name /"); | ||||
| 	if (fileStr.empty()) | ||||
| @@ -206,15 +216,17 @@ void Compress::addDirectory(const Poco::Path& entryName, const Poco::DateTime& l | ||||
| 	ZipLocalFileHeader hdr(entryName, lastModifiedAt, cm, cl); | ||||
| 	hdr.setStartPos(localHeaderOffset); | ||||
| 	ZipOutputStream zipOut(_out, hdr, _seekableOut); | ||||
| 	zipOut.close(); | ||||
|     Poco::UInt64 extraDataSize; | ||||
| 	zipOut.close(extraDataSize); | ||||
| 	hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known | ||||
| 	_offset = hdr.getEndPos(); | ||||
| 	if (hdr.searchCRCAndSizesAfterData()) | ||||
| 		_offset += ZipDataInfo::getFullHeaderSize(); | ||||
| 		_offset += extraDataSize; | ||||
| 	_files.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), hdr)); | ||||
| 	poco_assert (_out); | ||||
| 	ZipFileInfo nfo(hdr); | ||||
| 	nfo.setOffset(localHeaderOffset); | ||||
|     nfo.setZip64Data(); | ||||
| 	_infos.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), nfo)); | ||||
| 	EDone.notify(this, hdr); | ||||
| } | ||||
| @@ -274,34 +286,57 @@ void Compress::addRecursive(const Poco::Path& entry, ZipCommon::CompressionMetho | ||||
|  | ||||
| ZipArchive Compress::close() | ||||
| { | ||||
| 	if (!_dirs.empty()) | ||||
| 		return ZipArchive(_files, _infos, _dirs); | ||||
| 	if (!_dirs.empty() || ! _dirs64.empty()) | ||||
| 		return ZipArchive(_files, _infos, _dirs, _dirs64); | ||||
|  | ||||
| 	poco_assert (_infos.size() == _files.size()); | ||||
| 	poco_assert (_files.size() < 65536); | ||||
| 	Poco::UInt32 centralDirStart = _offset; | ||||
| 	Poco::UInt32 centralDirSize = 0; | ||||
| 	Poco::UInt64 centralDirSize64 = 0; | ||||
| 	Poco::UInt64 centralDirStart64 = _offset; | ||||
| 	// write all infos | ||||
| 	ZipArchive::FileInfos::const_iterator it = _infos.begin(); | ||||
| 	ZipArchive::FileInfos::const_iterator itEnd = _infos.end(); | ||||
|     bool needZip64 = _forceZip64; | ||||
|     needZip64 = needZip64  || _files.size() >= ZipCommon::ZIP64_MAGIC_SHORT || centralDirStart64 >= ZipCommon::ZIP64_MAGIC; | ||||
| 	for (; it != itEnd; ++it) | ||||
| 	{ | ||||
| 		const ZipFileInfo& nfo = it->second; | ||||
|         needZip64 = needZip64  || nfo.needsZip64(); | ||||
|  | ||||
| 		std::string info(nfo.createHeader()); | ||||
| 		_out.write(info.c_str(), static_cast<std::streamsize>(info.size())); | ||||
| 		Poco::UInt32 entrySize = static_cast<Poco::UInt32>(info.size()); | ||||
| 		centralDirSize += entrySize; | ||||
| 		centralDirSize64 += entrySize; | ||||
| 		_offset += entrySize; | ||||
| 	} | ||||
| 	poco_assert (_out); | ||||
|  | ||||
| 	 | ||||
| 	Poco::UInt16 numEntries = static_cast<Poco::UInt16>(_infos.size()); | ||||
| 	Poco::UInt64 numEntries64 = _infos.size(); | ||||
|     needZip64 = needZip64  || _offset >= ZipCommon::ZIP64_MAGIC; | ||||
|     if(needZip64) { | ||||
|  	    ZipArchiveInfo64 central; | ||||
| 	    central.setCentralDirectorySize(centralDirSize64); | ||||
| 	    central.setCentralDirectoryOffset(centralDirStart64); | ||||
| 	    central.setNumberOfEntries(numEntries64); | ||||
| 	    central.setTotalNumberOfEntries(numEntries64); | ||||
| 	    central.setHeaderOffset(_offset); | ||||
|         central.setTotalNumberOfDisks(1); | ||||
| 	    std::string centr(central.createHeader()); | ||||
| 	    _out.write(centr.c_str(), static_cast<std::streamsize>(centr.size())); | ||||
| 	    _out.flush(); | ||||
|         _offset += centr.size(); | ||||
| 	    _dirs64.insert(std::make_pair(0, central)); | ||||
|     } | ||||
|  | ||||
|     Poco::UInt16 numEntries = numEntries64 >= ZipCommon::ZIP64_MAGIC_SHORT ? ZipCommon::ZIP64_MAGIC_SHORT : static_cast<Poco::UInt16>(numEntries64); | ||||
|     Poco::UInt32 centralDirStart = centralDirStart64 >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(centralDirStart64); | ||||
|     Poco::UInt32 centralDirSize = centralDirSize64 >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(centralDirSize64); | ||||
|     Poco::UInt32 offset = _offset >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(_offset); | ||||
| 	ZipArchiveInfo central; | ||||
| 	central.setCentralDirectorySize(centralDirSize); | ||||
| 	central.setCentralDirectoryOffset(centralDirStart); | ||||
| 	central.setNumberOfEntries(numEntries); | ||||
| 	central.setTotalNumberOfEntries(numEntries); | ||||
| 	central.setHeaderOffset(centralDirStart); | ||||
| 	central.setHeaderOffset(offset); | ||||
| 	if (!_comment.empty() && _comment.size() <= 65535) | ||||
| 	{ | ||||
| 		central.setZipComment(_comment); | ||||
| @@ -309,11 +344,11 @@ ZipArchive Compress::close() | ||||
| 	std::string centr(central.createHeader()); | ||||
| 	_out.write(centr.c_str(), static_cast<std::streamsize>(centr.size())); | ||||
| 	_out.flush(); | ||||
|     _offset += centr.size(); | ||||
| 	_dirs.insert(std::make_pair(0, central)); | ||||
| 	return ZipArchive(_files, _infos, _dirs); | ||||
| 	return ZipArchive(_files, _infos, _dirs, _dirs64); | ||||
| } | ||||
|  | ||||
|  | ||||
| void Compress::setStoreExtensions(const std::set<std::string>& extensions) | ||||
| { | ||||
| 	_storeExtensions.clear(); | ||||
|   | ||||
| @@ -27,7 +27,8 @@ namespace Zip { | ||||
| ZipArchive::ZipArchive(std::istream& in): | ||||
| 	_entries(), | ||||
| 	_infos(), | ||||
| 	_disks() | ||||
| 	_disks(), | ||||
| 	_disks64() | ||||
| { | ||||
| 	poco_assert_dbg (in); | ||||
| 	SkipCallback skip; | ||||
| @@ -35,10 +36,11 @@ ZipArchive::ZipArchive(std::istream& in): | ||||
| } | ||||
|  | ||||
|  | ||||
| ZipArchive::ZipArchive(const FileHeaders& entries, const FileInfos& infos, const DirectoryInfos& dirs): | ||||
| ZipArchive::ZipArchive(const FileHeaders& entries, const FileInfos& infos, const DirectoryInfos& dirs, const DirectoryInfos64& dirs64): | ||||
| 	_entries(entries), | ||||
| 	_infos(infos), | ||||
| 	_disks(dirs) | ||||
| 	_disks(dirs), | ||||
| 	_disks64(dirs64) | ||||
| { | ||||
| } | ||||
|  | ||||
| @@ -46,7 +48,8 @@ ZipArchive::ZipArchive(const FileHeaders& entries, const FileInfos& infos, const | ||||
| ZipArchive::ZipArchive(std::istream& in, ParseCallback& pc): | ||||
| 	_entries(), | ||||
| 	_infos(), | ||||
| 	_disks() | ||||
| 	_disks(), | ||||
| 	_disks64() | ||||
| { | ||||
| 	poco_assert_dbg (in); | ||||
| 	parse(in, pc); | ||||
| @@ -78,7 +81,7 @@ void ZipArchive::parse(std::istream& in, ParseCallback& pc) | ||||
| 			FileHeaders::iterator it = _entries.find(info.getFileName()); | ||||
| 			if (it != _entries.end()) | ||||
| 			{ | ||||
| 				it->second.setStartPos(info.getRelativeOffsetOfLocalHeader()); | ||||
| 				it->second.setStartPos(info.getOffset()); | ||||
| 			} | ||||
| 			poco_assert (_infos.insert(std::make_pair(info.getFileName(), info)).second); | ||||
| 		} | ||||
| @@ -87,9 +90,14 @@ void ZipArchive::parse(std::istream& in, ParseCallback& pc) | ||||
| 			ZipArchiveInfo nfo(in, true); | ||||
| 			poco_assert (_disks.insert(std::make_pair(nfo.getDiskNumber(), nfo)).second); | ||||
| 		} | ||||
| 		else if (std::memcmp(header, ZipArchiveInfo64::HEADER, ZipCommon::HEADER_SIZE) == 0) | ||||
| 		{ | ||||
| 			ZipArchiveInfo64 nfo(in, true); | ||||
| 			poco_assert (_disks64.insert(std::make_pair(nfo.getDiskNumber(), nfo)).second); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if (_disks.empty()) | ||||
| 			if (_disks.empty() && _disks64.empty()) | ||||
| 				throw Poco::IllegalStateException("Illegal header in zip file"); | ||||
| 			else | ||||
| 				throw Poco::IllegalStateException("Garbage after directory header"); | ||||
|   | ||||
| @@ -98,4 +98,77 @@ void ZipArchiveInfo::setZipComment(const std::string& comment) | ||||
| } | ||||
|  | ||||
|  | ||||
| const char ZipArchiveInfo64::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x06', '\x06'}; | ||||
| const char ZipArchiveInfo64::LOCATOR_HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x06', '\x07'}; | ||||
|  | ||||
|  | ||||
| ZipArchiveInfo64::ZipArchiveInfo64(std::istream& in, bool assumeHeaderRead): | ||||
| 	_rawInfo(), | ||||
| 	_startPos(in.tellg()) | ||||
| { | ||||
| 	if (assumeHeaderRead) | ||||
| 		_startPos -= ZipCommon::HEADER_SIZE; | ||||
| 	parse(in, assumeHeaderRead); | ||||
| } | ||||
|  | ||||
| ZipArchiveInfo64::ZipArchiveInfo64(): | ||||
| 	_rawInfo(), | ||||
| 	_startPos(0) | ||||
| { | ||||
| 	std::memset(_rawInfo, 0, FULL_HEADER_SIZE); | ||||
| 	std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); | ||||
|     ZipUtil::set64BitValue(FULL_HEADER_SIZE - (RECORDSIZE_POS + RECORDSIZE_SIZE), _rawInfo, RECORDSIZE_POS); | ||||
| 	std::memset(_locInfo, 0, FULL_LOCATOR_SIZE); | ||||
| 	std::memcpy(_locInfo, LOCATOR_HEADER, ZipCommon::HEADER_SIZE); | ||||
|     setRequiredVersion(4, 5); | ||||
| } | ||||
|  | ||||
|  | ||||
| ZipArchiveInfo64::~ZipArchiveInfo64() | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
| void ZipArchiveInfo64::parse(std::istream& inp, bool assumeHeaderRead) | ||||
| { | ||||
| 	if (!assumeHeaderRead) | ||||
| 	{ | ||||
| 		inp.read(_rawInfo, ZipCommon::HEADER_SIZE); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); | ||||
| 	} | ||||
| 	poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); | ||||
| 	std::memset(_rawInfo + ZipCommon::HEADER_SIZE, 0, FULL_HEADER_SIZE - ZipCommon::HEADER_SIZE); | ||||
|  | ||||
| 	// read the rest of the header | ||||
|     Poco::UInt64 offset = RECORDSIZE_POS; | ||||
| 	inp.read(_rawInfo + ZipCommon::HEADER_SIZE, RECORDSIZE_SIZE); | ||||
|     offset += RECORDSIZE_SIZE; | ||||
|     Poco::UInt64 len = ZipUtil::get64BitValue(_rawInfo, RECORDSIZE_POS); | ||||
|     if(len <= FULL_HEADER_SIZE - offset) { | ||||
| 	    inp.read(_rawInfo + offset, len); | ||||
|         ZipUtil::set64BitValue(FULL_HEADER_SIZE - offset, _rawInfo, RECORDSIZE_POS); | ||||
|     } else { | ||||
| 	    inp.read(_rawInfo + offset, FULL_HEADER_SIZE - offset); | ||||
|         len -= (FULL_HEADER_SIZE - offset); | ||||
| 	    Poco::Buffer<char> xtra(len); | ||||
| 	    inp.read(xtra.begin(), len); | ||||
| 	    _extraField = std::string(xtra.begin(), len); | ||||
|         ZipUtil::set64BitValue(FULL_HEADER_SIZE + len - offset, _rawInfo, RECORDSIZE_POS); | ||||
|     } | ||||
| 	inp.read(_locInfo, FULL_LOCATOR_SIZE); | ||||
| 	poco_assert (std::memcmp(_locInfo, LOCATOR_HEADER, ZipCommon::HEADER_SIZE) == 0); | ||||
| } | ||||
|  | ||||
|  | ||||
| std::string ZipArchiveInfo64::createHeader() const | ||||
| { | ||||
| 	std::string result(_rawInfo, FULL_HEADER_SIZE); | ||||
| 	result.append(_extraField); | ||||
| 	result.append(_locInfo, FULL_LOCATOR_SIZE); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| } } // namespace Poco::Zip | ||||
|   | ||||
| @@ -56,4 +56,38 @@ ZipDataInfo::~ZipDataInfo() | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| const char ZipDataInfo64::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x07', '\x08'}; | ||||
|  | ||||
|  | ||||
| ZipDataInfo64::ZipDataInfo64(): | ||||
| 	_rawInfo(), | ||||
| 	_valid(true) | ||||
| { | ||||
| 	std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); | ||||
| 	std::memset(_rawInfo+ZipCommon::HEADER_SIZE, 0, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); | ||||
| 	_valid = true; | ||||
| } | ||||
|  | ||||
|  | ||||
| ZipDataInfo64::ZipDataInfo64(std::istream& in, bool assumeHeaderRead): | ||||
| 	_rawInfo(), | ||||
| 	_valid(false) | ||||
| { | ||||
| 	if (assumeHeaderRead) | ||||
| 		std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); | ||||
| 	else | ||||
| 		in.read(_rawInfo, ZipCommon::HEADER_SIZE); | ||||
| 	poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); | ||||
| 	// now copy the rest of the header | ||||
| 	in.read(_rawInfo+ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); | ||||
| 	_valid = (!in.eof() && in.good()); | ||||
| } | ||||
|  | ||||
|  | ||||
| ZipDataInfo64::~ZipDataInfo64() | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
| } } // namespace Poco::Zip | ||||
|   | ||||
| @@ -10,7 +10,27 @@ | ||||
| // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. | ||||
| // and Contributors. | ||||
| // | ||||
| // SPDX-License-Identifier:	BSL-1.0 | ||||
| // Permission is hereby granted, free of charge, to any person or organization | ||||
| // obtaining a copy of the software and accompanying documentation covered by | ||||
| // this license (the "Software") to use, reproduce, display, distribute, | ||||
| // execute, and transmit the Software, and to prepare derivative works of the | ||||
| // Software, and to permit third-parties to whom the Software is furnished to | ||||
| // do so, all subject to the following: | ||||
| //  | ||||
| // The copyright notices in the Software and this entire statement, including | ||||
| // the above license grant, this restriction and the following disclaimer, | ||||
| // must be included in all copies of the Software, in whole or in part, and | ||||
| // all derivative works of the Software, unless such copies or derivative | ||||
| // works are solely in the form of machine-executable object code generated by | ||||
| // a source language processor. | ||||
| //  | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT | ||||
| // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE | ||||
| // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, | ||||
| // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
| // DEALINGS IN THE SOFTWARE. | ||||
| // | ||||
|  | ||||
|  | ||||
| @@ -33,6 +53,7 @@ ZipFileInfo::ZipFileInfo(const ZipLocalFileHeader& header): | ||||
| 	_crc32(0), | ||||
| 	_compressedSize(0), | ||||
| 	_uncompressedSize(0), | ||||
|     _localHeaderOffset(0), | ||||
| 	_fileName(), | ||||
| 	_lastModifiedAt(), | ||||
| 	_extraField() | ||||
| @@ -51,7 +72,9 @@ ZipFileInfo::ZipFileInfo(const ZipLocalFileHeader& header): | ||||
| 	setFileName(header.getFileName()); | ||||
|  | ||||
| 	if (getHostSystem() == ZipCommon::HS_UNIX) | ||||
| 		setUnixAttributes(); | ||||
|         setUnixAttributes(); | ||||
|  | ||||
|     _rawInfo[GENERAL_PURPOSE_POS+1] |= 0x08; // Set "language encoding flag" to indicate that filenames and paths are in UTF-8.    ZipFileInfo::ZipFileInfo(const ZipLocalFileHeader& header): | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -60,6 +83,7 @@ ZipFileInfo::ZipFileInfo(std::istream& in, bool assumeHeaderRead): | ||||
| 	_crc32(0), | ||||
| 	_compressedSize(0), | ||||
| 	_uncompressedSize(0), | ||||
|     _localHeaderOffset(0), | ||||
| 	_fileName(), | ||||
| 	_lastModifiedAt(), | ||||
| 	_extraField() | ||||
| @@ -102,6 +126,25 @@ void ZipFileInfo::parse(std::istream& inp, bool assumeHeaderRead) | ||||
| 		Poco::Buffer<char> xtra(len); | ||||
| 		inp.read(xtra.begin(), len); | ||||
| 		_extraField = std::string(xtra.begin(), len); | ||||
|         char* ptr = xtra.begin(); | ||||
|         while(ptr <= xtra.begin() + len - 4) { | ||||
|             Poco::UInt16 id = ZipUtil::get16BitValue(ptr, 0); ptr +=2; | ||||
|             Poco::UInt16 size = ZipUtil::get16BitValue(ptr, 0); ptr += 2; | ||||
|             if(id == ZipCommon::ZIP64_EXTRA_ID) { | ||||
|                 poco_assert(size >= 8); | ||||
|                 if(getUncompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) { | ||||
|                     setUncompressedSize(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; | ||||
|                 } | ||||
|                 if(size >= 8 && getCompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) { | ||||
|                     setCompressedSize(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; | ||||
|                 } | ||||
|                 if(size >= 8 && getOffsetFromHeader() == ZipCommon::ZIP64_MAGIC) { | ||||
|                     setOffset(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; | ||||
|                 } | ||||
|             } else { | ||||
|                 ptr += size; | ||||
|             } | ||||
|         } | ||||
| 	} | ||||
| 	len = getFileCommentLength(); | ||||
| 	if (len > 0) | ||||
|   | ||||
| @@ -10,7 +10,27 @@ | ||||
| // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. | ||||
| // and Contributors. | ||||
| // | ||||
| // SPDX-License-Identifier:	BSL-1.0 | ||||
| // Permission is hereby granted, free of charge, to any person or organization | ||||
| // obtaining a copy of the software and accompanying documentation covered by | ||||
| // this license (the "Software") to use, reproduce, display, distribute, | ||||
| // execute, and transmit the Software, and to prepare derivative works of the | ||||
| // Software, and to permit third-parties to whom the Software is furnished to | ||||
| // do so, all subject to the following: | ||||
| //  | ||||
| // The copyright notices in the Software and this entire statement, including | ||||
| // the above license grant, this restriction and the following disclaimer, | ||||
| // must be included in all copies of the Software, in whole or in part, and | ||||
| // all derivative works of the Software, unless such copies or derivative | ||||
| // works are solely in the form of machine-executable object code generated by | ||||
| // a source language processor. | ||||
| //  | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT | ||||
| // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE | ||||
| // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, | ||||
| // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
| // DEALINGS IN THE SOFTWARE. | ||||
| // | ||||
|  | ||||
|  | ||||
| @@ -33,8 +53,10 @@ const char ZipLocalFileHeader::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', | ||||
| ZipLocalFileHeader::ZipLocalFileHeader(const Poco::Path& fileName,  | ||||
| 	const Poco::DateTime& lastModifiedAt, | ||||
| 	ZipCommon::CompressionMethod cm,  | ||||
| 	ZipCommon::CompressionLevel cl): | ||||
| 	_rawHeader(), | ||||
| 	ZipCommon::CompressionLevel cl, | ||||
|     bool forceZip64): | ||||
| 	_forceZip64(forceZip64), | ||||
|     _rawHeader(), | ||||
| 	_startPos(-1), | ||||
| 	_endPos(-1), | ||||
| 	_fileName(), | ||||
| @@ -66,6 +88,7 @@ ZipLocalFileHeader::ZipLocalFileHeader(const Poco::Path& fileName, | ||||
|  | ||||
|  | ||||
| ZipLocalFileHeader::ZipLocalFileHeader(std::istream& inp, bool assumeHeaderRead, ParseCallback& callback): | ||||
| 	_forceZip64(false), | ||||
| 	_rawHeader(), | ||||
| 	_startPos(inp.tellg()), | ||||
| 	_endPos(-1), | ||||
| @@ -76,7 +99,7 @@ ZipLocalFileHeader::ZipLocalFileHeader(std::istream& inp, bool assumeHeaderRead, | ||||
| 	_compressedSize(0), | ||||
| 	_uncompressedSize(0) | ||||
| { | ||||
| 	poco_assert_dbg( (EXTRAFIELD_POS+EXTRAFIELD_LENGTH) == FULLHEADER_SIZE); | ||||
| 	poco_assert_dbg( (EXTRA_FIELD_POS+EXTRA_FIELD_LENGTH) == FULLHEADER_SIZE); | ||||
|  | ||||
| 	if (assumeHeaderRead) | ||||
| 		_startPos -= ZipCommon::HEADER_SIZE; | ||||
| @@ -89,10 +112,19 @@ ZipLocalFileHeader::ZipLocalFileHeader(std::istream& inp, bool assumeHeaderRead, | ||||
| 	{ | ||||
| 		if (searchCRCAndSizesAfterData()) | ||||
| 		{ | ||||
| 			ZipDataInfo nfo(inp, false); | ||||
| 			setCRC(nfo.getCRC32()); | ||||
| 			setCompressedSize(nfo.getCompressedSize()); | ||||
| 			setUncompressedSize(nfo.getUncompressedSize()); | ||||
|             char header[ZipCommon::HEADER_SIZE]={'\x00', '\x00', '\x00', '\x00'}; | ||||
|             inp.read(header, ZipCommon::HEADER_SIZE); | ||||
| 			if(::memcmp(header, ZipDataInfo64::HEADER, sizeof(header)) == 0) { | ||||
|                 ZipDataInfo64 nfo(inp, true); | ||||
| 			    setCRC(nfo.getCRC32()); | ||||
| 			    setCompressedSize(nfo.getCompressedSize()); | ||||
| 			    setUncompressedSize(nfo.getUncompressedSize()); | ||||
|             } else { | ||||
|                 ZipDataInfo nfo(inp, true); | ||||
| 			    setCRC(nfo.getCRC32()); | ||||
| 			    setCompressedSize(nfo.getCompressedSize()); | ||||
| 			    setUncompressedSize(nfo.getUncompressedSize()); | ||||
|             } | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| @@ -122,28 +154,46 @@ void ZipLocalFileHeader::parse(std::istream& inp, bool assumeHeaderRead) | ||||
| 	poco_assert (std::memcmp(_rawHeader, HEADER, ZipCommon::HEADER_SIZE) == 0); | ||||
| 	// read the rest of the header | ||||
| 	inp.read(_rawHeader + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); | ||||
| 	if (!(_rawHeader[VERSION_POS + 1]>= ZipCommon::HS_FAT && _rawHeader[VERSION_POS + 1] < ZipCommon::HS_UNUSED)) | ||||
| 		throw Poco::DataFormatException("bad ZIP file header", "invalid version"); | ||||
| 	if (ZipUtil::get16BitValue(_rawHeader, COMPR_METHOD_POS) >= ZipCommon::CM_UNUSED) | ||||
| 		throw Poco::DataFormatException("bad ZIP file header", "invalid compression method"); | ||||
| 	poco_assert (_rawHeader[VERSION_POS + 1]>= ZipCommon::HS_FAT && _rawHeader[VERSION_POS + 1] < ZipCommon::HS_UNUSED); | ||||
| 	poco_assert (getMajorVersionNumber() <= 4); // Allow for Zip64 version 4.5 | ||||
| 	poco_assert (ZipUtil::get16BitValue(_rawHeader, COMPR_METHOD_POS) < ZipCommon::CM_UNUSED); | ||||
| 	parseDateTime(); | ||||
| 	Poco::UInt16 len = getFileNameLength(); | ||||
| 	Poco::Buffer<char> buf(len); | ||||
| 	inp.read(buf.begin(), len); | ||||
| 	_fileName = std::string(buf.begin(), len); | ||||
| 	if (hasExtraField()) | ||||
| 	{ | ||||
| 		len = getExtraFieldLength(); | ||||
| 		Poco::Buffer<char> xtra(len); | ||||
| 		inp.read(xtra.begin(), len); | ||||
| 		_extraField = std::string(xtra.begin(), len); | ||||
| 	} | ||||
|  | ||||
| 	if (!searchCRCAndSizesAfterData()) | ||||
| 	{ | ||||
| 		_crc32 = getCRCFromHeader(); | ||||
| 		_compressedSize = getCompressedSizeFromHeader(); | ||||
| 		_uncompressedSize = getUncompressedSizeFromHeader(); | ||||
| 	} | ||||
|  | ||||
|     if (hasExtraField()) | ||||
| 	{ | ||||
| 		len = getExtraFieldLength(); | ||||
| 		Poco::Buffer<char> xtra(len); | ||||
| 		inp.read(xtra.begin(), len); | ||||
| 		_extraField = std::string(xtra.begin(), len); | ||||
|         char* ptr = xtra.begin(); | ||||
|         while(ptr <= xtra.begin() + len - 4) { | ||||
|             Poco::UInt16 id = ZipUtil::get16BitValue(ptr, 0); ptr +=2; | ||||
|             Poco::UInt16 size = ZipUtil::get16BitValue(ptr, 0); ptr += 2; | ||||
|             if(id == ZipCommon::ZIP64_EXTRA_ID) { | ||||
|                 poco_assert(size >= 8); | ||||
|                 if(getUncompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) { | ||||
|                     setUncompressedSize(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; | ||||
|                 } | ||||
|                 if(size >= 8 && getCompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) { | ||||
|                     setCompressedSize(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; | ||||
|                 } | ||||
|             } else { | ||||
|                 ptr += size; | ||||
|             } | ||||
|         } | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -204,6 +254,9 @@ void ZipLocalFileHeader::init(	const Poco::Path& fName, | ||||
| 	} | ||||
| 	else | ||||
| 		setCompressionMethod(ZipCommon::CM_STORE); | ||||
|     if(_forceZip64) | ||||
|         setZip64Data(); | ||||
|      _rawHeader[GENERAL_PURPOSE_POS+1] |= 0x08; // Set "language encoding flag" to indicate that filenames and paths are in UTF-8. | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -135,6 +135,8 @@ ZipStreamBuf::ZipStreamBuf(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bo | ||||
| 		else throw Poco::NotImplementedException("Unsupported compression method"); | ||||
|  | ||||
| 		// now write the header to the ostr! | ||||
|         if(fileEntry.needsZip64()) | ||||
|             fileEntry.setZip64Data(); | ||||
| 		std::string header = fileEntry.createHeader(); | ||||
| 		ostr.write(header.c_str(), static_cast<std::streamsize>(header.size())); | ||||
| 	} | ||||
| @@ -198,8 +200,9 @@ int ZipStreamBuf::writeToDevice(const char* buffer, std::streamsize length) | ||||
| } | ||||
|  | ||||
|  | ||||
| void ZipStreamBuf::close() | ||||
| void ZipStreamBuf::close(Poco::UInt64& extraDataSize) | ||||
| { | ||||
|     extraDataSize = 0; | ||||
| 	if (_ptrOBuf && _pHeader) | ||||
| 	{ | ||||
| 		_ptrOBuf->flush(); | ||||
| @@ -217,20 +220,33 @@ void ZipStreamBuf::close() | ||||
| 		// or fix the crc entries | ||||
| 		if (_pHeader->searchCRCAndSizesAfterData()) | ||||
| 		{ | ||||
| 			ZipDataInfo info; | ||||
| 			info.setCRC32(_crc32.checksum()); | ||||
| 			info.setUncompressedSize(_bytesWritten); | ||||
| 			info.setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten())); | ||||
| 			_pOstr->write(info.getRawHeader(), static_cast<std::streamsize>(info.getFullHeaderSize())); | ||||
|             if(_pHeader->needsZip64()) { | ||||
| 			    ZipDataInfo64 info; | ||||
| 			    info.setCRC32(_crc32.checksum()); | ||||
| 			    info.setUncompressedSize(_bytesWritten); | ||||
| 			    info.setCompressedSize(_ptrOHelper->bytesWritten()); | ||||
|                 extraDataSize = info.getFullHeaderSize(); | ||||
| 			    _pOstr->write(info.getRawHeader(), static_cast<std::streamsize>(extraDataSize)); | ||||
|             } else { | ||||
|  			    ZipDataInfo info; | ||||
| 			    info.setCRC32(_crc32.checksum()); | ||||
| 			    info.setUncompressedSize(static_cast<Poco::UInt32>(_bytesWritten)); | ||||
| 			    info.setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten())); | ||||
|                 extraDataSize = info.getFullHeaderSize(); | ||||
| 			    _pOstr->write(info.getRawHeader(), static_cast<std::streamsize>(extraDataSize)); | ||||
|            } | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			poco_check_ptr (_pHeader); | ||||
| 			_pHeader->setCRC(_crc32.checksum()); | ||||
| 			_pHeader->setUncompressedSize(_bytesWritten); | ||||
| 			_pHeader->setCompressedSize(static_cast<Poco::UInt32>(_ptrOHelper->bytesWritten())); | ||||
| 			_pHeader->setCompressedSize(_ptrOHelper->bytesWritten()); | ||||
| 			_pOstr->seekp(_pHeader->getStartPos(), std::ios_base::beg); | ||||
| 			poco_assert (*_pOstr); | ||||
| 	        _pHeader->setStartPos(_pHeader->getStartPos()); // This resets EndPos now that compressed Size is known | ||||
|             if(_pHeader->hasExtraField())   // Update sizes in header extension. | ||||
|                 _pHeader->setZip64Data(); | ||||
| 			std::string header = _pHeader->createHeader(); | ||||
| 			_pOstr->write(header.c_str(), static_cast<std::streamsize>(header.size())); | ||||
| 			_pOstr->seekp(0, std::ios_base::end); | ||||
| @@ -297,10 +313,10 @@ ZipOutputStream::~ZipOutputStream() | ||||
| } | ||||
|  | ||||
|  | ||||
| void ZipOutputStream::close() | ||||
| void ZipOutputStream::close(Poco::UInt64& extraDataSize) | ||||
| { | ||||
| 	flush(); | ||||
| 	_buf.close(); | ||||
| 	_buf.close(extraDataSize); | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -12,14 +12,19 @@ | ||||
|  | ||||
| #include "CompressTest.h" | ||||
| #include "ZipTest.h" | ||||
|  | ||||
| #include "Poco/Buffer.h" | ||||
| #include "Poco/Zip/Compress.h" | ||||
| #include "Poco/Zip/ZipManipulator.h" | ||||
| #include "Poco/File.h" | ||||
| #include "Poco/FileStream.h" | ||||
|  | ||||
| #include "CppUnit/TestCaller.h" | ||||
| #include "CppUnit/TestSuite.h" | ||||
| #include <fstream> | ||||
|  | ||||
| #undef min | ||||
| #include <algorithm> | ||||
|  | ||||
| using namespace Poco::Zip; | ||||
|  | ||||
| @@ -133,6 +138,50 @@ void CompressTest::testSetZipComment() | ||||
| 	assert(a.getZipComment() == comment); | ||||
| } | ||||
|  | ||||
| void CompressTest::createDataFile(const std::string& path, Poco::UInt64 size) { | ||||
|     std::ofstream out(path, std::ios::binary | std::ios::trunc); | ||||
|     assert( ! out.fail() ); | ||||
|     Poco::Buffer<char> buffer(MB); | ||||
|     for(int i = 0; size != 0; i++) { | ||||
|         std::memset(buffer.begin(), i, buffer.size()); | ||||
|         Poco::UInt64 bytesToWrite = std::min(size, buffer.size()); | ||||
|         out.write(buffer.begin(), bytesToWrite); | ||||
|         assert( ! out.fail() ); | ||||
|         size -= bytesToWrite; | ||||
|     } | ||||
|     out.flush(); | ||||
|     assert( ! out.fail() ); | ||||
|     out.close(); | ||||
|     assert( ! out.fail() ); | ||||
| } | ||||
|  | ||||
| void CompressTest::testZip64() | ||||
| { | ||||
|     std::map<std::string, Poco::UInt64> files; | ||||
|     files["data1.bin"] = static_cast<Poco::UInt64>(MB)*4096+1; | ||||
|     files["data2.bin"] = static_cast<Poco::UInt64>(MB)*16; | ||||
|     files["data3.bin"] = static_cast<Poco::UInt64>(MB)*4096-1; | ||||
|      | ||||
|     for(std::map<std::string, Poco::UInt64>::const_iterator it = files.begin(); it != files.end(); it++) { | ||||
|         createDataFile(it->first, it->second); | ||||
|     } | ||||
| 	std::ofstream out("zip64.zip", std::ios::binary | std::ios::trunc); | ||||
|     Compress c(out, true, true); | ||||
|     for(std::map<std::string, Poco::UInt64>::const_iterator it = files.begin(); it != files.end(); it++) { | ||||
|         const std::string& path = it->first; | ||||
|     	c.addFile(path, path, ZipCommon::CM_STORE); | ||||
|     } | ||||
|     ZipArchive a(c.close()); | ||||
|     for(std::map<std::string, Poco::UInt64>::const_iterator it = files.begin(); it != files.end(); it++) { | ||||
|         const std::string& path = it->first; | ||||
|         Poco::UInt64 size = it->second; | ||||
|         ZipArchive::FileHeaders::const_iterator it2 = a.findHeader(path); | ||||
| 	    assert (it2 != a.headerEnd()); | ||||
|         const Poco::Zip::ZipLocalFileHeader& file = it2->second; | ||||
|         assert(file.getUncompressedSize() == size); | ||||
|         assert(file.getCompressedSize() == size); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void CompressTest::setUp() | ||||
| { | ||||
| @@ -154,6 +203,7 @@ CppUnit::Test* CompressTest::suite() | ||||
| 	CppUnit_addTest(pSuite, CompressTest, testManipulatorDel); | ||||
| 	CppUnit_addTest(pSuite, CompressTest, testManipulatorReplace); | ||||
| 	CppUnit_addTest(pSuite, CompressTest, testSetZipComment); | ||||
| 	CppUnit_addTest(pSuite, CompressTest, testZip64); | ||||
|  | ||||
| 	return pSuite; | ||||
| } | ||||
|   | ||||
| @@ -19,7 +19,6 @@ | ||||
| #include "Poco/Zip/Zip.h" | ||||
| #include "CppUnit/TestCase.h" | ||||
|  | ||||
|  | ||||
| class CompressTest: public CppUnit::TestCase | ||||
| { | ||||
| public: | ||||
| @@ -33,11 +32,16 @@ public: | ||||
| 	void testManipulatorReplace(); | ||||
| 	void testSetZipComment(); | ||||
|  | ||||
|     static const Poco::UInt64 MB = (1024*1024); | ||||
|     void createDataFile(const std::string& path, Poco::UInt64 size); | ||||
|     void testZip64(); | ||||
|  | ||||
| 	void setUp(); | ||||
| 	void tearDown(); | ||||
|  | ||||
| 	static CppUnit::Test* suite(); | ||||
|  | ||||
|  | ||||
| private: | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -25,10 +25,12 @@ | ||||
| #include "Poco/StreamCopier.h" | ||||
| #include "CppUnit/TestCaller.h" | ||||
| #include "CppUnit/TestSuite.h" | ||||
|  | ||||
| #undef min | ||||
| #include <algorithm> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
|  | ||||
|  | ||||
| using namespace Poco::Zip; | ||||
|  | ||||
|  | ||||
| @@ -58,8 +60,8 @@ void ZipTest::testSkipSingleFile() | ||||
| 	ZipCommon::CompressionMethod cm = hdr.getCompressionMethod(); | ||||
| 	assert (!hdr.isEncrypted()); | ||||
| 	Poco::DateTime aDate = hdr.lastModifiedAt(); | ||||
| 	Poco::UInt32 cS = hdr.getCompressedSize(); | ||||
| 	Poco::UInt32 uS = hdr.getUncompressedSize(); | ||||
| 	Poco::UInt64 cS = hdr.getCompressedSize(); | ||||
| 	Poco::UInt64 uS = hdr.getUncompressedSize(); | ||||
| 	const std::string& fileName = hdr.getFileName(); | ||||
| } | ||||
|  | ||||
| @@ -163,6 +165,44 @@ void ZipTest::testDecompressFlat() | ||||
| 	assert (!dec.mapping().empty()); | ||||
| } | ||||
|  | ||||
| void ZipTest::verifyDataFile(const std::string& path, Poco::UInt64 size) { | ||||
|     std::ifstream in(path, std::ios::binary); | ||||
|     assert( ! in.fail() ); | ||||
|     Poco::Buffer<char> buffer1(MB); | ||||
|     Poco::Buffer<char> buffer2(MB); | ||||
|     for(int i = 0; size != 0; i++) { | ||||
|         std::memset(buffer1.begin(), i, buffer1.size()); | ||||
|         std::memset(buffer2.begin(), 0, buffer2.size()); | ||||
|         Poco::UInt64 bytesToRead = std::min(size, buffer2.size()); | ||||
|         in.read(buffer2.begin(), bytesToRead); | ||||
|         assert( ! in.fail() ); | ||||
|         assert( std::memcmp(buffer1.begin(), buffer2.begin(), bytesToRead) == 0); | ||||
|         size -= bytesToRead; | ||||
|     } | ||||
|     char c; | ||||
|     in.read(&c, 1); | ||||
|     assert ( in.eof() ); | ||||
| } | ||||
|  | ||||
| void ZipTest::testDecompressZip64() | ||||
| { | ||||
|     std::map<std::string, Poco::UInt64> files; | ||||
|     files["data1.bin"] = static_cast<Poco::UInt64>(MB)*4096+1; | ||||
|     files["data2.bin"] = static_cast<Poco::UInt64>(MB)*16; | ||||
|     files["data3.bin"] = static_cast<Poco::UInt64>(MB)*4096-1; | ||||
|      | ||||
|     for(std::map<std::string, Poco::UInt64>::const_iterator it = files.begin(); it != files.end(); it++) { | ||||
|         Poco::File file(it->first); | ||||
|         if(file.exists()) | ||||
|             file.remove(); | ||||
|     } | ||||
| 	std::ifstream in("zip64.zip", std::ios::binary); | ||||
|     Decompress c(in, "."); | ||||
|    	c.decompressAllFiles(); | ||||
|     for(std::map<std::string, Poco::UInt64>::const_iterator it = files.begin(); it != files.end(); it++) { | ||||
|         verifyDataFile(it->first, it->second); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void ZipTest::onDecompressError(const void* pSender, std::pair<const Poco::Zip::ZipLocalFileHeader, const std::string>& info) | ||||
| { | ||||
| @@ -191,5 +231,7 @@ CppUnit::Test* ZipTest::suite() | ||||
| 	CppUnit_addTest(pSuite, ZipTest, testDecompressFlat); | ||||
| 	CppUnit_addTest(pSuite, ZipTest, testCrcAndSizeAfterData); | ||||
| 	CppUnit_addTest(pSuite, ZipTest, testCrcAndSizeAfterDataWithArchive); | ||||
| 	CppUnit_addTest(pSuite, ZipTest, testDecompressZip64); | ||||
|  | ||||
| 	return pSuite; | ||||
| } | ||||
|   | ||||
| @@ -35,6 +35,10 @@ public: | ||||
|  | ||||
| 	void testDecompressFlat(); | ||||
|  | ||||
|     static const Poco::UInt64 MB = (1024*1024); | ||||
|     void verifyDataFile(const std::string& path, Poco::UInt64 size); | ||||
|     void testDecompressZip64(); | ||||
|  | ||||
| 	void setUp(); | ||||
| 	void tearDown(); | ||||
|  | ||||
|   | ||||
| @@ -20,9 +20,9 @@ CppUnit::Test* ZipTestSuite::suite() | ||||
| { | ||||
| 	CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ZipTestSuite"); | ||||
|  | ||||
| 	pSuite->addTest(CompressTest::suite()); | ||||
| 	pSuite->addTest(ZipTest::suite()); | ||||
| 	pSuite->addTest(PartialStreamTest::suite()); | ||||
| 	pSuite->addTest(CompressTest::suite()); | ||||
|  | ||||
| 	return pSuite; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Günter Obiltschnig
					Günter Obiltschnig