xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Zip/ZipHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // ZipHandler.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 "../../../Common/ComTry.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringConvert.h"
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariant.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariantUtils.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/TimeUtils.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #include "../../IPassword.h"
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/FilterCoder.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/LimitedStreams.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ProgressUtils.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamObjects.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
19*f6dc9357SAndroid Build Coastguard Worker 
20*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/CopyCoder.h"
21*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ZIP_LZFSE_DISABLE
22*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/LzfseDecoder.h"
23*f6dc9357SAndroid Build Coastguard Worker #endif
24*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/LzmaDecoder.h"
25*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/ImplodeDecoder.h"
26*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/PpmdZip.h"
27*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/ShrinkDecoder.h"
28*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/XzDecoder.h"
29*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/ZstdDecoder.h"
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker #include "../../Crypto/WzAes.h"
32*f6dc9357SAndroid Build Coastguard Worker #include "../../Crypto/ZipCrypto.h"
33*f6dc9357SAndroid Build Coastguard Worker #include "../../Crypto/ZipStrong.h"
34*f6dc9357SAndroid Build Coastguard Worker 
35*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ItemNameUtils.h"
36*f6dc9357SAndroid Build Coastguard Worker #include "../Common/OutStreamWithCRC.h"
37*f6dc9357SAndroid Build Coastguard Worker 
38*f6dc9357SAndroid Build Coastguard Worker 
39*f6dc9357SAndroid Build Coastguard Worker #include "ZipHandler.h"
40*f6dc9357SAndroid Build Coastguard Worker 
41*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
42*f6dc9357SAndroid Build Coastguard Worker 
43*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
44*f6dc9357SAndroid Build Coastguard Worker namespace NZip {
45*f6dc9357SAndroid Build Coastguard Worker 
46*f6dc9357SAndroid Build Coastguard Worker static const char * const kHostOS[] =
47*f6dc9357SAndroid Build Coastguard Worker {
48*f6dc9357SAndroid Build Coastguard Worker     "FAT"
49*f6dc9357SAndroid Build Coastguard Worker   , "AMIGA"
50*f6dc9357SAndroid Build Coastguard Worker   , "VMS"
51*f6dc9357SAndroid Build Coastguard Worker   , "Unix"
52*f6dc9357SAndroid Build Coastguard Worker   , "VM/CMS"
53*f6dc9357SAndroid Build Coastguard Worker   , "Atari"
54*f6dc9357SAndroid Build Coastguard Worker   , "HPFS"
55*f6dc9357SAndroid Build Coastguard Worker   , "Macintosh"
56*f6dc9357SAndroid Build Coastguard Worker   , "Z-System"
57*f6dc9357SAndroid Build Coastguard Worker   , "CP/M"
58*f6dc9357SAndroid Build Coastguard Worker   , "TOPS-20"
59*f6dc9357SAndroid Build Coastguard Worker   , "NTFS"
60*f6dc9357SAndroid Build Coastguard Worker   , "SMS/QDOS"
61*f6dc9357SAndroid Build Coastguard Worker   , "Acorn"
62*f6dc9357SAndroid Build Coastguard Worker   , "VFAT"
63*f6dc9357SAndroid Build Coastguard Worker   , "MVS"
64*f6dc9357SAndroid Build Coastguard Worker   , "BeOS"
65*f6dc9357SAndroid Build Coastguard Worker   , "Tandem"
66*f6dc9357SAndroid Build Coastguard Worker   , "OS/400"
67*f6dc9357SAndroid Build Coastguard Worker   , "OS/X"
68*f6dc9357SAndroid Build Coastguard Worker };
69*f6dc9357SAndroid Build Coastguard Worker 
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker const char * const kMethodNames1[kNumMethodNames1] =
72*f6dc9357SAndroid Build Coastguard Worker {
73*f6dc9357SAndroid Build Coastguard Worker     "Store"
74*f6dc9357SAndroid Build Coastguard Worker   , "Shrink"
75*f6dc9357SAndroid Build Coastguard Worker   , "Reduce1"
76*f6dc9357SAndroid Build Coastguard Worker   , "Reduce2"
77*f6dc9357SAndroid Build Coastguard Worker   , "Reduce3"
78*f6dc9357SAndroid Build Coastguard Worker   , "Reduce4"
79*f6dc9357SAndroid Build Coastguard Worker   , "Implode"
80*f6dc9357SAndroid Build Coastguard Worker   , NULL // "Tokenize"
81*f6dc9357SAndroid Build Coastguard Worker   , "Deflate"
82*f6dc9357SAndroid Build Coastguard Worker   , "Deflate64"
83*f6dc9357SAndroid Build Coastguard Worker   , "PKImploding"
84*f6dc9357SAndroid Build Coastguard Worker   , NULL
85*f6dc9357SAndroid Build Coastguard Worker   , "BZip2"
86*f6dc9357SAndroid Build Coastguard Worker   , NULL
87*f6dc9357SAndroid Build Coastguard Worker   , "LZMA"
88*f6dc9357SAndroid Build Coastguard Worker   /*
89*f6dc9357SAndroid Build Coastguard Worker   , NULL
90*f6dc9357SAndroid Build Coastguard Worker   , NULL
91*f6dc9357SAndroid Build Coastguard Worker   , NULL
92*f6dc9357SAndroid Build Coastguard Worker   , NULL
93*f6dc9357SAndroid Build Coastguard Worker   , NULL
94*f6dc9357SAndroid Build Coastguard Worker   , "zstd-pk" // deprecated
95*f6dc9357SAndroid Build Coastguard Worker   */
96*f6dc9357SAndroid Build Coastguard Worker };
97*f6dc9357SAndroid Build Coastguard Worker 
98*f6dc9357SAndroid Build Coastguard Worker 
99*f6dc9357SAndroid Build Coastguard Worker const char * const kMethodNames2[kNumMethodNames2] =
100*f6dc9357SAndroid Build Coastguard Worker {
101*f6dc9357SAndroid Build Coastguard Worker     "zstd"
102*f6dc9357SAndroid Build Coastguard Worker   , "MP3"
103*f6dc9357SAndroid Build Coastguard Worker   , "xz"
104*f6dc9357SAndroid Build Coastguard Worker   , "Jpeg"
105*f6dc9357SAndroid Build Coastguard Worker   , "WavPack"
106*f6dc9357SAndroid Build Coastguard Worker   , "PPMd"
107*f6dc9357SAndroid Build Coastguard Worker   , "LZFSE" // , "WzAES"
108*f6dc9357SAndroid Build Coastguard Worker };
109*f6dc9357SAndroid Build Coastguard Worker 
110*f6dc9357SAndroid Build Coastguard Worker #define kMethod_AES "AES"
111*f6dc9357SAndroid Build Coastguard Worker #define kMethod_ZipCrypto "ZipCrypto"
112*f6dc9357SAndroid Build Coastguard Worker #define kMethod_StrongCrypto "StrongCrypto"
113*f6dc9357SAndroid Build Coastguard Worker 
114*f6dc9357SAndroid Build Coastguard Worker static const char * const kDeflateLevels[4] =
115*f6dc9357SAndroid Build Coastguard Worker {
116*f6dc9357SAndroid Build Coastguard Worker     "Normal"
117*f6dc9357SAndroid Build Coastguard Worker   , "Maximum"
118*f6dc9357SAndroid Build Coastguard Worker   , "Fast"
119*f6dc9357SAndroid Build Coastguard Worker   , "Fastest"
120*f6dc9357SAndroid Build Coastguard Worker };
121*f6dc9357SAndroid Build Coastguard Worker 
122*f6dc9357SAndroid Build Coastguard Worker 
123*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_HeaderCharacts[] =
124*f6dc9357SAndroid Build Coastguard Worker {
125*f6dc9357SAndroid Build Coastguard Worker   { 0, "Encrypt" },
126*f6dc9357SAndroid Build Coastguard Worker   { 3, "Descriptor" },
127*f6dc9357SAndroid Build Coastguard Worker   // { 4, "Enhanced" },
128*f6dc9357SAndroid Build Coastguard Worker   // { 5, "Patched" },
129*f6dc9357SAndroid Build Coastguard Worker   { 6, kMethod_StrongCrypto },
130*f6dc9357SAndroid Build Coastguard Worker   { 11, "UTF8" },
131*f6dc9357SAndroid Build Coastguard Worker   { 14, "Alt" }
132*f6dc9357SAndroid Build Coastguard Worker };
133*f6dc9357SAndroid Build Coastguard Worker 
134*f6dc9357SAndroid Build Coastguard Worker struct CIdToNamePair
135*f6dc9357SAndroid Build Coastguard Worker {
136*f6dc9357SAndroid Build Coastguard Worker   unsigned Id;
137*f6dc9357SAndroid Build Coastguard Worker   const char *Name;
138*f6dc9357SAndroid Build Coastguard Worker };
139*f6dc9357SAndroid Build Coastguard Worker 
140*f6dc9357SAndroid Build Coastguard Worker 
141*f6dc9357SAndroid Build Coastguard Worker static const CIdToNamePair k_StrongCryptoPairs[] =
142*f6dc9357SAndroid Build Coastguard Worker {
143*f6dc9357SAndroid Build Coastguard Worker   { NStrongCrypto_AlgId::kDES, "DES" },
144*f6dc9357SAndroid Build Coastguard Worker   { NStrongCrypto_AlgId::kRC2old, "RC2a" },
145*f6dc9357SAndroid Build Coastguard Worker   { NStrongCrypto_AlgId::k3DES168, "3DES-168" },
146*f6dc9357SAndroid Build Coastguard Worker   { NStrongCrypto_AlgId::k3DES112, "3DES-112" },
147*f6dc9357SAndroid Build Coastguard Worker   { NStrongCrypto_AlgId::kAES128, "pkAES-128" },
148*f6dc9357SAndroid Build Coastguard Worker   { NStrongCrypto_AlgId::kAES192, "pkAES-192" },
149*f6dc9357SAndroid Build Coastguard Worker   { NStrongCrypto_AlgId::kAES256, "pkAES-256" },
150*f6dc9357SAndroid Build Coastguard Worker   { NStrongCrypto_AlgId::kRC2, "RC2" },
151*f6dc9357SAndroid Build Coastguard Worker   { NStrongCrypto_AlgId::kBlowfish, "Blowfish" },
152*f6dc9357SAndroid Build Coastguard Worker   { NStrongCrypto_AlgId::kTwofish, "Twofish" },
153*f6dc9357SAndroid Build Coastguard Worker   { NStrongCrypto_AlgId::kRC4, "RC4" }
154*f6dc9357SAndroid Build Coastguard Worker };
155*f6dc9357SAndroid Build Coastguard Worker 
FindNameForId(const CIdToNamePair * pairs,unsigned num,unsigned id)156*f6dc9357SAndroid Build Coastguard Worker static const char *FindNameForId(const CIdToNamePair *pairs, unsigned num, unsigned id)
157*f6dc9357SAndroid Build Coastguard Worker {
158*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < num; i++)
159*f6dc9357SAndroid Build Coastguard Worker   {
160*f6dc9357SAndroid Build Coastguard Worker     const CIdToNamePair &pair = pairs[i];
161*f6dc9357SAndroid Build Coastguard Worker     if (id == pair.Id)
162*f6dc9357SAndroid Build Coastguard Worker       return pair.Name;
163*f6dc9357SAndroid Build Coastguard Worker   }
164*f6dc9357SAndroid Build Coastguard Worker   return NULL;
165*f6dc9357SAndroid Build Coastguard Worker }
166*f6dc9357SAndroid Build Coastguard Worker 
167*f6dc9357SAndroid Build Coastguard Worker 
168*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
169*f6dc9357SAndroid Build Coastguard Worker {
170*f6dc9357SAndroid Build Coastguard Worker   kpidPath,
171*f6dc9357SAndroid Build Coastguard Worker   kpidIsDir,
172*f6dc9357SAndroid Build Coastguard Worker   kpidSize,
173*f6dc9357SAndroid Build Coastguard Worker   kpidPackSize,
174*f6dc9357SAndroid Build Coastguard Worker   kpidMTime,
175*f6dc9357SAndroid Build Coastguard Worker   kpidCTime,
176*f6dc9357SAndroid Build Coastguard Worker   kpidATime,
177*f6dc9357SAndroid Build Coastguard Worker   kpidAttrib,
178*f6dc9357SAndroid Build Coastguard Worker   // kpidPosixAttrib,
179*f6dc9357SAndroid Build Coastguard Worker   kpidEncrypted,
180*f6dc9357SAndroid Build Coastguard Worker   kpidComment,
181*f6dc9357SAndroid Build Coastguard Worker   kpidCRC,
182*f6dc9357SAndroid Build Coastguard Worker   kpidMethod,
183*f6dc9357SAndroid Build Coastguard Worker   kpidCharacts,
184*f6dc9357SAndroid Build Coastguard Worker   kpidHostOS,
185*f6dc9357SAndroid Build Coastguard Worker   kpidUnpackVer,
186*f6dc9357SAndroid Build Coastguard Worker   kpidVolumeIndex,
187*f6dc9357SAndroid Build Coastguard Worker   kpidOffset
188*f6dc9357SAndroid Build Coastguard Worker   // kpidIsAltStream
189*f6dc9357SAndroid Build Coastguard Worker   // , kpidChangeTime // for debug
190*f6dc9357SAndroid Build Coastguard Worker   // , 255  // for debug
191*f6dc9357SAndroid Build Coastguard Worker };
192*f6dc9357SAndroid Build Coastguard Worker 
193*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
194*f6dc9357SAndroid Build Coastguard Worker {
195*f6dc9357SAndroid Build Coastguard Worker   kpidEmbeddedStubSize,
196*f6dc9357SAndroid Build Coastguard Worker   kpidBit64,
197*f6dc9357SAndroid Build Coastguard Worker   kpidComment,
198*f6dc9357SAndroid Build Coastguard Worker   kpidCharacts,
199*f6dc9357SAndroid Build Coastguard Worker   kpidTotalPhySize,
200*f6dc9357SAndroid Build Coastguard Worker   kpidIsVolume,
201*f6dc9357SAndroid Build Coastguard Worker   kpidVolumeIndex,
202*f6dc9357SAndroid Build Coastguard Worker   kpidNumVolumes
203*f6dc9357SAndroid Build Coastguard Worker };
204*f6dc9357SAndroid Build Coastguard Worker 
CHandler()205*f6dc9357SAndroid Build Coastguard Worker CHandler::CHandler()
206*f6dc9357SAndroid Build Coastguard Worker {
207*f6dc9357SAndroid Build Coastguard Worker   InitMethodProps();
208*f6dc9357SAndroid Build Coastguard Worker }
209*f6dc9357SAndroid Build Coastguard Worker 
BytesToString(const CByteBuffer & data)210*f6dc9357SAndroid Build Coastguard Worker static AString BytesToString(const CByteBuffer &data)
211*f6dc9357SAndroid Build Coastguard Worker {
212*f6dc9357SAndroid Build Coastguard Worker   AString s;
213*f6dc9357SAndroid Build Coastguard Worker   s.SetFrom_CalcLen((const char *)(const Byte *)data, (unsigned)data.Size());
214*f6dc9357SAndroid Build Coastguard Worker   return s;
215*f6dc9357SAndroid Build Coastguard Worker }
216*f6dc9357SAndroid Build Coastguard Worker 
217*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
218*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
219*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetArchiveProperty (PROPID propID,PROPVARIANT * value))220*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
221*f6dc9357SAndroid Build Coastguard Worker {
222*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
223*f6dc9357SAndroid Build Coastguard Worker   NWindows::NCOM::CPropVariant prop;
224*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
225*f6dc9357SAndroid Build Coastguard Worker   {
226*f6dc9357SAndroid Build Coastguard Worker     case kpidBit64:  if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break;
227*f6dc9357SAndroid Build Coastguard Worker     case kpidComment:  if (m_Archive.ArcInfo.Comment.Size() != 0) prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break;
228*f6dc9357SAndroid Build Coastguard Worker 
229*f6dc9357SAndroid Build Coastguard Worker     case kpidPhySize:  prop = m_Archive.GetPhySize(); break;
230*f6dc9357SAndroid Build Coastguard Worker     case kpidOffset:  prop = m_Archive.GetOffset(); break;
231*f6dc9357SAndroid Build Coastguard Worker 
232*f6dc9357SAndroid Build Coastguard Worker     case kpidEmbeddedStubSize:
233*f6dc9357SAndroid Build Coastguard Worker     {
234*f6dc9357SAndroid Build Coastguard Worker       UInt64 stubSize = m_Archive.GetEmbeddedStubSize();
235*f6dc9357SAndroid Build Coastguard Worker       if (stubSize != 0)
236*f6dc9357SAndroid Build Coastguard Worker         prop = stubSize;
237*f6dc9357SAndroid Build Coastguard Worker       break;
238*f6dc9357SAndroid Build Coastguard Worker     }
239*f6dc9357SAndroid Build Coastguard Worker 
240*f6dc9357SAndroid Build Coastguard Worker     case kpidTotalPhySize: if (m_Archive.IsMultiVol) prop = m_Archive.Vols.TotalBytesSize; break;
241*f6dc9357SAndroid Build Coastguard Worker     case kpidVolumeIndex: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.StartVolIndex; break;
242*f6dc9357SAndroid Build Coastguard Worker     case kpidIsVolume: if (m_Archive.IsMultiVol) prop = true; break;
243*f6dc9357SAndroid Build Coastguard Worker     case kpidNumVolumes: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.Streams.Size(); break;
244*f6dc9357SAndroid Build Coastguard Worker 
245*f6dc9357SAndroid Build Coastguard Worker     case kpidCharacts:
246*f6dc9357SAndroid Build Coastguard Worker     {
247*f6dc9357SAndroid Build Coastguard Worker       AString s;
248*f6dc9357SAndroid Build Coastguard Worker 
249*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.LocalsWereRead)
250*f6dc9357SAndroid Build Coastguard Worker       {
251*f6dc9357SAndroid Build Coastguard Worker         s.Add_OptSpaced("Local");
252*f6dc9357SAndroid Build Coastguard Worker 
253*f6dc9357SAndroid Build Coastguard Worker         if (m_Archive.LocalsCenterMerged)
254*f6dc9357SAndroid Build Coastguard Worker           s.Add_OptSpaced("Central");
255*f6dc9357SAndroid Build Coastguard Worker       }
256*f6dc9357SAndroid Build Coastguard Worker 
257*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.IsZip64)
258*f6dc9357SAndroid Build Coastguard Worker         s.Add_OptSpaced("Zip64");
259*f6dc9357SAndroid Build Coastguard Worker 
260*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.IsCdUnsorted)
261*f6dc9357SAndroid Build Coastguard Worker         s.Add_OptSpaced("Unsorted_CD");
262*f6dc9357SAndroid Build Coastguard Worker 
263*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.IsApk)
264*f6dc9357SAndroid Build Coastguard Worker         s.Add_OptSpaced("apk");
265*f6dc9357SAndroid Build Coastguard Worker 
266*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.ExtraMinorError)
267*f6dc9357SAndroid Build Coastguard Worker         s.Add_OptSpaced("Minor_Extra_ERROR");
268*f6dc9357SAndroid Build Coastguard Worker 
269*f6dc9357SAndroid Build Coastguard Worker       if (!s.IsEmpty())
270*f6dc9357SAndroid Build Coastguard Worker         prop = s;
271*f6dc9357SAndroid Build Coastguard Worker       break;
272*f6dc9357SAndroid Build Coastguard Worker     }
273*f6dc9357SAndroid Build Coastguard Worker 
274*f6dc9357SAndroid Build Coastguard Worker     case kpidWarningFlags:
275*f6dc9357SAndroid Build Coastguard Worker     {
276*f6dc9357SAndroid Build Coastguard Worker       UInt32 v = 0;
277*f6dc9357SAndroid Build Coastguard Worker       // if (m_Archive.ExtraMinorError) v |= kpv_ErrorFlags_HeadersError;
278*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.HeadersWarning) v |= kpv_ErrorFlags_HeadersError;
279*f6dc9357SAndroid Build Coastguard Worker       if (v != 0)
280*f6dc9357SAndroid Build Coastguard Worker         prop = v;
281*f6dc9357SAndroid Build Coastguard Worker       break;
282*f6dc9357SAndroid Build Coastguard Worker     }
283*f6dc9357SAndroid Build Coastguard Worker 
284*f6dc9357SAndroid Build Coastguard Worker     case kpidWarning:
285*f6dc9357SAndroid Build Coastguard Worker     {
286*f6dc9357SAndroid Build Coastguard Worker       AString s;
287*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.Overflow32bit)
288*f6dc9357SAndroid Build Coastguard Worker         s.Add_OptSpaced("32-bit overflow in headers");
289*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.Cd_NumEntries_Overflow_16bit)
290*f6dc9357SAndroid Build Coastguard Worker         s.Add_OptSpaced("16-bit overflow for number of files in headers");
291*f6dc9357SAndroid Build Coastguard Worker       if (!s.IsEmpty())
292*f6dc9357SAndroid Build Coastguard Worker         prop = s;
293*f6dc9357SAndroid Build Coastguard Worker       break;
294*f6dc9357SAndroid Build Coastguard Worker     }
295*f6dc9357SAndroid Build Coastguard Worker 
296*f6dc9357SAndroid Build Coastguard Worker     case kpidError:
297*f6dc9357SAndroid Build Coastguard Worker     {
298*f6dc9357SAndroid Build Coastguard Worker       if (!m_Archive.Vols.MissingName.IsEmpty())
299*f6dc9357SAndroid Build Coastguard Worker       {
300*f6dc9357SAndroid Build Coastguard Worker         UString s("Missing volume : ");
301*f6dc9357SAndroid Build Coastguard Worker         s += m_Archive.Vols.MissingName;
302*f6dc9357SAndroid Build Coastguard Worker         prop = s;
303*f6dc9357SAndroid Build Coastguard Worker       }
304*f6dc9357SAndroid Build Coastguard Worker       break;
305*f6dc9357SAndroid Build Coastguard Worker     }
306*f6dc9357SAndroid Build Coastguard Worker 
307*f6dc9357SAndroid Build Coastguard Worker     case kpidErrorFlags:
308*f6dc9357SAndroid Build Coastguard Worker     {
309*f6dc9357SAndroid Build Coastguard Worker       UInt32 v = 0;
310*f6dc9357SAndroid Build Coastguard Worker       if (!m_Archive.IsArc) v |= kpv_ErrorFlags_IsNotArc;
311*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.HeadersError) v |= kpv_ErrorFlags_HeadersError;
312*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
313*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.ArcInfo.Base < 0)
314*f6dc9357SAndroid Build Coastguard Worker       {
315*f6dc9357SAndroid Build Coastguard Worker         /* We try to support case when we have sfx-zip with embedded stub,
316*f6dc9357SAndroid Build Coastguard Worker            but the stream has access only to zip part.
317*f6dc9357SAndroid Build Coastguard Worker            In that case we ignore UnavailableStart error.
318*f6dc9357SAndroid Build Coastguard Worker            maybe we must show warning in that case. */
319*f6dc9357SAndroid Build Coastguard Worker         UInt64 stubSize = m_Archive.GetEmbeddedStubSize();
320*f6dc9357SAndroid Build Coastguard Worker         if (stubSize < (UInt64)-m_Archive.ArcInfo.Base)
321*f6dc9357SAndroid Build Coastguard Worker           v |= kpv_ErrorFlags_UnavailableStart;
322*f6dc9357SAndroid Build Coastguard Worker       }
323*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.NoCentralDir) v |= kpv_ErrorFlags_UnconfirmedStart;
324*f6dc9357SAndroid Build Coastguard Worker       prop = v;
325*f6dc9357SAndroid Build Coastguard Worker       break;
326*f6dc9357SAndroid Build Coastguard Worker     }
327*f6dc9357SAndroid Build Coastguard Worker 
328*f6dc9357SAndroid Build Coastguard Worker     case kpidReadOnly:
329*f6dc9357SAndroid Build Coastguard Worker     {
330*f6dc9357SAndroid Build Coastguard Worker       if (m_Archive.IsOpen())
331*f6dc9357SAndroid Build Coastguard Worker         if (!m_Archive.CanUpdate())
332*f6dc9357SAndroid Build Coastguard Worker           prop = true;
333*f6dc9357SAndroid Build Coastguard Worker       break;
334*f6dc9357SAndroid Build Coastguard Worker     }
335*f6dc9357SAndroid Build Coastguard Worker 
336*f6dc9357SAndroid Build Coastguard Worker     // case kpidIsAltStream: prop = true; break;
337*f6dc9357SAndroid Build Coastguard Worker     default: break;
338*f6dc9357SAndroid Build Coastguard Worker   }
339*f6dc9357SAndroid Build Coastguard Worker   return prop.Detach(value);
340*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
341*f6dc9357SAndroid Build Coastguard Worker }
342*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetNumberOfItems (UInt32 * numItems))343*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
344*f6dc9357SAndroid Build Coastguard Worker {
345*f6dc9357SAndroid Build Coastguard Worker   *numItems = m_Items.Size();
346*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
347*f6dc9357SAndroid Build Coastguard Worker }
348*f6dc9357SAndroid Build Coastguard Worker 
349*f6dc9357SAndroid Build Coastguard Worker 
NtfsUnixTimeToProp(bool fromCentral,const CExtraBlock & extra,unsigned ntfsIndex,unsigned unixIndex,NWindows::NCOM::CPropVariant & prop)350*f6dc9357SAndroid Build Coastguard Worker static bool NtfsUnixTimeToProp(bool fromCentral,
351*f6dc9357SAndroid Build Coastguard Worker     const CExtraBlock &extra,
352*f6dc9357SAndroid Build Coastguard Worker     unsigned ntfsIndex, unsigned unixIndex, NWindows::NCOM::CPropVariant &prop)
353*f6dc9357SAndroid Build Coastguard Worker {
354*f6dc9357SAndroid Build Coastguard Worker   {
355*f6dc9357SAndroid Build Coastguard Worker     FILETIME ft;
356*f6dc9357SAndroid Build Coastguard Worker     if (extra.GetNtfsTime(ntfsIndex, ft))
357*f6dc9357SAndroid Build Coastguard Worker     {
358*f6dc9357SAndroid Build Coastguard Worker       PropVariant_SetFrom_NtfsTime(prop, ft);
359*f6dc9357SAndroid Build Coastguard Worker       return true;
360*f6dc9357SAndroid Build Coastguard Worker     }
361*f6dc9357SAndroid Build Coastguard Worker   }
362*f6dc9357SAndroid Build Coastguard Worker   {
363*f6dc9357SAndroid Build Coastguard Worker     UInt32 unixTime = 0;
364*f6dc9357SAndroid Build Coastguard Worker     if (!extra.GetUnixTime(fromCentral, unixIndex, unixTime))
365*f6dc9357SAndroid Build Coastguard Worker       return false;
366*f6dc9357SAndroid Build Coastguard Worker     /*
367*f6dc9357SAndroid Build Coastguard Worker     // we allow unixTime == 0
368*f6dc9357SAndroid Build Coastguard Worker     if (unixTime == 0)
369*f6dc9357SAndroid Build Coastguard Worker       return false;
370*f6dc9357SAndroid Build Coastguard Worker     */
371*f6dc9357SAndroid Build Coastguard Worker     PropVariant_SetFrom_UnixTime(prop, unixTime);
372*f6dc9357SAndroid Build Coastguard Worker     return true;
373*f6dc9357SAndroid Build Coastguard Worker   }
374*f6dc9357SAndroid Build Coastguard Worker }
375*f6dc9357SAndroid Build Coastguard Worker 
376*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetProperty (UInt32 index,PROPID propID,PROPVARIANT * value))377*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
378*f6dc9357SAndroid Build Coastguard Worker {
379*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
380*f6dc9357SAndroid Build Coastguard Worker   NWindows::NCOM::CPropVariant prop;
381*f6dc9357SAndroid Build Coastguard Worker   const CItemEx &item = m_Items[index];
382*f6dc9357SAndroid Build Coastguard Worker   const CExtraBlock &extra = item.GetMainExtra();
383*f6dc9357SAndroid Build Coastguard Worker 
384*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
385*f6dc9357SAndroid Build Coastguard Worker   {
386*f6dc9357SAndroid Build Coastguard Worker     case kpidPath:
387*f6dc9357SAndroid Build Coastguard Worker     {
388*f6dc9357SAndroid Build Coastguard Worker       UString res;
389*f6dc9357SAndroid Build Coastguard Worker       item.GetUnicodeString(res, item.Name, false, _forceCodePage, _specifiedCodePage);
390*f6dc9357SAndroid Build Coastguard Worker       NItemName::ReplaceToOsSlashes_Remove_TailSlash(res,
391*f6dc9357SAndroid Build Coastguard Worker           item.Is_MadeBy_Unix() // useBackslashReplacement
392*f6dc9357SAndroid Build Coastguard Worker           );
393*f6dc9357SAndroid Build Coastguard Worker       /*
394*f6dc9357SAndroid Build Coastguard Worker       if (item.ParentOfAltStream >= 0)
395*f6dc9357SAndroid Build Coastguard Worker       {
396*f6dc9357SAndroid Build Coastguard Worker         const CItemEx &prevItem = m_Items[item.ParentOfAltStream];
397*f6dc9357SAndroid Build Coastguard Worker         UString prevName;
398*f6dc9357SAndroid Build Coastguard Worker         prevItem.GetUnicodeString(prevName, prevItem.Name, false, _forceCodePage, _specifiedCodePage);
399*f6dc9357SAndroid Build Coastguard Worker         NItemName::ReplaceToOsSlashes_Remove_TailSlash(prevName);
400*f6dc9357SAndroid Build Coastguard Worker         if (res.IsPrefixedBy(prevName))
401*f6dc9357SAndroid Build Coastguard Worker           if (IsString1PrefixedByString2(res.Ptr(prevName.Len()), k_SpecName_NTFS_STREAM))
402*f6dc9357SAndroid Build Coastguard Worker           {
403*f6dc9357SAndroid Build Coastguard Worker             res.Delete(prevName.Len(), (unsigned)strlen(k_SpecName_NTFS_STREAM));
404*f6dc9357SAndroid Build Coastguard Worker             res.Insert(prevName.Len(), L":");
405*f6dc9357SAndroid Build Coastguard Worker           }
406*f6dc9357SAndroid Build Coastguard Worker       }
407*f6dc9357SAndroid Build Coastguard Worker       */
408*f6dc9357SAndroid Build Coastguard Worker       prop = res;
409*f6dc9357SAndroid Build Coastguard Worker       break;
410*f6dc9357SAndroid Build Coastguard Worker     }
411*f6dc9357SAndroid Build Coastguard Worker 
412*f6dc9357SAndroid Build Coastguard Worker     case kpidIsDir:  prop = item.IsDir(); break;
413*f6dc9357SAndroid Build Coastguard Worker     case kpidSize:
414*f6dc9357SAndroid Build Coastguard Worker     {
415*f6dc9357SAndroid Build Coastguard Worker       if (!item.IsBadDescriptor())
416*f6dc9357SAndroid Build Coastguard Worker         prop = item.Size;
417*f6dc9357SAndroid Build Coastguard Worker       break;
418*f6dc9357SAndroid Build Coastguard Worker     }
419*f6dc9357SAndroid Build Coastguard Worker 
420*f6dc9357SAndroid Build Coastguard Worker     case kpidPackSize:  prop = item.PackSize; break;
421*f6dc9357SAndroid Build Coastguard Worker 
422*f6dc9357SAndroid Build Coastguard Worker     case kpidCTime:
423*f6dc9357SAndroid Build Coastguard Worker       NtfsUnixTimeToProp(item.FromCentral, extra,
424*f6dc9357SAndroid Build Coastguard Worker           NFileHeader::NNtfsExtra::kCTime,
425*f6dc9357SAndroid Build Coastguard Worker           NFileHeader::NUnixTime::kCTime, prop);
426*f6dc9357SAndroid Build Coastguard Worker       break;
427*f6dc9357SAndroid Build Coastguard Worker 
428*f6dc9357SAndroid Build Coastguard Worker     case kpidATime:
429*f6dc9357SAndroid Build Coastguard Worker       NtfsUnixTimeToProp(item.FromCentral, extra,
430*f6dc9357SAndroid Build Coastguard Worker           NFileHeader::NNtfsExtra::kATime,
431*f6dc9357SAndroid Build Coastguard Worker           NFileHeader::NUnixTime::kATime, prop);
432*f6dc9357SAndroid Build Coastguard Worker       break;
433*f6dc9357SAndroid Build Coastguard Worker 
434*f6dc9357SAndroid Build Coastguard Worker     case kpidMTime:
435*f6dc9357SAndroid Build Coastguard Worker     {
436*f6dc9357SAndroid Build Coastguard Worker       if (!NtfsUnixTimeToProp(item.FromCentral, extra,
437*f6dc9357SAndroid Build Coastguard Worker           NFileHeader::NNtfsExtra::kMTime,
438*f6dc9357SAndroid Build Coastguard Worker           NFileHeader::NUnixTime::kMTime, prop))
439*f6dc9357SAndroid Build Coastguard Worker       {
440*f6dc9357SAndroid Build Coastguard Worker         if (item.Time != 0)
441*f6dc9357SAndroid Build Coastguard Worker           PropVariant_SetFrom_DosTime(prop, item.Time);
442*f6dc9357SAndroid Build Coastguard Worker       }
443*f6dc9357SAndroid Build Coastguard Worker       break;
444*f6dc9357SAndroid Build Coastguard Worker     }
445*f6dc9357SAndroid Build Coastguard Worker 
446*f6dc9357SAndroid Build Coastguard Worker     case kpidTimeType:
447*f6dc9357SAndroid Build Coastguard Worker     {
448*f6dc9357SAndroid Build Coastguard Worker       FILETIME ft;
449*f6dc9357SAndroid Build Coastguard Worker       UInt32 unixTime;
450*f6dc9357SAndroid Build Coastguard Worker       UInt32 type;
451*f6dc9357SAndroid Build Coastguard Worker       if (extra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft))
452*f6dc9357SAndroid Build Coastguard Worker         type = NFileTimeType::kWindows;
453*f6dc9357SAndroid Build Coastguard Worker       else if (extra.GetUnixTime(item.FromCentral, NFileHeader::NUnixTime::kMTime, unixTime))
454*f6dc9357SAndroid Build Coastguard Worker         type = NFileTimeType::kUnix;
455*f6dc9357SAndroid Build Coastguard Worker       else
456*f6dc9357SAndroid Build Coastguard Worker         type = NFileTimeType::kDOS;
457*f6dc9357SAndroid Build Coastguard Worker       prop = type;
458*f6dc9357SAndroid Build Coastguard Worker       break;
459*f6dc9357SAndroid Build Coastguard Worker     }
460*f6dc9357SAndroid Build Coastguard Worker 
461*f6dc9357SAndroid Build Coastguard Worker     /*
462*f6dc9357SAndroid Build Coastguard Worker     // for debug to get Dos time values:
463*f6dc9357SAndroid Build Coastguard Worker     case kpidChangeTime: if (item.Time != 0) PropVariant_SetFrom_DosTime(prop, item.Time); break;
464*f6dc9357SAndroid Build Coastguard Worker     // for debug
465*f6dc9357SAndroid Build Coastguard Worker     // time difference (dos - utc)
466*f6dc9357SAndroid Build Coastguard Worker     case 255:
467*f6dc9357SAndroid Build Coastguard Worker     {
468*f6dc9357SAndroid Build Coastguard Worker       if (NtfsUnixTimeToProp(item.FromCentral, extra,
469*f6dc9357SAndroid Build Coastguard Worker           NFileHeader::NNtfsExtra::kMTime,
470*f6dc9357SAndroid Build Coastguard Worker           NFileHeader::NUnixTime::kMTime, prop))
471*f6dc9357SAndroid Build Coastguard Worker       {
472*f6dc9357SAndroid Build Coastguard Worker         FILETIME localFileTime;
473*f6dc9357SAndroid Build Coastguard Worker         if (item.Time != 0 && NTime::DosTime_To_FileTime(item.Time, localFileTime))
474*f6dc9357SAndroid Build Coastguard Worker         {
475*f6dc9357SAndroid Build Coastguard Worker           UInt64 t1 = FILETIME_To_UInt64(prop.filetime);
476*f6dc9357SAndroid Build Coastguard Worker           UInt64 t2 = FILETIME_To_UInt64(localFileTime);
477*f6dc9357SAndroid Build Coastguard Worker           prop.Set_Int64(t2 - t1);
478*f6dc9357SAndroid Build Coastguard Worker         }
479*f6dc9357SAndroid Build Coastguard Worker       }
480*f6dc9357SAndroid Build Coastguard Worker       break;
481*f6dc9357SAndroid Build Coastguard Worker     }
482*f6dc9357SAndroid Build Coastguard Worker     */
483*f6dc9357SAndroid Build Coastguard Worker 
484*f6dc9357SAndroid Build Coastguard Worker     case kpidAttrib:  prop = item.GetWinAttrib(); break;
485*f6dc9357SAndroid Build Coastguard Worker 
486*f6dc9357SAndroid Build Coastguard Worker     case kpidPosixAttrib:
487*f6dc9357SAndroid Build Coastguard Worker     {
488*f6dc9357SAndroid Build Coastguard Worker       UInt32 attrib;
489*f6dc9357SAndroid Build Coastguard Worker       if (item.GetPosixAttrib(attrib))
490*f6dc9357SAndroid Build Coastguard Worker         prop = attrib;
491*f6dc9357SAndroid Build Coastguard Worker       break;
492*f6dc9357SAndroid Build Coastguard Worker     }
493*f6dc9357SAndroid Build Coastguard Worker 
494*f6dc9357SAndroid Build Coastguard Worker     case kpidEncrypted:  prop = item.IsEncrypted(); break;
495*f6dc9357SAndroid Build Coastguard Worker 
496*f6dc9357SAndroid Build Coastguard Worker     case kpidComment:
497*f6dc9357SAndroid Build Coastguard Worker     {
498*f6dc9357SAndroid Build Coastguard Worker       if (item.Comment.Size() != 0)
499*f6dc9357SAndroid Build Coastguard Worker       {
500*f6dc9357SAndroid Build Coastguard Worker         UString res;
501*f6dc9357SAndroid Build Coastguard Worker         item.GetUnicodeString(res, BytesToString(item.Comment), true, _forceCodePage, _specifiedCodePage);
502*f6dc9357SAndroid Build Coastguard Worker         prop = res;
503*f6dc9357SAndroid Build Coastguard Worker       }
504*f6dc9357SAndroid Build Coastguard Worker       break;
505*f6dc9357SAndroid Build Coastguard Worker     }
506*f6dc9357SAndroid Build Coastguard Worker 
507*f6dc9357SAndroid Build Coastguard Worker     case kpidCRC:  if (item.IsThereCrc()) prop = item.Crc; break;
508*f6dc9357SAndroid Build Coastguard Worker 
509*f6dc9357SAndroid Build Coastguard Worker     case kpidMethod:
510*f6dc9357SAndroid Build Coastguard Worker     {
511*f6dc9357SAndroid Build Coastguard Worker       AString m;
512*f6dc9357SAndroid Build Coastguard Worker       bool isWzAes = false;
513*f6dc9357SAndroid Build Coastguard Worker       unsigned id = item.Method;
514*f6dc9357SAndroid Build Coastguard Worker 
515*f6dc9357SAndroid Build Coastguard Worker       if (id == NFileHeader::NCompressionMethod::kWzAES)
516*f6dc9357SAndroid Build Coastguard Worker       {
517*f6dc9357SAndroid Build Coastguard Worker         CWzAesExtra aesField;
518*f6dc9357SAndroid Build Coastguard Worker         if (extra.GetWzAes(aesField))
519*f6dc9357SAndroid Build Coastguard Worker         {
520*f6dc9357SAndroid Build Coastguard Worker           m += kMethod_AES;
521*f6dc9357SAndroid Build Coastguard Worker           m.Add_Minus();
522*f6dc9357SAndroid Build Coastguard Worker           m.Add_UInt32(((unsigned)aesField.Strength + 1) * 64);
523*f6dc9357SAndroid Build Coastguard Worker           id = aesField.Method;
524*f6dc9357SAndroid Build Coastguard Worker           isWzAes = true;
525*f6dc9357SAndroid Build Coastguard Worker         }
526*f6dc9357SAndroid Build Coastguard Worker       }
527*f6dc9357SAndroid Build Coastguard Worker 
528*f6dc9357SAndroid Build Coastguard Worker       if (item.IsEncrypted())
529*f6dc9357SAndroid Build Coastguard Worker       if (!isWzAes)
530*f6dc9357SAndroid Build Coastguard Worker       {
531*f6dc9357SAndroid Build Coastguard Worker         if (item.IsStrongEncrypted())
532*f6dc9357SAndroid Build Coastguard Worker         {
533*f6dc9357SAndroid Build Coastguard Worker           CStrongCryptoExtra f;
534*f6dc9357SAndroid Build Coastguard Worker           f.AlgId = 0;
535*f6dc9357SAndroid Build Coastguard Worker           if (extra.GetStrongCrypto(f))
536*f6dc9357SAndroid Build Coastguard Worker           {
537*f6dc9357SAndroid Build Coastguard Worker             const char *s = FindNameForId(k_StrongCryptoPairs, Z7_ARRAY_SIZE(k_StrongCryptoPairs), f.AlgId);
538*f6dc9357SAndroid Build Coastguard Worker             if (s)
539*f6dc9357SAndroid Build Coastguard Worker               m += s;
540*f6dc9357SAndroid Build Coastguard Worker             else
541*f6dc9357SAndroid Build Coastguard Worker             {
542*f6dc9357SAndroid Build Coastguard Worker               m += kMethod_StrongCrypto;
543*f6dc9357SAndroid Build Coastguard Worker               m.Add_Colon();
544*f6dc9357SAndroid Build Coastguard Worker               m.Add_UInt32(f.AlgId);
545*f6dc9357SAndroid Build Coastguard Worker             }
546*f6dc9357SAndroid Build Coastguard Worker             if (f.CertificateIsUsed())
547*f6dc9357SAndroid Build Coastguard Worker               m += "-Cert";
548*f6dc9357SAndroid Build Coastguard Worker           }
549*f6dc9357SAndroid Build Coastguard Worker           else
550*f6dc9357SAndroid Build Coastguard Worker             m += kMethod_StrongCrypto;
551*f6dc9357SAndroid Build Coastguard Worker         }
552*f6dc9357SAndroid Build Coastguard Worker         else
553*f6dc9357SAndroid Build Coastguard Worker           m += kMethod_ZipCrypto;
554*f6dc9357SAndroid Build Coastguard Worker       }
555*f6dc9357SAndroid Build Coastguard Worker 
556*f6dc9357SAndroid Build Coastguard Worker       m.Add_Space_if_NotEmpty();
557*f6dc9357SAndroid Build Coastguard Worker 
558*f6dc9357SAndroid Build Coastguard Worker       {
559*f6dc9357SAndroid Build Coastguard Worker         const char *s = NULL;
560*f6dc9357SAndroid Build Coastguard Worker         if (id < kNumMethodNames1)
561*f6dc9357SAndroid Build Coastguard Worker           s = kMethodNames1[id];
562*f6dc9357SAndroid Build Coastguard Worker         else
563*f6dc9357SAndroid Build Coastguard Worker         {
564*f6dc9357SAndroid Build Coastguard Worker           const int id2 = (int)id - (int)kMethodNames2Start;
565*f6dc9357SAndroid Build Coastguard Worker           if (id2 >= 0 && (unsigned)id2 < kNumMethodNames2)
566*f6dc9357SAndroid Build Coastguard Worker             s = kMethodNames2[id2];
567*f6dc9357SAndroid Build Coastguard Worker         }
568*f6dc9357SAndroid Build Coastguard Worker         if (s)
569*f6dc9357SAndroid Build Coastguard Worker           m += s;
570*f6dc9357SAndroid Build Coastguard Worker         else
571*f6dc9357SAndroid Build Coastguard Worker           m.Add_UInt32(id);
572*f6dc9357SAndroid Build Coastguard Worker       }
573*f6dc9357SAndroid Build Coastguard Worker       {
574*f6dc9357SAndroid Build Coastguard Worker         unsigned level = item.GetDeflateLevel();
575*f6dc9357SAndroid Build Coastguard Worker         if (level != 0)
576*f6dc9357SAndroid Build Coastguard Worker         {
577*f6dc9357SAndroid Build Coastguard Worker           if (id == NFileHeader::NCompressionMethod::kLZMA)
578*f6dc9357SAndroid Build Coastguard Worker           {
579*f6dc9357SAndroid Build Coastguard Worker             if (level & 1)
580*f6dc9357SAndroid Build Coastguard Worker               m += ":eos";
581*f6dc9357SAndroid Build Coastguard Worker             level &= ~(unsigned)1;
582*f6dc9357SAndroid Build Coastguard Worker           }
583*f6dc9357SAndroid Build Coastguard Worker           else if (id == NFileHeader::NCompressionMethod::kDeflate)
584*f6dc9357SAndroid Build Coastguard Worker           {
585*f6dc9357SAndroid Build Coastguard Worker             m.Add_Colon();
586*f6dc9357SAndroid Build Coastguard Worker             m += kDeflateLevels[level];
587*f6dc9357SAndroid Build Coastguard Worker             level = 0;
588*f6dc9357SAndroid Build Coastguard Worker           }
589*f6dc9357SAndroid Build Coastguard Worker 
590*f6dc9357SAndroid Build Coastguard Worker           if (level != 0)
591*f6dc9357SAndroid Build Coastguard Worker           {
592*f6dc9357SAndroid Build Coastguard Worker             m += ":v";
593*f6dc9357SAndroid Build Coastguard Worker             m.Add_UInt32(level);
594*f6dc9357SAndroid Build Coastguard Worker           }
595*f6dc9357SAndroid Build Coastguard Worker         }
596*f6dc9357SAndroid Build Coastguard Worker       }
597*f6dc9357SAndroid Build Coastguard Worker 
598*f6dc9357SAndroid Build Coastguard Worker       prop = m;
599*f6dc9357SAndroid Build Coastguard Worker       break;
600*f6dc9357SAndroid Build Coastguard Worker     }
601*f6dc9357SAndroid Build Coastguard Worker 
602*f6dc9357SAndroid Build Coastguard Worker     case kpidCharacts:
603*f6dc9357SAndroid Build Coastguard Worker     {
604*f6dc9357SAndroid Build Coastguard Worker       AString s;
605*f6dc9357SAndroid Build Coastguard Worker 
606*f6dc9357SAndroid Build Coastguard Worker       if (item.FromLocal)
607*f6dc9357SAndroid Build Coastguard Worker       {
608*f6dc9357SAndroid Build Coastguard Worker         s.Add_OptSpaced("Local");
609*f6dc9357SAndroid Build Coastguard Worker 
610*f6dc9357SAndroid Build Coastguard Worker         item.LocalExtra.PrintInfo(s);
611*f6dc9357SAndroid Build Coastguard Worker 
612*f6dc9357SAndroid Build Coastguard Worker         if (item.FromCentral)
613*f6dc9357SAndroid Build Coastguard Worker         {
614*f6dc9357SAndroid Build Coastguard Worker           s.Add_OptSpaced(":");
615*f6dc9357SAndroid Build Coastguard Worker           s.Add_OptSpaced("Central");
616*f6dc9357SAndroid Build Coastguard Worker         }
617*f6dc9357SAndroid Build Coastguard Worker       }
618*f6dc9357SAndroid Build Coastguard Worker 
619*f6dc9357SAndroid Build Coastguard Worker       if (item.FromCentral)
620*f6dc9357SAndroid Build Coastguard Worker       {
621*f6dc9357SAndroid Build Coastguard Worker         item.CentralExtra.PrintInfo(s);
622*f6dc9357SAndroid Build Coastguard Worker       }
623*f6dc9357SAndroid Build Coastguard Worker 
624*f6dc9357SAndroid Build Coastguard Worker       UInt32 flags = item.Flags;
625*f6dc9357SAndroid Build Coastguard Worker       flags &= ~(unsigned)6; // we don't need compression related bits here.
626*f6dc9357SAndroid Build Coastguard Worker 
627*f6dc9357SAndroid Build Coastguard Worker       if (flags != 0)
628*f6dc9357SAndroid Build Coastguard Worker       {
629*f6dc9357SAndroid Build Coastguard Worker         const AString s2 = FlagsToString(g_HeaderCharacts, Z7_ARRAY_SIZE(g_HeaderCharacts), flags);
630*f6dc9357SAndroid Build Coastguard Worker         if (!s2.IsEmpty())
631*f6dc9357SAndroid Build Coastguard Worker         {
632*f6dc9357SAndroid Build Coastguard Worker           if (!s.IsEmpty())
633*f6dc9357SAndroid Build Coastguard Worker             s.Add_OptSpaced(":");
634*f6dc9357SAndroid Build Coastguard Worker           s.Add_OptSpaced(s2);
635*f6dc9357SAndroid Build Coastguard Worker         }
636*f6dc9357SAndroid Build Coastguard Worker       }
637*f6dc9357SAndroid Build Coastguard Worker 
638*f6dc9357SAndroid Build Coastguard Worker       if (item.IsBadDescriptor())
639*f6dc9357SAndroid Build Coastguard Worker         s.Add_OptSpaced("Descriptor_ERROR");
640*f6dc9357SAndroid Build Coastguard Worker 
641*f6dc9357SAndroid Build Coastguard Worker       if (!s.IsEmpty())
642*f6dc9357SAndroid Build Coastguard Worker         prop = s;
643*f6dc9357SAndroid Build Coastguard Worker       break;
644*f6dc9357SAndroid Build Coastguard Worker     }
645*f6dc9357SAndroid Build Coastguard Worker 
646*f6dc9357SAndroid Build Coastguard Worker     case kpidHostOS:
647*f6dc9357SAndroid Build Coastguard Worker     {
648*f6dc9357SAndroid Build Coastguard Worker       if (item.FromCentral)
649*f6dc9357SAndroid Build Coastguard Worker       {
650*f6dc9357SAndroid Build Coastguard Worker         // 18.06: now we use HostOS only from Central::MadeByVersion
651*f6dc9357SAndroid Build Coastguard Worker         const Byte hostOS = item.MadeByVersion.HostOS;
652*f6dc9357SAndroid Build Coastguard Worker         TYPE_TO_PROP(kHostOS, hostOS, prop);
653*f6dc9357SAndroid Build Coastguard Worker       }
654*f6dc9357SAndroid Build Coastguard Worker       break;
655*f6dc9357SAndroid Build Coastguard Worker     }
656*f6dc9357SAndroid Build Coastguard Worker 
657*f6dc9357SAndroid Build Coastguard Worker     case kpidUnpackVer:
658*f6dc9357SAndroid Build Coastguard Worker       prop = (UInt32)item.ExtractVersion.Version;
659*f6dc9357SAndroid Build Coastguard Worker       break;
660*f6dc9357SAndroid Build Coastguard Worker 
661*f6dc9357SAndroid Build Coastguard Worker     case kpidVolumeIndex:
662*f6dc9357SAndroid Build Coastguard Worker       prop = item.Disk;
663*f6dc9357SAndroid Build Coastguard Worker       break;
664*f6dc9357SAndroid Build Coastguard Worker 
665*f6dc9357SAndroid Build Coastguard Worker     case kpidOffset:
666*f6dc9357SAndroid Build Coastguard Worker       prop = item.LocalHeaderPos;
667*f6dc9357SAndroid Build Coastguard Worker       break;
668*f6dc9357SAndroid Build Coastguard Worker 
669*f6dc9357SAndroid Build Coastguard Worker     /*
670*f6dc9357SAndroid Build Coastguard Worker     case kpidIsAltStream:
671*f6dc9357SAndroid Build Coastguard Worker       prop = (bool)(item.ParentOfAltStream >= 0); // item.IsAltStream();
672*f6dc9357SAndroid Build Coastguard Worker       break;
673*f6dc9357SAndroid Build Coastguard Worker 
674*f6dc9357SAndroid Build Coastguard Worker     case kpidName:
675*f6dc9357SAndroid Build Coastguard Worker       if (item.ParentOfAltStream >= 0)
676*f6dc9357SAndroid Build Coastguard Worker       {
677*f6dc9357SAndroid Build Coastguard Worker         // extract name of stream here
678*f6dc9357SAndroid Build Coastguard Worker       }
679*f6dc9357SAndroid Build Coastguard Worker       break;
680*f6dc9357SAndroid Build Coastguard Worker     */
681*f6dc9357SAndroid Build Coastguard Worker     default: break;
682*f6dc9357SAndroid Build Coastguard Worker   }
683*f6dc9357SAndroid Build Coastguard Worker 
684*f6dc9357SAndroid Build Coastguard Worker   return prop.Detach(value);
685*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
686*f6dc9357SAndroid Build Coastguard Worker }
687*f6dc9357SAndroid Build Coastguard Worker 
688*f6dc9357SAndroid Build Coastguard Worker 
689*f6dc9357SAndroid Build Coastguard Worker 
690*f6dc9357SAndroid Build Coastguard Worker /*
691*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps)
692*f6dc9357SAndroid Build Coastguard Worker {
693*f6dc9357SAndroid Build Coastguard Worker   *numProps = 0;
694*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
695*f6dc9357SAndroid Build Coastguard Worker }
696*f6dc9357SAndroid Build Coastguard Worker 
697*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID)
698*f6dc9357SAndroid Build Coastguard Worker {
699*f6dc9357SAndroid Build Coastguard Worker   UNUSED_VAR(index);
700*f6dc9357SAndroid Build Coastguard Worker   *propID = 0;
701*f6dc9357SAndroid Build Coastguard Worker   *name = 0;
702*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
703*f6dc9357SAndroid Build Coastguard Worker }
704*f6dc9357SAndroid Build Coastguard Worker 
705*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType)
706*f6dc9357SAndroid Build Coastguard Worker {
707*f6dc9357SAndroid Build Coastguard Worker   *parentType = NParentType::kDir;
708*f6dc9357SAndroid Build Coastguard Worker   *parent = (UInt32)(Int32)-1;
709*f6dc9357SAndroid Build Coastguard Worker   if (index >= m_Items.Size())
710*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
711*f6dc9357SAndroid Build Coastguard Worker   const CItemEx &item = m_Items[index];
712*f6dc9357SAndroid Build Coastguard Worker 
713*f6dc9357SAndroid Build Coastguard Worker   if (item.ParentOfAltStream >= 0)
714*f6dc9357SAndroid Build Coastguard Worker   {
715*f6dc9357SAndroid Build Coastguard Worker     *parentType = NParentType::kAltStream;
716*f6dc9357SAndroid Build Coastguard Worker     *parent = item.ParentOfAltStream;
717*f6dc9357SAndroid Build Coastguard Worker   }
718*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
719*f6dc9357SAndroid Build Coastguard Worker }
720*f6dc9357SAndroid Build Coastguard Worker 
721*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
722*f6dc9357SAndroid Build Coastguard Worker {
723*f6dc9357SAndroid Build Coastguard Worker   UNUSED_VAR(index);
724*f6dc9357SAndroid Build Coastguard Worker   UNUSED_VAR(propID);
725*f6dc9357SAndroid Build Coastguard Worker   *data = NULL;
726*f6dc9357SAndroid Build Coastguard Worker   *dataSize = 0;
727*f6dc9357SAndroid Build Coastguard Worker   *propType = 0;
728*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
729*f6dc9357SAndroid Build Coastguard Worker }
730*f6dc9357SAndroid Build Coastguard Worker 
731*f6dc9357SAndroid Build Coastguard Worker 
732*f6dc9357SAndroid Build Coastguard Worker void CHandler::MarkAltStreams(CObjectVector<CItemEx> &items)
733*f6dc9357SAndroid Build Coastguard Worker {
734*f6dc9357SAndroid Build Coastguard Worker   int prevIndex = -1;
735*f6dc9357SAndroid Build Coastguard Worker   UString prevName;
736*f6dc9357SAndroid Build Coastguard Worker   UString name;
737*f6dc9357SAndroid Build Coastguard Worker 
738*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < items.Size(); i++)
739*f6dc9357SAndroid Build Coastguard Worker   {
740*f6dc9357SAndroid Build Coastguard Worker     CItemEx &item = m_Items[i];
741*f6dc9357SAndroid Build Coastguard Worker     if (item.IsAltStream())
742*f6dc9357SAndroid Build Coastguard Worker     {
743*f6dc9357SAndroid Build Coastguard Worker       if (prevIndex == -1)
744*f6dc9357SAndroid Build Coastguard Worker         continue;
745*f6dc9357SAndroid Build Coastguard Worker       if (prevName.IsEmpty())
746*f6dc9357SAndroid Build Coastguard Worker       {
747*f6dc9357SAndroid Build Coastguard Worker         const CItemEx &prevItem = m_Items[prevIndex];
748*f6dc9357SAndroid Build Coastguard Worker         prevItem.GetUnicodeString(prevName, prevItem.Name, false, _forceCodePage, _specifiedCodePage);
749*f6dc9357SAndroid Build Coastguard Worker         NItemName::ReplaceToOsSlashes_Remove_TailSlash(prevName);
750*f6dc9357SAndroid Build Coastguard Worker       }
751*f6dc9357SAndroid Build Coastguard Worker       name.Empty();
752*f6dc9357SAndroid Build Coastguard Worker       item.GetUnicodeString(name, item.Name, false, _forceCodePage, _specifiedCodePage);
753*f6dc9357SAndroid Build Coastguard Worker       NItemName::ReplaceToOsSlashes_Remove_TailSlash(name);
754*f6dc9357SAndroid Build Coastguard Worker 
755*f6dc9357SAndroid Build Coastguard Worker       if (name.IsPrefixedBy(prevName))
756*f6dc9357SAndroid Build Coastguard Worker         if (IsString1PrefixedByString2(name.Ptr(prevName.Len()), k_SpecName_NTFS_STREAM))
757*f6dc9357SAndroid Build Coastguard Worker           item.ParentOfAltStream = prevIndex;
758*f6dc9357SAndroid Build Coastguard Worker     }
759*f6dc9357SAndroid Build Coastguard Worker     else
760*f6dc9357SAndroid Build Coastguard Worker     {
761*f6dc9357SAndroid Build Coastguard Worker       prevIndex = i;
762*f6dc9357SAndroid Build Coastguard Worker       prevName.Empty();
763*f6dc9357SAndroid Build Coastguard Worker     }
764*f6dc9357SAndroid Build Coastguard Worker   }
765*f6dc9357SAndroid Build Coastguard Worker }
766*f6dc9357SAndroid Build Coastguard Worker */
767*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::Open (IInStream * inStream,const UInt64 * maxCheckStartPosition,IArchiveOpenCallback * callback))768*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
769*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback))
770*f6dc9357SAndroid Build Coastguard Worker {
771*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
772*f6dc9357SAndroid Build Coastguard Worker   try
773*f6dc9357SAndroid Build Coastguard Worker   {
774*f6dc9357SAndroid Build Coastguard Worker     Close();
775*f6dc9357SAndroid Build Coastguard Worker     m_Archive.Force_ReadLocals_Mode = _force_OpenSeq;
776*f6dc9357SAndroid Build Coastguard Worker     // m_Archive.Disable_VolsRead = _force_OpenSeq;
777*f6dc9357SAndroid Build Coastguard Worker     // m_Archive.Disable_FindMarker = _force_OpenSeq;
778*f6dc9357SAndroid Build Coastguard Worker     HRESULT res = m_Archive.Open(inStream, maxCheckStartPosition, callback, m_Items);
779*f6dc9357SAndroid Build Coastguard Worker     if (res != S_OK)
780*f6dc9357SAndroid Build Coastguard Worker     {
781*f6dc9357SAndroid Build Coastguard Worker       m_Items.Clear();
782*f6dc9357SAndroid Build Coastguard Worker       m_Archive.ClearRefs(); // we don't want to clear error flags
783*f6dc9357SAndroid Build Coastguard Worker     }
784*f6dc9357SAndroid Build Coastguard Worker     // MarkAltStreams(m_Items);
785*f6dc9357SAndroid Build Coastguard Worker     return res;
786*f6dc9357SAndroid Build Coastguard Worker   }
787*f6dc9357SAndroid Build Coastguard Worker   catch(...) { Close(); throw; }
788*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
789*f6dc9357SAndroid Build Coastguard Worker }
790*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::Close ())791*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
792*f6dc9357SAndroid Build Coastguard Worker {
793*f6dc9357SAndroid Build Coastguard Worker   m_Items.Clear();
794*f6dc9357SAndroid Build Coastguard Worker   m_Archive.Close();
795*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
796*f6dc9357SAndroid Build Coastguard Worker }
797*f6dc9357SAndroid Build Coastguard Worker 
798*f6dc9357SAndroid Build Coastguard Worker 
799*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_3(
800*f6dc9357SAndroid Build Coastguard Worker   CLzmaDecoder
801*f6dc9357SAndroid Build Coastguard Worker   , ICompressCoder
802*f6dc9357SAndroid Build Coastguard Worker   , ICompressSetFinishMode
803*f6dc9357SAndroid Build Coastguard Worker   , ICompressGetInStreamProcessedSize
804*f6dc9357SAndroid Build Coastguard Worker )
805*f6dc9357SAndroid Build Coastguard Worker public:
806*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ICompressCoder, NCompress::NLzma::CDecoder> Decoder;
807*f6dc9357SAndroid Build Coastguard Worker };
808*f6dc9357SAndroid Build Coastguard Worker 
809*f6dc9357SAndroid Build Coastguard Worker static const unsigned kZipLzmaPropsSize = 4 + LZMA_PROPS_SIZE;
810*f6dc9357SAndroid Build Coastguard Worker 
811*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
812*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
813*f6dc9357SAndroid Build Coastguard Worker {
814*f6dc9357SAndroid Build Coastguard Worker   Byte buf[kZipLzmaPropsSize];
815*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadStream_FALSE(inStream, buf, kZipLzmaPropsSize))
816*f6dc9357SAndroid Build Coastguard Worker   if (buf[2] != LZMA_PROPS_SIZE || buf[3] != 0)
817*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
818*f6dc9357SAndroid Build Coastguard Worker   RINOK(Decoder->SetDecoderProperties2(buf + 4, LZMA_PROPS_SIZE))
819*f6dc9357SAndroid Build Coastguard Worker   UInt64 inSize2 = 0;
820*f6dc9357SAndroid Build Coastguard Worker   if (inSize)
821*f6dc9357SAndroid Build Coastguard Worker   {
822*f6dc9357SAndroid Build Coastguard Worker     inSize2 = *inSize;
823*f6dc9357SAndroid Build Coastguard Worker     if (inSize2 < kZipLzmaPropsSize)
824*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
825*f6dc9357SAndroid Build Coastguard Worker     inSize2 -= kZipLzmaPropsSize;
826*f6dc9357SAndroid Build Coastguard Worker   }
827*f6dc9357SAndroid Build Coastguard Worker   return Decoder.Interface()->Code(inStream, outStream, inSize ? &inSize2 : NULL, outSize, progress);
828*f6dc9357SAndroid Build Coastguard Worker }
829*f6dc9357SAndroid Build Coastguard Worker 
830*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CLzmaDecoder::SetFinishMode(UInt32 finishMode))
831*f6dc9357SAndroid Build Coastguard Worker {
832*f6dc9357SAndroid Build Coastguard Worker   Decoder->FinishStream = (finishMode != 0);
833*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
834*f6dc9357SAndroid Build Coastguard Worker }
835*f6dc9357SAndroid Build Coastguard Worker 
836*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CLzmaDecoder::GetInStreamProcessedSize(UInt64 *value))
837*f6dc9357SAndroid Build Coastguard Worker {
838*f6dc9357SAndroid Build Coastguard Worker   *value = Decoder->GetInputProcessedSize() + kZipLzmaPropsSize;
839*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
840*f6dc9357SAndroid Build Coastguard Worker }
841*f6dc9357SAndroid Build Coastguard Worker 
842*f6dc9357SAndroid Build Coastguard Worker 
843*f6dc9357SAndroid Build Coastguard Worker 
844*f6dc9357SAndroid Build Coastguard Worker 
845*f6dc9357SAndroid Build Coastguard Worker 
846*f6dc9357SAndroid Build Coastguard Worker 
847*f6dc9357SAndroid Build Coastguard Worker 
848*f6dc9357SAndroid Build Coastguard Worker struct CMethodItem
849*f6dc9357SAndroid Build Coastguard Worker {
850*f6dc9357SAndroid Build Coastguard Worker   unsigned ZipMethod;
851*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ICompressCoder> Coder;
852*f6dc9357SAndroid Build Coastguard Worker };
853*f6dc9357SAndroid Build Coastguard Worker 
854*f6dc9357SAndroid Build Coastguard Worker 
855*f6dc9357SAndroid Build Coastguard Worker 
856*f6dc9357SAndroid Build Coastguard Worker class CZipDecoder
857*f6dc9357SAndroid Build Coastguard Worker {
858*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2<ICompressFilter, NCrypto::NZip::CDecoder> _zipCryptoDecoder;
859*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2<ICompressFilter, NCrypto::NZipStrong::CDecoder> _pkAesDecoder;
860*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2<ICompressFilter, NCrypto::NWzAes::CDecoder> _wzAesDecoder;
861*f6dc9357SAndroid Build Coastguard Worker 
862*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2<ISequentialInStream, CFilterCoder> filterStream;
863*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ICryptoGetTextPassword> getTextPassword;
864*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CMethodItem> methodItems;
865*f6dc9357SAndroid Build Coastguard Worker 
866*f6dc9357SAndroid Build Coastguard Worker   CLzmaDecoder *lzmaDecoderSpec;
867*f6dc9357SAndroid Build Coastguard Worker public:
868*f6dc9357SAndroid Build Coastguard Worker   CZipDecoder():
869*f6dc9357SAndroid Build Coastguard Worker       lzmaDecoderSpec(NULL)
870*f6dc9357SAndroid Build Coastguard Worker     {}
871*f6dc9357SAndroid Build Coastguard Worker 
872*f6dc9357SAndroid Build Coastguard Worker   HRESULT Decode(
873*f6dc9357SAndroid Build Coastguard Worker     DECL_EXTERNAL_CODECS_LOC_VARS
874*f6dc9357SAndroid Build Coastguard Worker     CInArchive &archive, const CItemEx &item,
875*f6dc9357SAndroid Build Coastguard Worker     ISequentialOutStream *realOutStream,
876*f6dc9357SAndroid Build Coastguard Worker     IArchiveExtractCallback *extractCallback,
877*f6dc9357SAndroid Build Coastguard Worker     ICompressProgressInfo *compressProgress,
878*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_ST
879*f6dc9357SAndroid Build Coastguard Worker     UInt32 numThreads, UInt64 memUsage,
880*f6dc9357SAndroid Build Coastguard Worker     #endif
881*f6dc9357SAndroid Build Coastguard Worker     Int32 &res);
882*f6dc9357SAndroid Build Coastguard Worker };
883*f6dc9357SAndroid Build Coastguard Worker 
884*f6dc9357SAndroid Build Coastguard Worker 
885*f6dc9357SAndroid Build Coastguard Worker static HRESULT SkipStreamData(ISequentialInStream *stream,
886*f6dc9357SAndroid Build Coastguard Worker     ICompressProgressInfo *progress, UInt64 packSize, UInt64 unpackSize,
887*f6dc9357SAndroid Build Coastguard Worker     bool &thereAreData)
888*f6dc9357SAndroid Build Coastguard Worker {
889*f6dc9357SAndroid Build Coastguard Worker   thereAreData = false;
890*f6dc9357SAndroid Build Coastguard Worker   const size_t kBufSize = 1 << 12;
891*f6dc9357SAndroid Build Coastguard Worker   Byte buf[kBufSize];
892*f6dc9357SAndroid Build Coastguard Worker   UInt64 prev = packSize;
893*f6dc9357SAndroid Build Coastguard Worker   for (;;)
894*f6dc9357SAndroid Build Coastguard Worker   {
895*f6dc9357SAndroid Build Coastguard Worker     size_t size = kBufSize;
896*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadStream(stream, buf, &size))
897*f6dc9357SAndroid Build Coastguard Worker     if (size == 0)
898*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
899*f6dc9357SAndroid Build Coastguard Worker     thereAreData = true;
900*f6dc9357SAndroid Build Coastguard Worker     packSize += size;
901*f6dc9357SAndroid Build Coastguard Worker     if ((packSize - prev) >= (1 << 22))
902*f6dc9357SAndroid Build Coastguard Worker     {
903*f6dc9357SAndroid Build Coastguard Worker       prev = packSize;
904*f6dc9357SAndroid Build Coastguard Worker       RINOK(progress->SetRatioInfo(&packSize, &unpackSize))
905*f6dc9357SAndroid Build Coastguard Worker     }
906*f6dc9357SAndroid Build Coastguard Worker   }
907*f6dc9357SAndroid Build Coastguard Worker }
908*f6dc9357SAndroid Build Coastguard Worker 
909*f6dc9357SAndroid Build Coastguard Worker 
910*f6dc9357SAndroid Build Coastguard Worker 
911*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_1(
912*f6dc9357SAndroid Build Coastguard Worker   COutStreamWithPadPKCS7
913*f6dc9357SAndroid Build Coastguard Worker   , ISequentialOutStream
914*f6dc9357SAndroid Build Coastguard Worker )
915*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> _stream;
916*f6dc9357SAndroid Build Coastguard Worker   UInt64 _size;
917*f6dc9357SAndroid Build Coastguard Worker   UInt64 _padPos;
918*f6dc9357SAndroid Build Coastguard Worker   UInt32 _padSize;
919*f6dc9357SAndroid Build Coastguard Worker   bool _padFailure;
920*f6dc9357SAndroid Build Coastguard Worker public:
921*f6dc9357SAndroid Build Coastguard Worker   void SetStream(ISequentialOutStream *stream) { _stream = stream; }
922*f6dc9357SAndroid Build Coastguard Worker   void ReleaseStream() { _stream.Release(); }
923*f6dc9357SAndroid Build Coastguard Worker 
924*f6dc9357SAndroid Build Coastguard Worker   // padSize == 0 means (no_pad Mode)
925*f6dc9357SAndroid Build Coastguard Worker   void Init(UInt64 padPos, UInt32 padSize)
926*f6dc9357SAndroid Build Coastguard Worker   {
927*f6dc9357SAndroid Build Coastguard Worker     _padPos = padPos;
928*f6dc9357SAndroid Build Coastguard Worker     _padSize = padSize;
929*f6dc9357SAndroid Build Coastguard Worker     _size = 0;
930*f6dc9357SAndroid Build Coastguard Worker     _padFailure = false;
931*f6dc9357SAndroid Build Coastguard Worker   }
932*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetSize() const { return _size; }
933*f6dc9357SAndroid Build Coastguard Worker   bool WasPadFailure() const { return _padFailure; }
934*f6dc9357SAndroid Build Coastguard Worker };
935*f6dc9357SAndroid Build Coastguard Worker 
936*f6dc9357SAndroid Build Coastguard Worker 
937*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(COutStreamWithPadPKCS7::Write(const void *data, UInt32 size, UInt32 *processedSize))
938*f6dc9357SAndroid Build Coastguard Worker {
939*f6dc9357SAndroid Build Coastguard Worker   UInt32 written = 0;
940*f6dc9357SAndroid Build Coastguard Worker   HRESULT result = S_OK;
941*f6dc9357SAndroid Build Coastguard Worker   if (_size < _padPos)
942*f6dc9357SAndroid Build Coastguard Worker   {
943*f6dc9357SAndroid Build Coastguard Worker     const UInt64 rem = _padPos - _size;
944*f6dc9357SAndroid Build Coastguard Worker     UInt32 num = size;
945*f6dc9357SAndroid Build Coastguard Worker     if (num > rem)
946*f6dc9357SAndroid Build Coastguard Worker       num = (UInt32)rem;
947*f6dc9357SAndroid Build Coastguard Worker     result = _stream->Write(data, num, &written);
948*f6dc9357SAndroid Build Coastguard Worker     _size += written;
949*f6dc9357SAndroid Build Coastguard Worker     if (processedSize)
950*f6dc9357SAndroid Build Coastguard Worker       *processedSize = written;
951*f6dc9357SAndroid Build Coastguard Worker     if (_size != _padPos || result != S_OK)
952*f6dc9357SAndroid Build Coastguard Worker       return result;
953*f6dc9357SAndroid Build Coastguard Worker     size -= written;
954*f6dc9357SAndroid Build Coastguard Worker     data = ((const Byte *)data) + written;
955*f6dc9357SAndroid Build Coastguard Worker   }
956*f6dc9357SAndroid Build Coastguard Worker   _size += size;
957*f6dc9357SAndroid Build Coastguard Worker   written += size;
958*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
959*f6dc9357SAndroid Build Coastguard Worker     *processedSize = written;
960*f6dc9357SAndroid Build Coastguard Worker   if (_padSize != 0)
961*f6dc9357SAndroid Build Coastguard Worker   for (; size != 0; size--)
962*f6dc9357SAndroid Build Coastguard Worker   {
963*f6dc9357SAndroid Build Coastguard Worker     if (*(const Byte *)data != _padSize)
964*f6dc9357SAndroid Build Coastguard Worker       _padFailure = true;
965*f6dc9357SAndroid Build Coastguard Worker     data = ((const Byte *)data) + 1;
966*f6dc9357SAndroid Build Coastguard Worker   }
967*f6dc9357SAndroid Build Coastguard Worker   return result;
968*f6dc9357SAndroid Build Coastguard Worker }
969*f6dc9357SAndroid Build Coastguard Worker 
970*f6dc9357SAndroid Build Coastguard Worker 
971*f6dc9357SAndroid Build Coastguard Worker 
972*f6dc9357SAndroid Build Coastguard Worker HRESULT CZipDecoder::Decode(
973*f6dc9357SAndroid Build Coastguard Worker     DECL_EXTERNAL_CODECS_LOC_VARS
974*f6dc9357SAndroid Build Coastguard Worker     CInArchive &archive, const CItemEx &item,
975*f6dc9357SAndroid Build Coastguard Worker     ISequentialOutStream *realOutStream,
976*f6dc9357SAndroid Build Coastguard Worker     IArchiveExtractCallback *extractCallback,
977*f6dc9357SAndroid Build Coastguard Worker     ICompressProgressInfo *compressProgress,
978*f6dc9357SAndroid Build Coastguard Worker     #ifndef Z7_ST
979*f6dc9357SAndroid Build Coastguard Worker     UInt32 numThreads, UInt64 memUsage,
980*f6dc9357SAndroid Build Coastguard Worker     #endif
981*f6dc9357SAndroid Build Coastguard Worker     Int32 &res)
982*f6dc9357SAndroid Build Coastguard Worker {
983*f6dc9357SAndroid Build Coastguard Worker   res = NExtract::NOperationResult::kHeadersError;
984*f6dc9357SAndroid Build Coastguard Worker 
985*f6dc9357SAndroid Build Coastguard Worker   CFilterCoder::C_InStream_Releaser inStreamReleaser;
986*f6dc9357SAndroid Build Coastguard Worker   CFilterCoder::C_Filter_Releaser filterReleaser;
987*f6dc9357SAndroid Build Coastguard Worker 
988*f6dc9357SAndroid Build Coastguard Worker   bool needCRC = true;
989*f6dc9357SAndroid Build Coastguard Worker   bool wzAesMode = false;
990*f6dc9357SAndroid Build Coastguard Worker   bool pkAesMode = false;
991*f6dc9357SAndroid Build Coastguard Worker 
992*f6dc9357SAndroid Build Coastguard Worker   bool badDescriptor = item.IsBadDescriptor();
993*f6dc9357SAndroid Build Coastguard Worker   if (badDescriptor)
994*f6dc9357SAndroid Build Coastguard Worker     needCRC = false;
995*f6dc9357SAndroid Build Coastguard Worker 
996*f6dc9357SAndroid Build Coastguard Worker 
997*f6dc9357SAndroid Build Coastguard Worker   unsigned id = item.Method;
998*f6dc9357SAndroid Build Coastguard Worker 
999*f6dc9357SAndroid Build Coastguard Worker   CWzAesExtra aesField;
1000*f6dc9357SAndroid Build Coastguard Worker   // LZFSE and WinZip's AES use same id - kWzAES.
1001*f6dc9357SAndroid Build Coastguard Worker 
1002*f6dc9357SAndroid Build Coastguard Worker   if (id == NFileHeader::NCompressionMethod::kWzAES)
1003*f6dc9357SAndroid Build Coastguard Worker   {
1004*f6dc9357SAndroid Build Coastguard Worker     if (item.GetMainExtra().GetWzAes(aesField))
1005*f6dc9357SAndroid Build Coastguard Worker     {
1006*f6dc9357SAndroid Build Coastguard Worker       if (!item.IsEncrypted())
1007*f6dc9357SAndroid Build Coastguard Worker       {
1008*f6dc9357SAndroid Build Coastguard Worker         res = NExtract::NOperationResult::kUnsupportedMethod;
1009*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
1010*f6dc9357SAndroid Build Coastguard Worker       }
1011*f6dc9357SAndroid Build Coastguard Worker       wzAesMode = true;
1012*f6dc9357SAndroid Build Coastguard Worker       needCRC = aesField.NeedCrc();
1013*f6dc9357SAndroid Build Coastguard Worker     }
1014*f6dc9357SAndroid Build Coastguard Worker   }
1015*f6dc9357SAndroid Build Coastguard Worker 
1016*f6dc9357SAndroid Build Coastguard Worker   if (!wzAesMode)
1017*f6dc9357SAndroid Build Coastguard Worker   if (item.IsEncrypted())
1018*f6dc9357SAndroid Build Coastguard Worker   {
1019*f6dc9357SAndroid Build Coastguard Worker     if (item.IsStrongEncrypted())
1020*f6dc9357SAndroid Build Coastguard Worker     {
1021*f6dc9357SAndroid Build Coastguard Worker       CStrongCryptoExtra f;
1022*f6dc9357SAndroid Build Coastguard Worker       if (!item.CentralExtra.GetStrongCrypto(f))
1023*f6dc9357SAndroid Build Coastguard Worker       {
1024*f6dc9357SAndroid Build Coastguard Worker         res = NExtract::NOperationResult::kUnsupportedMethod;
1025*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
1026*f6dc9357SAndroid Build Coastguard Worker       }
1027*f6dc9357SAndroid Build Coastguard Worker       pkAesMode = true;
1028*f6dc9357SAndroid Build Coastguard Worker     }
1029*f6dc9357SAndroid Build Coastguard Worker   }
1030*f6dc9357SAndroid Build Coastguard Worker 
1031*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;
1032*f6dc9357SAndroid Build Coastguard Worker   outStream->SetStream(realOutStream);
1033*f6dc9357SAndroid Build Coastguard Worker   outStream->Init(needCRC);
1034*f6dc9357SAndroid Build Coastguard Worker 
1035*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> packStream;
1036*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
1037*f6dc9357SAndroid Build Coastguard Worker 
1038*f6dc9357SAndroid Build Coastguard Worker   {
1039*f6dc9357SAndroid Build Coastguard Worker     UInt64 packSize = item.PackSize;
1040*f6dc9357SAndroid Build Coastguard Worker     if (wzAesMode)
1041*f6dc9357SAndroid Build Coastguard Worker     {
1042*f6dc9357SAndroid Build Coastguard Worker       if (packSize < NCrypto::NWzAes::kMacSize)
1043*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
1044*f6dc9357SAndroid Build Coastguard Worker       packSize -= NCrypto::NWzAes::kMacSize;
1045*f6dc9357SAndroid Build Coastguard Worker     }
1046*f6dc9357SAndroid Build Coastguard Worker     RINOK(archive.GetItemStream(item, true, packStream))
1047*f6dc9357SAndroid Build Coastguard Worker     if (!packStream)
1048*f6dc9357SAndroid Build Coastguard Worker     {
1049*f6dc9357SAndroid Build Coastguard Worker       res = NExtract::NOperationResult::kUnavailable;
1050*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1051*f6dc9357SAndroid Build Coastguard Worker     }
1052*f6dc9357SAndroid Build Coastguard Worker     inStream->SetStream(packStream);
1053*f6dc9357SAndroid Build Coastguard Worker     inStream->Init(packSize);
1054*f6dc9357SAndroid Build Coastguard Worker   }
1055*f6dc9357SAndroid Build Coastguard Worker 
1056*f6dc9357SAndroid Build Coastguard Worker 
1057*f6dc9357SAndroid Build Coastguard Worker   res = NExtract::NOperationResult::kDataError;
1058*f6dc9357SAndroid Build Coastguard Worker 
1059*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ICompressFilter> cryptoFilter;
1060*f6dc9357SAndroid Build Coastguard Worker 
1061*f6dc9357SAndroid Build Coastguard Worker   if (item.IsEncrypted())
1062*f6dc9357SAndroid Build Coastguard Worker   {
1063*f6dc9357SAndroid Build Coastguard Worker     if (wzAesMode)
1064*f6dc9357SAndroid Build Coastguard Worker     {
1065*f6dc9357SAndroid Build Coastguard Worker       id = aesField.Method;
1066*f6dc9357SAndroid Build Coastguard Worker       _wzAesDecoder.Create_if_Empty();
1067*f6dc9357SAndroid Build Coastguard Worker       cryptoFilter = _wzAesDecoder;
1068*f6dc9357SAndroid Build Coastguard Worker       if (!_wzAesDecoder->SetKeyMode(aesField.Strength))
1069*f6dc9357SAndroid Build Coastguard Worker       {
1070*f6dc9357SAndroid Build Coastguard Worker         res = NExtract::NOperationResult::kUnsupportedMethod;
1071*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
1072*f6dc9357SAndroid Build Coastguard Worker       }
1073*f6dc9357SAndroid Build Coastguard Worker     }
1074*f6dc9357SAndroid Build Coastguard Worker     else if (pkAesMode)
1075*f6dc9357SAndroid Build Coastguard Worker     {
1076*f6dc9357SAndroid Build Coastguard Worker       _pkAesDecoder.Create_if_Empty();
1077*f6dc9357SAndroid Build Coastguard Worker       cryptoFilter = _pkAesDecoder;
1078*f6dc9357SAndroid Build Coastguard Worker     }
1079*f6dc9357SAndroid Build Coastguard Worker     else
1080*f6dc9357SAndroid Build Coastguard Worker     {
1081*f6dc9357SAndroid Build Coastguard Worker       _zipCryptoDecoder.Create_if_Empty();
1082*f6dc9357SAndroid Build Coastguard Worker       cryptoFilter = _zipCryptoDecoder;
1083*f6dc9357SAndroid Build Coastguard Worker     }
1084*f6dc9357SAndroid Build Coastguard Worker 
1085*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
1086*f6dc9357SAndroid Build Coastguard Worker     RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword))
1087*f6dc9357SAndroid Build Coastguard Worker     if (!cryptoSetPassword)
1088*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
1089*f6dc9357SAndroid Build Coastguard Worker 
1090*f6dc9357SAndroid Build Coastguard Worker     if (!getTextPassword)
1091*f6dc9357SAndroid Build Coastguard Worker       extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
1092*f6dc9357SAndroid Build Coastguard Worker 
1093*f6dc9357SAndroid Build Coastguard Worker     if (getTextPassword)
1094*f6dc9357SAndroid Build Coastguard Worker     {
1095*f6dc9357SAndroid Build Coastguard Worker       CMyComBSTR_Wipe password;
1096*f6dc9357SAndroid Build Coastguard Worker       RINOK(getTextPassword->CryptoGetTextPassword(&password))
1097*f6dc9357SAndroid Build Coastguard Worker       AString_Wipe charPassword;
1098*f6dc9357SAndroid Build Coastguard Worker       if (password)
1099*f6dc9357SAndroid Build Coastguard Worker       {
1100*f6dc9357SAndroid Build Coastguard Worker #if 0 && defined(_WIN32)
1101*f6dc9357SAndroid Build Coastguard Worker         // do we need UTF-8 passwords here ?
1102*f6dc9357SAndroid Build Coastguard Worker         if (item.GetHostOS() == NFileHeader::NHostOS::kUnix // 24.05
1103*f6dc9357SAndroid Build Coastguard Worker             // || item.IsUtf8() // 22.00
1104*f6dc9357SAndroid Build Coastguard Worker             )
1105*f6dc9357SAndroid Build Coastguard Worker         {
1106*f6dc9357SAndroid Build Coastguard Worker           // throw 1;
1107*f6dc9357SAndroid Build Coastguard Worker           ConvertUnicodeToUTF8((LPCOLESTR)password, charPassword);
1108*f6dc9357SAndroid Build Coastguard Worker         }
1109*f6dc9357SAndroid Build Coastguard Worker         else
1110*f6dc9357SAndroid Build Coastguard Worker #endif
1111*f6dc9357SAndroid Build Coastguard Worker         {
1112*f6dc9357SAndroid Build Coastguard Worker           UnicodeStringToMultiByte2(charPassword, (LPCOLESTR)password, CP_ACP);
1113*f6dc9357SAndroid Build Coastguard Worker         }
1114*f6dc9357SAndroid Build Coastguard Worker         /*
1115*f6dc9357SAndroid Build Coastguard Worker         if (wzAesMode || pkAesMode)
1116*f6dc9357SAndroid Build Coastguard Worker         {
1117*f6dc9357SAndroid Build Coastguard Worker         }
1118*f6dc9357SAndroid Build Coastguard Worker         else
1119*f6dc9357SAndroid Build Coastguard Worker         {
1120*f6dc9357SAndroid Build Coastguard Worker           // PASSWORD encoding for ZipCrypto:
1121*f6dc9357SAndroid Build Coastguard Worker           // pkzip25 / WinZip / Windows probably use ANSI
1122*f6dc9357SAndroid Build Coastguard Worker           // 7-Zip <  4.43 creates ZIP archives with OEM encoding in password
1123*f6dc9357SAndroid Build Coastguard Worker           // 7-Zip >= 4.43 creates ZIP archives only with ASCII characters in password
1124*f6dc9357SAndroid Build Coastguard Worker           // 7-Zip <  17.00 uses CP_OEMCP for password decoding
1125*f6dc9357SAndroid Build Coastguard Worker           // 7-Zip >= 17.00 uses CP_ACP   for password decoding
1126*f6dc9357SAndroid Build Coastguard Worker         }
1127*f6dc9357SAndroid Build Coastguard Worker         */
1128*f6dc9357SAndroid Build Coastguard Worker       }
1129*f6dc9357SAndroid Build Coastguard Worker       HRESULT result = cryptoSetPassword->CryptoSetPassword(
1130*f6dc9357SAndroid Build Coastguard Worker         (const Byte *)(const char *)charPassword, charPassword.Len());
1131*f6dc9357SAndroid Build Coastguard Worker       if (result != S_OK)
1132*f6dc9357SAndroid Build Coastguard Worker       {
1133*f6dc9357SAndroid Build Coastguard Worker         res = NExtract::NOperationResult::kWrongPassword;
1134*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
1135*f6dc9357SAndroid Build Coastguard Worker       }
1136*f6dc9357SAndroid Build Coastguard Worker     }
1137*f6dc9357SAndroid Build Coastguard Worker     else
1138*f6dc9357SAndroid Build Coastguard Worker     {
1139*f6dc9357SAndroid Build Coastguard Worker       res = NExtract::NOperationResult::kWrongPassword;
1140*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1141*f6dc9357SAndroid Build Coastguard Worker       // RINOK(cryptoSetPassword->CryptoSetPassword(NULL, 0));
1142*f6dc9357SAndroid Build Coastguard Worker     }
1143*f6dc9357SAndroid Build Coastguard Worker   }
1144*f6dc9357SAndroid Build Coastguard Worker 
1145*f6dc9357SAndroid Build Coastguard Worker   unsigned m;
1146*f6dc9357SAndroid Build Coastguard Worker   for (m = 0; m < methodItems.Size(); m++)
1147*f6dc9357SAndroid Build Coastguard Worker     if (methodItems[m].ZipMethod == id)
1148*f6dc9357SAndroid Build Coastguard Worker       break;
1149*f6dc9357SAndroid Build Coastguard Worker 
1150*f6dc9357SAndroid Build Coastguard Worker   if (m == methodItems.Size())
1151*f6dc9357SAndroid Build Coastguard Worker   {
1152*f6dc9357SAndroid Build Coastguard Worker     CMethodItem mi;
1153*f6dc9357SAndroid Build Coastguard Worker     mi.ZipMethod = id;
1154*f6dc9357SAndroid Build Coastguard Worker     if (id == NFileHeader::NCompressionMethod::kStore)
1155*f6dc9357SAndroid Build Coastguard Worker       mi.Coder = new NCompress::CCopyCoder;
1156*f6dc9357SAndroid Build Coastguard Worker     else if (id == NFileHeader::NCompressionMethod::kShrink)
1157*f6dc9357SAndroid Build Coastguard Worker       mi.Coder = new NCompress::NShrink::CDecoder;
1158*f6dc9357SAndroid Build Coastguard Worker     else if (id == NFileHeader::NCompressionMethod::kImplode)
1159*f6dc9357SAndroid Build Coastguard Worker       mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
1160*f6dc9357SAndroid Build Coastguard Worker     else if (id == NFileHeader::NCompressionMethod::kLZMA)
1161*f6dc9357SAndroid Build Coastguard Worker     {
1162*f6dc9357SAndroid Build Coastguard Worker       lzmaDecoderSpec = new CLzmaDecoder;
1163*f6dc9357SAndroid Build Coastguard Worker       mi.Coder = lzmaDecoderSpec;
1164*f6dc9357SAndroid Build Coastguard Worker     }
1165*f6dc9357SAndroid Build Coastguard Worker     else if (id == NFileHeader::NCompressionMethod::kXz)
1166*f6dc9357SAndroid Build Coastguard Worker       mi.Coder = new NCompress::NXz::CComDecoder;
1167*f6dc9357SAndroid Build Coastguard Worker     else if (id == NFileHeader::NCompressionMethod::kPPMd)
1168*f6dc9357SAndroid Build Coastguard Worker       mi.Coder = new NCompress::NPpmdZip::CDecoder(true);
1169*f6dc9357SAndroid Build Coastguard Worker     else if (id == NFileHeader::NCompressionMethod::kZstdWz)
1170*f6dc9357SAndroid Build Coastguard Worker       mi.Coder = new NCompress::NZstd::CDecoder();
1171*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ZIP_LZFSE_DISABLE
1172*f6dc9357SAndroid Build Coastguard Worker     else if (id == NFileHeader::NCompressionMethod::kWzAES)
1173*f6dc9357SAndroid Build Coastguard Worker       mi.Coder = new NCompress::NLzfse::CDecoder;
1174*f6dc9357SAndroid Build Coastguard Worker #endif
1175*f6dc9357SAndroid Build Coastguard Worker     else
1176*f6dc9357SAndroid Build Coastguard Worker     {
1177*f6dc9357SAndroid Build Coastguard Worker       CMethodId szMethodID;
1178*f6dc9357SAndroid Build Coastguard Worker       if (id == NFileHeader::NCompressionMethod::kBZip2)
1179*f6dc9357SAndroid Build Coastguard Worker         szMethodID = kMethodId_BZip2;
1180*f6dc9357SAndroid Build Coastguard Worker       else
1181*f6dc9357SAndroid Build Coastguard Worker       {
1182*f6dc9357SAndroid Build Coastguard Worker         if (id > 0xFF)
1183*f6dc9357SAndroid Build Coastguard Worker         {
1184*f6dc9357SAndroid Build Coastguard Worker           res = NExtract::NOperationResult::kUnsupportedMethod;
1185*f6dc9357SAndroid Build Coastguard Worker           return S_OK;
1186*f6dc9357SAndroid Build Coastguard Worker         }
1187*f6dc9357SAndroid Build Coastguard Worker         szMethodID = kMethodId_ZipBase + (Byte)id;
1188*f6dc9357SAndroid Build Coastguard Worker       }
1189*f6dc9357SAndroid Build Coastguard Worker 
1190*f6dc9357SAndroid Build Coastguard Worker       RINOK(CreateCoder_Id(EXTERNAL_CODECS_LOC_VARS szMethodID, false, mi.Coder))
1191*f6dc9357SAndroid Build Coastguard Worker 
1192*f6dc9357SAndroid Build Coastguard Worker       if (!mi.Coder)
1193*f6dc9357SAndroid Build Coastguard Worker       {
1194*f6dc9357SAndroid Build Coastguard Worker         res = NExtract::NOperationResult::kUnsupportedMethod;
1195*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
1196*f6dc9357SAndroid Build Coastguard Worker       }
1197*f6dc9357SAndroid Build Coastguard Worker     }
1198*f6dc9357SAndroid Build Coastguard Worker     m = methodItems.Add(mi);
1199*f6dc9357SAndroid Build Coastguard Worker   }
1200*f6dc9357SAndroid Build Coastguard Worker 
1201*f6dc9357SAndroid Build Coastguard Worker   const CMethodItem &mi = methodItems[m];
1202*f6dc9357SAndroid Build Coastguard Worker   ICompressCoder *coder = mi.Coder;
1203*f6dc9357SAndroid Build Coastguard Worker 
1204*f6dc9357SAndroid Build Coastguard Worker 
1205*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ST
1206*f6dc9357SAndroid Build Coastguard Worker   {
1207*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ICompressSetCoderMt> setCoderMt;
1208*f6dc9357SAndroid Build Coastguard Worker     coder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
1209*f6dc9357SAndroid Build Coastguard Worker     if (setCoderMt)
1210*f6dc9357SAndroid Build Coastguard Worker     {
1211*f6dc9357SAndroid Build Coastguard Worker       RINOK(setCoderMt->SetNumberOfThreads(numThreads))
1212*f6dc9357SAndroid Build Coastguard Worker     }
1213*f6dc9357SAndroid Build Coastguard Worker   }
1214*f6dc9357SAndroid Build Coastguard Worker   // if (memUsage != 0)
1215*f6dc9357SAndroid Build Coastguard Worker   {
1216*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ICompressSetMemLimit> setMemLimit;
1217*f6dc9357SAndroid Build Coastguard Worker     coder->QueryInterface(IID_ICompressSetMemLimit, (void **)&setMemLimit);
1218*f6dc9357SAndroid Build Coastguard Worker     if (setMemLimit)
1219*f6dc9357SAndroid Build Coastguard Worker     {
1220*f6dc9357SAndroid Build Coastguard Worker       RINOK(setMemLimit->SetMemLimit(memUsage))
1221*f6dc9357SAndroid Build Coastguard Worker     }
1222*f6dc9357SAndroid Build Coastguard Worker   }
1223*f6dc9357SAndroid Build Coastguard Worker   #endif
1224*f6dc9357SAndroid Build Coastguard Worker 
1225*f6dc9357SAndroid Build Coastguard Worker   {
1226*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
1227*f6dc9357SAndroid Build Coastguard Worker     coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
1228*f6dc9357SAndroid Build Coastguard Worker     if (setDecoderProperties)
1229*f6dc9357SAndroid Build Coastguard Worker     {
1230*f6dc9357SAndroid Build Coastguard Worker       Byte properties = (Byte)item.Flags;
1231*f6dc9357SAndroid Build Coastguard Worker       RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1))
1232*f6dc9357SAndroid Build Coastguard Worker     }
1233*f6dc9357SAndroid Build Coastguard Worker   }
1234*f6dc9357SAndroid Build Coastguard Worker 
1235*f6dc9357SAndroid Build Coastguard Worker 
1236*f6dc9357SAndroid Build Coastguard Worker   bool isFullStreamExpected = (!item.HasDescriptor() || item.PackSize != 0);
1237*f6dc9357SAndroid Build Coastguard Worker   bool needReminderCheck = false;
1238*f6dc9357SAndroid Build Coastguard Worker 
1239*f6dc9357SAndroid Build Coastguard Worker   bool dataAfterEnd = false;
1240*f6dc9357SAndroid Build Coastguard Worker   bool truncatedError = false;
1241*f6dc9357SAndroid Build Coastguard Worker   bool lzmaEosError = false;
1242*f6dc9357SAndroid Build Coastguard Worker   bool headersError  = false;
1243*f6dc9357SAndroid Build Coastguard Worker   bool padError = false;
1244*f6dc9357SAndroid Build Coastguard Worker   bool readFromFilter = false;
1245*f6dc9357SAndroid Build Coastguard Worker 
1246*f6dc9357SAndroid Build Coastguard Worker   const bool useUnpackLimit = (id == NFileHeader::NCompressionMethod::kStore
1247*f6dc9357SAndroid Build Coastguard Worker       || !item.HasDescriptor()
1248*f6dc9357SAndroid Build Coastguard Worker       || item.Size >= ((UInt64)1 << 32)
1249*f6dc9357SAndroid Build Coastguard Worker       || item.LocalExtra.IsZip64
1250*f6dc9357SAndroid Build Coastguard Worker       || item.CentralExtra.IsZip64
1251*f6dc9357SAndroid Build Coastguard Worker       );
1252*f6dc9357SAndroid Build Coastguard Worker 
1253*f6dc9357SAndroid Build Coastguard Worker   {
1254*f6dc9357SAndroid Build Coastguard Worker     HRESULT result = S_OK;
1255*f6dc9357SAndroid Build Coastguard Worker     if (item.IsEncrypted())
1256*f6dc9357SAndroid Build Coastguard Worker     {
1257*f6dc9357SAndroid Build Coastguard Worker       if (!filterStream.IsDefined())
1258*f6dc9357SAndroid Build Coastguard Worker         filterStream.SetFromCls(new CFilterCoder(false));
1259*f6dc9357SAndroid Build Coastguard Worker 
1260*f6dc9357SAndroid Build Coastguard Worker       filterReleaser.FilterCoder = filterStream.ClsPtr();
1261*f6dc9357SAndroid Build Coastguard Worker       filterStream->Filter = cryptoFilter;
1262*f6dc9357SAndroid Build Coastguard Worker 
1263*f6dc9357SAndroid Build Coastguard Worker       if (wzAesMode)
1264*f6dc9357SAndroid Build Coastguard Worker       {
1265*f6dc9357SAndroid Build Coastguard Worker         result = _wzAesDecoder->ReadHeader(inStream);
1266*f6dc9357SAndroid Build Coastguard Worker         if (result == S_OK)
1267*f6dc9357SAndroid Build Coastguard Worker         {
1268*f6dc9357SAndroid Build Coastguard Worker           if (!_wzAesDecoder->Init_and_CheckPassword())
1269*f6dc9357SAndroid Build Coastguard Worker           {
1270*f6dc9357SAndroid Build Coastguard Worker             res = NExtract::NOperationResult::kWrongPassword;
1271*f6dc9357SAndroid Build Coastguard Worker             return S_OK;
1272*f6dc9357SAndroid Build Coastguard Worker           }
1273*f6dc9357SAndroid Build Coastguard Worker         }
1274*f6dc9357SAndroid Build Coastguard Worker       }
1275*f6dc9357SAndroid Build Coastguard Worker       else if (pkAesMode)
1276*f6dc9357SAndroid Build Coastguard Worker       {
1277*f6dc9357SAndroid Build Coastguard Worker         isFullStreamExpected = false;
1278*f6dc9357SAndroid Build Coastguard Worker         result = _pkAesDecoder->ReadHeader(inStream, item.Crc, item.Size);
1279*f6dc9357SAndroid Build Coastguard Worker         if (result == S_OK)
1280*f6dc9357SAndroid Build Coastguard Worker         {
1281*f6dc9357SAndroid Build Coastguard Worker           bool passwOK;
1282*f6dc9357SAndroid Build Coastguard Worker           result = _pkAesDecoder->Init_and_CheckPassword(passwOK);
1283*f6dc9357SAndroid Build Coastguard Worker           if (result == S_OK && !passwOK)
1284*f6dc9357SAndroid Build Coastguard Worker           {
1285*f6dc9357SAndroid Build Coastguard Worker             res = NExtract::NOperationResult::kWrongPassword;
1286*f6dc9357SAndroid Build Coastguard Worker             return S_OK;
1287*f6dc9357SAndroid Build Coastguard Worker           }
1288*f6dc9357SAndroid Build Coastguard Worker         }
1289*f6dc9357SAndroid Build Coastguard Worker       }
1290*f6dc9357SAndroid Build Coastguard Worker       else
1291*f6dc9357SAndroid Build Coastguard Worker       {
1292*f6dc9357SAndroid Build Coastguard Worker         result = _zipCryptoDecoder->ReadHeader(inStream);
1293*f6dc9357SAndroid Build Coastguard Worker         if (result == S_OK)
1294*f6dc9357SAndroid Build Coastguard Worker         {
1295*f6dc9357SAndroid Build Coastguard Worker           _zipCryptoDecoder->Init_BeforeDecode();
1296*f6dc9357SAndroid Build Coastguard Worker 
1297*f6dc9357SAndroid Build Coastguard Worker           /* Info-ZIP modification to ZipCrypto format:
1298*f6dc9357SAndroid Build Coastguard Worker                if bit 3 of the general purpose bit flag is set,
1299*f6dc9357SAndroid Build Coastguard Worker                it uses high byte of 16-bit File Time.
1300*f6dc9357SAndroid Build Coastguard Worker              Info-ZIP code probably writes 2 bytes of File Time.
1301*f6dc9357SAndroid Build Coastguard Worker              We check only 1 byte. */
1302*f6dc9357SAndroid Build Coastguard Worker 
1303*f6dc9357SAndroid Build Coastguard Worker           // UInt32 v1 = GetUi16(_zipCryptoDecoder->_header + NCrypto::NZip::kHeaderSize - 2);
1304*f6dc9357SAndroid Build Coastguard Worker           // UInt32 v2 = (item.HasDescriptor() ? (item.Time & 0xFFFF) : (item.Crc >> 16));
1305*f6dc9357SAndroid Build Coastguard Worker 
1306*f6dc9357SAndroid Build Coastguard Worker           Byte v1 = _zipCryptoDecoder->_header[NCrypto::NZip::kHeaderSize - 1];
1307*f6dc9357SAndroid Build Coastguard Worker           Byte v2 = (Byte)(item.HasDescriptor() ? (item.Time >> 8) : (item.Crc >> 24));
1308*f6dc9357SAndroid Build Coastguard Worker 
1309*f6dc9357SAndroid Build Coastguard Worker           if (v1 != v2)
1310*f6dc9357SAndroid Build Coastguard Worker           {
1311*f6dc9357SAndroid Build Coastguard Worker             res = NExtract::NOperationResult::kWrongPassword;
1312*f6dc9357SAndroid Build Coastguard Worker             return S_OK;
1313*f6dc9357SAndroid Build Coastguard Worker           }
1314*f6dc9357SAndroid Build Coastguard Worker         }
1315*f6dc9357SAndroid Build Coastguard Worker       }
1316*f6dc9357SAndroid Build Coastguard Worker     }
1317*f6dc9357SAndroid Build Coastguard Worker 
1318*f6dc9357SAndroid Build Coastguard Worker     if (result == S_OK)
1319*f6dc9357SAndroid Build Coastguard Worker     {
1320*f6dc9357SAndroid Build Coastguard Worker       CMyComPtr<ICompressSetFinishMode> setFinishMode;
1321*f6dc9357SAndroid Build Coastguard Worker       coder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
1322*f6dc9357SAndroid Build Coastguard Worker       if (setFinishMode)
1323*f6dc9357SAndroid Build Coastguard Worker       {
1324*f6dc9357SAndroid Build Coastguard Worker         RINOK(setFinishMode->SetFinishMode(BoolToUInt(true)))
1325*f6dc9357SAndroid Build Coastguard Worker       }
1326*f6dc9357SAndroid Build Coastguard Worker 
1327*f6dc9357SAndroid Build Coastguard Worker       const UInt64 coderPackSize = inStream->GetRem();
1328*f6dc9357SAndroid Build Coastguard Worker 
1329*f6dc9357SAndroid Build Coastguard Worker       if (id == NFileHeader::NCompressionMethod::kStore && item.IsEncrypted())
1330*f6dc9357SAndroid Build Coastguard Worker       {
1331*f6dc9357SAndroid Build Coastguard Worker         // for debug : we can disable this code (kStore + 50), if we want to test CopyCoder+Filter
1332*f6dc9357SAndroid Build Coastguard Worker         // here we use filter without CopyCoder
1333*f6dc9357SAndroid Build Coastguard Worker         readFromFilter = false;
1334*f6dc9357SAndroid Build Coastguard Worker 
1335*f6dc9357SAndroid Build Coastguard Worker         COutStreamWithPadPKCS7 *padStreamSpec = NULL;
1336*f6dc9357SAndroid Build Coastguard Worker         CMyComPtr<ISequentialOutStream> padStream;
1337*f6dc9357SAndroid Build Coastguard Worker         UInt32 padSize = 0;
1338*f6dc9357SAndroid Build Coastguard Worker 
1339*f6dc9357SAndroid Build Coastguard Worker         if (pkAesMode)
1340*f6dc9357SAndroid Build Coastguard Worker         {
1341*f6dc9357SAndroid Build Coastguard Worker           padStreamSpec = new COutStreamWithPadPKCS7;
1342*f6dc9357SAndroid Build Coastguard Worker           padStream = padStreamSpec;
1343*f6dc9357SAndroid Build Coastguard Worker           padSize = _pkAesDecoder->GetPadSize((UInt32)item.Size);
1344*f6dc9357SAndroid Build Coastguard Worker           padStreamSpec->SetStream(outStream);
1345*f6dc9357SAndroid Build Coastguard Worker           padStreamSpec->Init(item.Size, padSize);
1346*f6dc9357SAndroid Build Coastguard Worker         }
1347*f6dc9357SAndroid Build Coastguard Worker 
1348*f6dc9357SAndroid Build Coastguard Worker         // Here we decode minimal required size, including padding
1349*f6dc9357SAndroid Build Coastguard Worker         const UInt64 expectedSize = item.Size + padSize;
1350*f6dc9357SAndroid Build Coastguard Worker         UInt64 size = coderPackSize;
1351*f6dc9357SAndroid Build Coastguard Worker         if (item.Size > coderPackSize)
1352*f6dc9357SAndroid Build Coastguard Worker           headersError = true;
1353*f6dc9357SAndroid Build Coastguard Worker         else if (expectedSize != coderPackSize)
1354*f6dc9357SAndroid Build Coastguard Worker         {
1355*f6dc9357SAndroid Build Coastguard Worker           headersError = true;
1356*f6dc9357SAndroid Build Coastguard Worker           if (coderPackSize > expectedSize)
1357*f6dc9357SAndroid Build Coastguard Worker             size = expectedSize;
1358*f6dc9357SAndroid Build Coastguard Worker         }
1359*f6dc9357SAndroid Build Coastguard Worker 
1360*f6dc9357SAndroid Build Coastguard Worker         result = filterStream->Code(inStream, padStream ?
1361*f6dc9357SAndroid Build Coastguard Worker             padStream.Interface() :
1362*f6dc9357SAndroid Build Coastguard Worker             outStream.Interface(),
1363*f6dc9357SAndroid Build Coastguard Worker             NULL, &size, compressProgress);
1364*f6dc9357SAndroid Build Coastguard Worker 
1365*f6dc9357SAndroid Build Coastguard Worker         if (outStream->GetSize() != item.Size)
1366*f6dc9357SAndroid Build Coastguard Worker           truncatedError = true;
1367*f6dc9357SAndroid Build Coastguard Worker 
1368*f6dc9357SAndroid Build Coastguard Worker         if (pkAesMode)
1369*f6dc9357SAndroid Build Coastguard Worker         {
1370*f6dc9357SAndroid Build Coastguard Worker           if (padStreamSpec->GetSize() != size)
1371*f6dc9357SAndroid Build Coastguard Worker             truncatedError = true;
1372*f6dc9357SAndroid Build Coastguard Worker           if (padStreamSpec->WasPadFailure())
1373*f6dc9357SAndroid Build Coastguard Worker             padError = true;
1374*f6dc9357SAndroid Build Coastguard Worker         }
1375*f6dc9357SAndroid Build Coastguard Worker       }
1376*f6dc9357SAndroid Build Coastguard Worker       else
1377*f6dc9357SAndroid Build Coastguard Worker       {
1378*f6dc9357SAndroid Build Coastguard Worker         if (item.IsEncrypted())
1379*f6dc9357SAndroid Build Coastguard Worker         {
1380*f6dc9357SAndroid Build Coastguard Worker           readFromFilter = true;
1381*f6dc9357SAndroid Build Coastguard Worker           inStreamReleaser.FilterCoder = filterStream.ClsPtr();
1382*f6dc9357SAndroid Build Coastguard Worker           RINOK(filterStream->SetInStream(inStream))
1383*f6dc9357SAndroid Build Coastguard Worker 
1384*f6dc9357SAndroid Build Coastguard Worker           /* IFilter::Init() does nothing in all zip crypto filters.
1385*f6dc9357SAndroid Build Coastguard Worker           So we can call any Initialize function in CFilterCoder. */
1386*f6dc9357SAndroid Build Coastguard Worker 
1387*f6dc9357SAndroid Build Coastguard Worker           RINOK(filterStream->Init_NoSubFilterInit())
1388*f6dc9357SAndroid Build Coastguard Worker           // RINOK(filterStream->SetOutStreamSize(NULL));
1389*f6dc9357SAndroid Build Coastguard Worker         }
1390*f6dc9357SAndroid Build Coastguard Worker 
1391*f6dc9357SAndroid Build Coastguard Worker         try {
1392*f6dc9357SAndroid Build Coastguard Worker         result = coder->Code(readFromFilter ?
1393*f6dc9357SAndroid Build Coastguard Worker               filterStream.Interface() :
1394*f6dc9357SAndroid Build Coastguard Worker               inStream.Interface(),
1395*f6dc9357SAndroid Build Coastguard Worker             outStream,
1396*f6dc9357SAndroid Build Coastguard Worker             isFullStreamExpected ? &coderPackSize : NULL,
1397*f6dc9357SAndroid Build Coastguard Worker             // NULL,
1398*f6dc9357SAndroid Build Coastguard Worker             useUnpackLimit ? &item.Size : NULL,
1399*f6dc9357SAndroid Build Coastguard Worker             compressProgress);
1400*f6dc9357SAndroid Build Coastguard Worker         } catch (...) { return E_FAIL; }
1401*f6dc9357SAndroid Build Coastguard Worker 
1402*f6dc9357SAndroid Build Coastguard Worker         if (result == S_OK)
1403*f6dc9357SAndroid Build Coastguard Worker         {
1404*f6dc9357SAndroid Build Coastguard Worker         CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;
1405*f6dc9357SAndroid Build Coastguard Worker         coder->QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize);
1406*f6dc9357SAndroid Build Coastguard Worker         if (getInStreamProcessedSize && setFinishMode)
1407*f6dc9357SAndroid Build Coastguard Worker         {
1408*f6dc9357SAndroid Build Coastguard Worker           UInt64 processed;
1409*f6dc9357SAndroid Build Coastguard Worker           RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed))
1410*f6dc9357SAndroid Build Coastguard Worker           if (processed != (UInt64)(Int64)-1)
1411*f6dc9357SAndroid Build Coastguard Worker           {
1412*f6dc9357SAndroid Build Coastguard Worker             if (pkAesMode)
1413*f6dc9357SAndroid Build Coastguard Worker             {
1414*f6dc9357SAndroid Build Coastguard Worker               const UInt32 padSize = _pkAesDecoder->GetPadSize((UInt32)processed);
1415*f6dc9357SAndroid Build Coastguard Worker               if (processed + padSize > coderPackSize)
1416*f6dc9357SAndroid Build Coastguard Worker                 truncatedError = true;
1417*f6dc9357SAndroid Build Coastguard Worker               else if (processed + padSize < coderPackSize)
1418*f6dc9357SAndroid Build Coastguard Worker                 dataAfterEnd = true;
1419*f6dc9357SAndroid Build Coastguard Worker               else
1420*f6dc9357SAndroid Build Coastguard Worker               {
1421*f6dc9357SAndroid Build Coastguard Worker                 {
1422*f6dc9357SAndroid Build Coastguard Worker                   // here we check PKCS7 padding data from reminder (it can be inside stream buffer in coder).
1423*f6dc9357SAndroid Build Coastguard Worker                   CMyComPtr<ICompressReadUnusedFromInBuf> readInStream;
1424*f6dc9357SAndroid Build Coastguard Worker                   coder->QueryInterface(IID_ICompressReadUnusedFromInBuf, (void **)&readInStream);
1425*f6dc9357SAndroid Build Coastguard Worker                   // CCopyCoder() for kStore doesn't read data outside of (item.Size)
1426*f6dc9357SAndroid Build Coastguard Worker                   if (readInStream || id == NFileHeader::NCompressionMethod::kStore)
1427*f6dc9357SAndroid Build Coastguard Worker                   {
1428*f6dc9357SAndroid Build Coastguard Worker                     // change pad size, if we support another block size in ZipStrong.
1429*f6dc9357SAndroid Build Coastguard Worker                     // here we request more data to detect error with data after end.
1430*f6dc9357SAndroid Build Coastguard Worker                     const UInt32 kBufSize = NCrypto::NZipStrong::kAesPadAllign + 16;
1431*f6dc9357SAndroid Build Coastguard Worker                     Byte buf[kBufSize];
1432*f6dc9357SAndroid Build Coastguard Worker                     UInt32 processedSize = 0;
1433*f6dc9357SAndroid Build Coastguard Worker                     if (readInStream)
1434*f6dc9357SAndroid Build Coastguard Worker                     {
1435*f6dc9357SAndroid Build Coastguard Worker                       RINOK(readInStream->ReadUnusedFromInBuf(buf, kBufSize, &processedSize))
1436*f6dc9357SAndroid Build Coastguard Worker                     }
1437*f6dc9357SAndroid Build Coastguard Worker                     if (processedSize > padSize)
1438*f6dc9357SAndroid Build Coastguard Worker                       dataAfterEnd = true;
1439*f6dc9357SAndroid Build Coastguard Worker                     else
1440*f6dc9357SAndroid Build Coastguard Worker                     {
1441*f6dc9357SAndroid Build Coastguard Worker                       size_t processedSize2 = kBufSize - processedSize;
1442*f6dc9357SAndroid Build Coastguard Worker                       result = ReadStream(filterStream, buf + processedSize, &processedSize2);
1443*f6dc9357SAndroid Build Coastguard Worker                       if (result == S_OK)
1444*f6dc9357SAndroid Build Coastguard Worker                       {
1445*f6dc9357SAndroid Build Coastguard Worker                         processedSize2 += processedSize;
1446*f6dc9357SAndroid Build Coastguard Worker                         if (processedSize2 > padSize)
1447*f6dc9357SAndroid Build Coastguard Worker                           dataAfterEnd = true;
1448*f6dc9357SAndroid Build Coastguard Worker                         else if (processedSize2 < padSize)
1449*f6dc9357SAndroid Build Coastguard Worker                           truncatedError = true;
1450*f6dc9357SAndroid Build Coastguard Worker                         else
1451*f6dc9357SAndroid Build Coastguard Worker                           for (unsigned i = 0; i < padSize; i++)
1452*f6dc9357SAndroid Build Coastguard Worker                             if (buf[i] != padSize)
1453*f6dc9357SAndroid Build Coastguard Worker                               padError = true;
1454*f6dc9357SAndroid Build Coastguard Worker                       }
1455*f6dc9357SAndroid Build Coastguard Worker                     }
1456*f6dc9357SAndroid Build Coastguard Worker                   }
1457*f6dc9357SAndroid Build Coastguard Worker                 }
1458*f6dc9357SAndroid Build Coastguard Worker               }
1459*f6dc9357SAndroid Build Coastguard Worker             }
1460*f6dc9357SAndroid Build Coastguard Worker             else
1461*f6dc9357SAndroid Build Coastguard Worker             {
1462*f6dc9357SAndroid Build Coastguard Worker               if (processed < coderPackSize)
1463*f6dc9357SAndroid Build Coastguard Worker               {
1464*f6dc9357SAndroid Build Coastguard Worker                 if (isFullStreamExpected)
1465*f6dc9357SAndroid Build Coastguard Worker                   dataAfterEnd = true;
1466*f6dc9357SAndroid Build Coastguard Worker               }
1467*f6dc9357SAndroid Build Coastguard Worker               else if (processed > coderPackSize)
1468*f6dc9357SAndroid Build Coastguard Worker               {
1469*f6dc9357SAndroid Build Coastguard Worker                 // that case is additional check, that can show the bugs in code (coder)
1470*f6dc9357SAndroid Build Coastguard Worker                 truncatedError = true;
1471*f6dc9357SAndroid Build Coastguard Worker               }
1472*f6dc9357SAndroid Build Coastguard Worker               needReminderCheck = isFullStreamExpected;
1473*f6dc9357SAndroid Build Coastguard Worker             }
1474*f6dc9357SAndroid Build Coastguard Worker           }
1475*f6dc9357SAndroid Build Coastguard Worker         }
1476*f6dc9357SAndroid Build Coastguard Worker         }
1477*f6dc9357SAndroid Build Coastguard Worker       }
1478*f6dc9357SAndroid Build Coastguard Worker 
1479*f6dc9357SAndroid Build Coastguard Worker       if (result == S_OK && id == NFileHeader::NCompressionMethod::kLZMA)
1480*f6dc9357SAndroid Build Coastguard Worker         if (!lzmaDecoderSpec->Decoder->CheckFinishStatus(item.IsLzmaEOS()))
1481*f6dc9357SAndroid Build Coastguard Worker           lzmaEosError = true;
1482*f6dc9357SAndroid Build Coastguard Worker     }
1483*f6dc9357SAndroid Build Coastguard Worker 
1484*f6dc9357SAndroid Build Coastguard Worker     if (result == S_FALSE)
1485*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1486*f6dc9357SAndroid Build Coastguard Worker 
1487*f6dc9357SAndroid Build Coastguard Worker     if (result == E_NOTIMPL)
1488*f6dc9357SAndroid Build Coastguard Worker     {
1489*f6dc9357SAndroid Build Coastguard Worker       res = NExtract::NOperationResult::kUnsupportedMethod;
1490*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1491*f6dc9357SAndroid Build Coastguard Worker     }
1492*f6dc9357SAndroid Build Coastguard Worker 
1493*f6dc9357SAndroid Build Coastguard Worker     RINOK(result)
1494*f6dc9357SAndroid Build Coastguard Worker   }
1495*f6dc9357SAndroid Build Coastguard Worker 
1496*f6dc9357SAndroid Build Coastguard Worker   bool crcOK = true;
1497*f6dc9357SAndroid Build Coastguard Worker   bool authOk = true;
1498*f6dc9357SAndroid Build Coastguard Worker   if (needCRC)
1499*f6dc9357SAndroid Build Coastguard Worker     crcOK = (outStream->GetCRC() == item.Crc);
1500*f6dc9357SAndroid Build Coastguard Worker 
1501*f6dc9357SAndroid Build Coastguard Worker   if (useUnpackLimit)
1502*f6dc9357SAndroid Build Coastguard Worker     if (outStream->GetSize() != item.Size)
1503*f6dc9357SAndroid Build Coastguard Worker       truncatedError = true;
1504*f6dc9357SAndroid Build Coastguard Worker 
1505*f6dc9357SAndroid Build Coastguard Worker   if (wzAesMode)
1506*f6dc9357SAndroid Build Coastguard Worker   {
1507*f6dc9357SAndroid Build Coastguard Worker     const UInt64 unpackSize = outStream->GetSize();
1508*f6dc9357SAndroid Build Coastguard Worker     const UInt64 packSize = inStream->GetSize();
1509*f6dc9357SAndroid Build Coastguard Worker     bool thereAreData = false;
1510*f6dc9357SAndroid Build Coastguard Worker     // read to the end from filter or from packed stream
1511*f6dc9357SAndroid Build Coastguard Worker     if (SkipStreamData(readFromFilter ?
1512*f6dc9357SAndroid Build Coastguard Worker           filterStream.Interface() :
1513*f6dc9357SAndroid Build Coastguard Worker           inStream.Interface(),
1514*f6dc9357SAndroid Build Coastguard Worker         compressProgress, packSize, unpackSize, thereAreData) != S_OK)
1515*f6dc9357SAndroid Build Coastguard Worker       authOk = false;
1516*f6dc9357SAndroid Build Coastguard Worker     if (needReminderCheck && thereAreData)
1517*f6dc9357SAndroid Build Coastguard Worker       dataAfterEnd = true;
1518*f6dc9357SAndroid Build Coastguard Worker 
1519*f6dc9357SAndroid Build Coastguard Worker     if (inStream->GetRem() != 0)
1520*f6dc9357SAndroid Build Coastguard Worker       truncatedError = true;
1521*f6dc9357SAndroid Build Coastguard Worker     else
1522*f6dc9357SAndroid Build Coastguard Worker     {
1523*f6dc9357SAndroid Build Coastguard Worker       inStream->Init(NCrypto::NWzAes::kMacSize);
1524*f6dc9357SAndroid Build Coastguard Worker       if (_wzAesDecoder->CheckMac(inStream, authOk) != S_OK)
1525*f6dc9357SAndroid Build Coastguard Worker         authOk = false;
1526*f6dc9357SAndroid Build Coastguard Worker     }
1527*f6dc9357SAndroid Build Coastguard Worker   }
1528*f6dc9357SAndroid Build Coastguard Worker 
1529*f6dc9357SAndroid Build Coastguard Worker   res = NExtract::NOperationResult::kCRCError;
1530*f6dc9357SAndroid Build Coastguard Worker 
1531*f6dc9357SAndroid Build Coastguard Worker   if (crcOK && authOk)
1532*f6dc9357SAndroid Build Coastguard Worker   {
1533*f6dc9357SAndroid Build Coastguard Worker     res = NExtract::NOperationResult::kOK;
1534*f6dc9357SAndroid Build Coastguard Worker 
1535*f6dc9357SAndroid Build Coastguard Worker     if (dataAfterEnd)
1536*f6dc9357SAndroid Build Coastguard Worker       res = NExtract::NOperationResult::kDataAfterEnd;
1537*f6dc9357SAndroid Build Coastguard Worker     else if (padError)
1538*f6dc9357SAndroid Build Coastguard Worker       res = NExtract::NOperationResult::kCRCError;
1539*f6dc9357SAndroid Build Coastguard Worker     else if (truncatedError)
1540*f6dc9357SAndroid Build Coastguard Worker       res = NExtract::NOperationResult::kUnexpectedEnd;
1541*f6dc9357SAndroid Build Coastguard Worker     else if (headersError)
1542*f6dc9357SAndroid Build Coastguard Worker       res = NExtract::NOperationResult::kHeadersError;
1543*f6dc9357SAndroid Build Coastguard Worker     else if (lzmaEosError)
1544*f6dc9357SAndroid Build Coastguard Worker       res = NExtract::NOperationResult::kHeadersError;
1545*f6dc9357SAndroid Build Coastguard Worker     else if (badDescriptor)
1546*f6dc9357SAndroid Build Coastguard Worker       res = NExtract::NOperationResult::kUnexpectedEnd;
1547*f6dc9357SAndroid Build Coastguard Worker 
1548*f6dc9357SAndroid Build Coastguard Worker     // CheckDescriptor() supports only data descriptor with signature and
1549*f6dc9357SAndroid Build Coastguard Worker     // it doesn't support "old" pkzip's data descriptor without signature.
1550*f6dc9357SAndroid Build Coastguard Worker     // So we disable that check.
1551*f6dc9357SAndroid Build Coastguard Worker     /*
1552*f6dc9357SAndroid Build Coastguard Worker     if (item.HasDescriptor() && archive.CheckDescriptor(item) != S_OK)
1553*f6dc9357SAndroid Build Coastguard Worker       res = NExtract::NOperationResult::kHeadersError;
1554*f6dc9357SAndroid Build Coastguard Worker     */
1555*f6dc9357SAndroid Build Coastguard Worker   }
1556*f6dc9357SAndroid Build Coastguard Worker 
1557*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1558*f6dc9357SAndroid Build Coastguard Worker }
1559*f6dc9357SAndroid Build Coastguard Worker 
1560*f6dc9357SAndroid Build Coastguard Worker 
1561*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1562*f6dc9357SAndroid Build Coastguard Worker     Int32 testMode, IArchiveExtractCallback *extractCallback))
1563*f6dc9357SAndroid Build Coastguard Worker {
1564*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
1565*f6dc9357SAndroid Build Coastguard Worker   const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
1566*f6dc9357SAndroid Build Coastguard Worker   if (allFilesMode)
1567*f6dc9357SAndroid Build Coastguard Worker     numItems = m_Items.Size();
1568*f6dc9357SAndroid Build Coastguard Worker   if (numItems == 0)
1569*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1570*f6dc9357SAndroid Build Coastguard Worker   UInt64 total = 0; // , totalPacked = 0;
1571*f6dc9357SAndroid Build Coastguard Worker   UInt32 i;
1572*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < numItems; i++)
1573*f6dc9357SAndroid Build Coastguard Worker   {
1574*f6dc9357SAndroid Build Coastguard Worker     const CItemEx &item = m_Items[allFilesMode ? i : indices[i]];
1575*f6dc9357SAndroid Build Coastguard Worker     total += item.Size;
1576*f6dc9357SAndroid Build Coastguard Worker     // totalPacked += item.PackSize;
1577*f6dc9357SAndroid Build Coastguard Worker   }
1578*f6dc9357SAndroid Build Coastguard Worker   RINOK(extractCallback->SetTotal(total))
1579*f6dc9357SAndroid Build Coastguard Worker 
1580*f6dc9357SAndroid Build Coastguard Worker   CZipDecoder myDecoder;
1581*f6dc9357SAndroid Build Coastguard Worker   UInt64 cur_Unpacked, cur_Packed;
1582*f6dc9357SAndroid Build Coastguard Worker 
1583*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1584*f6dc9357SAndroid Build Coastguard Worker   lps->Init(extractCallback, false);
1585*f6dc9357SAndroid Build Coastguard Worker 
1586*f6dc9357SAndroid Build Coastguard Worker   for (i = 0;; i++,
1587*f6dc9357SAndroid Build Coastguard Worker       lps->OutSize += cur_Unpacked,
1588*f6dc9357SAndroid Build Coastguard Worker       lps->InSize += cur_Packed)
1589*f6dc9357SAndroid Build Coastguard Worker   {
1590*f6dc9357SAndroid Build Coastguard Worker     RINOK(lps->SetCur())
1591*f6dc9357SAndroid Build Coastguard Worker     if (i >= numItems)
1592*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1593*f6dc9357SAndroid Build Coastguard Worker     const UInt32 index = allFilesMode ? i : indices[i];
1594*f6dc9357SAndroid Build Coastguard Worker     CItemEx item = m_Items[index];
1595*f6dc9357SAndroid Build Coastguard Worker     cur_Unpacked = item.Size;
1596*f6dc9357SAndroid Build Coastguard Worker     cur_Packed = item.PackSize;
1597*f6dc9357SAndroid Build Coastguard Worker 
1598*f6dc9357SAndroid Build Coastguard Worker     const bool isLocalOffsetOK = m_Archive.IsLocalOffsetOK(item);
1599*f6dc9357SAndroid Build Coastguard Worker     const bool skip = !isLocalOffsetOK && !item.IsDir();
1600*f6dc9357SAndroid Build Coastguard Worker     const Int32 askMode = skip ?
1601*f6dc9357SAndroid Build Coastguard Worker         NExtract::NAskMode::kSkip : testMode ?
1602*f6dc9357SAndroid Build Coastguard Worker         NExtract::NAskMode::kTest :
1603*f6dc9357SAndroid Build Coastguard Worker         NExtract::NAskMode::kExtract;
1604*f6dc9357SAndroid Build Coastguard Worker 
1605*f6dc9357SAndroid Build Coastguard Worker     Int32 opRes;
1606*f6dc9357SAndroid Build Coastguard Worker     {
1607*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ISequentialOutStream> realOutStream;
1608*f6dc9357SAndroid Build Coastguard Worker     RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
1609*f6dc9357SAndroid Build Coastguard Worker 
1610*f6dc9357SAndroid Build Coastguard Worker     if (!isLocalOffsetOK)
1611*f6dc9357SAndroid Build Coastguard Worker     {
1612*f6dc9357SAndroid Build Coastguard Worker       RINOK(extractCallback->PrepareOperation(askMode))
1613*f6dc9357SAndroid Build Coastguard Worker       realOutStream.Release();
1614*f6dc9357SAndroid Build Coastguard Worker       RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnavailable))
1615*f6dc9357SAndroid Build Coastguard Worker       continue;
1616*f6dc9357SAndroid Build Coastguard Worker     }
1617*f6dc9357SAndroid Build Coastguard Worker 
1618*f6dc9357SAndroid Build Coastguard Worker     bool headersError = false;
1619*f6dc9357SAndroid Build Coastguard Worker 
1620*f6dc9357SAndroid Build Coastguard Worker     if (!item.FromLocal)
1621*f6dc9357SAndroid Build Coastguard Worker     {
1622*f6dc9357SAndroid Build Coastguard Worker       bool isAvail = true;
1623*f6dc9357SAndroid Build Coastguard Worker       const HRESULT hres = m_Archive.Read_LocalItem_After_CdItem(item, isAvail, headersError);
1624*f6dc9357SAndroid Build Coastguard Worker       if (hres == S_FALSE)
1625*f6dc9357SAndroid Build Coastguard Worker       {
1626*f6dc9357SAndroid Build Coastguard Worker         if (item.IsDir() || realOutStream || testMode)
1627*f6dc9357SAndroid Build Coastguard Worker         {
1628*f6dc9357SAndroid Build Coastguard Worker           RINOK(extractCallback->PrepareOperation(askMode))
1629*f6dc9357SAndroid Build Coastguard Worker           realOutStream.Release();
1630*f6dc9357SAndroid Build Coastguard Worker           RINOK(extractCallback->SetOperationResult(
1631*f6dc9357SAndroid Build Coastguard Worker               isAvail ?
1632*f6dc9357SAndroid Build Coastguard Worker                 NExtract::NOperationResult::kHeadersError :
1633*f6dc9357SAndroid Build Coastguard Worker                 NExtract::NOperationResult::kUnavailable))
1634*f6dc9357SAndroid Build Coastguard Worker         }
1635*f6dc9357SAndroid Build Coastguard Worker         continue;
1636*f6dc9357SAndroid Build Coastguard Worker       }
1637*f6dc9357SAndroid Build Coastguard Worker       RINOK(hres)
1638*f6dc9357SAndroid Build Coastguard Worker     }
1639*f6dc9357SAndroid Build Coastguard Worker 
1640*f6dc9357SAndroid Build Coastguard Worker     if (item.IsDir())
1641*f6dc9357SAndroid Build Coastguard Worker     {
1642*f6dc9357SAndroid Build Coastguard Worker       // if (!testMode)
1643*f6dc9357SAndroid Build Coastguard Worker       {
1644*f6dc9357SAndroid Build Coastguard Worker         RINOK(extractCallback->PrepareOperation(askMode))
1645*f6dc9357SAndroid Build Coastguard Worker         realOutStream.Release();
1646*f6dc9357SAndroid Build Coastguard Worker         RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
1647*f6dc9357SAndroid Build Coastguard Worker       }
1648*f6dc9357SAndroid Build Coastguard Worker       continue;
1649*f6dc9357SAndroid Build Coastguard Worker     }
1650*f6dc9357SAndroid Build Coastguard Worker 
1651*f6dc9357SAndroid Build Coastguard Worker     if (!testMode && !realOutStream)
1652*f6dc9357SAndroid Build Coastguard Worker       continue;
1653*f6dc9357SAndroid Build Coastguard Worker 
1654*f6dc9357SAndroid Build Coastguard Worker     RINOK(extractCallback->PrepareOperation(askMode))
1655*f6dc9357SAndroid Build Coastguard Worker 
1656*f6dc9357SAndroid Build Coastguard Worker     const HRESULT hres = myDecoder.Decode(
1657*f6dc9357SAndroid Build Coastguard Worker         EXTERNAL_CODECS_VARS
1658*f6dc9357SAndroid Build Coastguard Worker         m_Archive, item, realOutStream, extractCallback,
1659*f6dc9357SAndroid Build Coastguard Worker         lps,
1660*f6dc9357SAndroid Build Coastguard Worker         #ifndef Z7_ST
1661*f6dc9357SAndroid Build Coastguard Worker         _props._numThreads, _props._memUsage_Decompress,
1662*f6dc9357SAndroid Build Coastguard Worker         #endif
1663*f6dc9357SAndroid Build Coastguard Worker         opRes);
1664*f6dc9357SAndroid Build Coastguard Worker 
1665*f6dc9357SAndroid Build Coastguard Worker     RINOK(hres)
1666*f6dc9357SAndroid Build Coastguard Worker     // realOutStream.Release();
1667*f6dc9357SAndroid Build Coastguard Worker 
1668*f6dc9357SAndroid Build Coastguard Worker     if (opRes == NExtract::NOperationResult::kOK && headersError)
1669*f6dc9357SAndroid Build Coastguard Worker       opRes = NExtract::NOperationResult::kHeadersError;
1670*f6dc9357SAndroid Build Coastguard Worker     }
1671*f6dc9357SAndroid Build Coastguard Worker     RINOK(extractCallback->SetOperationResult(opRes))
1672*f6dc9357SAndroid Build Coastguard Worker   }
1673*f6dc9357SAndroid Build Coastguard Worker 
1674*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
1675*f6dc9357SAndroid Build Coastguard Worker }
1676*f6dc9357SAndroid Build Coastguard Worker 
1677*f6dc9357SAndroid Build Coastguard Worker IMPL_ISetCompressCodecsInfo
1678*f6dc9357SAndroid Build Coastguard Worker 
1679*f6dc9357SAndroid Build Coastguard Worker }}
1680