1*f6dc9357SAndroid Build Coastguard Worker // Archive/ZipItem.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/7zCrc.h"
7*f6dc9357SAndroid Build Coastguard Worker
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/IntToString.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/MyLinux.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringConvert.h"
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariantUtils.h"
13*f6dc9357SAndroid Build Coastguard Worker
14*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ItemNameUtils.h"
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker #include "ZipItem.h"
17*f6dc9357SAndroid Build Coastguard Worker
18*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
19*f6dc9357SAndroid Build Coastguard Worker namespace NZip {
20*f6dc9357SAndroid Build Coastguard Worker
21*f6dc9357SAndroid Build Coastguard Worker using namespace NFileHeader;
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker
24*f6dc9357SAndroid Build Coastguard Worker /*
25*f6dc9357SAndroid Build Coastguard Worker const char *k_SpecName_NTFS_STREAM = "@@NTFS@STREAM@";
26*f6dc9357SAndroid Build Coastguard Worker const char *k_SpecName_MAC_RESOURCE_FORK = "@@MAC@RESOURCE-FORK@";
27*f6dc9357SAndroid Build Coastguard Worker */
28*f6dc9357SAndroid Build Coastguard Worker
29*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_ExtraTypes[] =
30*f6dc9357SAndroid Build Coastguard Worker {
31*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kZip64, "Zip64" },
32*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kNTFS, "NTFS" },
33*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kUnix0, "UNIX" },
34*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kStrongEncrypt, "StrongCrypto" },
35*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kUnixTime, "UT" },
36*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kUnix1, "UX" },
37*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kUnix2, "Ux" },
38*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kUnixN, "ux" },
39*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kIzUnicodeComment, "uc" },
40*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kIzUnicodeName, "up" },
41*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kIzNtSecurityDescriptor, "SD" },
42*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kWzAES, "WzAES" },
43*f6dc9357SAndroid Build Coastguard Worker { NExtraID::kApkAlign, "ApkAlign" }
44*f6dc9357SAndroid Build Coastguard Worker };
45*f6dc9357SAndroid Build Coastguard Worker
PrintInfo(AString & s) const46*f6dc9357SAndroid Build Coastguard Worker void CExtraSubBlock::PrintInfo(AString &s) const
47*f6dc9357SAndroid Build Coastguard Worker {
48*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExtraTypes); i++)
49*f6dc9357SAndroid Build Coastguard Worker {
50*f6dc9357SAndroid Build Coastguard Worker const CUInt32PCharPair &pair = g_ExtraTypes[i];
51*f6dc9357SAndroid Build Coastguard Worker if (pair.Value == ID)
52*f6dc9357SAndroid Build Coastguard Worker {
53*f6dc9357SAndroid Build Coastguard Worker s += pair.Name;
54*f6dc9357SAndroid Build Coastguard Worker if (ID == NExtraID::kUnixTime)
55*f6dc9357SAndroid Build Coastguard Worker {
56*f6dc9357SAndroid Build Coastguard Worker if (Data.Size() >= 1)
57*f6dc9357SAndroid Build Coastguard Worker {
58*f6dc9357SAndroid Build Coastguard Worker s.Add_Colon();
59*f6dc9357SAndroid Build Coastguard Worker const Byte flags = Data[0];
60*f6dc9357SAndroid Build Coastguard Worker if (flags & 1) s.Add_Char('M');
61*f6dc9357SAndroid Build Coastguard Worker if (flags & 2) s.Add_Char('A');
62*f6dc9357SAndroid Build Coastguard Worker if (flags & 4) s.Add_Char('C');
63*f6dc9357SAndroid Build Coastguard Worker const UInt32 size = (UInt32)(Data.Size()) - 1;
64*f6dc9357SAndroid Build Coastguard Worker if (size % 4 == 0)
65*f6dc9357SAndroid Build Coastguard Worker {
66*f6dc9357SAndroid Build Coastguard Worker s.Add_Colon();
67*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(size / 4);
68*f6dc9357SAndroid Build Coastguard Worker }
69*f6dc9357SAndroid Build Coastguard Worker }
70*f6dc9357SAndroid Build Coastguard Worker }
71*f6dc9357SAndroid Build Coastguard Worker /*
72*f6dc9357SAndroid Build Coastguard Worker if (ID == NExtraID::kApkAlign && Data.Size() >= 2)
73*f6dc9357SAndroid Build Coastguard Worker {
74*f6dc9357SAndroid Build Coastguard Worker char sz[32];
75*f6dc9357SAndroid Build Coastguard Worker sz[0] = ':';
76*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToHex(GetUi16(Data), sz + 1);
77*f6dc9357SAndroid Build Coastguard Worker s += sz;
78*f6dc9357SAndroid Build Coastguard Worker for (unsigned j = 2; j < Data.Size(); j++)
79*f6dc9357SAndroid Build Coastguard Worker {
80*f6dc9357SAndroid Build Coastguard Worker char sz[32];
81*f6dc9357SAndroid Build Coastguard Worker sz[0] = '-';
82*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToHex(Data[j], sz + 1);
83*f6dc9357SAndroid Build Coastguard Worker s += sz;
84*f6dc9357SAndroid Build Coastguard Worker }
85*f6dc9357SAndroid Build Coastguard Worker }
86*f6dc9357SAndroid Build Coastguard Worker */
87*f6dc9357SAndroid Build Coastguard Worker return;
88*f6dc9357SAndroid Build Coastguard Worker }
89*f6dc9357SAndroid Build Coastguard Worker }
90*f6dc9357SAndroid Build Coastguard Worker {
91*f6dc9357SAndroid Build Coastguard Worker char sz[16];
92*f6dc9357SAndroid Build Coastguard Worker sz[0] = '0';
93*f6dc9357SAndroid Build Coastguard Worker sz[1] = 'x';
94*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToHex(ID, sz + 2);
95*f6dc9357SAndroid Build Coastguard Worker s += sz;
96*f6dc9357SAndroid Build Coastguard Worker }
97*f6dc9357SAndroid Build Coastguard Worker }
98*f6dc9357SAndroid Build Coastguard Worker
99*f6dc9357SAndroid Build Coastguard Worker
PrintInfo(AString & s) const100*f6dc9357SAndroid Build Coastguard Worker void CExtraBlock::PrintInfo(AString &s) const
101*f6dc9357SAndroid Build Coastguard Worker {
102*f6dc9357SAndroid Build Coastguard Worker if (Error)
103*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("Extra_ERROR");
104*f6dc9357SAndroid Build Coastguard Worker
105*f6dc9357SAndroid Build Coastguard Worker if (MinorError)
106*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("Minor_Extra_ERROR");
107*f6dc9357SAndroid Build Coastguard Worker
108*f6dc9357SAndroid Build Coastguard Worker if (IsZip64 || IsZip64_Error)
109*f6dc9357SAndroid Build Coastguard Worker {
110*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("Zip64");
111*f6dc9357SAndroid Build Coastguard Worker if (IsZip64_Error)
112*f6dc9357SAndroid Build Coastguard Worker s += "_ERROR";
113*f6dc9357SAndroid Build Coastguard Worker }
114*f6dc9357SAndroid Build Coastguard Worker
115*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, SubBlocks)
116*f6dc9357SAndroid Build Coastguard Worker {
117*f6dc9357SAndroid Build Coastguard Worker s.Add_Space_if_NotEmpty();
118*f6dc9357SAndroid Build Coastguard Worker SubBlocks[i].PrintInfo(s);
119*f6dc9357SAndroid Build Coastguard Worker }
120*f6dc9357SAndroid Build Coastguard Worker }
121*f6dc9357SAndroid Build Coastguard Worker
122*f6dc9357SAndroid Build Coastguard Worker
ExtractNtfsTime(unsigned index,FILETIME & ft) const123*f6dc9357SAndroid Build Coastguard Worker bool CExtraSubBlock::ExtractNtfsTime(unsigned index, FILETIME &ft) const
124*f6dc9357SAndroid Build Coastguard Worker {
125*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = ft.dwLowDateTime = 0;
126*f6dc9357SAndroid Build Coastguard Worker UInt32 size = (UInt32)Data.Size();
127*f6dc9357SAndroid Build Coastguard Worker if (ID != NExtraID::kNTFS || size < 32)
128*f6dc9357SAndroid Build Coastguard Worker return false;
129*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)Data;
130*f6dc9357SAndroid Build Coastguard Worker p += 4; // for reserved
131*f6dc9357SAndroid Build Coastguard Worker size -= 4;
132*f6dc9357SAndroid Build Coastguard Worker while (size > 4)
133*f6dc9357SAndroid Build Coastguard Worker {
134*f6dc9357SAndroid Build Coastguard Worker UInt16 tag = GetUi16(p);
135*f6dc9357SAndroid Build Coastguard Worker unsigned attrSize = GetUi16(p + 2);
136*f6dc9357SAndroid Build Coastguard Worker p += 4;
137*f6dc9357SAndroid Build Coastguard Worker size -= 4;
138*f6dc9357SAndroid Build Coastguard Worker if (attrSize > size)
139*f6dc9357SAndroid Build Coastguard Worker attrSize = size;
140*f6dc9357SAndroid Build Coastguard Worker
141*f6dc9357SAndroid Build Coastguard Worker if (tag == NNtfsExtra::kTagTime && attrSize >= 24)
142*f6dc9357SAndroid Build Coastguard Worker {
143*f6dc9357SAndroid Build Coastguard Worker p += 8 * index;
144*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = GetUi32(p);
145*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = GetUi32(p + 4);
146*f6dc9357SAndroid Build Coastguard Worker return true;
147*f6dc9357SAndroid Build Coastguard Worker }
148*f6dc9357SAndroid Build Coastguard Worker p += attrSize;
149*f6dc9357SAndroid Build Coastguard Worker size -= attrSize;
150*f6dc9357SAndroid Build Coastguard Worker }
151*f6dc9357SAndroid Build Coastguard Worker return false;
152*f6dc9357SAndroid Build Coastguard Worker }
153*f6dc9357SAndroid Build Coastguard Worker
Extract_UnixTime(bool isCentral,unsigned index,UInt32 & res) const154*f6dc9357SAndroid Build Coastguard Worker bool CExtraSubBlock::Extract_UnixTime(bool isCentral, unsigned index, UInt32 &res) const
155*f6dc9357SAndroid Build Coastguard Worker {
156*f6dc9357SAndroid Build Coastguard Worker /* Info-Zip :
157*f6dc9357SAndroid Build Coastguard Worker The central-header extra field contains the modification
158*f6dc9357SAndroid Build Coastguard Worker time only, or no timestamp at all.
159*f6dc9357SAndroid Build Coastguard Worker Size of Data is used to flag its presence or absence
160*f6dc9357SAndroid Build Coastguard Worker If "Flags" indicates that Modtime is present in the local header
161*f6dc9357SAndroid Build Coastguard Worker field, it MUST be present in the central header field, too
162*f6dc9357SAndroid Build Coastguard Worker */
163*f6dc9357SAndroid Build Coastguard Worker
164*f6dc9357SAndroid Build Coastguard Worker res = 0;
165*f6dc9357SAndroid Build Coastguard Worker UInt32 size = (UInt32)Data.Size();
166*f6dc9357SAndroid Build Coastguard Worker if (ID != NExtraID::kUnixTime || size < 5)
167*f6dc9357SAndroid Build Coastguard Worker return false;
168*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)Data;
169*f6dc9357SAndroid Build Coastguard Worker const Byte flags = *p++;
170*f6dc9357SAndroid Build Coastguard Worker size--;
171*f6dc9357SAndroid Build Coastguard Worker if (isCentral)
172*f6dc9357SAndroid Build Coastguard Worker {
173*f6dc9357SAndroid Build Coastguard Worker if (index != NUnixTime::kMTime ||
174*f6dc9357SAndroid Build Coastguard Worker (flags & (1 << NUnixTime::kMTime)) == 0 ||
175*f6dc9357SAndroid Build Coastguard Worker size < 4)
176*f6dc9357SAndroid Build Coastguard Worker return false;
177*f6dc9357SAndroid Build Coastguard Worker res = GetUi32(p);
178*f6dc9357SAndroid Build Coastguard Worker return true;
179*f6dc9357SAndroid Build Coastguard Worker }
180*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < 3; i++)
181*f6dc9357SAndroid Build Coastguard Worker if ((flags & (1 << i)) != 0)
182*f6dc9357SAndroid Build Coastguard Worker {
183*f6dc9357SAndroid Build Coastguard Worker if (size < 4)
184*f6dc9357SAndroid Build Coastguard Worker return false;
185*f6dc9357SAndroid Build Coastguard Worker if (index == i)
186*f6dc9357SAndroid Build Coastguard Worker {
187*f6dc9357SAndroid Build Coastguard Worker res = GetUi32(p);
188*f6dc9357SAndroid Build Coastguard Worker return true;
189*f6dc9357SAndroid Build Coastguard Worker }
190*f6dc9357SAndroid Build Coastguard Worker p += 4;
191*f6dc9357SAndroid Build Coastguard Worker size -= 4;
192*f6dc9357SAndroid Build Coastguard Worker }
193*f6dc9357SAndroid Build Coastguard Worker return false;
194*f6dc9357SAndroid Build Coastguard Worker }
195*f6dc9357SAndroid Build Coastguard Worker
196*f6dc9357SAndroid Build Coastguard Worker
197*f6dc9357SAndroid Build Coastguard Worker // Info-ZIP's abandoned "Unix1 timestamps & owner ID info"
198*f6dc9357SAndroid Build Coastguard Worker
Extract_Unix01_Time(unsigned index,UInt32 & res) const199*f6dc9357SAndroid Build Coastguard Worker bool CExtraSubBlock::Extract_Unix01_Time(unsigned index, UInt32 &res) const
200*f6dc9357SAndroid Build Coastguard Worker {
201*f6dc9357SAndroid Build Coastguard Worker res = 0;
202*f6dc9357SAndroid Build Coastguard Worker const unsigned offset = index * 4;
203*f6dc9357SAndroid Build Coastguard Worker if (Data.Size() < offset + 4)
204*f6dc9357SAndroid Build Coastguard Worker return false;
205*f6dc9357SAndroid Build Coastguard Worker if (ID != NExtraID::kUnix0 &&
206*f6dc9357SAndroid Build Coastguard Worker ID != NExtraID::kUnix1)
207*f6dc9357SAndroid Build Coastguard Worker return false;
208*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)Data + offset;
209*f6dc9357SAndroid Build Coastguard Worker res = GetUi32(p);
210*f6dc9357SAndroid Build Coastguard Worker return true;
211*f6dc9357SAndroid Build Coastguard Worker }
212*f6dc9357SAndroid Build Coastguard Worker
213*f6dc9357SAndroid Build Coastguard Worker /*
214*f6dc9357SAndroid Build Coastguard Worker // PKWARE's Unix "extra" is similar to Info-ZIP's abandoned "Unix1 timestamps"
215*f6dc9357SAndroid Build Coastguard Worker bool CExtraSubBlock::Extract_Unix_Time(unsigned index, UInt32 &res) const
216*f6dc9357SAndroid Build Coastguard Worker {
217*f6dc9357SAndroid Build Coastguard Worker res = 0;
218*f6dc9357SAndroid Build Coastguard Worker const unsigned offset = index * 4;
219*f6dc9357SAndroid Build Coastguard Worker if (ID != NExtraID::kUnix0 || Data.Size() < offset)
220*f6dc9357SAndroid Build Coastguard Worker return false;
221*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)Data + offset;
222*f6dc9357SAndroid Build Coastguard Worker res = GetUi32(p);
223*f6dc9357SAndroid Build Coastguard Worker return true;
224*f6dc9357SAndroid Build Coastguard Worker }
225*f6dc9357SAndroid Build Coastguard Worker */
226*f6dc9357SAndroid Build Coastguard Worker
GetNtfsTime(unsigned index,FILETIME & ft) const227*f6dc9357SAndroid Build Coastguard Worker bool CExtraBlock::GetNtfsTime(unsigned index, FILETIME &ft) const
228*f6dc9357SAndroid Build Coastguard Worker {
229*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, SubBlocks)
230*f6dc9357SAndroid Build Coastguard Worker {
231*f6dc9357SAndroid Build Coastguard Worker const CExtraSubBlock &sb = SubBlocks[i];
232*f6dc9357SAndroid Build Coastguard Worker if (sb.ID == NFileHeader::NExtraID::kNTFS)
233*f6dc9357SAndroid Build Coastguard Worker return sb.ExtractNtfsTime(index, ft);
234*f6dc9357SAndroid Build Coastguard Worker }
235*f6dc9357SAndroid Build Coastguard Worker return false;
236*f6dc9357SAndroid Build Coastguard Worker }
237*f6dc9357SAndroid Build Coastguard Worker
GetUnixTime(bool isCentral,unsigned index,UInt32 & res) const238*f6dc9357SAndroid Build Coastguard Worker bool CExtraBlock::GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const
239*f6dc9357SAndroid Build Coastguard Worker {
240*f6dc9357SAndroid Build Coastguard Worker {
241*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, SubBlocks)
242*f6dc9357SAndroid Build Coastguard Worker {
243*f6dc9357SAndroid Build Coastguard Worker const CExtraSubBlock &sb = SubBlocks[i];
244*f6dc9357SAndroid Build Coastguard Worker if (sb.ID == NFileHeader::NExtraID::kUnixTime)
245*f6dc9357SAndroid Build Coastguard Worker return sb.Extract_UnixTime(isCentral, index, res);
246*f6dc9357SAndroid Build Coastguard Worker }
247*f6dc9357SAndroid Build Coastguard Worker }
248*f6dc9357SAndroid Build Coastguard Worker
249*f6dc9357SAndroid Build Coastguard Worker switch (index)
250*f6dc9357SAndroid Build Coastguard Worker {
251*f6dc9357SAndroid Build Coastguard Worker case NUnixTime::kMTime: index = NUnixExtra::kMTime; break;
252*f6dc9357SAndroid Build Coastguard Worker case NUnixTime::kATime: index = NUnixExtra::kATime; break;
253*f6dc9357SAndroid Build Coastguard Worker default: return false;
254*f6dc9357SAndroid Build Coastguard Worker }
255*f6dc9357SAndroid Build Coastguard Worker
256*f6dc9357SAndroid Build Coastguard Worker {
257*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, SubBlocks)
258*f6dc9357SAndroid Build Coastguard Worker {
259*f6dc9357SAndroid Build Coastguard Worker const CExtraSubBlock &sb = SubBlocks[i];
260*f6dc9357SAndroid Build Coastguard Worker if (sb.ID == NFileHeader::NExtraID::kUnix0 ||
261*f6dc9357SAndroid Build Coastguard Worker sb.ID == NFileHeader::NExtraID::kUnix1)
262*f6dc9357SAndroid Build Coastguard Worker return sb.Extract_Unix01_Time(index, res);
263*f6dc9357SAndroid Build Coastguard Worker }
264*f6dc9357SAndroid Build Coastguard Worker }
265*f6dc9357SAndroid Build Coastguard Worker return false;
266*f6dc9357SAndroid Build Coastguard Worker }
267*f6dc9357SAndroid Build Coastguard Worker
268*f6dc9357SAndroid Build Coastguard Worker
IsDir() const269*f6dc9357SAndroid Build Coastguard Worker bool CLocalItem::IsDir() const
270*f6dc9357SAndroid Build Coastguard Worker {
271*f6dc9357SAndroid Build Coastguard Worker return NItemName::HasTailSlash(Name, GetCodePage());
272*f6dc9357SAndroid Build Coastguard Worker }
273*f6dc9357SAndroid Build Coastguard Worker
IsDir() const274*f6dc9357SAndroid Build Coastguard Worker bool CItem::IsDir() const
275*f6dc9357SAndroid Build Coastguard Worker {
276*f6dc9357SAndroid Build Coastguard Worker // FIXME: we can check InfoZip UTF-8 name at first.
277*f6dc9357SAndroid Build Coastguard Worker if (NItemName::HasTailSlash(Name, GetCodePage()))
278*f6dc9357SAndroid Build Coastguard Worker return true;
279*f6dc9357SAndroid Build Coastguard Worker
280*f6dc9357SAndroid Build Coastguard Worker Byte hostOS = GetHostOS();
281*f6dc9357SAndroid Build Coastguard Worker
282*f6dc9357SAndroid Build Coastguard Worker if (Size == 0 && PackSize == 0 && !Name.IsEmpty() && Name.Back() == '\\')
283*f6dc9357SAndroid Build Coastguard Worker {
284*f6dc9357SAndroid Build Coastguard Worker // do we need to use CharPrevExA?
285*f6dc9357SAndroid Build Coastguard Worker // .NET Framework 4.5 : System.IO.Compression::CreateFromDirectory() probably writes backslashes to headers?
286*f6dc9357SAndroid Build Coastguard Worker // so we support that case
287*f6dc9357SAndroid Build Coastguard Worker switch (hostOS)
288*f6dc9357SAndroid Build Coastguard Worker {
289*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kFAT:
290*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kNTFS:
291*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kHPFS:
292*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kVFAT:
293*f6dc9357SAndroid Build Coastguard Worker return true;
294*f6dc9357SAndroid Build Coastguard Worker default: break;
295*f6dc9357SAndroid Build Coastguard Worker }
296*f6dc9357SAndroid Build Coastguard Worker }
297*f6dc9357SAndroid Build Coastguard Worker
298*f6dc9357SAndroid Build Coastguard Worker if (!FromCentral)
299*f6dc9357SAndroid Build Coastguard Worker return false;
300*f6dc9357SAndroid Build Coastguard Worker
301*f6dc9357SAndroid Build Coastguard Worker UInt16 highAttrib = (UInt16)((ExternalAttrib >> 16 ) & 0xFFFF);
302*f6dc9357SAndroid Build Coastguard Worker
303*f6dc9357SAndroid Build Coastguard Worker switch (hostOS)
304*f6dc9357SAndroid Build Coastguard Worker {
305*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kAMIGA:
306*f6dc9357SAndroid Build Coastguard Worker switch (highAttrib & NAmigaAttrib::kIFMT)
307*f6dc9357SAndroid Build Coastguard Worker {
308*f6dc9357SAndroid Build Coastguard Worker case NAmigaAttrib::kIFDIR: return true;
309*f6dc9357SAndroid Build Coastguard Worker case NAmigaAttrib::kIFREG: return false;
310*f6dc9357SAndroid Build Coastguard Worker default: return false; // change it throw kUnknownAttributes;
311*f6dc9357SAndroid Build Coastguard Worker }
312*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kFAT:
313*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kNTFS:
314*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kHPFS:
315*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kVFAT:
316*f6dc9357SAndroid Build Coastguard Worker return ((ExternalAttrib & FILE_ATTRIBUTE_DIRECTORY) != 0);
317*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kAtari:
318*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kMac:
319*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kVMS:
320*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kVM_CMS:
321*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kAcorn:
322*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kMVS:
323*f6dc9357SAndroid Build Coastguard Worker return false; // change it throw kUnknownAttributes;
324*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kUnix:
325*f6dc9357SAndroid Build Coastguard Worker return MY_LIN_S_ISDIR(highAttrib);
326*f6dc9357SAndroid Build Coastguard Worker default:
327*f6dc9357SAndroid Build Coastguard Worker return false;
328*f6dc9357SAndroid Build Coastguard Worker }
329*f6dc9357SAndroid Build Coastguard Worker }
330*f6dc9357SAndroid Build Coastguard Worker
GetWinAttrib() const331*f6dc9357SAndroid Build Coastguard Worker UInt32 CItem::GetWinAttrib() const
332*f6dc9357SAndroid Build Coastguard Worker {
333*f6dc9357SAndroid Build Coastguard Worker UInt32 winAttrib = 0;
334*f6dc9357SAndroid Build Coastguard Worker switch (GetHostOS())
335*f6dc9357SAndroid Build Coastguard Worker {
336*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kFAT:
337*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kNTFS:
338*f6dc9357SAndroid Build Coastguard Worker if (FromCentral)
339*f6dc9357SAndroid Build Coastguard Worker winAttrib = ExternalAttrib;
340*f6dc9357SAndroid Build Coastguard Worker break;
341*f6dc9357SAndroid Build Coastguard Worker case NHostOS::kUnix:
342*f6dc9357SAndroid Build Coastguard Worker // do we need to clear 16 low bits in this case?
343*f6dc9357SAndroid Build Coastguard Worker if (FromCentral)
344*f6dc9357SAndroid Build Coastguard Worker {
345*f6dc9357SAndroid Build Coastguard Worker /*
346*f6dc9357SAndroid Build Coastguard Worker Some programs write posix attributes in high 16 bits of ExternalAttrib
347*f6dc9357SAndroid Build Coastguard Worker Also some programs can write additional marker flag:
348*f6dc9357SAndroid Build Coastguard Worker 0x8000 - p7zip
349*f6dc9357SAndroid Build Coastguard Worker 0x4000 - Zip in MacOS
350*f6dc9357SAndroid Build Coastguard Worker no marker - Info-Zip
351*f6dc9357SAndroid Build Coastguard Worker
352*f6dc9357SAndroid Build Coastguard Worker Client code has two options to detect posix field:
353*f6dc9357SAndroid Build Coastguard Worker 1) check 0x8000 marker. In that case we must add 0x8000 marker here.
354*f6dc9357SAndroid Build Coastguard Worker 2) check that high 4 bits (file type bits in posix field) of attributes are not zero.
355*f6dc9357SAndroid Build Coastguard Worker */
356*f6dc9357SAndroid Build Coastguard Worker
357*f6dc9357SAndroid Build Coastguard Worker winAttrib = ExternalAttrib & 0xFFFF0000;
358*f6dc9357SAndroid Build Coastguard Worker
359*f6dc9357SAndroid Build Coastguard Worker // #ifndef _WIN32
360*f6dc9357SAndroid Build Coastguard Worker winAttrib |= 0x8000; // add posix mode marker
361*f6dc9357SAndroid Build Coastguard Worker // #endif
362*f6dc9357SAndroid Build Coastguard Worker }
363*f6dc9357SAndroid Build Coastguard Worker break;
364*f6dc9357SAndroid Build Coastguard Worker default: break;
365*f6dc9357SAndroid Build Coastguard Worker }
366*f6dc9357SAndroid Build Coastguard Worker if (IsDir()) // test it;
367*f6dc9357SAndroid Build Coastguard Worker winAttrib |= FILE_ATTRIBUTE_DIRECTORY;
368*f6dc9357SAndroid Build Coastguard Worker return winAttrib;
369*f6dc9357SAndroid Build Coastguard Worker }
370*f6dc9357SAndroid Build Coastguard Worker
GetPosixAttrib(UInt32 & attrib) const371*f6dc9357SAndroid Build Coastguard Worker bool CItem::GetPosixAttrib(UInt32 &attrib) const
372*f6dc9357SAndroid Build Coastguard Worker {
373*f6dc9357SAndroid Build Coastguard Worker // some archivers can store PosixAttrib in high 16 bits even with HostOS=FAT.
374*f6dc9357SAndroid Build Coastguard Worker if (FromCentral && GetHostOS() == NHostOS::kUnix)
375*f6dc9357SAndroid Build Coastguard Worker {
376*f6dc9357SAndroid Build Coastguard Worker attrib = ExternalAttrib >> 16;
377*f6dc9357SAndroid Build Coastguard Worker return (attrib != 0);
378*f6dc9357SAndroid Build Coastguard Worker }
379*f6dc9357SAndroid Build Coastguard Worker attrib = 0;
380*f6dc9357SAndroid Build Coastguard Worker if (IsDir())
381*f6dc9357SAndroid Build Coastguard Worker attrib = MY_LIN_S_IFDIR;
382*f6dc9357SAndroid Build Coastguard Worker return false;
383*f6dc9357SAndroid Build Coastguard Worker }
384*f6dc9357SAndroid Build Coastguard Worker
385*f6dc9357SAndroid Build Coastguard Worker
CheckIzUnicode(const AString & s) const386*f6dc9357SAndroid Build Coastguard Worker bool CExtraSubBlock::CheckIzUnicode(const AString &s) const
387*f6dc9357SAndroid Build Coastguard Worker {
388*f6dc9357SAndroid Build Coastguard Worker size_t size = Data.Size();
389*f6dc9357SAndroid Build Coastguard Worker if (size < 1 + 4)
390*f6dc9357SAndroid Build Coastguard Worker return false;
391*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)Data;
392*f6dc9357SAndroid Build Coastguard Worker if (p[0] > 1)
393*f6dc9357SAndroid Build Coastguard Worker return false;
394*f6dc9357SAndroid Build Coastguard Worker if (CrcCalc(s, s.Len()) != GetUi32(p + 1))
395*f6dc9357SAndroid Build Coastguard Worker return false;
396*f6dc9357SAndroid Build Coastguard Worker size -= 5;
397*f6dc9357SAndroid Build Coastguard Worker p += 5;
398*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < size; i++)
399*f6dc9357SAndroid Build Coastguard Worker if (p[i] == 0)
400*f6dc9357SAndroid Build Coastguard Worker return false;
401*f6dc9357SAndroid Build Coastguard Worker return Check_UTF8_Buf((const char *)(const void *)p, size, false);
402*f6dc9357SAndroid Build Coastguard Worker }
403*f6dc9357SAndroid Build Coastguard Worker
404*f6dc9357SAndroid Build Coastguard Worker
GetUnicodeString(UString & res,const AString & s,bool isComment,bool useSpecifiedCodePage,UINT codePage) const405*f6dc9357SAndroid Build Coastguard Worker void CItem::GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const
406*f6dc9357SAndroid Build Coastguard Worker {
407*f6dc9357SAndroid Build Coastguard Worker bool isUtf8 = IsUtf8();
408*f6dc9357SAndroid Build Coastguard Worker // bool ignore_Utf8_Errors = true;
409*f6dc9357SAndroid Build Coastguard Worker
410*f6dc9357SAndroid Build Coastguard Worker if (!isUtf8)
411*f6dc9357SAndroid Build Coastguard Worker {
412*f6dc9357SAndroid Build Coastguard Worker {
413*f6dc9357SAndroid Build Coastguard Worker const unsigned id = isComment ?
414*f6dc9357SAndroid Build Coastguard Worker NFileHeader::NExtraID::kIzUnicodeComment:
415*f6dc9357SAndroid Build Coastguard Worker NFileHeader::NExtraID::kIzUnicodeName;
416*f6dc9357SAndroid Build Coastguard Worker const CObjectVector<CExtraSubBlock> &subBlocks = GetMainExtra().SubBlocks;
417*f6dc9357SAndroid Build Coastguard Worker
418*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, subBlocks)
419*f6dc9357SAndroid Build Coastguard Worker {
420*f6dc9357SAndroid Build Coastguard Worker const CExtraSubBlock &sb = subBlocks[i];
421*f6dc9357SAndroid Build Coastguard Worker if (sb.ID == id)
422*f6dc9357SAndroid Build Coastguard Worker {
423*f6dc9357SAndroid Build Coastguard Worker if (sb.CheckIzUnicode(s))
424*f6dc9357SAndroid Build Coastguard Worker {
425*f6dc9357SAndroid Build Coastguard Worker // const unsigned kIzUnicodeHeaderSize = 5;
426*f6dc9357SAndroid Build Coastguard Worker if (Convert_UTF8_Buf_To_Unicode(
427*f6dc9357SAndroid Build Coastguard Worker (const char *)(const void *)(const Byte *)sb.Data + 5,
428*f6dc9357SAndroid Build Coastguard Worker sb.Data.Size() - 5, res))
429*f6dc9357SAndroid Build Coastguard Worker return;
430*f6dc9357SAndroid Build Coastguard Worker }
431*f6dc9357SAndroid Build Coastguard Worker break;
432*f6dc9357SAndroid Build Coastguard Worker }
433*f6dc9357SAndroid Build Coastguard Worker }
434*f6dc9357SAndroid Build Coastguard Worker }
435*f6dc9357SAndroid Build Coastguard Worker
436*f6dc9357SAndroid Build Coastguard Worker if (useSpecifiedCodePage)
437*f6dc9357SAndroid Build Coastguard Worker isUtf8 = (codePage == CP_UTF8);
438*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
439*f6dc9357SAndroid Build Coastguard Worker else if (GetHostOS() == NFileHeader::NHostOS::kUnix)
440*f6dc9357SAndroid Build Coastguard Worker {
441*f6dc9357SAndroid Build Coastguard Worker /* Some ZIP archives in Unix use UTF-8 encoding without Utf8 flag in header.
442*f6dc9357SAndroid Build Coastguard Worker We try to get name as UTF-8.
443*f6dc9357SAndroid Build Coastguard Worker Do we need to do it in POSIX version also? */
444*f6dc9357SAndroid Build Coastguard Worker isUtf8 = true;
445*f6dc9357SAndroid Build Coastguard Worker
446*f6dc9357SAndroid Build Coastguard Worker /* 21.02: we want to ignore UTF-8 errors to support file paths that are mixed
447*f6dc9357SAndroid Build Coastguard Worker of UTF-8 and non-UTF-8 characters. */
448*f6dc9357SAndroid Build Coastguard Worker // ignore_Utf8_Errors = false;
449*f6dc9357SAndroid Build Coastguard Worker // ignore_Utf8_Errors = true;
450*f6dc9357SAndroid Build Coastguard Worker }
451*f6dc9357SAndroid Build Coastguard Worker #endif
452*f6dc9357SAndroid Build Coastguard Worker }
453*f6dc9357SAndroid Build Coastguard Worker
454*f6dc9357SAndroid Build Coastguard Worker
455*f6dc9357SAndroid Build Coastguard Worker if (isUtf8)
456*f6dc9357SAndroid Build Coastguard Worker {
457*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(s, res);
458*f6dc9357SAndroid Build Coastguard Worker return;
459*f6dc9357SAndroid Build Coastguard Worker }
460*f6dc9357SAndroid Build Coastguard Worker
461*f6dc9357SAndroid Build Coastguard Worker MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage());
462*f6dc9357SAndroid Build Coastguard Worker }
463*f6dc9357SAndroid Build Coastguard Worker
464*f6dc9357SAndroid Build Coastguard Worker }}
465