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