| // Archive/ZipItem.h |
| |
| #ifndef __ARCHIVE_ZIP_ITEM_H |
| #define __ARCHIVE_ZIP_ITEM_H |
| |
| #include "Common/Types.h" |
| #include "Common/MyString.h" |
| #include "Common/Buffer.h" |
| #include "Common/UTFConvert.h" |
| #include "Common/StringConvert.h" |
| |
| #include "ZipHeader.h" |
| |
| namespace NArchive { |
| namespace NZip { |
| |
| struct CVersion |
| { |
| Byte Version; |
| Byte HostOS; |
| }; |
| |
| bool operator==(const CVersion &v1, const CVersion &v2); |
| bool operator!=(const CVersion &v1, const CVersion &v2); |
| |
| struct CExtraSubBlock |
| { |
| UInt16 ID; |
| CByteBuffer Data; |
| bool ExtractNtfsTime(int index, FILETIME &ft) const; |
| bool ExtractUnixTime(int index, UInt32 &res) const; |
| }; |
| |
| struct CWzAesExtraField |
| { |
| UInt16 VendorVersion; // 0x0001 - AE-1, 0x0002 - AE-2, |
| // UInt16 VendorId; // "AE" |
| Byte Strength; // 1 - 128-bit , 2 - 192-bit , 3 - 256-bit |
| UInt16 Method; |
| |
| CWzAesExtraField(): VendorVersion(2), Strength(3), Method(0) {} |
| |
| bool NeedCrc() const { return (VendorVersion == 1); } |
| |
| bool ParseFromSubBlock(const CExtraSubBlock &sb) |
| { |
| if (sb.ID != NFileHeader::NExtraID::kWzAES) |
| return false; |
| if (sb.Data.GetCapacity() < 7) |
| return false; |
| const Byte *p = (const Byte *)sb.Data; |
| VendorVersion = (((UInt16)p[1]) << 8) | p[0]; |
| if (p[2] != 'A' || p[3] != 'E') |
| return false; |
| Strength = p[4]; |
| Method = (((UInt16)p[6]) << 16) | p[5]; |
| return true; |
| } |
| void SetSubBlock(CExtraSubBlock &sb) const |
| { |
| sb.Data.SetCapacity(7); |
| sb.ID = NFileHeader::NExtraID::kWzAES; |
| Byte *p = (Byte *)sb.Data; |
| p[0] = (Byte)VendorVersion; |
| p[1] = (Byte)(VendorVersion >> 8); |
| p[2] = 'A'; |
| p[3] = 'E'; |
| p[4] = Strength; |
| p[5] = (Byte)Method; |
| p[6] = (Byte)(Method >> 8); |
| } |
| }; |
| |
| namespace NStrongCryptoFlags |
| { |
| const UInt16 kDES = 0x6601; |
| const UInt16 kRC2old = 0x6602; |
| const UInt16 k3DES168 = 0x6603; |
| const UInt16 k3DES112 = 0x6609; |
| const UInt16 kAES128 = 0x660E; |
| const UInt16 kAES192 = 0x660F; |
| const UInt16 kAES256 = 0x6610; |
| const UInt16 kRC2 = 0x6702; |
| const UInt16 kBlowfish = 0x6720; |
| const UInt16 kTwofish = 0x6721; |
| const UInt16 kRC4 = 0x6801; |
| } |
| |
| struct CStrongCryptoField |
| { |
| UInt16 Format; |
| UInt16 AlgId; |
| UInt16 BitLen; |
| UInt16 Flags; |
| |
| bool ParseFromSubBlock(const CExtraSubBlock &sb) |
| { |
| if (sb.ID != NFileHeader::NExtraID::kStrongEncrypt) |
| return false; |
| const Byte *p = (const Byte *)sb.Data; |
| if (sb.Data.GetCapacity() < 8) |
| return false; |
| Format = (((UInt16)p[1]) << 8) | p[0]; |
| AlgId = (((UInt16)p[3]) << 8) | p[2]; |
| BitLen = (((UInt16)p[5]) << 8) | p[4]; |
| Flags = (((UInt16)p[7]) << 8) | p[6]; |
| return (Format == 2); |
| } |
| }; |
| |
| struct CExtraBlock |
| { |
| CObjectVector<CExtraSubBlock> SubBlocks; |
| void Clear() { SubBlocks.Clear(); } |
| size_t GetSize() const |
| { |
| size_t res = 0; |
| for (int i = 0; i < SubBlocks.Size(); i++) |
| res += SubBlocks[i].Data.GetCapacity() + 2 + 2; |
| return res; |
| } |
| bool GetWzAesField(CWzAesExtraField &aesField) const |
| { |
| for (int i = 0; i < SubBlocks.Size(); i++) |
| if (aesField.ParseFromSubBlock(SubBlocks[i])) |
| return true; |
| return false; |
| } |
| |
| bool GetStrongCryptoField(CStrongCryptoField &f) const |
| { |
| for (int i = 0; i < SubBlocks.Size(); i++) |
| if (f.ParseFromSubBlock(SubBlocks[i])) |
| return true; |
| return false; |
| } |
| |
| bool HasWzAesField() const |
| { |
| CWzAesExtraField aesField; |
| return GetWzAesField(aesField); |
| } |
| |
| bool GetNtfsTime(int index, FILETIME &ft) const |
| { |
| for (int i = 0; i < SubBlocks.Size(); i++) |
| { |
| const CExtraSubBlock &sb = SubBlocks[i]; |
| if (sb.ID == NFileHeader::NExtraID::kNTFS) |
| return sb.ExtractNtfsTime(index, ft); |
| } |
| return false; |
| } |
| |
| bool GetUnixTime(int index, UInt32 &res) const |
| { |
| for (int i = 0; i < SubBlocks.Size(); i++) |
| { |
| const CExtraSubBlock &sb = SubBlocks[i]; |
| if (sb.ID == NFileHeader::NExtraID::kUnixTime) |
| return sb.ExtractUnixTime(index, res); |
| } |
| return false; |
| } |
| |
| /* |
| bool HasStrongCryptoField() const |
| { |
| CStrongCryptoField f; |
| return GetStrongCryptoField(f); |
| } |
| */ |
| |
| void RemoveUnknownSubBlocks() |
| { |
| for (int i = SubBlocks.Size() - 1; i >= 0; i--) |
| if (SubBlocks[i].ID != NFileHeader::NExtraID::kWzAES) |
| SubBlocks.Delete(i); |
| } |
| }; |
| |
| |
| class CLocalItem |
| { |
| public: |
| CVersion ExtractVersion; |
| UInt16 Flags; |
| UInt16 CompressionMethod; |
| UInt32 Time; |
| UInt32 FileCRC; |
| UInt64 PackSize; |
| UInt64 UnPackSize; |
| |
| AString Name; |
| |
| CExtraBlock LocalExtra; |
| |
| bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; } |
| |
| bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; } |
| bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; }; |
| bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || CompressionMethod == NFileHeader::NCompressionMethod::kWzAES); }; |
| |
| bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; } |
| |
| bool IsDir() const; |
| bool IgnoreItem() const { return false; } |
| UInt32 GetWinAttributes() const; |
| |
| bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; } |
| |
| UString GetUnicodeString(const AString &s) const |
| { |
| UString res; |
| if (IsUtf8()) |
| if (!ConvertUTF8ToUnicode(s, res)) |
| res.Empty(); |
| if (res.IsEmpty()) |
| res = MultiByteToUnicodeString(s, GetCodePage()); |
| return res; |
| } |
| |
| private: |
| void SetFlagBits(int startBitNumber, int numBits, int value); |
| void SetBitMask(int bitMask, bool enable); |
| public: |
| void ClearFlags() { Flags = 0; } |
| void SetEncrypted(bool encrypted); |
| void SetUtf8(bool isUtf8); |
| |
| WORD GetCodePage() const { return CP_OEMCP; } |
| }; |
| |
| class CItem: public CLocalItem |
| { |
| public: |
| CVersion MadeByVersion; |
| UInt16 InternalAttributes; |
| UInt32 ExternalAttributes; |
| |
| UInt64 LocalHeaderPosition; |
| |
| FILETIME NtfsMTime; |
| FILETIME NtfsATime; |
| FILETIME NtfsCTime; |
| |
| CExtraBlock CentralExtra; |
| CByteBuffer Comment; |
| |
| bool FromLocal; |
| bool FromCentral; |
| bool NtfsTimeIsDefined; |
| |
| bool IsDir() const; |
| UInt32 GetWinAttributes() const; |
| |
| bool IsThereCrc() const |
| { |
| if (CompressionMethod == NFileHeader::NCompressionMethod::kWzAES) |
| { |
| CWzAesExtraField aesField; |
| if (CentralExtra.GetWzAesField(aesField)) |
| return aesField.NeedCrc(); |
| } |
| return (FileCRC != 0 || !IsDir()); |
| } |
| |
| WORD GetCodePage() const |
| { |
| return (WORD)((MadeByVersion.HostOS == NFileHeader::NHostOS::kFAT |
| || MadeByVersion.HostOS == NFileHeader::NHostOS::kNTFS |
| ) ? CP_OEMCP : CP_ACP); |
| } |
| CItem() : FromLocal(false), FromCentral(false), NtfsTimeIsDefined(false) {} |
| }; |
| |
| }} |
| |
| #endif |
| |
| |