//  // // ##### #### # # -= Zipex Library =-  // //  ## # # ## ## ZipData.h - Zip archive data structures  // //  ## #### ###  // //  ## # ### Data structures contained in a zip archives and methods to  // // ## # ## ## read and write these structures  // // ##### # # # R1 (C)2003-2005 Markus Ewald -> License.txt  // //  // #ifndef ZIPEX_ZIPDATA_H #define ZIPEX_ZIPDATA_H #include "zipex/config.h" #include "zipex/stream.h" #include "zipex/exception.h" #include #include namespace Zipex { namespace Detail { namespace { //  // //  Zipex::StringBuffer  // //  // // Helper used as workaround for writing into std::strings struct StringBuffer { inline StringBuffer(unsigned short nSize) : m_pBuffer(new char[nSize]) {} inline ~StringBuffer() { delete []m_pBuffer; } inline operator char *() { return m_pBuffer; } inline operator const char *() const { return m_pBuffer; } inline operator void *() { return m_pBuffer; } inline operator const void *() const { return m_pBuffer; } private: char *m_pBuffer; }; } // anonymous namespace typedef unsigned short unsigned_16; typedef unsigned long unsigned_32; typedef unsigned_huge unsigned_64; enum MadeBy { MB_MSDOS_OS2 = 0, ///< MSDOS or OS/2 MB_AMIGA = 1, ///< Amiga MB_OPENVMS = 2, ///< OpenVMS MB_UNIX = 3, ///< Unix or Linux MB_VM_CMS = 4, ///< CMS VM MB_ATARIST = 5, ///< Atari ST MB_OS2_HPFS = 6, ///< OS/2 HPFS MB_MACINTOSH = 7, ///< Apple Macintosh MB_ZSYSTEM = 8, ///< ZSystem MB_CPM = 9, ///< CP/M MB_WINDOWS_NTFS = 10, ///< Windows NTFS MB_MVS = 11, ///< MVS MB_VSE = 12, ///< VSE MB_ACORN_RISC = 13, ///< Acorn/RISC MB_VFAT = 14, ///< VFAT MB_ALTERNATE_MVS = 15, ///< Alternate MVS MB_BEOS = 16, ///< BeOS MB_TANDEM = 17 ///< Tandem }; //  // //  Zipex::LocalFileHeader  // //  // /// Local zip file header /** This header is preprended to every file in the zip */ struct LocalFileHeader { enum { SIGNATURE = 0x04034b50 }; /// Constructor /** Initializes an instance of LocalFileHeader @param nRequiredVersion Version required to extract @param nFlags General purpose bit flags @param nCompressionMethod Compression method @param nLastModifyTime Last mod file time @param nLastModifyDate Last mod file date @param nCRC32 Crc-32 @param nCompressedSize Compressed size @param nUncompressedSize Uncompressed size @param sFilename Filename @param sExtraField Extra field */ inline LocalFileHeader( unsigned_16 nRequiredVersion = 0, unsigned_16 nFlags = 0, unsigned_16 nCompressionMethod = 8, unsigned_16 nLastModifyTime = 0, unsigned_16 nLastModifyDate = 0, unsigned_32 nCRC32 = 0, unsigned_32 nCompressedSize = 0, unsigned_32 nUncompressedSize = 0, std::string sFilename = "", std::string sExtraField = "" ) : nRequiredVersion(nRequiredVersion), nFlags(nFlags), nCompressionMethod(nCompressionMethod), nLastModifyTime(nLastModifyTime), nLastModifyDate(nLastModifyDate), nCRC32(nCRC32), nCompressedSize(nCompressedSize), nUncompressedSize(nUncompressedSize), sFilename(sFilename), sExtraField(sExtraField) {} /// Read structure from stream /** Reads the contents of the structure from a stream in a data layout that is compliant to the one used within zip files. @param SourceStream Stream to read from @param bWithSignature Whether to read the signature */ inline void loadFromStream(Stream &SourceStream, bool bWithSignature = true) { if(bWithSignature) { unsigned_32 nSignature; SourceStream.read(nSignature); if(nSignature != SIGNATURE) throw ArchiveCorruptedError("Local file header of file in zip has invalid signature"); } SourceStream.read(nRequiredVersion); SourceStream.read(nFlags); SourceStream.read(nCompressionMethod); SourceStream.read(nLastModifyTime); SourceStream.read(nLastModifyDate); SourceStream.read(nCRC32); SourceStream.read(nCompressedSize); SourceStream.read(nUncompressedSize); unsigned_16 nFilenameLength; SourceStream.read(nFilenameLength); unsigned_16 nExtraFieldLength; SourceStream.read(nExtraFieldLength); if(nFilenameLength) { StringBuffer Filename(nFilenameLength); SourceStream.readData(Filename, nFilenameLength); sFilename = std::string(Filename, nFilenameLength); } else { sFilename = ""; } if(nExtraFieldLength) { StringBuffer ExtraField(nExtraFieldLength); SourceStream.readData(ExtraField, nExtraFieldLength); sExtraField = std::string(ExtraField, nExtraFieldLength); } else { sExtraField = ""; } } /// Save structure into stream /** Saves the contents of the structure into a stream using a data layout htat is compliant to the one used within zip files. @param DestStream Stream to write to @param bWithSignature Whether to write the signature */ inline void saveToStream(Stream &DestStream, bool bWithSignature = true) { if(bWithSignature) DestStream.write(SIGNATURE); DestStream.write(nRequiredVersion); DestStream.write(nFlags); DestStream.write(nCompressionMethod); DestStream.write(nLastModifyTime); DestStream.write(nLastModifyDate); DestStream.write(nCRC32); DestStream.write(nCompressedSize); DestStream.write(nUncompressedSize); DestStream.write(static_cast(sFilename.length())); DestStream.write(static_cast(sExtraField.length())); DestStream.writeData(sFilename.c_str(), sFilename.length()); DestStream.writeData(sExtraField.c_str(), sExtraField.length()); } /// Version required to extract unsigned_16 nRequiredVersion; /// General purpose bit flags unsigned_16 nFlags; /// Compression method unsigned_16 nCompressionMethod; /// Last mod file time unsigned_16 nLastModifyTime; /// Last mod file date unsigned_16 nLastModifyDate; /// Crc-32 unsigned_32 nCRC32; /// Compressed size unsigned_32 nCompressedSize; /// Uncompressed size unsigned_32 nUncompressedSize; // unsigned short nFilenameLength // unsigned short nExtraFieldLength /// Filename std::string sFilename; /// Extra field std::string sExtraField; }; //  // //  Zipex::FileHeader  // //  // /// Central directory file header /** For each zipped file, this header is placed once in the central directory record */ struct FileHeader { enum { SIGNATURE = 0x02014b50 }; /// Default constructor /** Inializes an instance of FIleHeader @param eMadeBy Version made by @param nRequiredVersion Version needed to extract @param nFlags General purpose bit flag @param nCompressionMethod Compression method @param nLastModifyTime Last mod file time @param nLastModifyDate Last mod file date @param nCRC32 Crc-32 @param nCompressedSize Compressed size @param nUncompressedSize Uncompressed siz @param nDiskNumber Disk number start @param nInternalAttributes Internal file attributes @param nExternalAttributes External file attributes @param nLocalHeaderOffset Relative offset of local header @param sFilename File name @param sExtraField Extra field @param sComment File comment */ inline FileHeader( MadeBy eMadeBy = MB_MSDOS_OS2, unsigned_16 nRequiredVersion = 0, unsigned_16 nFlags = 0, unsigned_16 nCompressionMethod = 0, unsigned_16 nLastModifyTime = 0, unsigned_16 nLastModifyDate = 0, unsigned_32 nCRC32 = 0, unsigned_32 nCompressedSize = 0, unsigned_32 nUncompressedSize = 0, unsigned_16 nDiskNumber = 0, unsigned_16 nInternalAttributes = 0, unsigned_32 nExternalAttributes = 0, unsigned_32 nLocalHeaderOffset = 0, std::string sFilename = "", std::string sExtraField = "", std::string sComment = "" ) : eMadeBy(eMadeBy), nRequiredVersion(nRequiredVersion), nFlags(nFlags), nCompressionMethod(nCompressionMethod), nLastModifyTime(nLastModifyTime), nLastModifyDate(nLastModifyDate), nCRC32(nCRC32), nCompressedSize(nCompressedSize), nUncompressedSize(nUncompressedSize), nDiskNumber(nDiskNumber), nInternalAttributes(nInternalAttributes), nExternalAttributes(nExternalAttributes), nLocalHeaderOffset(nLocalHeaderOffset), sFilename(sFilename), sExtraField(sExtraField), sComment(sComment) {} /// Read structure from stream /** Reads the contents of the structure from a stream in a data layout that is compliant to the one used within zip files. @param SourceStream Stream to read from @param bWithSignature Whether to read the signature */ inline void loadFromStream(Stream &SourceStream, bool bWithSignature = true) { if(bWithSignature) { unsigned_32 nSignature; SourceStream.read(nSignature); if(nSignature != SIGNATURE) throw ArchiveCorruptedError("File header of file in zip has invalid signature"); } unsigned_16 nMadeBy; SourceStream.read(nMadeBy); eMadeBy = static_cast(nMadeBy); SourceStream.read(nRequiredVersion); SourceStream.read(nFlags); SourceStream.read(nCompressionMethod); SourceStream.read(nLastModifyTime); SourceStream.read(nLastModifyDate); SourceStream.read(nCRC32); SourceStream.read(nCompressedSize); SourceStream.read(nUncompressedSize); unsigned_16 nFilenameLength; SourceStream.read(nFilenameLength); unsigned_16 nExtraFieldLength; SourceStream.read(nExtraFieldLength); unsigned_16 nFileCommentLength; SourceStream.read(nFileCommentLength); SourceStream.read(nDiskNumber); SourceStream.read(nInternalAttributes); SourceStream.read(nExternalAttributes); SourceStream.read(nLocalHeaderOffset); if(nFilenameLength) { StringBuffer Filename(nFilenameLength); SourceStream.readData(Filename, nFilenameLength); sFilename = std::string(Filename, nFilenameLength); } else { sFilename = ""; } if(nExtraFieldLength) { StringBuffer ExtraField(nExtraFieldLength); SourceStream.readData(ExtraField, nExtraFieldLength); sExtraField = std::string(ExtraField, nExtraFieldLength); } else { sExtraField = ""; } if(nFileCommentLength) { StringBuffer FileComment(nFileCommentLength); SourceStream.readData(FileComment, nFileCommentLength); sComment = std::string(FileComment, nFileCommentLength); } else { sComment = ""; } } /// Save structure into stream /** Saves the contents of the structure into a stream using a data layout htat is compliant to the one used within zip files. @param DestStream Stream to write to @param bWithSignature Whether to write the signature */ inline void saveToStream(Stream &DestStream, bool bWithSignature = true) { if(bWithSignature) DestStream.write(SIGNATURE); DestStream.write(static_cast(eMadeBy)); DestStream.write(nRequiredVersion); DestStream.write(nFlags); DestStream.write(nCompressionMethod); DestStream.write(nLastModifyTime); DestStream.write(nLastModifyDate); DestStream.write(nCRC32); DestStream.write(nCompressedSize); DestStream.write(nUncompressedSize); DestStream.write(static_cast(sFilename.length())); DestStream.write(static_cast(sExtraField.length())); DestStream.write(static_cast(sComment.length())); DestStream.write(nDiskNumber); DestStream.write(nInternalAttributes); DestStream.write(nExternalAttributes); DestStream.write(nLocalHeaderOffset); DestStream.writeData(sFilename.c_str(), sFilename.length()); DestStream.writeData(sExtraField.c_str(), sExtraField.length()); DestStream.writeData(sComment.c_str(), sComment.length()); } // unsigned long nSignature; /// Version made by MadeBy eMadeBy; /// Version needed to extract unsigned_16 nRequiredVersion; /// General purpose bit flag unsigned_16 nFlags; /// Compression method unsigned_16 nCompressionMethod; /// Last mod file time unsigned_16 nLastModifyTime; /// Last mod file date unsigned_16 nLastModifyDate; /// Crc-32 unsigned_32 nCRC32; /// Compressed size unsigned_32 nCompressedSize; /// Uncompressed size unsigned_32 nUncompressedSize; // unsigned short nFilenameLength; // unsigned short nExtraFieldLength; // unsigned short nFileCommentLength; /// Disk number start unsigned_16 nDiskNumber; /// Internal file attributes unsigned_16 nInternalAttributes; /// External file attributes unsigned_32 nExternalAttributes; /// Relative offset of local header unsigned_32 nLocalHeaderOffset; /// File name std::string sFilename; /// Extra field std::string sExtraField; /// File comment std::string sComment; }; //  // //  Zipex::DigitalSignature  // //  // struct DigitalSignature { enum { SIGNATURE = 0x05054b50 }; /// Default constructor /** Initializes an instance of DigitalSignature @param sSignature Signature data */ inline DigitalSignature(const std::string &sSignature = "") : sSignature(sSignature) {} /// Read structure from stream /** Reads the contents of the structure from a stream in a data layout that is compliant to the one used within zip files. @param SourceStream Stream to read from @param bWithSignature Whether to read the signature */ inline void loadFromStream(Stream &SourceStream, bool bWithSignature = true) { if(bWithSignature) { unsigned_32 nSignature; SourceStream.read(nSignature); if(nSignature != SIGNATURE) throw ArchiveCorruptedError( "End of central directory record of zip64 has invalid signature" ); } unsigned_16 nDataLength; SourceStream.read(nDataLength); if(nDataLength) { StringBuffer Signature(nDataLength); SourceStream.readData(Signature, nDataLength); sSignature = std::string(Signature, nDataLength); } else { sSignature = ""; } } /// Save structure into stream /** Saves the contents of the structure into a stream using a data layout htat is compliant to the one used within zip files. @param DestStream Stream to write to @param bWithSignature Whether to write the signature */ inline void saveToStream(Stream &DestStream, bool bWithSignature = true) { if(bWithSignature) DestStream.write(SIGNATURE); DestStream.write(static_cast(sSignature.length())); if(sSignature.length()) DestStream.writeData(sSignature.c_str(), sSignature.length()); } // unsigned long nHeaderSignature; // unsigned short nDataLength; std::string sSignature; ///< Signature data }; //  // //  Zipex::EndOfCentralDirectoryRecord64  // //  // struct EndOfCentralDirectoryRecord64 { enum { SIGNATURE = 0x06064b50 }; /// Default constructor /** Initializes an instance of EndOfCentralDirectoryRecord64 @param nSize Size of zip64 end of central directory record @param eMadeBy Version made by @param nRequiredVersion Version required to extract @param nDiskNumber Number of this disk @param nCentralDirStartDiskNumber Number of the disk with the start of the central directory @param nCentralDirEntriesDisk Total number of entries in the central directory on this disk @param nCentralDirEntriesTotal Total number of entries in the central directory @param nCentralDirLength Size of the central directory @param nCentralDirOffset Offset of start of central directory with respect to the starting disk number */ inline EndOfCentralDirectoryRecord64( unsigned_64 nSize = 0, MadeBy eMadeBy = MB_MSDOS_OS2, unsigned_16 nRequiredVersion = 0, unsigned_32 nDiskNumber = 0, unsigned_32 nCentralDirStartDiskNumber = 0, unsigned_64 nCentralDirEntriesDisk = 0, unsigned_64 nCentralDirEntriesTotal = 0, unsigned_64 nCentralDirLength = 0, unsigned_64 nCentralDirOffset = 0 ) : nSize(nSize), eMadeBy(eMadeBy), nRequiredVersion(nRequiredVersion), nDiskNumber(nDiskNumber), nCentralDirStartDiskNumber(nCentralDirStartDiskNumber), nCentralDirEntriesDisk(nCentralDirEntriesDisk), nCentralDirEntriesTotal(nCentralDirEntriesTotal), nCentralDirLength(nCentralDirLength), nCentralDirOffset(nCentralDirOffset) {} /// Read structure from stream /** Reads the contents of the structure from a stream in a data layout that is compliant to the one used within zip files. @param SourceStream Stream to read from @param bWithSignature Whether to read the signature */ inline void loadFromStream(Stream &SourceStream, bool bWithSignature = true) { if(bWithSignature) { unsigned_32 nSignature; SourceStream.read(nSignature); if(nSignature != SIGNATURE) throw ArchiveCorruptedError("End of central directory records of zip64 has invalid signature"); } SourceStream.read(nSize); unsigned_16 nMadeBy; SourceStream.read(nMadeBy); eMadeBy = static_cast(nMadeBy); SourceStream.read(nRequiredVersion); SourceStream.read(nDiskNumber); SourceStream.read(nCentralDirStartDiskNumber); SourceStream.read(nCentralDirEntriesDisk); SourceStream.read(nCentralDirEntriesTotal); SourceStream.read(nCentralDirLength); SourceStream.read(nCentralDirOffset); } /// Save structure into stream /** Saves the contents of the structure into a stream using a data layout htat is compliant to the one used within zip files. @param DestStream Stream to write to @param bWithSignature Whether to write the signature */ inline void saveToStream(Stream &DestStream, bool bWithSignature = true) { if(bWithSignature) DestStream.write(SIGNATURE); DestStream.write(nSize); DestStream.write(static_cast(eMadeBy)); DestStream.write(nRequiredVersion); DestStream.write(nDiskNumber); DestStream.write(nCentralDirStartDiskNumber); DestStream.write(nCentralDirEntriesDisk); DestStream.write(nCentralDirEntriesTotal); DestStream.write(nCentralDirLength); DestStream.write(nCentralDirOffset); } // unsigned long nSignature; /// Size of zip64 end of central directory record unsigned_64 nSize; /// Version made by MadeBy eMadeBy; /// Version required to extract unsigned_16 nRequiredVersion; /// Number of this disk unsigned_32 nDiskNumber; /// Number of the disk with the start of the central directory unsigned_32 nCentralDirStartDiskNumber; /// Total number of entries in the central directory on this disk unsigned_64 nCentralDirEntriesDisk; /// Total number of entries in the central directory unsigned_64 nCentralDirEntriesTotal; /// Size of the central directory unsigned_64 nCentralDirLength; /// Offset of start of central directory with respect to the starting disk number unsigned_64 nCentralDirOffset; // zip64 extensible data sector }; //  // //  Zipex::EndOfCentralDirectoryLocator64  // //  // struct EndOfCentralDirectoryLocator64 { enum { SIGNATURE = 0x07064b50 }; /// Default constructor /** Initializes an instance of EndOfCentralDirectoryLocator64. @param nEndCentralDirStartDiskNumber Number of the disk with the start of the zip64 end of central directory @param nEndCentralDirOffset Relative offset of the zip64 end of central directory record @param nTotalNumDisks Total number of disks */ inline EndOfCentralDirectoryLocator64( unsigned_32 nEndCentralDirStartDiskNumber = 0, unsigned_64 nEndCentralDirOffset = 0, unsigned_32 nTotalNumDisks = 0 ) : nEndCentralDirStartDiskNumber(nEndCentralDirStartDiskNumber), nEndCentralDirOffset(nEndCentralDirOffset), nTotalNumDisks(nTotalNumDisks) {} /// Read structure from stream /** Reads the contents of the structure from a stream in a data layout that is compliant to the one used within zip files. @param SourceStream Stream to read from @param bWithSignature Whether to read to signature */ inline void loadFromStream(Stream &SourceStream, bool bWithSignature = true) { if(bWithSignature) { unsigned_32 nSignature; SourceStream.read(nSignature); if(nSignature != SIGNATURE) throw ArchiveCorruptedError("Central directory locator of zip64 has invalid signature"); } SourceStream.read(nEndCentralDirStartDiskNumber); SourceStream.read(nEndCentralDirOffset); SourceStream.read(nTotalNumDisks); } /// Save structure into stream /** Saves the contents of the structure into a stream using a data layout htat is compliant to the one used within zip files. @param DestStream Stream to write to @param bWithSignature Whether to write the signature */ inline void saveToStream(Stream &DestStream, bool bWithSignature = true) { if(bWithSignature) DestStream.write(SIGNATURE); DestStream.write(nEndCentralDirStartDiskNumber); DestStream.write(nEndCentralDirOffset); DestStream.write(nTotalNumDisks); } // unsigned long nSignature; /// Number of the disk with the start of the zip64 end of central directory unsigned_32 nEndCentralDirStartDiskNumber; /// Relative offset of the zip64 end of central directory record unsigned_64 nEndCentralDirOffset; /// Total number of disks unsigned_32 nTotalNumDisks; }; //  // //  Zipex::EndOfCentralDirectoryRecord  // //  // struct EndOfCentralDirectoryRecord { enum { SIGNATURE = 0x06054b50 }; /// Default constructor /** Initializes an instance of EndOfCentralDirectoryRecord @param nDiskNumber Number of this disk @param nCentralDirStartDiskNumber Number of the disk with the start of the central directory @param nCentralDirEntriesDisk Total number of entries in the central directory on this disk @param nCentralDirEntriesTotal Total number of entries in the central directory @param nCentralDirSize Size of the central directory @param nCentralDirOffset Offset of start of central directory with respect to the starting disk number @param sComment ZIP file comment */ inline EndOfCentralDirectoryRecord( unsigned_16 nDiskNumber = 0, unsigned_16 nCentralDirStartDiskNumber = 0, unsigned_16 nCentralDirEntriesDisk = 0, unsigned_16 nCentralDirEntriesTotal = 0, unsigned_32 nCentralDirSize = 0, unsigned_32 nCentralDirOffset = 0, const std::string &sComment = "" ) : nDiskNumber(nDiskNumber), nCentralDirStartDiskNumber(nCentralDirStartDiskNumber), nCentralDirEntriesDisk(nCentralDirEntriesDisk), nCentralDirEntriesTotal(nCentralDirEntriesTotal), nCentralDirSize(nCentralDirSize), nCentralDirOffset(nCentralDirOffset), sComment(sComment) {} /// Read structure from stream /** Reads the contents of the structure from a stream in a data layout that is compliant to the one used within zip files. @param SourceStream Stream to read from @param bWithSignature Whether to read the signature */ inline void loadFromStream(Stream &SourceStream, bool bWithSignature = true) { if(bWithSignature) { unsigned_32 nSignature; SourceStream.read(nSignature); if(nSignature != SIGNATURE) throw ArchiveCorruptedError("Central directory record of zip has invalid signature"); } SourceStream.read(nDiskNumber); SourceStream.read(nCentralDirStartDiskNumber); SourceStream.read(nCentralDirEntriesDisk); SourceStream.read(nCentralDirEntriesTotal); SourceStream.read(nCentralDirSize); SourceStream.read(nCentralDirOffset); unsigned_16 nCommentLength; SourceStream.read(nCommentLength); if(nCommentLength) { StringBuffer Comment(nCommentLength); SourceStream.readData(Comment, nCommentLength); sComment = std::string(Comment, nCommentLength); } else { sComment = ""; } } /// Save structure into stream /** Saves the contents of the structure into a stream using a data layout htat is compliant to the one used within zip files. @param DestStream Stream to write to @param bWithSignature Whether to write the signature */ inline void saveToStream(Stream &DestStream, bool bWithSignature = true) { if(bWithSignature) DestStream.write(SIGNATURE); DestStream.write(nDiskNumber); DestStream.write(nCentralDirStartDiskNumber); DestStream.write(nCentralDirEntriesDisk); DestStream.write(nCentralDirEntriesTotal); DestStream.write(nCentralDirSize); DestStream.write(nCentralDirOffset); DestStream.write(static_cast(sComment.length())); DestStream.writeData(sComment.c_str(), sComment.length()); } // unsigned long nSignature; /// Number of this disk unsigned_16 nDiskNumber; /// Number of the disk with the start of the central directory unsigned_16 nCentralDirStartDiskNumber; /// Total number of entries in the central directory on this disk unsigned_16 nCentralDirEntriesDisk; /// Total number of entries in the central directory unsigned_16 nCentralDirEntriesTotal; /// Size of the central directory unsigned_32 nCentralDirSize; /// Offset of start of central directory with respect to the starting disk number unsigned_32 nCentralDirOffset; // unsigned short nCommentLength; /// ZIP file comment std::string sComment; }; }} // namespace Zipex::Detail #endif // ZIPEX_ZIPDATA_H