aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Archive/Zip/ZipItem.h
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/Zip/ZipItem.h')
-rw-r--r--CPP/7zip/Archive/Zip/ZipItem.h355
1 files changed, 355 insertions, 0 deletions
diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h
new file mode 100644
index 0000000..6ee8765
--- /dev/null
+++ b/CPP/7zip/Archive/Zip/ZipItem.h
@@ -0,0 +1,355 @@
1// Archive/ZipItem.h
2
3#ifndef __ARCHIVE_ZIP_ITEM_H
4#define __ARCHIVE_ZIP_ITEM_H
5
6#include "../../../../C/CpuArch.h"
7
8#include "../../../Common/MyBuffer.h"
9#include "../../../Common/MyString.h"
10#include "../../../Common/UTFConvert.h"
11
12#include "ZipHeader.h"
13
14namespace NArchive {
15namespace NZip {
16
17/*
18extern const char *k_SpecName_NTFS_STREAM;
19extern const char *k_SpecName_MAC_RESOURCE_FORK;
20*/
21
22struct CVersion
23{
24 Byte Version;
25 Byte HostOS;
26};
27
28struct CExtraSubBlock
29{
30 UInt32 ID;
31 CByteBuffer Data;
32
33 bool ExtractNtfsTime(unsigned index, FILETIME &ft) const;
34 bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const;
35 bool ExtractUnixExtraTime(unsigned index, UInt32 &res) const;
36
37 bool CheckIzUnicode(const AString &s) const;
38
39 void PrintInfo(AString &s) const;
40};
41
42const unsigned k_WzAesExtra_Size = 7;
43
44struct CWzAesExtra
45{
46 UInt16 VendorVersion; // 1: AE-1, 2: AE-2,
47 // UInt16 VendorId; // 'A' 'E'
48 Byte Strength; // 1: 128-bit, 2: 192-bit, 3: 256-bit
49 UInt16 Method;
50
51 CWzAesExtra(): VendorVersion(2), Strength(3), Method(0) {}
52
53 bool NeedCrc() const { return (VendorVersion == 1); }
54
55 bool ParseFromSubBlock(const CExtraSubBlock &sb)
56 {
57 if (sb.ID != NFileHeader::NExtraID::kWzAES)
58 return false;
59 if (sb.Data.Size() < k_WzAesExtra_Size)
60 return false;
61 const Byte *p = (const Byte *)sb.Data;
62 VendorVersion = GetUi16(p);
63 if (p[2] != 'A' || p[3] != 'E')
64 return false;
65 Strength = p[4];
66 // 9.31: The BUG was fixed:
67 Method = GetUi16(p + 5);
68 return true;
69 }
70
71 void SetSubBlock(CExtraSubBlock &sb) const
72 {
73 sb.Data.Alloc(k_WzAesExtra_Size);
74 sb.ID = NFileHeader::NExtraID::kWzAES;
75 Byte *p = (Byte *)sb.Data;
76 p[0] = (Byte)VendorVersion;
77 p[1] = (Byte)(VendorVersion >> 8);
78 p[2] = 'A';
79 p[3] = 'E';
80 p[4] = Strength;
81 p[5] = (Byte)Method;
82 p[6] = (Byte)(Method >> 8);
83 }
84};
85
86namespace NStrongCrypto_AlgId
87{
88 const UInt16 kDES = 0x6601;
89 const UInt16 kRC2old = 0x6602;
90 const UInt16 k3DES168 = 0x6603;
91 const UInt16 k3DES112 = 0x6609;
92 const UInt16 kAES128 = 0x660E;
93 const UInt16 kAES192 = 0x660F;
94 const UInt16 kAES256 = 0x6610;
95 const UInt16 kRC2 = 0x6702;
96 const UInt16 kBlowfish = 0x6720;
97 const UInt16 kTwofish = 0x6721;
98 const UInt16 kRC4 = 0x6801;
99}
100
101struct CStrongCryptoExtra
102{
103 UInt16 Format;
104 UInt16 AlgId;
105 UInt16 BitLen;
106 UInt16 Flags;
107
108 bool ParseFromSubBlock(const CExtraSubBlock &sb)
109 {
110 if (sb.ID != NFileHeader::NExtraID::kStrongEncrypt)
111 return false;
112 const Byte *p = (const Byte *)sb.Data;
113 if (sb.Data.Size() < 8)
114 return false;
115 Format = GetUi16(p + 0);
116 AlgId = GetUi16(p + 2);
117 BitLen = GetUi16(p + 4);
118 Flags = GetUi16(p + 6);
119 return (Format == 2);
120 }
121
122 bool CertificateIsUsed() const { return (Flags > 0x0001); }
123};
124
125
126struct CExtraBlock
127{
128 CObjectVector<CExtraSubBlock> SubBlocks;
129 bool Error;
130 bool MinorError;
131 bool IsZip64;
132 bool IsZip64_Error;
133
134 CExtraBlock(): Error(false), MinorError(false), IsZip64(false), IsZip64_Error(false) {}
135
136 void Clear()
137 {
138 SubBlocks.Clear();
139 IsZip64 = false;
140 }
141
142 size_t GetSize() const
143 {
144 size_t res = 0;
145 FOR_VECTOR (i, SubBlocks)
146 res += SubBlocks[i].Data.Size() + 2 + 2;
147 return res;
148 }
149
150 bool GetWzAes(CWzAesExtra &e) const
151 {
152 FOR_VECTOR (i, SubBlocks)
153 if (e.ParseFromSubBlock(SubBlocks[i]))
154 return true;
155 return false;
156 }
157
158 bool HasWzAes() const
159 {
160 CWzAesExtra e;
161 return GetWzAes(e);
162 }
163
164 bool GetStrongCrypto(CStrongCryptoExtra &e) const
165 {
166 FOR_VECTOR (i, SubBlocks)
167 if (e.ParseFromSubBlock(SubBlocks[i]))
168 return true;
169 return false;
170 }
171
172 /*
173 bool HasStrongCrypto() const
174 {
175 CStrongCryptoExtra e;
176 return GetStrongCrypto(e);
177 }
178 */
179
180 bool GetNtfsTime(unsigned index, FILETIME &ft) const;
181 bool GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const;
182
183 void PrintInfo(AString &s) const;
184
185 void RemoveUnknownSubBlocks()
186 {
187 for (unsigned i = SubBlocks.Size(); i != 0;)
188 {
189 i--;
190 switch (SubBlocks[i].ID)
191 {
192 case NFileHeader::NExtraID::kStrongEncrypt:
193 case NFileHeader::NExtraID::kWzAES:
194 break;
195 default:
196 SubBlocks.Delete(i);
197 }
198 }
199 }
200};
201
202
203class CLocalItem
204{
205public:
206 UInt16 Flags;
207 UInt16 Method;
208
209 /*
210 Zip specification doesn't mention that ExtractVersion field uses HostOS subfield.
211 18.06: 7-Zip now doesn't use ExtractVersion::HostOS to detect codePage
212 */
213
214 CVersion ExtractVersion;
215
216 UInt64 Size;
217 UInt64 PackSize;
218 UInt32 Time;
219 UInt32 Crc;
220
221 UInt32 Disk;
222
223 AString Name;
224
225 CExtraBlock LocalExtra;
226
227 unsigned GetDescriptorSize() const { return LocalExtra.IsZip64 ? kDataDescriptorSize64 : kDataDescriptorSize32; }
228
229 UInt64 GetPackSizeWithDescriptor() const
230 { return PackSize + (HasDescriptor() ? GetDescriptorSize() : 0); }
231
232 bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; }
233 bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; }
234 bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; }
235 bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }
236 bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
237 bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
238 // bool IsAltStream() const { return (Flags & NFileHeader::NFlags::kAltStream) != 0; }
239
240 unsigned GetDeflateLevel() const { return (Flags >> 1) & 3; }
241
242 bool IsDir() const;
243
244 /*
245 void GetUnicodeString(const AString &s, UString &res) const
246 {
247 bool isUtf8 = IsUtf8();
248 if (isUtf8)
249 if (ConvertUTF8ToUnicode(s, res))
250 return;
251 MultiByteToUnicodeString2(res, s, GetCodePage());
252 }
253 */
254
255private:
256
257 void SetFlag(unsigned bitMask, bool enable)
258 {
259 if (enable)
260 Flags = (UInt16)(Flags | bitMask);
261 else
262 Flags = (UInt16)(Flags & ~bitMask);
263 }
264
265public:
266
267 void ClearFlags() { Flags = 0; }
268 void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); }
269 void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); }
270 // void SetFlag_AltStream(bool isAltStream) { SetFlag(NFileHeader::NFlags::kAltStream, isAltStream); }
271 void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); }
272
273 UINT GetCodePage() const
274 {
275 if (IsUtf8())
276 return CP_UTF8;
277 return CP_OEMCP;
278 }
279};
280
281
282class CItem: public CLocalItem
283{
284public:
285 CVersion MadeByVersion;
286 UInt16 InternalAttrib;
287 UInt32 ExternalAttrib;
288
289 UInt64 LocalHeaderPos;
290
291 CExtraBlock CentralExtra;
292 CByteBuffer Comment;
293
294 bool FromLocal;
295 bool FromCentral;
296
297 // CItem can be used as CLocalItem. So we must clear unused fields
298 CItem():
299 InternalAttrib(0),
300 ExternalAttrib(0),
301 FromLocal(false),
302 FromCentral(false)
303 {
304 MadeByVersion.Version = 0;
305 MadeByVersion.HostOS = 0;
306 }
307
308 const CExtraBlock &GetMainExtra() const { return *(FromCentral ? &CentralExtra : &LocalExtra); }
309
310 bool IsDir() const;
311 UInt32 GetWinAttrib() const;
312 bool GetPosixAttrib(UInt32 &attrib) const;
313
314 // 18.06: 0 instead of ExtractVersion.HostOS for local item
315 Byte GetHostOS() const { return FromCentral ? MadeByVersion.HostOS : (Byte)0; }
316
317 void GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const;
318
319 bool IsThereCrc() const
320 {
321 if (Method == NFileHeader::NCompressionMethod::kWzAES)
322 {
323 CWzAesExtra aesField;
324 if (GetMainExtra().GetWzAes(aesField))
325 return aesField.NeedCrc();
326 }
327 return (Crc != 0 || !IsDir());
328 }
329
330 bool Is_MadeBy_Unix() const
331 {
332 if (!FromCentral)
333 return false;
334 return (MadeByVersion.HostOS == NFileHeader::NHostOS::kUnix);
335 }
336
337 UINT GetCodePage() const
338 {
339 // 18.06: now we use HostOS only from Central::MadeByVersion
340 if (IsUtf8())
341 return CP_UTF8;
342 if (!FromCentral)
343 return CP_OEMCP;
344 Byte hostOS = MadeByVersion.HostOS;
345 return (UINT)((
346 hostOS == NFileHeader::NHostOS::kFAT
347 || hostOS == NFileHeader::NHostOS::kNTFS
348 || hostOS == NFileHeader::NHostOS::kUnix // do we need it?
349 ) ? CP_OEMCP : CP_ACP);
350 }
351};
352
353}}
354
355#endif