1*f6dc9357SAndroid Build Coastguard Worker // Rar5Handler.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/7zCrc.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
7*f6dc9357SAndroid Build Coastguard Worker
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/ComTry.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/IntToString.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/MyBuffer2.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/UTFConvert.h"
12*f6dc9357SAndroid Build Coastguard Worker
13*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariantUtils.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/TimeUtils.h"
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker #include "../../IPassword.h"
17*f6dc9357SAndroid Build Coastguard Worker
18*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/FilterCoder.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/LimitedStreams.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MethodProps.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ProgressUtils.h"
22*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/RegisterArc.h"
23*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamObjects.h"
24*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
25*f6dc9357SAndroid Build Coastguard Worker
26*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/RegisterCodec.h"
27*f6dc9357SAndroid Build Coastguard Worker
28*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/CopyCoder.h"
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker #include "../../Crypto/Rar5Aes.h"
31*f6dc9357SAndroid Build Coastguard Worker
32*f6dc9357SAndroid Build Coastguard Worker #include "../../Archive/Common/FindSignature.h"
33*f6dc9357SAndroid Build Coastguard Worker #include "../../Archive/Common/ItemNameUtils.h"
34*f6dc9357SAndroid Build Coastguard Worker #include "../../Archive/Common/HandlerOut.h"
35*f6dc9357SAndroid Build Coastguard Worker
36*f6dc9357SAndroid Build Coastguard Worker #include "../../Archive/HandlerCont.h"
37*f6dc9357SAndroid Build Coastguard Worker
38*f6dc9357SAndroid Build Coastguard Worker #include "../../Archive/Rar/RarVol.h"
39*f6dc9357SAndroid Build Coastguard Worker #include "Rar5Handler.h"
40*f6dc9357SAndroid Build Coastguard Worker
41*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
42*f6dc9357SAndroid Build Coastguard Worker
43*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
44*f6dc9357SAndroid Build Coastguard Worker
45*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
46*f6dc9357SAndroid Build Coastguard Worker namespace NRar5 {
47*f6dc9357SAndroid Build Coastguard Worker
48*f6dc9357SAndroid Build Coastguard Worker static const unsigned kMarkerSize = 8;
49*f6dc9357SAndroid Build Coastguard Worker
50*f6dc9357SAndroid Build Coastguard Worker static const Byte kMarker[kMarkerSize] =
51*f6dc9357SAndroid Build Coastguard Worker { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0 };
52*f6dc9357SAndroid Build Coastguard Worker
53*f6dc9357SAndroid Build Coastguard Worker // Comment length is limited to 256 KB in rar-encoder.
54*f6dc9357SAndroid Build Coastguard Worker // So we use same limitation
55*f6dc9357SAndroid Build Coastguard Worker static const size_t kCommentSize_Max = (size_t)1 << 18;
56*f6dc9357SAndroid Build Coastguard Worker
57*f6dc9357SAndroid Build Coastguard Worker
58*f6dc9357SAndroid Build Coastguard Worker static const char * const kHostOS[] =
59*f6dc9357SAndroid Build Coastguard Worker {
60*f6dc9357SAndroid Build Coastguard Worker "Windows"
61*f6dc9357SAndroid Build Coastguard Worker , "Unix"
62*f6dc9357SAndroid Build Coastguard Worker };
63*f6dc9357SAndroid Build Coastguard Worker
64*f6dc9357SAndroid Build Coastguard Worker
65*f6dc9357SAndroid Build Coastguard Worker static const char * const k_ArcFlags[] =
66*f6dc9357SAndroid Build Coastguard Worker {
67*f6dc9357SAndroid Build Coastguard Worker "Volume"
68*f6dc9357SAndroid Build Coastguard Worker , "VolumeField"
69*f6dc9357SAndroid Build Coastguard Worker , "Solid"
70*f6dc9357SAndroid Build Coastguard Worker , "Recovery"
71*f6dc9357SAndroid Build Coastguard Worker , "Lock" // 4
72*f6dc9357SAndroid Build Coastguard Worker };
73*f6dc9357SAndroid Build Coastguard Worker
74*f6dc9357SAndroid Build Coastguard Worker
75*f6dc9357SAndroid Build Coastguard Worker static const char * const k_FileFlags[] =
76*f6dc9357SAndroid Build Coastguard Worker {
77*f6dc9357SAndroid Build Coastguard Worker "Dir"
78*f6dc9357SAndroid Build Coastguard Worker , "UnixTime"
79*f6dc9357SAndroid Build Coastguard Worker , "CRC"
80*f6dc9357SAndroid Build Coastguard Worker , "UnknownSize"
81*f6dc9357SAndroid Build Coastguard Worker };
82*f6dc9357SAndroid Build Coastguard Worker
83*f6dc9357SAndroid Build Coastguard Worker
84*f6dc9357SAndroid Build Coastguard Worker static const char * const g_ExtraTypes[] =
85*f6dc9357SAndroid Build Coastguard Worker {
86*f6dc9357SAndroid Build Coastguard Worker "0"
87*f6dc9357SAndroid Build Coastguard Worker , "Crypto"
88*f6dc9357SAndroid Build Coastguard Worker , "Hash"
89*f6dc9357SAndroid Build Coastguard Worker , "Time"
90*f6dc9357SAndroid Build Coastguard Worker , "Version"
91*f6dc9357SAndroid Build Coastguard Worker , "Link"
92*f6dc9357SAndroid Build Coastguard Worker , "UnixOwner"
93*f6dc9357SAndroid Build Coastguard Worker , "Subdata"
94*f6dc9357SAndroid Build Coastguard Worker };
95*f6dc9357SAndroid Build Coastguard Worker
96*f6dc9357SAndroid Build Coastguard Worker
97*f6dc9357SAndroid Build Coastguard Worker static const char * const g_LinkTypes[] =
98*f6dc9357SAndroid Build Coastguard Worker {
99*f6dc9357SAndroid Build Coastguard Worker "0"
100*f6dc9357SAndroid Build Coastguard Worker , "UnixSymLink"
101*f6dc9357SAndroid Build Coastguard Worker , "WinSymLink"
102*f6dc9357SAndroid Build Coastguard Worker , "WinJunction"
103*f6dc9357SAndroid Build Coastguard Worker , "HardLink"
104*f6dc9357SAndroid Build Coastguard Worker , "FileCopy"
105*f6dc9357SAndroid Build Coastguard Worker };
106*f6dc9357SAndroid Build Coastguard Worker
107*f6dc9357SAndroid Build Coastguard Worker
108*f6dc9357SAndroid Build Coastguard Worker static const char g_ExtraTimeFlags[] = { 'u', 'M', 'C', 'A', 'n' };
109*f6dc9357SAndroid Build Coastguard Worker
110*f6dc9357SAndroid Build Coastguard Worker
111*f6dc9357SAndroid Build Coastguard Worker static
112*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
ReadVarInt(const Byte * p,size_t maxSize,UInt64 * val_ptr)113*f6dc9357SAndroid Build Coastguard Worker unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val_ptr)
114*f6dc9357SAndroid Build Coastguard Worker {
115*f6dc9357SAndroid Build Coastguard Worker if (maxSize > 10)
116*f6dc9357SAndroid Build Coastguard Worker maxSize = 10;
117*f6dc9357SAndroid Build Coastguard Worker UInt64 val = 0;
118*f6dc9357SAndroid Build Coastguard Worker unsigned i;
119*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < maxSize;)
120*f6dc9357SAndroid Build Coastguard Worker {
121*f6dc9357SAndroid Build Coastguard Worker const unsigned b = p[i];
122*f6dc9357SAndroid Build Coastguard Worker val |= (UInt64)(b & 0x7F) << (7 * i);
123*f6dc9357SAndroid Build Coastguard Worker i++;
124*f6dc9357SAndroid Build Coastguard Worker if ((b & 0x80) == 0)
125*f6dc9357SAndroid Build Coastguard Worker {
126*f6dc9357SAndroid Build Coastguard Worker *val_ptr = val;
127*f6dc9357SAndroid Build Coastguard Worker return i;
128*f6dc9357SAndroid Build Coastguard Worker }
129*f6dc9357SAndroid Build Coastguard Worker }
130*f6dc9357SAndroid Build Coastguard Worker *val_ptr = 0;
131*f6dc9357SAndroid Build Coastguard Worker #if 1
132*f6dc9357SAndroid Build Coastguard Worker return 0; // 7zip-unrar : strict check of error
133*f6dc9357SAndroid Build Coastguard Worker #else
134*f6dc9357SAndroid Build Coastguard Worker return i; // original-unrar : ignore error
135*f6dc9357SAndroid Build Coastguard Worker #endif
136*f6dc9357SAndroid Build Coastguard Worker }
137*f6dc9357SAndroid Build Coastguard Worker
138*f6dc9357SAndroid Build Coastguard Worker
139*f6dc9357SAndroid Build Coastguard Worker #define PARSE_VAR_INT(p, size, dest) \
140*f6dc9357SAndroid Build Coastguard Worker { const unsigned num_ = ReadVarInt(p, size, &dest); \
141*f6dc9357SAndroid Build Coastguard Worker if (num_ == 0) return false; \
142*f6dc9357SAndroid Build Coastguard Worker p += num_; \
143*f6dc9357SAndroid Build Coastguard Worker size -= num_; \
144*f6dc9357SAndroid Build Coastguard Worker }
145*f6dc9357SAndroid Build Coastguard Worker
146*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p,unsigned size)147*f6dc9357SAndroid Build Coastguard Worker bool CLinkInfo::Parse(const Byte *p, unsigned size)
148*f6dc9357SAndroid Build Coastguard Worker {
149*f6dc9357SAndroid Build Coastguard Worker const Byte *pStart = p;
150*f6dc9357SAndroid Build Coastguard Worker UInt64 len;
151*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, Type)
152*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, Flags)
153*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, len)
154*f6dc9357SAndroid Build Coastguard Worker if (size != len)
155*f6dc9357SAndroid Build Coastguard Worker return false;
156*f6dc9357SAndroid Build Coastguard Worker NameLen = (unsigned)len;
157*f6dc9357SAndroid Build Coastguard Worker NameOffset = (unsigned)(size_t)(p - pStart);
158*f6dc9357SAndroid Build Coastguard Worker return true;
159*f6dc9357SAndroid Build Coastguard Worker }
160*f6dc9357SAndroid Build Coastguard Worker
161*f6dc9357SAndroid Build Coastguard Worker
AddHex64(AString & s,UInt64 v)162*f6dc9357SAndroid Build Coastguard Worker static void AddHex64(AString &s, UInt64 v)
163*f6dc9357SAndroid Build Coastguard Worker {
164*f6dc9357SAndroid Build Coastguard Worker char sz[32];
165*f6dc9357SAndroid Build Coastguard Worker sz[0] = '0';
166*f6dc9357SAndroid Build Coastguard Worker sz[1] = 'x';
167*f6dc9357SAndroid Build Coastguard Worker ConvertUInt64ToHex(v, sz + 2);
168*f6dc9357SAndroid Build Coastguard Worker s += sz;
169*f6dc9357SAndroid Build Coastguard Worker }
170*f6dc9357SAndroid Build Coastguard Worker
171*f6dc9357SAndroid Build Coastguard Worker
PrintType(AString & s,const char * const table[],unsigned num,UInt64 val)172*f6dc9357SAndroid Build Coastguard Worker static void PrintType(AString &s, const char * const table[], unsigned num, UInt64 val)
173*f6dc9357SAndroid Build Coastguard Worker {
174*f6dc9357SAndroid Build Coastguard Worker char sz[32];
175*f6dc9357SAndroid Build Coastguard Worker const char *p = NULL;
176*f6dc9357SAndroid Build Coastguard Worker if (val < num)
177*f6dc9357SAndroid Build Coastguard Worker p = table[(unsigned)val];
178*f6dc9357SAndroid Build Coastguard Worker if (!p)
179*f6dc9357SAndroid Build Coastguard Worker {
180*f6dc9357SAndroid Build Coastguard Worker ConvertUInt64ToString(val, sz);
181*f6dc9357SAndroid Build Coastguard Worker p = sz;
182*f6dc9357SAndroid Build Coastguard Worker }
183*f6dc9357SAndroid Build Coastguard Worker s += p;
184*f6dc9357SAndroid Build Coastguard Worker }
185*f6dc9357SAndroid Build Coastguard Worker
186*f6dc9357SAndroid Build Coastguard Worker
FindExtra(unsigned extraID,unsigned & recordDataSize) const187*f6dc9357SAndroid Build Coastguard Worker int CItem::FindExtra(unsigned extraID, unsigned &recordDataSize) const
188*f6dc9357SAndroid Build Coastguard Worker {
189*f6dc9357SAndroid Build Coastguard Worker recordDataSize = 0;
190*f6dc9357SAndroid Build Coastguard Worker size_t offset = 0;
191*f6dc9357SAndroid Build Coastguard Worker
192*f6dc9357SAndroid Build Coastguard Worker for (;;)
193*f6dc9357SAndroid Build Coastguard Worker {
194*f6dc9357SAndroid Build Coastguard Worker size_t rem = Extra.Size() - offset;
195*f6dc9357SAndroid Build Coastguard Worker if (rem == 0)
196*f6dc9357SAndroid Build Coastguard Worker return -1;
197*f6dc9357SAndroid Build Coastguard Worker
198*f6dc9357SAndroid Build Coastguard Worker {
199*f6dc9357SAndroid Build Coastguard Worker UInt64 size;
200*f6dc9357SAndroid Build Coastguard Worker const unsigned num = ReadVarInt(Extra + offset, rem, &size);
201*f6dc9357SAndroid Build Coastguard Worker if (num == 0)
202*f6dc9357SAndroid Build Coastguard Worker return -1;
203*f6dc9357SAndroid Build Coastguard Worker offset += num;
204*f6dc9357SAndroid Build Coastguard Worker rem -= num;
205*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
206*f6dc9357SAndroid Build Coastguard Worker return -1;
207*f6dc9357SAndroid Build Coastguard Worker rem = (size_t)size;
208*f6dc9357SAndroid Build Coastguard Worker }
209*f6dc9357SAndroid Build Coastguard Worker {
210*f6dc9357SAndroid Build Coastguard Worker UInt64 id;
211*f6dc9357SAndroid Build Coastguard Worker const unsigned num = ReadVarInt(Extra + offset, rem, &id);
212*f6dc9357SAndroid Build Coastguard Worker if (num == 0)
213*f6dc9357SAndroid Build Coastguard Worker return -1;
214*f6dc9357SAndroid Build Coastguard Worker offset += num;
215*f6dc9357SAndroid Build Coastguard Worker rem -= num;
216*f6dc9357SAndroid Build Coastguard Worker
217*f6dc9357SAndroid Build Coastguard Worker // There was BUG in RAR 5.21- : it stored (size-1) instead of (size)
218*f6dc9357SAndroid Build Coastguard Worker // for Subdata record in Service header.
219*f6dc9357SAndroid Build Coastguard Worker // That record always was last in bad archives, so we can fix that case.
220*f6dc9357SAndroid Build Coastguard Worker if (id == NExtraID::kSubdata
221*f6dc9357SAndroid Build Coastguard Worker && RecordType == NHeaderType::kService
222*f6dc9357SAndroid Build Coastguard Worker && rem + 1 == Extra.Size() - offset)
223*f6dc9357SAndroid Build Coastguard Worker rem++;
224*f6dc9357SAndroid Build Coastguard Worker
225*f6dc9357SAndroid Build Coastguard Worker if (id == extraID)
226*f6dc9357SAndroid Build Coastguard Worker {
227*f6dc9357SAndroid Build Coastguard Worker recordDataSize = (unsigned)rem;
228*f6dc9357SAndroid Build Coastguard Worker return (int)offset;
229*f6dc9357SAndroid Build Coastguard Worker }
230*f6dc9357SAndroid Build Coastguard Worker
231*f6dc9357SAndroid Build Coastguard Worker offset += rem;
232*f6dc9357SAndroid Build Coastguard Worker }
233*f6dc9357SAndroid Build Coastguard Worker }
234*f6dc9357SAndroid Build Coastguard Worker }
235*f6dc9357SAndroid Build Coastguard Worker
236*f6dc9357SAndroid Build Coastguard Worker
PrintInfo(AString & s) const237*f6dc9357SAndroid Build Coastguard Worker void CItem::PrintInfo(AString &s) const
238*f6dc9357SAndroid Build Coastguard Worker {
239*f6dc9357SAndroid Build Coastguard Worker size_t offset = 0;
240*f6dc9357SAndroid Build Coastguard Worker
241*f6dc9357SAndroid Build Coastguard Worker for (;;)
242*f6dc9357SAndroid Build Coastguard Worker {
243*f6dc9357SAndroid Build Coastguard Worker size_t rem = Extra.Size() - offset;
244*f6dc9357SAndroid Build Coastguard Worker if (rem == 0)
245*f6dc9357SAndroid Build Coastguard Worker return;
246*f6dc9357SAndroid Build Coastguard Worker
247*f6dc9357SAndroid Build Coastguard Worker {
248*f6dc9357SAndroid Build Coastguard Worker UInt64 size;
249*f6dc9357SAndroid Build Coastguard Worker unsigned num = ReadVarInt(Extra + offset, rem, &size);
250*f6dc9357SAndroid Build Coastguard Worker if (num == 0)
251*f6dc9357SAndroid Build Coastguard Worker return;
252*f6dc9357SAndroid Build Coastguard Worker offset += num;
253*f6dc9357SAndroid Build Coastguard Worker rem -= num;
254*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
255*f6dc9357SAndroid Build Coastguard Worker break;
256*f6dc9357SAndroid Build Coastguard Worker rem = (size_t)size;
257*f6dc9357SAndroid Build Coastguard Worker }
258*f6dc9357SAndroid Build Coastguard Worker {
259*f6dc9357SAndroid Build Coastguard Worker UInt64 id;
260*f6dc9357SAndroid Build Coastguard Worker {
261*f6dc9357SAndroid Build Coastguard Worker unsigned num = ReadVarInt(Extra + offset, rem, &id);
262*f6dc9357SAndroid Build Coastguard Worker if (num == 0)
263*f6dc9357SAndroid Build Coastguard Worker break;
264*f6dc9357SAndroid Build Coastguard Worker offset += num;
265*f6dc9357SAndroid Build Coastguard Worker rem -= num;
266*f6dc9357SAndroid Build Coastguard Worker }
267*f6dc9357SAndroid Build Coastguard Worker
268*f6dc9357SAndroid Build Coastguard Worker // There was BUG in RAR 5.21- : it stored (size-1) instead of (size)
269*f6dc9357SAndroid Build Coastguard Worker // for Subdata record in Service header.
270*f6dc9357SAndroid Build Coastguard Worker // That record always was last in bad archives, so we can fix that case.
271*f6dc9357SAndroid Build Coastguard Worker if (id == NExtraID::kSubdata
272*f6dc9357SAndroid Build Coastguard Worker && RecordType == NHeaderType::kService
273*f6dc9357SAndroid Build Coastguard Worker && rem + 1 == Extra.Size() - offset)
274*f6dc9357SAndroid Build Coastguard Worker rem++;
275*f6dc9357SAndroid Build Coastguard Worker
276*f6dc9357SAndroid Build Coastguard Worker s.Add_Space_if_NotEmpty();
277*f6dc9357SAndroid Build Coastguard Worker PrintType(s, g_ExtraTypes, Z7_ARRAY_SIZE(g_ExtraTypes), id);
278*f6dc9357SAndroid Build Coastguard Worker
279*f6dc9357SAndroid Build Coastguard Worker if (id == NExtraID::kTime)
280*f6dc9357SAndroid Build Coastguard Worker {
281*f6dc9357SAndroid Build Coastguard Worker const Byte *p = Extra + offset;
282*f6dc9357SAndroid Build Coastguard Worker UInt64 flags;
283*f6dc9357SAndroid Build Coastguard Worker const unsigned num = ReadVarInt(p, rem, &flags);
284*f6dc9357SAndroid Build Coastguard Worker if (num != 0)
285*f6dc9357SAndroid Build Coastguard Worker {
286*f6dc9357SAndroid Build Coastguard Worker s.Add_Colon();
287*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExtraTimeFlags); i++)
288*f6dc9357SAndroid Build Coastguard Worker if ((flags & ((UInt64)1 << i)) != 0)
289*f6dc9357SAndroid Build Coastguard Worker s.Add_Char(g_ExtraTimeFlags[i]);
290*f6dc9357SAndroid Build Coastguard Worker flags &= ~(((UInt64)1 << Z7_ARRAY_SIZE(g_ExtraTimeFlags)) - 1);
291*f6dc9357SAndroid Build Coastguard Worker if (flags != 0)
292*f6dc9357SAndroid Build Coastguard Worker {
293*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('_');
294*f6dc9357SAndroid Build Coastguard Worker AddHex64(s, flags);
295*f6dc9357SAndroid Build Coastguard Worker }
296*f6dc9357SAndroid Build Coastguard Worker }
297*f6dc9357SAndroid Build Coastguard Worker }
298*f6dc9357SAndroid Build Coastguard Worker else if (id == NExtraID::kLink)
299*f6dc9357SAndroid Build Coastguard Worker {
300*f6dc9357SAndroid Build Coastguard Worker CLinkInfo linkInfo;
301*f6dc9357SAndroid Build Coastguard Worker if (linkInfo.Parse(Extra + offset, (unsigned)rem))
302*f6dc9357SAndroid Build Coastguard Worker {
303*f6dc9357SAndroid Build Coastguard Worker s.Add_Colon();
304*f6dc9357SAndroid Build Coastguard Worker PrintType(s, g_LinkTypes, Z7_ARRAY_SIZE(g_LinkTypes), linkInfo.Type);
305*f6dc9357SAndroid Build Coastguard Worker UInt64 flags = linkInfo.Flags;
306*f6dc9357SAndroid Build Coastguard Worker if (flags != 0)
307*f6dc9357SAndroid Build Coastguard Worker {
308*f6dc9357SAndroid Build Coastguard Worker s.Add_Colon();
309*f6dc9357SAndroid Build Coastguard Worker if (flags & NLinkFlags::kTargetIsDir)
310*f6dc9357SAndroid Build Coastguard Worker {
311*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('D');
312*f6dc9357SAndroid Build Coastguard Worker flags &= ~((UInt64)NLinkFlags::kTargetIsDir);
313*f6dc9357SAndroid Build Coastguard Worker }
314*f6dc9357SAndroid Build Coastguard Worker if (flags != 0)
315*f6dc9357SAndroid Build Coastguard Worker {
316*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('_');
317*f6dc9357SAndroid Build Coastguard Worker AddHex64(s, flags);
318*f6dc9357SAndroid Build Coastguard Worker }
319*f6dc9357SAndroid Build Coastguard Worker }
320*f6dc9357SAndroid Build Coastguard Worker }
321*f6dc9357SAndroid Build Coastguard Worker }
322*f6dc9357SAndroid Build Coastguard Worker
323*f6dc9357SAndroid Build Coastguard Worker offset += rem;
324*f6dc9357SAndroid Build Coastguard Worker }
325*f6dc9357SAndroid Build Coastguard Worker }
326*f6dc9357SAndroid Build Coastguard Worker
327*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("ERROR");
328*f6dc9357SAndroid Build Coastguard Worker }
329*f6dc9357SAndroid Build Coastguard Worker
330*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p,size_t size)331*f6dc9357SAndroid Build Coastguard Worker bool CCryptoInfo::Parse(const Byte *p, size_t size)
332*f6dc9357SAndroid Build Coastguard Worker {
333*f6dc9357SAndroid Build Coastguard Worker Algo = 0;
334*f6dc9357SAndroid Build Coastguard Worker Flags = 0;
335*f6dc9357SAndroid Build Coastguard Worker Cnt = 0;
336*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, Algo)
337*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, Flags)
338*f6dc9357SAndroid Build Coastguard Worker if (size > 0)
339*f6dc9357SAndroid Build Coastguard Worker Cnt = p[0];
340*f6dc9357SAndroid Build Coastguard Worker if (size != 1 + 16 + 16 + (unsigned)(IsThereCheck() ? 12 : 0))
341*f6dc9357SAndroid Build Coastguard Worker return false;
342*f6dc9357SAndroid Build Coastguard Worker return true;
343*f6dc9357SAndroid Build Coastguard Worker }
344*f6dc9357SAndroid Build Coastguard Worker
345*f6dc9357SAndroid Build Coastguard Worker
FindExtra_Version(UInt64 & version) const346*f6dc9357SAndroid Build Coastguard Worker bool CItem::FindExtra_Version(UInt64 &version) const
347*f6dc9357SAndroid Build Coastguard Worker {
348*f6dc9357SAndroid Build Coastguard Worker unsigned size;
349*f6dc9357SAndroid Build Coastguard Worker const int offset = FindExtra(NExtraID::kVersion, size);
350*f6dc9357SAndroid Build Coastguard Worker if (offset < 0)
351*f6dc9357SAndroid Build Coastguard Worker return false;
352*f6dc9357SAndroid Build Coastguard Worker const Byte *p = Extra + (unsigned)offset;
353*f6dc9357SAndroid Build Coastguard Worker
354*f6dc9357SAndroid Build Coastguard Worker UInt64 flags;
355*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, flags)
356*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, version)
357*f6dc9357SAndroid Build Coastguard Worker return size == 0;
358*f6dc9357SAndroid Build Coastguard Worker }
359*f6dc9357SAndroid Build Coastguard Worker
FindExtra_Link(CLinkInfo & link) const360*f6dc9357SAndroid Build Coastguard Worker bool CItem::FindExtra_Link(CLinkInfo &link) const
361*f6dc9357SAndroid Build Coastguard Worker {
362*f6dc9357SAndroid Build Coastguard Worker unsigned size;
363*f6dc9357SAndroid Build Coastguard Worker const int offset = FindExtra(NExtraID::kLink, size);
364*f6dc9357SAndroid Build Coastguard Worker if (offset < 0)
365*f6dc9357SAndroid Build Coastguard Worker return false;
366*f6dc9357SAndroid Build Coastguard Worker if (!link.Parse(Extra + (unsigned)offset, size))
367*f6dc9357SAndroid Build Coastguard Worker return false;
368*f6dc9357SAndroid Build Coastguard Worker link.NameOffset += (unsigned)offset;
369*f6dc9357SAndroid Build Coastguard Worker return true;
370*f6dc9357SAndroid Build Coastguard Worker }
371*f6dc9357SAndroid Build Coastguard Worker
Is_CopyLink() const372*f6dc9357SAndroid Build Coastguard Worker bool CItem::Is_CopyLink() const
373*f6dc9357SAndroid Build Coastguard Worker {
374*f6dc9357SAndroid Build Coastguard Worker CLinkInfo link;
375*f6dc9357SAndroid Build Coastguard Worker return FindExtra_Link(link) && link.Type == NLinkType::kFileCopy;
376*f6dc9357SAndroid Build Coastguard Worker }
377*f6dc9357SAndroid Build Coastguard Worker
Is_HardLink() const378*f6dc9357SAndroid Build Coastguard Worker bool CItem::Is_HardLink() const
379*f6dc9357SAndroid Build Coastguard Worker {
380*f6dc9357SAndroid Build Coastguard Worker CLinkInfo link;
381*f6dc9357SAndroid Build Coastguard Worker return FindExtra_Link(link) && link.Type == NLinkType::kHardLink;
382*f6dc9357SAndroid Build Coastguard Worker }
383*f6dc9357SAndroid Build Coastguard Worker
Is_CopyLink_or_HardLink() const384*f6dc9357SAndroid Build Coastguard Worker bool CItem::Is_CopyLink_or_HardLink() const
385*f6dc9357SAndroid Build Coastguard Worker {
386*f6dc9357SAndroid Build Coastguard Worker CLinkInfo link;
387*f6dc9357SAndroid Build Coastguard Worker return FindExtra_Link(link) && (link.Type == NLinkType::kFileCopy || link.Type == NLinkType::kHardLink);
388*f6dc9357SAndroid Build Coastguard Worker }
389*f6dc9357SAndroid Build Coastguard Worker
Link_to_Prop(unsigned linkType,NWindows::NCOM::CPropVariant & prop) const390*f6dc9357SAndroid Build Coastguard Worker void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const
391*f6dc9357SAndroid Build Coastguard Worker {
392*f6dc9357SAndroid Build Coastguard Worker CLinkInfo link;
393*f6dc9357SAndroid Build Coastguard Worker if (!FindExtra_Link(link))
394*f6dc9357SAndroid Build Coastguard Worker return;
395*f6dc9357SAndroid Build Coastguard Worker
396*f6dc9357SAndroid Build Coastguard Worker if (link.Type != linkType)
397*f6dc9357SAndroid Build Coastguard Worker {
398*f6dc9357SAndroid Build Coastguard Worker if (linkType != NLinkType::kUnixSymLink)
399*f6dc9357SAndroid Build Coastguard Worker return;
400*f6dc9357SAndroid Build Coastguard Worker switch ((unsigned)link.Type)
401*f6dc9357SAndroid Build Coastguard Worker {
402*f6dc9357SAndroid Build Coastguard Worker case NLinkType::kUnixSymLink:
403*f6dc9357SAndroid Build Coastguard Worker case NLinkType::kWinSymLink:
404*f6dc9357SAndroid Build Coastguard Worker case NLinkType::kWinJunction:
405*f6dc9357SAndroid Build Coastguard Worker break;
406*f6dc9357SAndroid Build Coastguard Worker default: return;
407*f6dc9357SAndroid Build Coastguard Worker }
408*f6dc9357SAndroid Build Coastguard Worker }
409*f6dc9357SAndroid Build Coastguard Worker
410*f6dc9357SAndroid Build Coastguard Worker AString s;
411*f6dc9357SAndroid Build Coastguard Worker s.SetFrom_CalcLen((const char *)(Extra + link.NameOffset), link.NameLen);
412*f6dc9357SAndroid Build Coastguard Worker
413*f6dc9357SAndroid Build Coastguard Worker UString unicode;
414*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(s, unicode);
415*f6dc9357SAndroid Build Coastguard Worker prop = NItemName::GetOsPath(unicode);
416*f6dc9357SAndroid Build Coastguard Worker }
417*f6dc9357SAndroid Build Coastguard Worker
GetAltStreamName(AString & name) const418*f6dc9357SAndroid Build Coastguard Worker bool CItem::GetAltStreamName(AString &name) const
419*f6dc9357SAndroid Build Coastguard Worker {
420*f6dc9357SAndroid Build Coastguard Worker name.Empty();
421*f6dc9357SAndroid Build Coastguard Worker unsigned size;
422*f6dc9357SAndroid Build Coastguard Worker const int offset = FindExtra(NExtraID::kSubdata, size);
423*f6dc9357SAndroid Build Coastguard Worker if (offset < 0)
424*f6dc9357SAndroid Build Coastguard Worker return false;
425*f6dc9357SAndroid Build Coastguard Worker name.SetFrom_CalcLen((const char *)(Extra + (unsigned)offset), size);
426*f6dc9357SAndroid Build Coastguard Worker return true;
427*f6dc9357SAndroid Build Coastguard Worker }
428*f6dc9357SAndroid Build Coastguard Worker
429*f6dc9357SAndroid Build Coastguard Worker
430*f6dc9357SAndroid Build Coastguard Worker class CHash
431*f6dc9357SAndroid Build Coastguard Worker {
432*f6dc9357SAndroid Build Coastguard Worker bool _calcCRC;
433*f6dc9357SAndroid Build Coastguard Worker UInt32 _crc;
434*f6dc9357SAndroid Build Coastguard Worker int _blakeOffset;
435*f6dc9357SAndroid Build Coastguard Worker CAlignedBuffer1 _buf;
436*f6dc9357SAndroid Build Coastguard Worker // CBlake2sp _blake;
BlakeObj()437*f6dc9357SAndroid Build Coastguard Worker CBlake2sp *BlakeObj() { return (CBlake2sp *)(void *)(Byte *)_buf; }
438*f6dc9357SAndroid Build Coastguard Worker public:
CHash()439*f6dc9357SAndroid Build Coastguard Worker CHash():
440*f6dc9357SAndroid Build Coastguard Worker _buf(sizeof(CBlake2sp))
441*f6dc9357SAndroid Build Coastguard Worker {}
442*f6dc9357SAndroid Build Coastguard Worker
Init_NoCalc()443*f6dc9357SAndroid Build Coastguard Worker void Init_NoCalc()
444*f6dc9357SAndroid Build Coastguard Worker {
445*f6dc9357SAndroid Build Coastguard Worker _calcCRC = false;
446*f6dc9357SAndroid Build Coastguard Worker _crc = CRC_INIT_VAL;
447*f6dc9357SAndroid Build Coastguard Worker _blakeOffset = -1;
448*f6dc9357SAndroid Build Coastguard Worker }
449*f6dc9357SAndroid Build Coastguard Worker
450*f6dc9357SAndroid Build Coastguard Worker void Init(const CItem &item);
451*f6dc9357SAndroid Build Coastguard Worker void Update(const void *data, size_t size);
GetCRC() const452*f6dc9357SAndroid Build Coastguard Worker UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
453*f6dc9357SAndroid Build Coastguard Worker
454*f6dc9357SAndroid Build Coastguard Worker bool Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoder);
455*f6dc9357SAndroid Build Coastguard Worker };
456*f6dc9357SAndroid Build Coastguard Worker
Init(const CItem & item)457*f6dc9357SAndroid Build Coastguard Worker void CHash::Init(const CItem &item)
458*f6dc9357SAndroid Build Coastguard Worker {
459*f6dc9357SAndroid Build Coastguard Worker _crc = CRC_INIT_VAL;
460*f6dc9357SAndroid Build Coastguard Worker _calcCRC = item.Has_CRC();
461*f6dc9357SAndroid Build Coastguard Worker _blakeOffset = item.FindExtra_Blake();
462*f6dc9357SAndroid Build Coastguard Worker if (_blakeOffset >= 0)
463*f6dc9357SAndroid Build Coastguard Worker Blake2sp_Init(BlakeObj());
464*f6dc9357SAndroid Build Coastguard Worker }
465*f6dc9357SAndroid Build Coastguard Worker
Update(const void * data,size_t size)466*f6dc9357SAndroid Build Coastguard Worker void CHash::Update(const void *data, size_t size)
467*f6dc9357SAndroid Build Coastguard Worker {
468*f6dc9357SAndroid Build Coastguard Worker if (_calcCRC)
469*f6dc9357SAndroid Build Coastguard Worker _crc = CrcUpdate(_crc, data, size);
470*f6dc9357SAndroid Build Coastguard Worker if (_blakeOffset >= 0)
471*f6dc9357SAndroid Build Coastguard Worker Blake2sp_Update(BlakeObj(), (const Byte *)data, size);
472*f6dc9357SAndroid Build Coastguard Worker }
473*f6dc9357SAndroid Build Coastguard Worker
Check(const CItem & item,NCrypto::NRar5::CDecoder * cryptoDecoder)474*f6dc9357SAndroid Build Coastguard Worker bool CHash::Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoder)
475*f6dc9357SAndroid Build Coastguard Worker {
476*f6dc9357SAndroid Build Coastguard Worker if (_calcCRC)
477*f6dc9357SAndroid Build Coastguard Worker {
478*f6dc9357SAndroid Build Coastguard Worker UInt32 crc = GetCRC();
479*f6dc9357SAndroid Build Coastguard Worker if (cryptoDecoder)
480*f6dc9357SAndroid Build Coastguard Worker crc = cryptoDecoder->Hmac_Convert_Crc32(crc);
481*f6dc9357SAndroid Build Coastguard Worker if (crc != item.CRC)
482*f6dc9357SAndroid Build Coastguard Worker return false;
483*f6dc9357SAndroid Build Coastguard Worker }
484*f6dc9357SAndroid Build Coastguard Worker if (_blakeOffset >= 0)
485*f6dc9357SAndroid Build Coastguard Worker {
486*f6dc9357SAndroid Build Coastguard Worker UInt32 digest[Z7_BLAKE2S_DIGEST_SIZE / sizeof(UInt32)];
487*f6dc9357SAndroid Build Coastguard Worker Blake2sp_Final(BlakeObj(), (Byte *)(void *)digest);
488*f6dc9357SAndroid Build Coastguard Worker if (cryptoDecoder)
489*f6dc9357SAndroid Build Coastguard Worker cryptoDecoder->Hmac_Convert_32Bytes((Byte *)(void *)digest);
490*f6dc9357SAndroid Build Coastguard Worker if (memcmp(digest, item.Extra + (unsigned)_blakeOffset, Z7_BLAKE2S_DIGEST_SIZE) != 0)
491*f6dc9357SAndroid Build Coastguard Worker return false;
492*f6dc9357SAndroid Build Coastguard Worker }
493*f6dc9357SAndroid Build Coastguard Worker return true;
494*f6dc9357SAndroid Build Coastguard Worker }
495*f6dc9357SAndroid Build Coastguard Worker
496*f6dc9357SAndroid Build Coastguard Worker
497*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_1(
498*f6dc9357SAndroid Build Coastguard Worker COutStreamWithHash
499*f6dc9357SAndroid Build Coastguard Worker , ISequentialOutStream
500*f6dc9357SAndroid Build Coastguard Worker )
501*f6dc9357SAndroid Build Coastguard Worker bool _size_Defined;
502*f6dc9357SAndroid Build Coastguard Worker ISequentialOutStream *_stream;
503*f6dc9357SAndroid Build Coastguard Worker UInt64 _pos;
504*f6dc9357SAndroid Build Coastguard Worker UInt64 _size;
505*f6dc9357SAndroid Build Coastguard Worker Byte *_destBuf;
506*f6dc9357SAndroid Build Coastguard Worker public:
507*f6dc9357SAndroid Build Coastguard Worker CHash _hash;
508*f6dc9357SAndroid Build Coastguard Worker
509*f6dc9357SAndroid Build Coastguard Worker COutStreamWithHash(): _destBuf(NULL) {}
510*f6dc9357SAndroid Build Coastguard Worker
511*f6dc9357SAndroid Build Coastguard Worker void SetStream(ISequentialOutStream *stream) { _stream = stream; }
512*f6dc9357SAndroid Build Coastguard Worker void Init(const CItem &item, Byte *destBuf, bool needChecksumCheck)
513*f6dc9357SAndroid Build Coastguard Worker {
514*f6dc9357SAndroid Build Coastguard Worker _size_Defined = false;
515*f6dc9357SAndroid Build Coastguard Worker _size = 0;
516*f6dc9357SAndroid Build Coastguard Worker _destBuf = NULL;
517*f6dc9357SAndroid Build Coastguard Worker if (!item.Is_UnknownSize())
518*f6dc9357SAndroid Build Coastguard Worker {
519*f6dc9357SAndroid Build Coastguard Worker _size_Defined = true;
520*f6dc9357SAndroid Build Coastguard Worker _size = item.Size;
521*f6dc9357SAndroid Build Coastguard Worker _destBuf = destBuf;
522*f6dc9357SAndroid Build Coastguard Worker }
523*f6dc9357SAndroid Build Coastguard Worker _pos = 0;
524*f6dc9357SAndroid Build Coastguard Worker if (needChecksumCheck)
525*f6dc9357SAndroid Build Coastguard Worker _hash.Init(item);
526*f6dc9357SAndroid Build Coastguard Worker else
527*f6dc9357SAndroid Build Coastguard Worker _hash.Init_NoCalc();
528*f6dc9357SAndroid Build Coastguard Worker }
529*f6dc9357SAndroid Build Coastguard Worker UInt64 GetPos() const { return _pos; }
530*f6dc9357SAndroid Build Coastguard Worker };
531*f6dc9357SAndroid Build Coastguard Worker
532*f6dc9357SAndroid Build Coastguard Worker
533*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize))
534*f6dc9357SAndroid Build Coastguard Worker {
535*f6dc9357SAndroid Build Coastguard Worker HRESULT result = S_OK;
536*f6dc9357SAndroid Build Coastguard Worker if (_size_Defined)
537*f6dc9357SAndroid Build Coastguard Worker {
538*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = _size - _pos;
539*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
540*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
541*f6dc9357SAndroid Build Coastguard Worker }
542*f6dc9357SAndroid Build Coastguard Worker if (_stream)
543*f6dc9357SAndroid Build Coastguard Worker result = _stream->Write(data, size, &size);
544*f6dc9357SAndroid Build Coastguard Worker if (_destBuf)
545*f6dc9357SAndroid Build Coastguard Worker memcpy(_destBuf + (size_t)_pos, data, size);
546*f6dc9357SAndroid Build Coastguard Worker _hash.Update(data, size);
547*f6dc9357SAndroid Build Coastguard Worker _pos += size;
548*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
549*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
550*f6dc9357SAndroid Build Coastguard Worker return result;
551*f6dc9357SAndroid Build Coastguard Worker }
552*f6dc9357SAndroid Build Coastguard Worker
553*f6dc9357SAndroid Build Coastguard Worker
554*f6dc9357SAndroid Build Coastguard Worker
555*f6dc9357SAndroid Build Coastguard Worker
556*f6dc9357SAndroid Build Coastguard Worker
557*f6dc9357SAndroid Build Coastguard Worker class CInArchive
558*f6dc9357SAndroid Build Coastguard Worker {
559*f6dc9357SAndroid Build Coastguard Worker CAlignedBuffer _buf;
560*f6dc9357SAndroid Build Coastguard Worker size_t _bufSize;
561*f6dc9357SAndroid Build Coastguard Worker size_t _bufPos;
562*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *_stream;
563*f6dc9357SAndroid Build Coastguard Worker
564*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2<ICompressFilter, NCrypto::NRar5::CDecoder> m_CryptoDecoder;
565*f6dc9357SAndroid Build Coastguard Worker
566*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_NO_COPY(CInArchive)
567*f6dc9357SAndroid Build Coastguard Worker
568*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadStream_Check(void *data, size_t size);
569*f6dc9357SAndroid Build Coastguard Worker
570*f6dc9357SAndroid Build Coastguard Worker public:
571*f6dc9357SAndroid Build Coastguard Worker bool m_CryptoMode;
572*f6dc9357SAndroid Build Coastguard Worker
573*f6dc9357SAndroid Build Coastguard Worker bool WrongPassword;
574*f6dc9357SAndroid Build Coastguard Worker bool IsArc;
575*f6dc9357SAndroid Build Coastguard Worker bool UnexpectedEnd;
576*f6dc9357SAndroid Build Coastguard Worker
577*f6dc9357SAndroid Build Coastguard Worker UInt64 StreamStartPosition;
578*f6dc9357SAndroid Build Coastguard Worker UInt64 Position;
579*f6dc9357SAndroid Build Coastguard Worker
580*f6dc9357SAndroid Build Coastguard Worker size_t Get_Buf_RemainSize() const { return _bufSize - _bufPos; }
581*f6dc9357SAndroid Build Coastguard Worker bool Is_Buf_Finished() const { return _bufPos == _bufSize; }
582*f6dc9357SAndroid Build Coastguard Worker const Byte *Get_Buf_Data() const { return _buf + _bufPos; }
583*f6dc9357SAndroid Build Coastguard Worker void Move_BufPos(size_t num) { _bufPos += num; }
584*f6dc9357SAndroid Build Coastguard Worker bool ReadVar(UInt64 &val);
585*f6dc9357SAndroid Build Coastguard Worker
586*f6dc9357SAndroid Build Coastguard Worker struct CHeader
587*f6dc9357SAndroid Build Coastguard Worker {
588*f6dc9357SAndroid Build Coastguard Worker UInt64 Type;
589*f6dc9357SAndroid Build Coastguard Worker UInt64 Flags;
590*f6dc9357SAndroid Build Coastguard Worker size_t ExtraSize;
591*f6dc9357SAndroid Build Coastguard Worker UInt64 DataSize;
592*f6dc9357SAndroid Build Coastguard Worker };
593*f6dc9357SAndroid Build Coastguard Worker
594*f6dc9357SAndroid Build Coastguard Worker CInArchive() {}
595*f6dc9357SAndroid Build Coastguard Worker
596*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadBlockHeader(CHeader &h);
597*f6dc9357SAndroid Build Coastguard Worker bool ReadFileHeader(const CHeader &header, CItem &item);
598*f6dc9357SAndroid Build Coastguard Worker void AddToSeekValue(UInt64 addValue)
599*f6dc9357SAndroid Build Coastguard Worker {
600*f6dc9357SAndroid Build Coastguard Worker Position += addValue;
601*f6dc9357SAndroid Build Coastguard Worker }
602*f6dc9357SAndroid Build Coastguard Worker
603*f6dc9357SAndroid Build Coastguard Worker HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, ICryptoGetTextPassword *getTextPassword,
604*f6dc9357SAndroid Build Coastguard Worker CInArcInfo &info);
605*f6dc9357SAndroid Build Coastguard Worker };
606*f6dc9357SAndroid Build Coastguard Worker
607*f6dc9357SAndroid Build Coastguard Worker
608*f6dc9357SAndroid Build Coastguard Worker static HRESULT MySetPassword(ICryptoGetTextPassword *getTextPassword, NCrypto::NRar5::CDecoder *cryptoDecoder)
609*f6dc9357SAndroid Build Coastguard Worker {
610*f6dc9357SAndroid Build Coastguard Worker CMyComBSTR_Wipe password;
611*f6dc9357SAndroid Build Coastguard Worker RINOK(getTextPassword->CryptoGetTextPassword(&password))
612*f6dc9357SAndroid Build Coastguard Worker AString_Wipe utf8;
613*f6dc9357SAndroid Build Coastguard Worker const unsigned kPasswordLen_MAX = 127;
614*f6dc9357SAndroid Build Coastguard Worker UString_Wipe unicode;
615*f6dc9357SAndroid Build Coastguard Worker unicode.SetFromBstr(password);
616*f6dc9357SAndroid Build Coastguard Worker if (unicode.Len() > kPasswordLen_MAX)
617*f6dc9357SAndroid Build Coastguard Worker unicode.DeleteFrom(kPasswordLen_MAX);
618*f6dc9357SAndroid Build Coastguard Worker ConvertUnicodeToUTF8(unicode, utf8);
619*f6dc9357SAndroid Build Coastguard Worker cryptoDecoder->SetPassword((const Byte *)(const char *)utf8, utf8.Len());
620*f6dc9357SAndroid Build Coastguard Worker return S_OK;
621*f6dc9357SAndroid Build Coastguard Worker }
622*f6dc9357SAndroid Build Coastguard Worker
623*f6dc9357SAndroid Build Coastguard Worker
624*f6dc9357SAndroid Build Coastguard Worker bool CInArchive::ReadVar(UInt64 &val)
625*f6dc9357SAndroid Build Coastguard Worker {
626*f6dc9357SAndroid Build Coastguard Worker const unsigned offset = ReadVarInt(Get_Buf_Data(), Get_Buf_RemainSize(), &val);
627*f6dc9357SAndroid Build Coastguard Worker Move_BufPos(offset);
628*f6dc9357SAndroid Build Coastguard Worker return (offset != 0);
629*f6dc9357SAndroid Build Coastguard Worker }
630*f6dc9357SAndroid Build Coastguard Worker
631*f6dc9357SAndroid Build Coastguard Worker
632*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::ReadStream_Check(void *data, size_t size)
633*f6dc9357SAndroid Build Coastguard Worker {
634*f6dc9357SAndroid Build Coastguard Worker size_t size2 = size;
635*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(_stream, data, &size2))
636*f6dc9357SAndroid Build Coastguard Worker if (size2 == size)
637*f6dc9357SAndroid Build Coastguard Worker return S_OK;
638*f6dc9357SAndroid Build Coastguard Worker UnexpectedEnd = true;
639*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
640*f6dc9357SAndroid Build Coastguard Worker }
641*f6dc9357SAndroid Build Coastguard Worker
642*f6dc9357SAndroid Build Coastguard Worker
643*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::ReadBlockHeader(CHeader &h)
644*f6dc9357SAndroid Build Coastguard Worker {
645*f6dc9357SAndroid Build Coastguard Worker h.Type = 0;
646*f6dc9357SAndroid Build Coastguard Worker h.Flags = 0;
647*f6dc9357SAndroid Build Coastguard Worker h.ExtraSize = 0;
648*f6dc9357SAndroid Build Coastguard Worker h.DataSize = 0;
649*f6dc9357SAndroid Build Coastguard Worker
650*f6dc9357SAndroid Build Coastguard Worker Byte buf[AES_BLOCK_SIZE];
651*f6dc9357SAndroid Build Coastguard Worker unsigned filled;
652*f6dc9357SAndroid Build Coastguard Worker
653*f6dc9357SAndroid Build Coastguard Worker if (m_CryptoMode)
654*f6dc9357SAndroid Build Coastguard Worker {
655*f6dc9357SAndroid Build Coastguard Worker _buf.AllocAtLeast(1 << 12); // at least (AES_BLOCK_SIZE * 2)
656*f6dc9357SAndroid Build Coastguard Worker if (!(Byte *)_buf)
657*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
658*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_Check(_buf, AES_BLOCK_SIZE * 2))
659*f6dc9357SAndroid Build Coastguard Worker memcpy(m_CryptoDecoder->_iv, _buf, AES_BLOCK_SIZE);
660*f6dc9357SAndroid Build Coastguard Worker RINOK(m_CryptoDecoder->Init())
661*f6dc9357SAndroid Build Coastguard Worker // we call RAR5_AES_Filter with:
662*f6dc9357SAndroid Build Coastguard Worker // data_ptr == aligned_ptr + 16
663*f6dc9357SAndroid Build Coastguard Worker // data_size == 16
664*f6dc9357SAndroid Build Coastguard Worker if (m_CryptoDecoder->Filter(_buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE) != AES_BLOCK_SIZE)
665*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
666*f6dc9357SAndroid Build Coastguard Worker memcpy(buf, _buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE);
667*f6dc9357SAndroid Build Coastguard Worker filled = AES_BLOCK_SIZE;
668*f6dc9357SAndroid Build Coastguard Worker }
669*f6dc9357SAndroid Build Coastguard Worker else
670*f6dc9357SAndroid Build Coastguard Worker {
671*f6dc9357SAndroid Build Coastguard Worker const unsigned kStartSize = 4 + 3;
672*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_Check(buf, kStartSize))
673*f6dc9357SAndroid Build Coastguard Worker filled = kStartSize;
674*f6dc9357SAndroid Build Coastguard Worker }
675*f6dc9357SAndroid Build Coastguard Worker
676*f6dc9357SAndroid Build Coastguard Worker {
677*f6dc9357SAndroid Build Coastguard Worker UInt64 val;
678*f6dc9357SAndroid Build Coastguard Worker unsigned offset = ReadVarInt(buf + 4, 3, &val);
679*f6dc9357SAndroid Build Coastguard Worker if (offset == 0)
680*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
681*f6dc9357SAndroid Build Coastguard Worker size_t size = (size_t)val;
682*f6dc9357SAndroid Build Coastguard Worker if (size < 2)
683*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
684*f6dc9357SAndroid Build Coastguard Worker offset += 4;
685*f6dc9357SAndroid Build Coastguard Worker _bufPos = offset;
686*f6dc9357SAndroid Build Coastguard Worker size += offset;
687*f6dc9357SAndroid Build Coastguard Worker _bufSize = size;
688*f6dc9357SAndroid Build Coastguard Worker if (m_CryptoMode)
689*f6dc9357SAndroid Build Coastguard Worker size = (size + AES_BLOCK_SIZE - 1) & ~(size_t)(AES_BLOCK_SIZE - 1);
690*f6dc9357SAndroid Build Coastguard Worker _buf.AllocAtLeast(size);
691*f6dc9357SAndroid Build Coastguard Worker if (!(Byte *)_buf)
692*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
693*f6dc9357SAndroid Build Coastguard Worker memcpy(_buf, buf, filled);
694*f6dc9357SAndroid Build Coastguard Worker const size_t rem = size - filled;
695*f6dc9357SAndroid Build Coastguard Worker // if (m_CryptoMode), we add AES_BLOCK_SIZE here, because _iv is not included to size.
696*f6dc9357SAndroid Build Coastguard Worker AddToSeekValue(size + (m_CryptoMode ? AES_BLOCK_SIZE : 0));
697*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_Check(_buf + filled, rem))
698*f6dc9357SAndroid Build Coastguard Worker if (m_CryptoMode)
699*f6dc9357SAndroid Build Coastguard Worker {
700*f6dc9357SAndroid Build Coastguard Worker // we call RAR5_AES_Filter with:
701*f6dc9357SAndroid Build Coastguard Worker // data_ptr == aligned_ptr + 16
702*f6dc9357SAndroid Build Coastguard Worker // (rem) can be big
703*f6dc9357SAndroid Build Coastguard Worker if (m_CryptoDecoder->Filter(_buf + filled, (UInt32)rem) != rem)
704*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
705*f6dc9357SAndroid Build Coastguard Worker #if 1
706*f6dc9357SAndroid Build Coastguard Worker // optional 7zip-unrar check : remainder must contain zeros.
707*f6dc9357SAndroid Build Coastguard Worker const size_t pad = size - _bufSize;
708*f6dc9357SAndroid Build Coastguard Worker const Byte *p = _buf + _bufSize;
709*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < pad; i++)
710*f6dc9357SAndroid Build Coastguard Worker if (p[i])
711*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
712*f6dc9357SAndroid Build Coastguard Worker #endif
713*f6dc9357SAndroid Build Coastguard Worker }
714*f6dc9357SAndroid Build Coastguard Worker }
715*f6dc9357SAndroid Build Coastguard Worker
716*f6dc9357SAndroid Build Coastguard Worker if (CrcCalc(_buf + 4, _bufSize - 4) != Get32(buf))
717*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
718*f6dc9357SAndroid Build Coastguard Worker
719*f6dc9357SAndroid Build Coastguard Worker if (!ReadVar(h.Type)) return S_FALSE;
720*f6dc9357SAndroid Build Coastguard Worker if (!ReadVar(h.Flags)) return S_FALSE;
721*f6dc9357SAndroid Build Coastguard Worker
722*f6dc9357SAndroid Build Coastguard Worker if (h.Flags & NHeaderFlags::kExtra)
723*f6dc9357SAndroid Build Coastguard Worker {
724*f6dc9357SAndroid Build Coastguard Worker UInt64 extraSize;
725*f6dc9357SAndroid Build Coastguard Worker if (!ReadVar(extraSize))
726*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
727*f6dc9357SAndroid Build Coastguard Worker if (extraSize >= (1u << 21))
728*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
729*f6dc9357SAndroid Build Coastguard Worker h.ExtraSize = (size_t)extraSize;
730*f6dc9357SAndroid Build Coastguard Worker }
731*f6dc9357SAndroid Build Coastguard Worker
732*f6dc9357SAndroid Build Coastguard Worker if (h.Flags & NHeaderFlags::kData)
733*f6dc9357SAndroid Build Coastguard Worker {
734*f6dc9357SAndroid Build Coastguard Worker if (!ReadVar(h.DataSize))
735*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
736*f6dc9357SAndroid Build Coastguard Worker }
737*f6dc9357SAndroid Build Coastguard Worker
738*f6dc9357SAndroid Build Coastguard Worker if (h.ExtraSize > Get_Buf_RemainSize())
739*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
740*f6dc9357SAndroid Build Coastguard Worker return S_OK;
741*f6dc9357SAndroid Build Coastguard Worker }
742*f6dc9357SAndroid Build Coastguard Worker
743*f6dc9357SAndroid Build Coastguard Worker
744*f6dc9357SAndroid Build Coastguard Worker bool CInArcInfo::CLocator::Parse(const Byte *p, size_t size)
745*f6dc9357SAndroid Build Coastguard Worker {
746*f6dc9357SAndroid Build Coastguard Worker Flags = 0;
747*f6dc9357SAndroid Build Coastguard Worker QuickOpen = 0;
748*f6dc9357SAndroid Build Coastguard Worker Recovery = 0;
749*f6dc9357SAndroid Build Coastguard Worker
750*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, Flags)
751*f6dc9357SAndroid Build Coastguard Worker
752*f6dc9357SAndroid Build Coastguard Worker if (Is_QuickOpen())
753*f6dc9357SAndroid Build Coastguard Worker {
754*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, QuickOpen)
755*f6dc9357SAndroid Build Coastguard Worker }
756*f6dc9357SAndroid Build Coastguard Worker if (Is_Recovery())
757*f6dc9357SAndroid Build Coastguard Worker {
758*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, Recovery)
759*f6dc9357SAndroid Build Coastguard Worker }
760*f6dc9357SAndroid Build Coastguard Worker #if 0
761*f6dc9357SAndroid Build Coastguard Worker // another records are possible in future rar formats.
762*f6dc9357SAndroid Build Coastguard Worker if (size != 0)
763*f6dc9357SAndroid Build Coastguard Worker return false;
764*f6dc9357SAndroid Build Coastguard Worker #endif
765*f6dc9357SAndroid Build Coastguard Worker return true;
766*f6dc9357SAndroid Build Coastguard Worker }
767*f6dc9357SAndroid Build Coastguard Worker
768*f6dc9357SAndroid Build Coastguard Worker
769*f6dc9357SAndroid Build Coastguard Worker bool CInArcInfo::CMetadata::Parse(const Byte *p, size_t size)
770*f6dc9357SAndroid Build Coastguard Worker {
771*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, Flags)
772*f6dc9357SAndroid Build Coastguard Worker if (Flags & NMetadataFlags::kArcName)
773*f6dc9357SAndroid Build Coastguard Worker {
774*f6dc9357SAndroid Build Coastguard Worker UInt64 nameLen;
775*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, nameLen)
776*f6dc9357SAndroid Build Coastguard Worker if (nameLen > size)
777*f6dc9357SAndroid Build Coastguard Worker return false;
778*f6dc9357SAndroid Build Coastguard Worker ArcName.SetFrom_CalcLen((const char *)(const void *)p, (unsigned)nameLen);
779*f6dc9357SAndroid Build Coastguard Worker p += (size_t)nameLen;
780*f6dc9357SAndroid Build Coastguard Worker size -= (size_t)nameLen;
781*f6dc9357SAndroid Build Coastguard Worker }
782*f6dc9357SAndroid Build Coastguard Worker if (Flags & NMetadataFlags::kCTime)
783*f6dc9357SAndroid Build Coastguard Worker {
784*f6dc9357SAndroid Build Coastguard Worker if ((Flags & NMetadataFlags::kUnixTime) &&
785*f6dc9357SAndroid Build Coastguard Worker (Flags & NMetadataFlags::kNanoSec) == 0)
786*f6dc9357SAndroid Build Coastguard Worker {
787*f6dc9357SAndroid Build Coastguard Worker if (size < 4)
788*f6dc9357SAndroid Build Coastguard Worker return false;
789*f6dc9357SAndroid Build Coastguard Worker CTime = GetUi32(p);
790*f6dc9357SAndroid Build Coastguard Worker p += 4;
791*f6dc9357SAndroid Build Coastguard Worker size -= 4;
792*f6dc9357SAndroid Build Coastguard Worker }
793*f6dc9357SAndroid Build Coastguard Worker else
794*f6dc9357SAndroid Build Coastguard Worker {
795*f6dc9357SAndroid Build Coastguard Worker if (size < 8)
796*f6dc9357SAndroid Build Coastguard Worker return false;
797*f6dc9357SAndroid Build Coastguard Worker CTime = GetUi64(p);
798*f6dc9357SAndroid Build Coastguard Worker p += 8;
799*f6dc9357SAndroid Build Coastguard Worker size -= 8;
800*f6dc9357SAndroid Build Coastguard Worker }
801*f6dc9357SAndroid Build Coastguard Worker }
802*f6dc9357SAndroid Build Coastguard Worker #if 0
803*f6dc9357SAndroid Build Coastguard Worker // another records are possible in future rar formats.
804*f6dc9357SAndroid Build Coastguard Worker if (size != 0)
805*f6dc9357SAndroid Build Coastguard Worker return false;
806*f6dc9357SAndroid Build Coastguard Worker #endif
807*f6dc9357SAndroid Build Coastguard Worker return true;
808*f6dc9357SAndroid Build Coastguard Worker }
809*f6dc9357SAndroid Build Coastguard Worker
810*f6dc9357SAndroid Build Coastguard Worker
811*f6dc9357SAndroid Build Coastguard Worker bool CInArcInfo::ParseExtra(const Byte *p, size_t size)
812*f6dc9357SAndroid Build Coastguard Worker {
813*f6dc9357SAndroid Build Coastguard Worker for (;;)
814*f6dc9357SAndroid Build Coastguard Worker {
815*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
816*f6dc9357SAndroid Build Coastguard Worker return true;
817*f6dc9357SAndroid Build Coastguard Worker UInt64 recSize64, id;
818*f6dc9357SAndroid Build Coastguard Worker PARSE_VAR_INT(p, size, recSize64)
819*f6dc9357SAndroid Build Coastguard Worker if (recSize64 > size)
820*f6dc9357SAndroid Build Coastguard Worker return false;
821*f6dc9357SAndroid Build Coastguard Worker size_t recSize = (size_t)recSize64;
822*f6dc9357SAndroid Build Coastguard Worker size -= recSize;
823*f6dc9357SAndroid Build Coastguard Worker // READ_VAR_INT(p, recSize, recSize)
824*f6dc9357SAndroid Build Coastguard Worker {
825*f6dc9357SAndroid Build Coastguard Worker const unsigned num = ReadVarInt(p, recSize, &id);
826*f6dc9357SAndroid Build Coastguard Worker if (num == 0)
827*f6dc9357SAndroid Build Coastguard Worker return false;
828*f6dc9357SAndroid Build Coastguard Worker p += num;
829*f6dc9357SAndroid Build Coastguard Worker recSize -= num;
830*f6dc9357SAndroid Build Coastguard Worker }
831*f6dc9357SAndroid Build Coastguard Worker if (id == kArcExtraRecordType_Metadata)
832*f6dc9357SAndroid Build Coastguard Worker {
833*f6dc9357SAndroid Build Coastguard Worker Metadata_Defined = true;
834*f6dc9357SAndroid Build Coastguard Worker if (!Metadata.Parse(p, recSize))
835*f6dc9357SAndroid Build Coastguard Worker Metadata_Error = true;
836*f6dc9357SAndroid Build Coastguard Worker }
837*f6dc9357SAndroid Build Coastguard Worker else if (id == kArcExtraRecordType_Locator)
838*f6dc9357SAndroid Build Coastguard Worker {
839*f6dc9357SAndroid Build Coastguard Worker Locator_Defined = true;
840*f6dc9357SAndroid Build Coastguard Worker if (!Locator.Parse(p, recSize))
841*f6dc9357SAndroid Build Coastguard Worker Locator_Error = true;
842*f6dc9357SAndroid Build Coastguard Worker }
843*f6dc9357SAndroid Build Coastguard Worker else
844*f6dc9357SAndroid Build Coastguard Worker UnknownExtraRecord = true;
845*f6dc9357SAndroid Build Coastguard Worker p += recSize;
846*f6dc9357SAndroid Build Coastguard Worker }
847*f6dc9357SAndroid Build Coastguard Worker }
848*f6dc9357SAndroid Build Coastguard Worker
849*f6dc9357SAndroid Build Coastguard Worker
850*f6dc9357SAndroid Build Coastguard Worker
851*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit, ICryptoGetTextPassword *getTextPassword,
852*f6dc9357SAndroid Build Coastguard Worker CInArcInfo &info)
853*f6dc9357SAndroid Build Coastguard Worker {
854*f6dc9357SAndroid Build Coastguard Worker m_CryptoMode = false;
855*f6dc9357SAndroid Build Coastguard Worker
856*f6dc9357SAndroid Build Coastguard Worker WrongPassword = false;
857*f6dc9357SAndroid Build Coastguard Worker IsArc = false;
858*f6dc9357SAndroid Build Coastguard Worker UnexpectedEnd = false;
859*f6dc9357SAndroid Build Coastguard Worker
860*f6dc9357SAndroid Build Coastguard Worker Position = StreamStartPosition;
861*f6dc9357SAndroid Build Coastguard Worker
862*f6dc9357SAndroid Build Coastguard Worker UInt64 arcStartPos = StreamStartPosition;
863*f6dc9357SAndroid Build Coastguard Worker {
864*f6dc9357SAndroid Build Coastguard Worker Byte marker[kMarkerSize];
865*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, marker, kMarkerSize))
866*f6dc9357SAndroid Build Coastguard Worker if (memcmp(marker, kMarker, kMarkerSize) == 0)
867*f6dc9357SAndroid Build Coastguard Worker Position += kMarkerSize;
868*f6dc9357SAndroid Build Coastguard Worker else
869*f6dc9357SAndroid Build Coastguard Worker {
870*f6dc9357SAndroid Build Coastguard Worker if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)
871*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
872*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, StreamStartPosition))
873*f6dc9357SAndroid Build Coastguard Worker RINOK(FindSignatureInStream(stream, kMarker, kMarkerSize,
874*f6dc9357SAndroid Build Coastguard Worker searchHeaderSizeLimit, arcStartPos))
875*f6dc9357SAndroid Build Coastguard Worker arcStartPos += StreamStartPosition;
876*f6dc9357SAndroid Build Coastguard Worker Position = arcStartPos + kMarkerSize;
877*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, Position))
878*f6dc9357SAndroid Build Coastguard Worker }
879*f6dc9357SAndroid Build Coastguard Worker }
880*f6dc9357SAndroid Build Coastguard Worker
881*f6dc9357SAndroid Build Coastguard Worker info.StartPos = arcStartPos;
882*f6dc9357SAndroid Build Coastguard Worker _stream = stream;
883*f6dc9357SAndroid Build Coastguard Worker
884*f6dc9357SAndroid Build Coastguard Worker CHeader h;
885*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadBlockHeader(h))
886*f6dc9357SAndroid Build Coastguard Worker info.IsEncrypted = false;
887*f6dc9357SAndroid Build Coastguard Worker
888*f6dc9357SAndroid Build Coastguard Worker if (h.Type == NHeaderType::kArcEncrypt)
889*f6dc9357SAndroid Build Coastguard Worker {
890*f6dc9357SAndroid Build Coastguard Worker info.IsEncrypted = true;
891*f6dc9357SAndroid Build Coastguard Worker IsArc = true;
892*f6dc9357SAndroid Build Coastguard Worker if (!getTextPassword)
893*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
894*f6dc9357SAndroid Build Coastguard Worker m_CryptoMode = true;
895*f6dc9357SAndroid Build Coastguard Worker m_CryptoDecoder.Create_if_Empty();
896*f6dc9357SAndroid Build Coastguard Worker RINOK(m_CryptoDecoder->SetDecoderProps(
897*f6dc9357SAndroid Build Coastguard Worker Get_Buf_Data(), (unsigned)Get_Buf_RemainSize(), false, false))
898*f6dc9357SAndroid Build Coastguard Worker RINOK(MySetPassword(getTextPassword, m_CryptoDecoder.ClsPtr()))
899*f6dc9357SAndroid Build Coastguard Worker if (!m_CryptoDecoder->CalcKey_and_CheckPassword())
900*f6dc9357SAndroid Build Coastguard Worker {
901*f6dc9357SAndroid Build Coastguard Worker WrongPassword = True;
902*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
903*f6dc9357SAndroid Build Coastguard Worker }
904*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadBlockHeader(h))
905*f6dc9357SAndroid Build Coastguard Worker }
906*f6dc9357SAndroid Build Coastguard Worker
907*f6dc9357SAndroid Build Coastguard Worker if (h.Type != NHeaderType::kArc)
908*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
909*f6dc9357SAndroid Build Coastguard Worker
910*f6dc9357SAndroid Build Coastguard Worker IsArc = true;
911*f6dc9357SAndroid Build Coastguard Worker info.VolNumber = 0;
912*f6dc9357SAndroid Build Coastguard Worker
913*f6dc9357SAndroid Build Coastguard Worker if (!ReadVar(info.Flags))
914*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
915*f6dc9357SAndroid Build Coastguard Worker
916*f6dc9357SAndroid Build Coastguard Worker if (info.Flags & NArcFlags::kVolNumber)
917*f6dc9357SAndroid Build Coastguard Worker if (!ReadVar(info.VolNumber))
918*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
919*f6dc9357SAndroid Build Coastguard Worker
920*f6dc9357SAndroid Build Coastguard Worker if (h.ExtraSize != Get_Buf_RemainSize())
921*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
922*f6dc9357SAndroid Build Coastguard Worker if (h.ExtraSize)
923*f6dc9357SAndroid Build Coastguard Worker {
924*f6dc9357SAndroid Build Coastguard Worker if (!info.ParseExtra(Get_Buf_Data(), h.ExtraSize))
925*f6dc9357SAndroid Build Coastguard Worker info.Extra_Error = true;
926*f6dc9357SAndroid Build Coastguard Worker }
927*f6dc9357SAndroid Build Coastguard Worker return S_OK;
928*f6dc9357SAndroid Build Coastguard Worker }
929*f6dc9357SAndroid Build Coastguard Worker
930*f6dc9357SAndroid Build Coastguard Worker
931*f6dc9357SAndroid Build Coastguard Worker bool CInArchive::ReadFileHeader(const CHeader &header, CItem &item)
932*f6dc9357SAndroid Build Coastguard Worker {
933*f6dc9357SAndroid Build Coastguard Worker item.CommonFlags = (UInt32)header.Flags;
934*f6dc9357SAndroid Build Coastguard Worker item.PackSize = header.DataSize;
935*f6dc9357SAndroid Build Coastguard Worker item.UnixMTime = 0;
936*f6dc9357SAndroid Build Coastguard Worker item.CRC = 0;
937*f6dc9357SAndroid Build Coastguard Worker
938*f6dc9357SAndroid Build Coastguard Worker {
939*f6dc9357SAndroid Build Coastguard Worker UInt64 flags64;
940*f6dc9357SAndroid Build Coastguard Worker if (!ReadVar(flags64)) return false;
941*f6dc9357SAndroid Build Coastguard Worker item.Flags = (UInt32)flags64;
942*f6dc9357SAndroid Build Coastguard Worker }
943*f6dc9357SAndroid Build Coastguard Worker
944*f6dc9357SAndroid Build Coastguard Worker if (!ReadVar(item.Size)) return false;
945*f6dc9357SAndroid Build Coastguard Worker
946*f6dc9357SAndroid Build Coastguard Worker {
947*f6dc9357SAndroid Build Coastguard Worker UInt64 attrib;
948*f6dc9357SAndroid Build Coastguard Worker if (!ReadVar(attrib)) return false;
949*f6dc9357SAndroid Build Coastguard Worker item.Attrib = (UInt32)attrib;
950*f6dc9357SAndroid Build Coastguard Worker }
951*f6dc9357SAndroid Build Coastguard Worker if (item.Has_UnixMTime())
952*f6dc9357SAndroid Build Coastguard Worker {
953*f6dc9357SAndroid Build Coastguard Worker if (Get_Buf_RemainSize() < 4)
954*f6dc9357SAndroid Build Coastguard Worker return false;
955*f6dc9357SAndroid Build Coastguard Worker item.UnixMTime = Get32(Get_Buf_Data());
956*f6dc9357SAndroid Build Coastguard Worker Move_BufPos(4);
957*f6dc9357SAndroid Build Coastguard Worker }
958*f6dc9357SAndroid Build Coastguard Worker if (item.Has_CRC())
959*f6dc9357SAndroid Build Coastguard Worker {
960*f6dc9357SAndroid Build Coastguard Worker if (Get_Buf_RemainSize() < 4)
961*f6dc9357SAndroid Build Coastguard Worker return false;
962*f6dc9357SAndroid Build Coastguard Worker item.CRC = Get32(Get_Buf_Data());
963*f6dc9357SAndroid Build Coastguard Worker Move_BufPos(4);
964*f6dc9357SAndroid Build Coastguard Worker }
965*f6dc9357SAndroid Build Coastguard Worker {
966*f6dc9357SAndroid Build Coastguard Worker UInt64 method;
967*f6dc9357SAndroid Build Coastguard Worker if (!ReadVar(method)) return false;
968*f6dc9357SAndroid Build Coastguard Worker item.Method = (UInt32)method;
969*f6dc9357SAndroid Build Coastguard Worker }
970*f6dc9357SAndroid Build Coastguard Worker
971*f6dc9357SAndroid Build Coastguard Worker if (!ReadVar(item.HostOS)) return false;
972*f6dc9357SAndroid Build Coastguard Worker
973*f6dc9357SAndroid Build Coastguard Worker {
974*f6dc9357SAndroid Build Coastguard Worker UInt64 len;
975*f6dc9357SAndroid Build Coastguard Worker if (!ReadVar(len)) return false;
976*f6dc9357SAndroid Build Coastguard Worker if (len > Get_Buf_RemainSize())
977*f6dc9357SAndroid Build Coastguard Worker return false;
978*f6dc9357SAndroid Build Coastguard Worker item.Name.SetFrom_CalcLen((const char *)Get_Buf_Data(), (unsigned)len);
979*f6dc9357SAndroid Build Coastguard Worker Move_BufPos((size_t)len);
980*f6dc9357SAndroid Build Coastguard Worker }
981*f6dc9357SAndroid Build Coastguard Worker
982*f6dc9357SAndroid Build Coastguard Worker item.Extra.Free();
983*f6dc9357SAndroid Build Coastguard Worker const size_t extraSize = header.ExtraSize;
984*f6dc9357SAndroid Build Coastguard Worker if (extraSize != 0)
985*f6dc9357SAndroid Build Coastguard Worker {
986*f6dc9357SAndroid Build Coastguard Worker if (Get_Buf_RemainSize() < extraSize)
987*f6dc9357SAndroid Build Coastguard Worker return false;
988*f6dc9357SAndroid Build Coastguard Worker item.Extra.Alloc(extraSize);
989*f6dc9357SAndroid Build Coastguard Worker memcpy(item.Extra, Get_Buf_Data(), extraSize);
990*f6dc9357SAndroid Build Coastguard Worker Move_BufPos(extraSize);
991*f6dc9357SAndroid Build Coastguard Worker }
992*f6dc9357SAndroid Build Coastguard Worker
993*f6dc9357SAndroid Build Coastguard Worker return Is_Buf_Finished();
994*f6dc9357SAndroid Build Coastguard Worker }
995*f6dc9357SAndroid Build Coastguard Worker
996*f6dc9357SAndroid Build Coastguard Worker
997*f6dc9357SAndroid Build Coastguard Worker
998*f6dc9357SAndroid Build Coastguard Worker struct CLinkFile
999*f6dc9357SAndroid Build Coastguard Worker {
1000*f6dc9357SAndroid Build Coastguard Worker unsigned Index;
1001*f6dc9357SAndroid Build Coastguard Worker unsigned NumLinks; // the number of links to Data
1002*f6dc9357SAndroid Build Coastguard Worker CByteBuffer Data;
1003*f6dc9357SAndroid Build Coastguard Worker HRESULT Res;
1004*f6dc9357SAndroid Build Coastguard Worker bool crcOK;
1005*f6dc9357SAndroid Build Coastguard Worker
1006*f6dc9357SAndroid Build Coastguard Worker CLinkFile(): Index(0), NumLinks(0), Res(S_OK), crcOK(true) {}
1007*f6dc9357SAndroid Build Coastguard Worker };
1008*f6dc9357SAndroid Build Coastguard Worker
1009*f6dc9357SAndroid Build Coastguard Worker
1010*f6dc9357SAndroid Build Coastguard Worker struct CUnpacker
1011*f6dc9357SAndroid Build Coastguard Worker {
1012*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2<ICompressCoder, NCompress::CCopyCoder> copyCoder;
1013*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressCoder> LzCoders[2];
1014*f6dc9357SAndroid Build Coastguard Worker bool SolidAllowed;
1015*f6dc9357SAndroid Build Coastguard Worker bool NeedCrc;
1016*f6dc9357SAndroid Build Coastguard Worker CFilterCoder *filterStreamSpec;
1017*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> filterStream;
1018*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2<ICompressFilter, NCrypto::NRar5::CDecoder> cryptoDecoder;
1019*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICryptoGetTextPassword> getTextPassword;
1020*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2<ISequentialOutStream, COutStreamWithHash> outStream;
1021*f6dc9357SAndroid Build Coastguard Worker
1022*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _tempBuf;
1023*f6dc9357SAndroid Build Coastguard Worker CLinkFile *linkFile;
1024*f6dc9357SAndroid Build Coastguard Worker
1025*f6dc9357SAndroid Build Coastguard Worker CUnpacker(): linkFile(NULL) { SolidAllowed = false; NeedCrc = true; }
1026*f6dc9357SAndroid Build Coastguard Worker
1027*f6dc9357SAndroid Build Coastguard Worker HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS
1028*f6dc9357SAndroid Build Coastguard Worker const CItem &item, bool isSolid, bool &wrongPassword);
1029*f6dc9357SAndroid Build Coastguard Worker
1030*f6dc9357SAndroid Build Coastguard Worker HRESULT Code(const CItem &item, const CItem &lastItem, UInt64 packSize,
1031*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress,
1032*f6dc9357SAndroid Build Coastguard Worker bool &isCrcOK);
1033*f6dc9357SAndroid Build Coastguard Worker
1034*f6dc9357SAndroid Build Coastguard Worker HRESULT DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS
1035*f6dc9357SAndroid Build Coastguard Worker const CItem &item, UInt64 packSize, ISequentialInStream *inStream, CByteBuffer &buffer);
1036*f6dc9357SAndroid Build Coastguard Worker };
1037*f6dc9357SAndroid Build Coastguard Worker
1038*f6dc9357SAndroid Build Coastguard Worker
1039*f6dc9357SAndroid Build Coastguard Worker static const unsigned kLzMethodMax = 5;
1040*f6dc9357SAndroid Build Coastguard Worker
1041*f6dc9357SAndroid Build Coastguard Worker HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS
1042*f6dc9357SAndroid Build Coastguard Worker const CItem &item, bool isSolid, bool &wrongPassword)
1043*f6dc9357SAndroid Build Coastguard Worker {
1044*f6dc9357SAndroid Build Coastguard Worker wrongPassword = false;
1045*f6dc9357SAndroid Build Coastguard Worker
1046*f6dc9357SAndroid Build Coastguard Worker if (item.Get_AlgoVersion_RawBits() > 1)
1047*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1048*f6dc9357SAndroid Build Coastguard Worker
1049*f6dc9357SAndroid Build Coastguard Worker outStream.Create_if_Empty();
1050*f6dc9357SAndroid Build Coastguard Worker
1051*f6dc9357SAndroid Build Coastguard Worker const unsigned method = item.Get_Method();
1052*f6dc9357SAndroid Build Coastguard Worker
1053*f6dc9357SAndroid Build Coastguard Worker if (method == 0)
1054*f6dc9357SAndroid Build Coastguard Worker copyCoder.Create_if_Empty();
1055*f6dc9357SAndroid Build Coastguard Worker else
1056*f6dc9357SAndroid Build Coastguard Worker {
1057*f6dc9357SAndroid Build Coastguard Worker if (method > kLzMethodMax)
1058*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1059*f6dc9357SAndroid Build Coastguard Worker /*
1060*f6dc9357SAndroid Build Coastguard Worker if (item.IsSplitBefore())
1061*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1062*f6dc9357SAndroid Build Coastguard Worker */
1063*f6dc9357SAndroid Build Coastguard Worker const unsigned lzIndex = item.IsService() ? 1 : 0;
1064*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressCoder> &lzCoder = LzCoders[lzIndex];
1065*f6dc9357SAndroid Build Coastguard Worker if (!lzCoder)
1066*f6dc9357SAndroid Build Coastguard Worker {
1067*f6dc9357SAndroid Build Coastguard Worker const UInt32 methodID = 0x40305;
1068*f6dc9357SAndroid Build Coastguard Worker RINOK(CreateCoder_Id(EXTERNAL_CODECS_LOC_VARS methodID, false, lzCoder))
1069*f6dc9357SAndroid Build Coastguard Worker if (!lzCoder)
1070*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1071*f6dc9357SAndroid Build Coastguard Worker }
1072*f6dc9357SAndroid Build Coastguard Worker
1073*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressSetDecoderProperties2> csdp;
1074*f6dc9357SAndroid Build Coastguard Worker RINOK(lzCoder.QueryInterface(IID_ICompressSetDecoderProperties2, &csdp))
1075*f6dc9357SAndroid Build Coastguard Worker if (!csdp)
1076*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1077*f6dc9357SAndroid Build Coastguard Worker const unsigned ver = item.Get_AlgoVersion_HuffRev();
1078*f6dc9357SAndroid Build Coastguard Worker if (ver > 1)
1079*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1080*f6dc9357SAndroid Build Coastguard Worker const Byte props[2] =
1081*f6dc9357SAndroid Build Coastguard Worker {
1082*f6dc9357SAndroid Build Coastguard Worker (Byte)item.Get_DictSize_Main(),
1083*f6dc9357SAndroid Build Coastguard Worker (Byte)((item.Get_DictSize_Frac() << 3) + (ver << 1) + (isSolid ? 1 : 0))
1084*f6dc9357SAndroid Build Coastguard Worker };
1085*f6dc9357SAndroid Build Coastguard Worker RINOK(csdp->SetDecoderProperties2(props, 2))
1086*f6dc9357SAndroid Build Coastguard Worker }
1087*f6dc9357SAndroid Build Coastguard Worker
1088*f6dc9357SAndroid Build Coastguard Worker unsigned cryptoSize = 0;
1089*f6dc9357SAndroid Build Coastguard Worker const int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize);
1090*f6dc9357SAndroid Build Coastguard Worker
1091*f6dc9357SAndroid Build Coastguard Worker if (cryptoOffset >= 0)
1092*f6dc9357SAndroid Build Coastguard Worker {
1093*f6dc9357SAndroid Build Coastguard Worker if (!filterStream)
1094*f6dc9357SAndroid Build Coastguard Worker {
1095*f6dc9357SAndroid Build Coastguard Worker filterStreamSpec = new CFilterCoder(false);
1096*f6dc9357SAndroid Build Coastguard Worker filterStream = filterStreamSpec;
1097*f6dc9357SAndroid Build Coastguard Worker }
1098*f6dc9357SAndroid Build Coastguard Worker
1099*f6dc9357SAndroid Build Coastguard Worker cryptoDecoder.Create_if_Empty();
1100*f6dc9357SAndroid Build Coastguard Worker
1101*f6dc9357SAndroid Build Coastguard Worker RINOK(cryptoDecoder->SetDecoderProps(item.Extra + (unsigned)cryptoOffset, cryptoSize, true, item.IsService()))
1102*f6dc9357SAndroid Build Coastguard Worker
1103*f6dc9357SAndroid Build Coastguard Worker if (!getTextPassword)
1104*f6dc9357SAndroid Build Coastguard Worker {
1105*f6dc9357SAndroid Build Coastguard Worker wrongPassword = True;
1106*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1107*f6dc9357SAndroid Build Coastguard Worker }
1108*f6dc9357SAndroid Build Coastguard Worker
1109*f6dc9357SAndroid Build Coastguard Worker RINOK(MySetPassword(getTextPassword, cryptoDecoder.ClsPtr()))
1110*f6dc9357SAndroid Build Coastguard Worker
1111*f6dc9357SAndroid Build Coastguard Worker if (!cryptoDecoder->CalcKey_and_CheckPassword())
1112*f6dc9357SAndroid Build Coastguard Worker wrongPassword = True;
1113*f6dc9357SAndroid Build Coastguard Worker }
1114*f6dc9357SAndroid Build Coastguard Worker
1115*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1116*f6dc9357SAndroid Build Coastguard Worker }
1117*f6dc9357SAndroid Build Coastguard Worker
1118*f6dc9357SAndroid Build Coastguard Worker
1119*f6dc9357SAndroid Build Coastguard Worker HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSize,
1120*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *volsInStream, ISequentialOutStream *realOutStream, ICompressProgressInfo *progress,
1121*f6dc9357SAndroid Build Coastguard Worker bool &isCrcOK)
1122*f6dc9357SAndroid Build Coastguard Worker {
1123*f6dc9357SAndroid Build Coastguard Worker isCrcOK = true;
1124*f6dc9357SAndroid Build Coastguard Worker
1125*f6dc9357SAndroid Build Coastguard Worker const unsigned method = item.Get_Method();
1126*f6dc9357SAndroid Build Coastguard Worker if (method > kLzMethodMax)
1127*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1128*f6dc9357SAndroid Build Coastguard Worker
1129*f6dc9357SAndroid Build Coastguard Worker const bool needBuf = (linkFile && linkFile->NumLinks != 0);
1130*f6dc9357SAndroid Build Coastguard Worker
1131*f6dc9357SAndroid Build Coastguard Worker if (needBuf && !lastItem.Is_UnknownSize())
1132*f6dc9357SAndroid Build Coastguard Worker {
1133*f6dc9357SAndroid Build Coastguard Worker const size_t dataSize = (size_t)lastItem.Size;
1134*f6dc9357SAndroid Build Coastguard Worker if (dataSize != lastItem.Size)
1135*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1136*f6dc9357SAndroid Build Coastguard Worker linkFile->Data.Alloc(dataSize);
1137*f6dc9357SAndroid Build Coastguard Worker }
1138*f6dc9357SAndroid Build Coastguard Worker
1139*f6dc9357SAndroid Build Coastguard Worker bool isCryptoMode = false;
1140*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *inStream;
1141*f6dc9357SAndroid Build Coastguard Worker
1142*f6dc9357SAndroid Build Coastguard Worker if (item.IsEncrypted())
1143*f6dc9357SAndroid Build Coastguard Worker {
1144*f6dc9357SAndroid Build Coastguard Worker filterStreamSpec->Filter = cryptoDecoder;
1145*f6dc9357SAndroid Build Coastguard Worker filterStreamSpec->SetInStream(volsInStream);
1146*f6dc9357SAndroid Build Coastguard Worker filterStreamSpec->SetOutStreamSize(NULL);
1147*f6dc9357SAndroid Build Coastguard Worker inStream = filterStream;
1148*f6dc9357SAndroid Build Coastguard Worker isCryptoMode = true;
1149*f6dc9357SAndroid Build Coastguard Worker }
1150*f6dc9357SAndroid Build Coastguard Worker else
1151*f6dc9357SAndroid Build Coastguard Worker inStream = volsInStream;
1152*f6dc9357SAndroid Build Coastguard Worker
1153*f6dc9357SAndroid Build Coastguard Worker ICompressCoder *commonCoder = (method == 0) ?
1154*f6dc9357SAndroid Build Coastguard Worker copyCoder.Interface() :
1155*f6dc9357SAndroid Build Coastguard Worker LzCoders[item.IsService() ? 1 : 0].Interface();
1156*f6dc9357SAndroid Build Coastguard Worker
1157*f6dc9357SAndroid Build Coastguard Worker outStream->SetStream(realOutStream);
1158*f6dc9357SAndroid Build Coastguard Worker outStream->Init(lastItem, (needBuf ? (Byte *)linkFile->Data : NULL), NeedCrc);
1159*f6dc9357SAndroid Build Coastguard Worker
1160*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_OK;
1161*f6dc9357SAndroid Build Coastguard Worker if (packSize != 0 || lastItem.Is_UnknownSize() || lastItem.Size != 0)
1162*f6dc9357SAndroid Build Coastguard Worker {
1163*f6dc9357SAndroid Build Coastguard Worker res = commonCoder->Code(inStream, outStream, &packSize,
1164*f6dc9357SAndroid Build Coastguard Worker lastItem.Is_UnknownSize() ? NULL : &lastItem.Size, progress);
1165*f6dc9357SAndroid Build Coastguard Worker if (!item.IsService())
1166*f6dc9357SAndroid Build Coastguard Worker SolidAllowed = true;
1167*f6dc9357SAndroid Build Coastguard Worker }
1168*f6dc9357SAndroid Build Coastguard Worker else
1169*f6dc9357SAndroid Build Coastguard Worker {
1170*f6dc9357SAndroid Build Coastguard Worker // res = res;
1171*f6dc9357SAndroid Build Coastguard Worker }
1172*f6dc9357SAndroid Build Coastguard Worker
1173*f6dc9357SAndroid Build Coastguard Worker if (isCryptoMode)
1174*f6dc9357SAndroid Build Coastguard Worker filterStreamSpec->ReleaseInStream();
1175*f6dc9357SAndroid Build Coastguard Worker
1176*f6dc9357SAndroid Build Coastguard Worker const UInt64 processedSize = outStream->GetPos();
1177*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK && !lastItem.Is_UnknownSize() && processedSize != lastItem.Size)
1178*f6dc9357SAndroid Build Coastguard Worker res = S_FALSE;
1179*f6dc9357SAndroid Build Coastguard Worker
1180*f6dc9357SAndroid Build Coastguard Worker // if (res == S_OK)
1181*f6dc9357SAndroid Build Coastguard Worker {
1182*f6dc9357SAndroid Build Coastguard Worker unsigned cryptoSize = 0;
1183*f6dc9357SAndroid Build Coastguard Worker const int cryptoOffset = lastItem.FindExtra(NExtraID::kCrypto, cryptoSize);
1184*f6dc9357SAndroid Build Coastguard Worker NCrypto::NRar5::CDecoder *crypto = NULL;
1185*f6dc9357SAndroid Build Coastguard Worker if (cryptoOffset >= 0)
1186*f6dc9357SAndroid Build Coastguard Worker {
1187*f6dc9357SAndroid Build Coastguard Worker CCryptoInfo cryptoInfo;
1188*f6dc9357SAndroid Build Coastguard Worker if (cryptoInfo.Parse(lastItem.Extra + (unsigned)cryptoOffset, cryptoSize))
1189*f6dc9357SAndroid Build Coastguard Worker if (cryptoInfo.UseMAC())
1190*f6dc9357SAndroid Build Coastguard Worker crypto = cryptoDecoder.ClsPtr();
1191*f6dc9357SAndroid Build Coastguard Worker }
1192*f6dc9357SAndroid Build Coastguard Worker if (NeedCrc)
1193*f6dc9357SAndroid Build Coastguard Worker isCrcOK = outStream->_hash.Check(lastItem, crypto);
1194*f6dc9357SAndroid Build Coastguard Worker }
1195*f6dc9357SAndroid Build Coastguard Worker
1196*f6dc9357SAndroid Build Coastguard Worker if (linkFile)
1197*f6dc9357SAndroid Build Coastguard Worker {
1198*f6dc9357SAndroid Build Coastguard Worker linkFile->Res = res;
1199*f6dc9357SAndroid Build Coastguard Worker linkFile->crcOK = isCrcOK;
1200*f6dc9357SAndroid Build Coastguard Worker if (needBuf
1201*f6dc9357SAndroid Build Coastguard Worker && !lastItem.Is_UnknownSize()
1202*f6dc9357SAndroid Build Coastguard Worker && processedSize != lastItem.Size)
1203*f6dc9357SAndroid Build Coastguard Worker linkFile->Data.ChangeSize_KeepData((size_t)processedSize, (size_t)processedSize);
1204*f6dc9357SAndroid Build Coastguard Worker }
1205*f6dc9357SAndroid Build Coastguard Worker
1206*f6dc9357SAndroid Build Coastguard Worker return res;
1207*f6dc9357SAndroid Build Coastguard Worker }
1208*f6dc9357SAndroid Build Coastguard Worker
1209*f6dc9357SAndroid Build Coastguard Worker
1210*f6dc9357SAndroid Build Coastguard Worker HRESULT CUnpacker::DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS
1211*f6dc9357SAndroid Build Coastguard Worker const CItem &item, UInt64 packSize,
1212*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *inStream,
1213*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &buffer)
1214*f6dc9357SAndroid Build Coastguard Worker {
1215*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> out;
1216*f6dc9357SAndroid Build Coastguard Worker _tempBuf.AllocAtLeast((size_t)item.Size);
1217*f6dc9357SAndroid Build Coastguard Worker out->Init(_tempBuf, (size_t)item.Size);
1218*f6dc9357SAndroid Build Coastguard Worker
1219*f6dc9357SAndroid Build Coastguard Worker bool wrongPassword;
1220*f6dc9357SAndroid Build Coastguard Worker
1221*f6dc9357SAndroid Build Coastguard Worker if (item.IsSolid())
1222*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1223*f6dc9357SAndroid Build Coastguard Worker
1224*f6dc9357SAndroid Build Coastguard Worker HRESULT res = Create(EXTERNAL_CODECS_LOC_VARS item, item.IsSolid(), wrongPassword);
1225*f6dc9357SAndroid Build Coastguard Worker
1226*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
1227*f6dc9357SAndroid Build Coastguard Worker {
1228*f6dc9357SAndroid Build Coastguard Worker if (wrongPassword)
1229*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1230*f6dc9357SAndroid Build Coastguard Worker
1231*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> limitedStream;
1232*f6dc9357SAndroid Build Coastguard Worker limitedStream->SetStream(inStream);
1233*f6dc9357SAndroid Build Coastguard Worker limitedStream->Init(packSize);
1234*f6dc9357SAndroid Build Coastguard Worker
1235*f6dc9357SAndroid Build Coastguard Worker bool crcOK = true;
1236*f6dc9357SAndroid Build Coastguard Worker res = Code(item, item, packSize, limitedStream, out, NULL, crcOK);
1237*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
1238*f6dc9357SAndroid Build Coastguard Worker {
1239*f6dc9357SAndroid Build Coastguard Worker if (!crcOK || out->GetPos() != item.Size)
1240*f6dc9357SAndroid Build Coastguard Worker res = S_FALSE;
1241*f6dc9357SAndroid Build Coastguard Worker else
1242*f6dc9357SAndroid Build Coastguard Worker buffer.CopyFrom(_tempBuf, (size_t)item.Size);
1243*f6dc9357SAndroid Build Coastguard Worker }
1244*f6dc9357SAndroid Build Coastguard Worker }
1245*f6dc9357SAndroid Build Coastguard Worker
1246*f6dc9357SAndroid Build Coastguard Worker return res;
1247*f6dc9357SAndroid Build Coastguard Worker }
1248*f6dc9357SAndroid Build Coastguard Worker
1249*f6dc9357SAndroid Build Coastguard Worker
1250*f6dc9357SAndroid Build Coastguard Worker struct CTempBuf
1251*f6dc9357SAndroid Build Coastguard Worker {
1252*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _buf;
1253*f6dc9357SAndroid Build Coastguard Worker size_t _offset;
1254*f6dc9357SAndroid Build Coastguard Worker bool _isOK;
1255*f6dc9357SAndroid Build Coastguard Worker
1256*f6dc9357SAndroid Build Coastguard Worker void Clear()
1257*f6dc9357SAndroid Build Coastguard Worker {
1258*f6dc9357SAndroid Build Coastguard Worker _offset = 0;
1259*f6dc9357SAndroid Build Coastguard Worker _isOK = true;
1260*f6dc9357SAndroid Build Coastguard Worker }
1261*f6dc9357SAndroid Build Coastguard Worker
1262*f6dc9357SAndroid Build Coastguard Worker CTempBuf() { Clear(); }
1263*f6dc9357SAndroid Build Coastguard Worker
1264*f6dc9357SAndroid Build Coastguard Worker HRESULT Decode(DECL_EXTERNAL_CODECS_LOC_VARS
1265*f6dc9357SAndroid Build Coastguard Worker const CItem &item,
1266*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *inStream,
1267*f6dc9357SAndroid Build Coastguard Worker CUnpacker &unpacker,
1268*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &destBuf);
1269*f6dc9357SAndroid Build Coastguard Worker };
1270*f6dc9357SAndroid Build Coastguard Worker
1271*f6dc9357SAndroid Build Coastguard Worker
1272*f6dc9357SAndroid Build Coastguard Worker HRESULT CTempBuf::Decode(DECL_EXTERNAL_CODECS_LOC_VARS
1273*f6dc9357SAndroid Build Coastguard Worker const CItem &item,
1274*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *inStream,
1275*f6dc9357SAndroid Build Coastguard Worker CUnpacker &unpacker,
1276*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &destBuf)
1277*f6dc9357SAndroid Build Coastguard Worker {
1278*f6dc9357SAndroid Build Coastguard Worker const size_t kPackSize_Max = (1 << 24);
1279*f6dc9357SAndroid Build Coastguard Worker if (item.Size > (1 << 24)
1280*f6dc9357SAndroid Build Coastguard Worker || item.Size == 0
1281*f6dc9357SAndroid Build Coastguard Worker || item.PackSize >= kPackSize_Max)
1282*f6dc9357SAndroid Build Coastguard Worker {
1283*f6dc9357SAndroid Build Coastguard Worker Clear();
1284*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1285*f6dc9357SAndroid Build Coastguard Worker }
1286*f6dc9357SAndroid Build Coastguard Worker
1287*f6dc9357SAndroid Build Coastguard Worker if (item.IsSplit() /* && _isOK */)
1288*f6dc9357SAndroid Build Coastguard Worker {
1289*f6dc9357SAndroid Build Coastguard Worker size_t packSize = (size_t)item.PackSize;
1290*f6dc9357SAndroid Build Coastguard Worker if (packSize > kPackSize_Max - _offset)
1291*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1292*f6dc9357SAndroid Build Coastguard Worker size_t newSize = _offset + packSize;
1293*f6dc9357SAndroid Build Coastguard Worker if (newSize > _buf.Size())
1294*f6dc9357SAndroid Build Coastguard Worker _buf.ChangeSize_KeepData(newSize, _offset);
1295*f6dc9357SAndroid Build Coastguard Worker
1296*f6dc9357SAndroid Build Coastguard Worker Byte *data = (Byte *)_buf + _offset;
1297*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(inStream, data, packSize))
1298*f6dc9357SAndroid Build Coastguard Worker
1299*f6dc9357SAndroid Build Coastguard Worker _offset += packSize;
1300*f6dc9357SAndroid Build Coastguard Worker
1301*f6dc9357SAndroid Build Coastguard Worker if (item.IsSplitAfter())
1302*f6dc9357SAndroid Build Coastguard Worker {
1303*f6dc9357SAndroid Build Coastguard Worker CHash hash;
1304*f6dc9357SAndroid Build Coastguard Worker hash.Init(item);
1305*f6dc9357SAndroid Build Coastguard Worker hash.Update(data, packSize);
1306*f6dc9357SAndroid Build Coastguard Worker _isOK = hash.Check(item, NULL); // RAR5 doesn't use HMAC for packed part
1307*f6dc9357SAndroid Build Coastguard Worker }
1308*f6dc9357SAndroid Build Coastguard Worker }
1309*f6dc9357SAndroid Build Coastguard Worker
1310*f6dc9357SAndroid Build Coastguard Worker if (_isOK)
1311*f6dc9357SAndroid Build Coastguard Worker {
1312*f6dc9357SAndroid Build Coastguard Worker if (!item.IsSplitAfter())
1313*f6dc9357SAndroid Build Coastguard Worker {
1314*f6dc9357SAndroid Build Coastguard Worker if (_offset == 0)
1315*f6dc9357SAndroid Build Coastguard Worker {
1316*f6dc9357SAndroid Build Coastguard Worker RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_LOC_VARS
1317*f6dc9357SAndroid Build Coastguard Worker item, item.PackSize, inStream, destBuf))
1318*f6dc9357SAndroid Build Coastguard Worker }
1319*f6dc9357SAndroid Build Coastguard Worker else
1320*f6dc9357SAndroid Build Coastguard Worker {
1321*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CBufInStream> bufInStream;
1322*f6dc9357SAndroid Build Coastguard Worker bufInStream->Init(_buf, _offset);
1323*f6dc9357SAndroid Build Coastguard Worker RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_LOC_VARS
1324*f6dc9357SAndroid Build Coastguard Worker item, _offset, bufInStream, destBuf))
1325*f6dc9357SAndroid Build Coastguard Worker }
1326*f6dc9357SAndroid Build Coastguard Worker }
1327*f6dc9357SAndroid Build Coastguard Worker }
1328*f6dc9357SAndroid Build Coastguard Worker
1329*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1330*f6dc9357SAndroid Build Coastguard Worker }
1331*f6dc9357SAndroid Build Coastguard Worker
1332*f6dc9357SAndroid Build Coastguard Worker
1333*f6dc9357SAndroid Build Coastguard Worker
1334*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
1335*f6dc9357SAndroid Build Coastguard Worker {
1336*f6dc9357SAndroid Build Coastguard Worker kpidPath,
1337*f6dc9357SAndroid Build Coastguard Worker kpidIsDir,
1338*f6dc9357SAndroid Build Coastguard Worker kpidSize,
1339*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
1340*f6dc9357SAndroid Build Coastguard Worker kpidMTime,
1341*f6dc9357SAndroid Build Coastguard Worker kpidCTime,
1342*f6dc9357SAndroid Build Coastguard Worker kpidATime,
1343*f6dc9357SAndroid Build Coastguard Worker kpidAttrib,
1344*f6dc9357SAndroid Build Coastguard Worker // kpidPosixAttrib, // for debug
1345*f6dc9357SAndroid Build Coastguard Worker
1346*f6dc9357SAndroid Build Coastguard Worker kpidIsAltStream,
1347*f6dc9357SAndroid Build Coastguard Worker kpidEncrypted,
1348*f6dc9357SAndroid Build Coastguard Worker kpidSolid,
1349*f6dc9357SAndroid Build Coastguard Worker kpidSplitBefore,
1350*f6dc9357SAndroid Build Coastguard Worker kpidSplitAfter,
1351*f6dc9357SAndroid Build Coastguard Worker kpidCRC,
1352*f6dc9357SAndroid Build Coastguard Worker kpidHostOS,
1353*f6dc9357SAndroid Build Coastguard Worker kpidMethod,
1354*f6dc9357SAndroid Build Coastguard Worker kpidCharacts,
1355*f6dc9357SAndroid Build Coastguard Worker kpidSymLink,
1356*f6dc9357SAndroid Build Coastguard Worker kpidHardLink,
1357*f6dc9357SAndroid Build Coastguard Worker kpidCopyLink,
1358*f6dc9357SAndroid Build Coastguard Worker
1359*f6dc9357SAndroid Build Coastguard Worker kpidVolumeIndex
1360*f6dc9357SAndroid Build Coastguard Worker };
1361*f6dc9357SAndroid Build Coastguard Worker
1362*f6dc9357SAndroid Build Coastguard Worker
1363*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
1364*f6dc9357SAndroid Build Coastguard Worker {
1365*f6dc9357SAndroid Build Coastguard Worker kpidTotalPhySize,
1366*f6dc9357SAndroid Build Coastguard Worker kpidCharacts,
1367*f6dc9357SAndroid Build Coastguard Worker kpidEncrypted,
1368*f6dc9357SAndroid Build Coastguard Worker kpidSolid,
1369*f6dc9357SAndroid Build Coastguard Worker kpidNumBlocks,
1370*f6dc9357SAndroid Build Coastguard Worker kpidMethod,
1371*f6dc9357SAndroid Build Coastguard Worker kpidIsVolume,
1372*f6dc9357SAndroid Build Coastguard Worker kpidVolumeIndex,
1373*f6dc9357SAndroid Build Coastguard Worker kpidNumVolumes,
1374*f6dc9357SAndroid Build Coastguard Worker kpidName,
1375*f6dc9357SAndroid Build Coastguard Worker kpidCTime,
1376*f6dc9357SAndroid Build Coastguard Worker kpidComment
1377*f6dc9357SAndroid Build Coastguard Worker };
1378*f6dc9357SAndroid Build Coastguard Worker
1379*f6dc9357SAndroid Build Coastguard Worker
1380*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
1381*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
1382*f6dc9357SAndroid Build Coastguard Worker
1383*f6dc9357SAndroid Build Coastguard Worker
1384*f6dc9357SAndroid Build Coastguard Worker UInt64 CHandler::GetPackSize(unsigned refIndex) const
1385*f6dc9357SAndroid Build Coastguard Worker {
1386*f6dc9357SAndroid Build Coastguard Worker UInt64 size = 0;
1387*f6dc9357SAndroid Build Coastguard Worker unsigned index = _refs[refIndex].Item;
1388*f6dc9357SAndroid Build Coastguard Worker for (;;)
1389*f6dc9357SAndroid Build Coastguard Worker {
1390*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[index];
1391*f6dc9357SAndroid Build Coastguard Worker size += item.PackSize;
1392*f6dc9357SAndroid Build Coastguard Worker if (item.NextItem < 0)
1393*f6dc9357SAndroid Build Coastguard Worker return size;
1394*f6dc9357SAndroid Build Coastguard Worker index = (unsigned)item.NextItem;
1395*f6dc9357SAndroid Build Coastguard Worker }
1396*f6dc9357SAndroid Build Coastguard Worker }
1397*f6dc9357SAndroid Build Coastguard Worker
1398*f6dc9357SAndroid Build Coastguard Worker static char *PrintDictSize(char *s, UInt64 w)
1399*f6dc9357SAndroid Build Coastguard Worker {
1400*f6dc9357SAndroid Build Coastguard Worker char c = 'K'; w >>= 10;
1401*f6dc9357SAndroid Build Coastguard Worker if ((w & ((1 << 10) - 1)) == 0) { c = 'M'; w >>= 10;
1402*f6dc9357SAndroid Build Coastguard Worker if ((w & ((1 << 10) - 1)) == 0) { c = 'G'; w >>= 10; }}
1403*f6dc9357SAndroid Build Coastguard Worker s = ConvertUInt64ToString(w, s);
1404*f6dc9357SAndroid Build Coastguard Worker *s++ = c;
1405*f6dc9357SAndroid Build Coastguard Worker *s = 0;
1406*f6dc9357SAndroid Build Coastguard Worker return s;
1407*f6dc9357SAndroid Build Coastguard Worker }
1408*f6dc9357SAndroid Build Coastguard Worker
1409*f6dc9357SAndroid Build Coastguard Worker
1410*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1411*f6dc9357SAndroid Build Coastguard Worker {
1412*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1413*f6dc9357SAndroid Build Coastguard Worker
1414*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
1415*f6dc9357SAndroid Build Coastguard Worker
1416*f6dc9357SAndroid Build Coastguard Worker const CInArcInfo *arcInfo = NULL;
1417*f6dc9357SAndroid Build Coastguard Worker if (!_arcs.IsEmpty())
1418*f6dc9357SAndroid Build Coastguard Worker arcInfo = &_arcs[0].Info;
1419*f6dc9357SAndroid Build Coastguard Worker
1420*f6dc9357SAndroid Build Coastguard Worker switch (propID)
1421*f6dc9357SAndroid Build Coastguard Worker {
1422*f6dc9357SAndroid Build Coastguard Worker case kpidVolumeIndex: if (arcInfo && arcInfo->IsVolume()) prop = arcInfo->GetVolIndex(); break;
1423*f6dc9357SAndroid Build Coastguard Worker case kpidSolid: if (arcInfo) prop = arcInfo->IsSolid(); break;
1424*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts:
1425*f6dc9357SAndroid Build Coastguard Worker {
1426*f6dc9357SAndroid Build Coastguard Worker AString s;
1427*f6dc9357SAndroid Build Coastguard Worker if (arcInfo)
1428*f6dc9357SAndroid Build Coastguard Worker {
1429*f6dc9357SAndroid Build Coastguard Worker s = FlagsToString(k_ArcFlags, Z7_ARRAY_SIZE(k_ArcFlags), (UInt32)arcInfo->Flags);
1430*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->Extra_Error)
1431*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("Extra-ERROR");
1432*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->UnsupportedFeature)
1433*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("unsupported-feature");
1434*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->Metadata_Defined)
1435*f6dc9357SAndroid Build Coastguard Worker {
1436*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("Metadata");
1437*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->Metadata_Error)
1438*f6dc9357SAndroid Build Coastguard Worker s += "-ERROR";
1439*f6dc9357SAndroid Build Coastguard Worker else
1440*f6dc9357SAndroid Build Coastguard Worker {
1441*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->Metadata.Flags & NMetadataFlags::kArcName)
1442*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("arc-name");
1443*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->Metadata.Flags & NMetadataFlags::kCTime)
1444*f6dc9357SAndroid Build Coastguard Worker {
1445*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("ctime-");
1446*f6dc9357SAndroid Build Coastguard Worker s +=
1447*f6dc9357SAndroid Build Coastguard Worker (arcInfo->Metadata.Flags & NMetadataFlags::kUnixTime) ?
1448*f6dc9357SAndroid Build Coastguard Worker (arcInfo->Metadata.Flags & NMetadataFlags::kNanoSec) ?
1449*f6dc9357SAndroid Build Coastguard Worker "1ns" : "1s" : "win";
1450*f6dc9357SAndroid Build Coastguard Worker }
1451*f6dc9357SAndroid Build Coastguard Worker }
1452*f6dc9357SAndroid Build Coastguard Worker }
1453*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->Locator_Defined)
1454*f6dc9357SAndroid Build Coastguard Worker {
1455*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("Locator");
1456*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->Locator_Error)
1457*f6dc9357SAndroid Build Coastguard Worker s += "-ERROR";
1458*f6dc9357SAndroid Build Coastguard Worker else
1459*f6dc9357SAndroid Build Coastguard Worker {
1460*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->Locator.Is_QuickOpen())
1461*f6dc9357SAndroid Build Coastguard Worker {
1462*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("QuickOpen:");
1463*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt64(arcInfo->Locator.QuickOpen);
1464*f6dc9357SAndroid Build Coastguard Worker }
1465*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->Locator.Is_Recovery())
1466*f6dc9357SAndroid Build Coastguard Worker {
1467*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("Recovery:");
1468*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt64(arcInfo->Locator.Recovery);
1469*f6dc9357SAndroid Build Coastguard Worker }
1470*f6dc9357SAndroid Build Coastguard Worker }
1471*f6dc9357SAndroid Build Coastguard Worker }
1472*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->UnknownExtraRecord)
1473*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("Unknown-Extra-Record");
1474*f6dc9357SAndroid Build Coastguard Worker
1475*f6dc9357SAndroid Build Coastguard Worker }
1476*f6dc9357SAndroid Build Coastguard Worker if (_comment_WasUsedInArc)
1477*f6dc9357SAndroid Build Coastguard Worker {
1478*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("Comment");
1479*f6dc9357SAndroid Build Coastguard Worker // s.Add_UInt32((UInt32)_comment.Size());
1480*f6dc9357SAndroid Build Coastguard Worker }
1481*f6dc9357SAndroid Build Coastguard Worker //
1482*f6dc9357SAndroid Build Coastguard Worker if (_acls.Size() != 0)
1483*f6dc9357SAndroid Build Coastguard Worker {
1484*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("ACL");
1485*f6dc9357SAndroid Build Coastguard Worker // s.Add_UInt32(_acls.Size());
1486*f6dc9357SAndroid Build Coastguard Worker }
1487*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
1488*f6dc9357SAndroid Build Coastguard Worker prop = s;
1489*f6dc9357SAndroid Build Coastguard Worker break;
1490*f6dc9357SAndroid Build Coastguard Worker }
1491*f6dc9357SAndroid Build Coastguard Worker case kpidEncrypted: if (arcInfo) prop = arcInfo->IsEncrypted; break; // it's for encrypted names.
1492*f6dc9357SAndroid Build Coastguard Worker case kpidIsVolume: if (arcInfo) prop = arcInfo->IsVolume(); break;
1493*f6dc9357SAndroid Build Coastguard Worker case kpidNumVolumes: prop = (UInt32)_arcs.Size(); break;
1494*f6dc9357SAndroid Build Coastguard Worker case kpidOffset: if (arcInfo && arcInfo->StartPos != 0) prop = arcInfo->StartPos; break;
1495*f6dc9357SAndroid Build Coastguard Worker
1496*f6dc9357SAndroid Build Coastguard Worker case kpidTotalPhySize:
1497*f6dc9357SAndroid Build Coastguard Worker {
1498*f6dc9357SAndroid Build Coastguard Worker if (_arcs.Size() > 1)
1499*f6dc9357SAndroid Build Coastguard Worker {
1500*f6dc9357SAndroid Build Coastguard Worker UInt64 sum = 0;
1501*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (v, _arcs)
1502*f6dc9357SAndroid Build Coastguard Worker sum += _arcs[v].Info.GetPhySize();
1503*f6dc9357SAndroid Build Coastguard Worker prop = sum;
1504*f6dc9357SAndroid Build Coastguard Worker }
1505*f6dc9357SAndroid Build Coastguard Worker break;
1506*f6dc9357SAndroid Build Coastguard Worker }
1507*f6dc9357SAndroid Build Coastguard Worker
1508*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize:
1509*f6dc9357SAndroid Build Coastguard Worker {
1510*f6dc9357SAndroid Build Coastguard Worker if (arcInfo)
1511*f6dc9357SAndroid Build Coastguard Worker prop = arcInfo->GetPhySize();
1512*f6dc9357SAndroid Build Coastguard Worker break;
1513*f6dc9357SAndroid Build Coastguard Worker }
1514*f6dc9357SAndroid Build Coastguard Worker
1515*f6dc9357SAndroid Build Coastguard Worker case kpidName:
1516*f6dc9357SAndroid Build Coastguard Worker if (arcInfo)
1517*f6dc9357SAndroid Build Coastguard Worker if (!arcInfo->Metadata_Error
1518*f6dc9357SAndroid Build Coastguard Worker && !arcInfo->Metadata.ArcName.IsEmpty())
1519*f6dc9357SAndroid Build Coastguard Worker {
1520*f6dc9357SAndroid Build Coastguard Worker UString s;
1521*f6dc9357SAndroid Build Coastguard Worker if (ConvertUTF8ToUnicode(arcInfo->Metadata.ArcName, s))
1522*f6dc9357SAndroid Build Coastguard Worker prop = s;
1523*f6dc9357SAndroid Build Coastguard Worker }
1524*f6dc9357SAndroid Build Coastguard Worker break;
1525*f6dc9357SAndroid Build Coastguard Worker
1526*f6dc9357SAndroid Build Coastguard Worker case kpidCTime:
1527*f6dc9357SAndroid Build Coastguard Worker if (arcInfo)
1528*f6dc9357SAndroid Build Coastguard Worker if (!arcInfo->Metadata_Error
1529*f6dc9357SAndroid Build Coastguard Worker && (arcInfo->Metadata.Flags & NMetadataFlags::kCTime))
1530*f6dc9357SAndroid Build Coastguard Worker {
1531*f6dc9357SAndroid Build Coastguard Worker const UInt64 ct = arcInfo->Metadata.CTime;
1532*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->Metadata.Flags & NMetadataFlags::kUnixTime)
1533*f6dc9357SAndroid Build Coastguard Worker {
1534*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->Metadata.Flags & NMetadataFlags::kNanoSec)
1535*f6dc9357SAndroid Build Coastguard Worker {
1536*f6dc9357SAndroid Build Coastguard Worker const UInt64 sec = ct / 1000000000;
1537*f6dc9357SAndroid Build Coastguard Worker const UInt64 ns = ct % 1000000000;
1538*f6dc9357SAndroid Build Coastguard Worker UInt64 wt = NTime::UnixTime64_To_FileTime64((Int64)sec);
1539*f6dc9357SAndroid Build Coastguard Worker wt += ns / 100;
1540*f6dc9357SAndroid Build Coastguard Worker const unsigned ns100 = (unsigned)(ns % 100);
1541*f6dc9357SAndroid Build Coastguard Worker FILETIME ft;
1542*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (DWORD)(UInt32)wt;
1543*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (DWORD)(UInt32)(wt >> 32);
1544*f6dc9357SAndroid Build Coastguard Worker prop.SetAsTimeFrom_FT_Prec_Ns100(ft, k_PropVar_TimePrec_1ns, ns100);
1545*f6dc9357SAndroid Build Coastguard Worker }
1546*f6dc9357SAndroid Build Coastguard Worker else
1547*f6dc9357SAndroid Build Coastguard Worker {
1548*f6dc9357SAndroid Build Coastguard Worker const UInt64 wt = NTime::UnixTime64_To_FileTime64((Int64)ct);
1549*f6dc9357SAndroid Build Coastguard Worker prop.SetAsTimeFrom_Ft64_Prec(wt, k_PropVar_TimePrec_Unix);
1550*f6dc9357SAndroid Build Coastguard Worker }
1551*f6dc9357SAndroid Build Coastguard Worker }
1552*f6dc9357SAndroid Build Coastguard Worker else
1553*f6dc9357SAndroid Build Coastguard Worker prop.SetAsTimeFrom_Ft64_Prec(ct, k_PropVar_TimePrec_100ns);
1554*f6dc9357SAndroid Build Coastguard Worker }
1555*f6dc9357SAndroid Build Coastguard Worker break;
1556*f6dc9357SAndroid Build Coastguard Worker
1557*f6dc9357SAndroid Build Coastguard Worker case kpidComment:
1558*f6dc9357SAndroid Build Coastguard Worker {
1559*f6dc9357SAndroid Build Coastguard Worker // if (!_arcs.IsEmpty())
1560*f6dc9357SAndroid Build Coastguard Worker {
1561*f6dc9357SAndroid Build Coastguard Worker // const CArc &arc = _arcs[0];
1562*f6dc9357SAndroid Build Coastguard Worker const CByteBuffer &cmt = _comment;
1563*f6dc9357SAndroid Build Coastguard Worker if (cmt.Size() != 0 /* && cmt.Size() < (1 << 16) */)
1564*f6dc9357SAndroid Build Coastguard Worker {
1565*f6dc9357SAndroid Build Coastguard Worker AString s;
1566*f6dc9357SAndroid Build Coastguard Worker s.SetFrom_CalcLen((const char *)(const Byte *)cmt, (unsigned)cmt.Size());
1567*f6dc9357SAndroid Build Coastguard Worker UString unicode;
1568*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(s, unicode);
1569*f6dc9357SAndroid Build Coastguard Worker prop = unicode;
1570*f6dc9357SAndroid Build Coastguard Worker }
1571*f6dc9357SAndroid Build Coastguard Worker }
1572*f6dc9357SAndroid Build Coastguard Worker break;
1573*f6dc9357SAndroid Build Coastguard Worker }
1574*f6dc9357SAndroid Build Coastguard Worker
1575*f6dc9357SAndroid Build Coastguard Worker case kpidNumBlocks:
1576*f6dc9357SAndroid Build Coastguard Worker {
1577*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)_numBlocks;
1578*f6dc9357SAndroid Build Coastguard Worker break;
1579*f6dc9357SAndroid Build Coastguard Worker }
1580*f6dc9357SAndroid Build Coastguard Worker
1581*f6dc9357SAndroid Build Coastguard Worker case kpidMethod:
1582*f6dc9357SAndroid Build Coastguard Worker {
1583*f6dc9357SAndroid Build Coastguard Worker AString s;
1584*f6dc9357SAndroid Build Coastguard Worker
1585*f6dc9357SAndroid Build Coastguard Worker UInt64 algo = _algo_Mask;
1586*f6dc9357SAndroid Build Coastguard Worker for (unsigned v = 0; algo != 0; v++, algo >>= 1)
1587*f6dc9357SAndroid Build Coastguard Worker {
1588*f6dc9357SAndroid Build Coastguard Worker if ((algo & 1) == 0)
1589*f6dc9357SAndroid Build Coastguard Worker continue;
1590*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("v");
1591*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(v + 6);
1592*f6dc9357SAndroid Build Coastguard Worker if (v < Z7_ARRAY_SIZE(_methodMasks))
1593*f6dc9357SAndroid Build Coastguard Worker {
1594*f6dc9357SAndroid Build Coastguard Worker const UInt64 dict = _dictMaxSizes[v];
1595*f6dc9357SAndroid Build Coastguard Worker if (dict)
1596*f6dc9357SAndroid Build Coastguard Worker {
1597*f6dc9357SAndroid Build Coastguard Worker char temp[24];
1598*f6dc9357SAndroid Build Coastguard Worker temp[0] = ':';
1599*f6dc9357SAndroid Build Coastguard Worker PrintDictSize(temp + 1, dict);
1600*f6dc9357SAndroid Build Coastguard Worker s += temp;
1601*f6dc9357SAndroid Build Coastguard Worker }
1602*f6dc9357SAndroid Build Coastguard Worker unsigned method = _methodMasks[v];
1603*f6dc9357SAndroid Build Coastguard Worker for (unsigned m = 0; method; m++, method >>= 1)
1604*f6dc9357SAndroid Build Coastguard Worker {
1605*f6dc9357SAndroid Build Coastguard Worker if ((method & 1) == 0)
1606*f6dc9357SAndroid Build Coastguard Worker continue;
1607*f6dc9357SAndroid Build Coastguard Worker s += ":m";
1608*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(m);
1609*f6dc9357SAndroid Build Coastguard Worker }
1610*f6dc9357SAndroid Build Coastguard Worker }
1611*f6dc9357SAndroid Build Coastguard Worker }
1612*f6dc9357SAndroid Build Coastguard Worker if (_rar5comapt_mask & 2)
1613*f6dc9357SAndroid Build Coastguard Worker {
1614*f6dc9357SAndroid Build Coastguard Worker s += ":c";
1615*f6dc9357SAndroid Build Coastguard Worker if (_rar5comapt_mask & 1)
1616*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('n');
1617*f6dc9357SAndroid Build Coastguard Worker }
1618*f6dc9357SAndroid Build Coastguard Worker prop = s;
1619*f6dc9357SAndroid Build Coastguard Worker break;
1620*f6dc9357SAndroid Build Coastguard Worker }
1621*f6dc9357SAndroid Build Coastguard Worker
1622*f6dc9357SAndroid Build Coastguard Worker case kpidError:
1623*f6dc9357SAndroid Build Coastguard Worker {
1624*f6dc9357SAndroid Build Coastguard Worker if (/* &_missingVol || */ !_missingVolName.IsEmpty())
1625*f6dc9357SAndroid Build Coastguard Worker {
1626*f6dc9357SAndroid Build Coastguard Worker UString s ("Missing volume : ");
1627*f6dc9357SAndroid Build Coastguard Worker s += _missingVolName;
1628*f6dc9357SAndroid Build Coastguard Worker prop = s;
1629*f6dc9357SAndroid Build Coastguard Worker }
1630*f6dc9357SAndroid Build Coastguard Worker break;
1631*f6dc9357SAndroid Build Coastguard Worker }
1632*f6dc9357SAndroid Build Coastguard Worker
1633*f6dc9357SAndroid Build Coastguard Worker case kpidErrorFlags:
1634*f6dc9357SAndroid Build Coastguard Worker {
1635*f6dc9357SAndroid Build Coastguard Worker UInt32 v = _errorFlags;
1636*f6dc9357SAndroid Build Coastguard Worker if (!_isArc)
1637*f6dc9357SAndroid Build Coastguard Worker v |= kpv_ErrorFlags_IsNotArc;
1638*f6dc9357SAndroid Build Coastguard Worker if (_error_in_ACL)
1639*f6dc9357SAndroid Build Coastguard Worker v |= kpv_ErrorFlags_HeadersError;
1640*f6dc9357SAndroid Build Coastguard Worker if (_split_Error)
1641*f6dc9357SAndroid Build Coastguard Worker v |= kpv_ErrorFlags_HeadersError;
1642*f6dc9357SAndroid Build Coastguard Worker prop = v;
1643*f6dc9357SAndroid Build Coastguard Worker break;
1644*f6dc9357SAndroid Build Coastguard Worker }
1645*f6dc9357SAndroid Build Coastguard Worker
1646*f6dc9357SAndroid Build Coastguard Worker /*
1647*f6dc9357SAndroid Build Coastguard Worker case kpidWarningFlags:
1648*f6dc9357SAndroid Build Coastguard Worker {
1649*f6dc9357SAndroid Build Coastguard Worker if (_warningFlags != 0)
1650*f6dc9357SAndroid Build Coastguard Worker prop = _warningFlags;
1651*f6dc9357SAndroid Build Coastguard Worker break;
1652*f6dc9357SAndroid Build Coastguard Worker }
1653*f6dc9357SAndroid Build Coastguard Worker */
1654*f6dc9357SAndroid Build Coastguard Worker
1655*f6dc9357SAndroid Build Coastguard Worker case kpidExtension:
1656*f6dc9357SAndroid Build Coastguard Worker if (_arcs.Size() == 1)
1657*f6dc9357SAndroid Build Coastguard Worker {
1658*f6dc9357SAndroid Build Coastguard Worker if (arcInfo->IsVolume())
1659*f6dc9357SAndroid Build Coastguard Worker {
1660*f6dc9357SAndroid Build Coastguard Worker AString s ("part");
1661*f6dc9357SAndroid Build Coastguard Worker UInt32 v = (UInt32)arcInfo->GetVolIndex() + 1;
1662*f6dc9357SAndroid Build Coastguard Worker if (v < 10)
1663*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('0');
1664*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(v);
1665*f6dc9357SAndroid Build Coastguard Worker s += ".rar";
1666*f6dc9357SAndroid Build Coastguard Worker prop = s;
1667*f6dc9357SAndroid Build Coastguard Worker }
1668*f6dc9357SAndroid Build Coastguard Worker }
1669*f6dc9357SAndroid Build Coastguard Worker break;
1670*f6dc9357SAndroid Build Coastguard Worker
1671*f6dc9357SAndroid Build Coastguard Worker case kpidIsAltStream: prop = true; break;
1672*f6dc9357SAndroid Build Coastguard Worker }
1673*f6dc9357SAndroid Build Coastguard Worker
1674*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
1675*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1676*f6dc9357SAndroid Build Coastguard Worker
1677*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1678*f6dc9357SAndroid Build Coastguard Worker }
1679*f6dc9357SAndroid Build Coastguard Worker
1680*f6dc9357SAndroid Build Coastguard Worker
1681*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
1682*f6dc9357SAndroid Build Coastguard Worker {
1683*f6dc9357SAndroid Build Coastguard Worker *numItems = (UInt32)_refs.Size();
1684*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1685*f6dc9357SAndroid Build Coastguard Worker }
1686*f6dc9357SAndroid Build Coastguard Worker
1687*f6dc9357SAndroid Build Coastguard Worker
1688*f6dc9357SAndroid Build Coastguard Worker static const Byte kRawProps[] =
1689*f6dc9357SAndroid Build Coastguard Worker {
1690*f6dc9357SAndroid Build Coastguard Worker kpidChecksum,
1691*f6dc9357SAndroid Build Coastguard Worker kpidNtSecure
1692*f6dc9357SAndroid Build Coastguard Worker };
1693*f6dc9357SAndroid Build Coastguard Worker
1694*f6dc9357SAndroid Build Coastguard Worker
1695*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))
1696*f6dc9357SAndroid Build Coastguard Worker {
1697*f6dc9357SAndroid Build Coastguard Worker *numProps = Z7_ARRAY_SIZE(kRawProps);
1698*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1699*f6dc9357SAndroid Build Coastguard Worker }
1700*f6dc9357SAndroid Build Coastguard Worker
1701*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID))
1702*f6dc9357SAndroid Build Coastguard Worker {
1703*f6dc9357SAndroid Build Coastguard Worker *propID = kRawProps[index];
1704*f6dc9357SAndroid Build Coastguard Worker *name = NULL;
1705*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1706*f6dc9357SAndroid Build Coastguard Worker }
1707*f6dc9357SAndroid Build Coastguard Worker
1708*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType))
1709*f6dc9357SAndroid Build Coastguard Worker {
1710*f6dc9357SAndroid Build Coastguard Worker *parentType = NParentType::kDir;
1711*f6dc9357SAndroid Build Coastguard Worker *parent = (UInt32)(Int32)-1;
1712*f6dc9357SAndroid Build Coastguard Worker
1713*f6dc9357SAndroid Build Coastguard Worker if (index >= _refs.Size())
1714*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1715*f6dc9357SAndroid Build Coastguard Worker
1716*f6dc9357SAndroid Build Coastguard Worker const CRefItem &ref = _refs[index];
1717*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[ref.Item];
1718*f6dc9357SAndroid Build Coastguard Worker
1719*f6dc9357SAndroid Build Coastguard Worker if (item.Is_STM() && ref.Parent >= 0)
1720*f6dc9357SAndroid Build Coastguard Worker {
1721*f6dc9357SAndroid Build Coastguard Worker *parent = (UInt32)ref.Parent;
1722*f6dc9357SAndroid Build Coastguard Worker *parentType = NParentType::kAltStream;
1723*f6dc9357SAndroid Build Coastguard Worker }
1724*f6dc9357SAndroid Build Coastguard Worker
1725*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1726*f6dc9357SAndroid Build Coastguard Worker }
1727*f6dc9357SAndroid Build Coastguard Worker
1728*f6dc9357SAndroid Build Coastguard Worker
1729*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))
1730*f6dc9357SAndroid Build Coastguard Worker {
1731*f6dc9357SAndroid Build Coastguard Worker *data = NULL;
1732*f6dc9357SAndroid Build Coastguard Worker *dataSize = 0;
1733*f6dc9357SAndroid Build Coastguard Worker *propType = 0;
1734*f6dc9357SAndroid Build Coastguard Worker
1735*f6dc9357SAndroid Build Coastguard Worker if (index >= _refs.Size())
1736*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1737*f6dc9357SAndroid Build Coastguard Worker
1738*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[_refs[index].Item];
1739*f6dc9357SAndroid Build Coastguard Worker
1740*f6dc9357SAndroid Build Coastguard Worker if (propID == kpidNtSecure)
1741*f6dc9357SAndroid Build Coastguard Worker {
1742*f6dc9357SAndroid Build Coastguard Worker if (item.ACL >= 0)
1743*f6dc9357SAndroid Build Coastguard Worker {
1744*f6dc9357SAndroid Build Coastguard Worker const CByteBuffer &buf = _acls[item.ACL];
1745*f6dc9357SAndroid Build Coastguard Worker *dataSize = (UInt32)buf.Size();
1746*f6dc9357SAndroid Build Coastguard Worker *propType = NPropDataType::kRaw;
1747*f6dc9357SAndroid Build Coastguard Worker *data = (const Byte *)buf;
1748*f6dc9357SAndroid Build Coastguard Worker }
1749*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1750*f6dc9357SAndroid Build Coastguard Worker }
1751*f6dc9357SAndroid Build Coastguard Worker
1752*f6dc9357SAndroid Build Coastguard Worker if (propID == kpidChecksum)
1753*f6dc9357SAndroid Build Coastguard Worker {
1754*f6dc9357SAndroid Build Coastguard Worker const int hashRecOffset = item.FindExtra_Blake();
1755*f6dc9357SAndroid Build Coastguard Worker if (hashRecOffset >= 0)
1756*f6dc9357SAndroid Build Coastguard Worker {
1757*f6dc9357SAndroid Build Coastguard Worker *dataSize = Z7_BLAKE2S_DIGEST_SIZE;
1758*f6dc9357SAndroid Build Coastguard Worker *propType = NPropDataType::kRaw;
1759*f6dc9357SAndroid Build Coastguard Worker *data = item.Extra + (unsigned)hashRecOffset;
1760*f6dc9357SAndroid Build Coastguard Worker }
1761*f6dc9357SAndroid Build Coastguard Worker /*
1762*f6dc9357SAndroid Build Coastguard Worker else if (item.Has_CRC() && item.IsEncrypted())
1763*f6dc9357SAndroid Build Coastguard Worker {
1764*f6dc9357SAndroid Build Coastguard Worker *dataSize = 4;
1765*f6dc9357SAndroid Build Coastguard Worker *propType = NPropDataType::kRaw;
1766*f6dc9357SAndroid Build Coastguard Worker *data = &item->CRC; // we must show same value for big/little endian here
1767*f6dc9357SAndroid Build Coastguard Worker }
1768*f6dc9357SAndroid Build Coastguard Worker */
1769*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1770*f6dc9357SAndroid Build Coastguard Worker }
1771*f6dc9357SAndroid Build Coastguard Worker
1772*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1773*f6dc9357SAndroid Build Coastguard Worker }
1774*f6dc9357SAndroid Build Coastguard Worker
1775*f6dc9357SAndroid Build Coastguard Worker
1776*f6dc9357SAndroid Build Coastguard Worker static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CPropVariant &prop)
1777*f6dc9357SAndroid Build Coastguard Worker {
1778*f6dc9357SAndroid Build Coastguard Worker unsigned size;
1779*f6dc9357SAndroid Build Coastguard Worker const int offset = item.FindExtra(NExtraID::kTime, size);
1780*f6dc9357SAndroid Build Coastguard Worker if (offset < 0)
1781*f6dc9357SAndroid Build Coastguard Worker return;
1782*f6dc9357SAndroid Build Coastguard Worker
1783*f6dc9357SAndroid Build Coastguard Worker const Byte *p = item.Extra + (unsigned)offset;
1784*f6dc9357SAndroid Build Coastguard Worker UInt64 flags;
1785*f6dc9357SAndroid Build Coastguard Worker // PARSE_VAR_INT(p, size, flags)
1786*f6dc9357SAndroid Build Coastguard Worker {
1787*f6dc9357SAndroid Build Coastguard Worker const unsigned num = ReadVarInt(p, size, &flags);
1788*f6dc9357SAndroid Build Coastguard Worker if (num == 0)
1789*f6dc9357SAndroid Build Coastguard Worker return;
1790*f6dc9357SAndroid Build Coastguard Worker p += num;
1791*f6dc9357SAndroid Build Coastguard Worker size -= num;
1792*f6dc9357SAndroid Build Coastguard Worker }
1793*f6dc9357SAndroid Build Coastguard Worker
1794*f6dc9357SAndroid Build Coastguard Worker if ((flags & (NTimeRecord::NFlags::kMTime << stampIndex)) == 0)
1795*f6dc9357SAndroid Build Coastguard Worker return;
1796*f6dc9357SAndroid Build Coastguard Worker
1797*f6dc9357SAndroid Build Coastguard Worker unsigned numStamps = 0;
1798*f6dc9357SAndroid Build Coastguard Worker unsigned curStamp = 0;
1799*f6dc9357SAndroid Build Coastguard Worker
1800*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < 3; i++)
1801*f6dc9357SAndroid Build Coastguard Worker if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0)
1802*f6dc9357SAndroid Build Coastguard Worker {
1803*f6dc9357SAndroid Build Coastguard Worker if (i == stampIndex)
1804*f6dc9357SAndroid Build Coastguard Worker curStamp = numStamps;
1805*f6dc9357SAndroid Build Coastguard Worker numStamps++;
1806*f6dc9357SAndroid Build Coastguard Worker }
1807*f6dc9357SAndroid Build Coastguard Worker
1808*f6dc9357SAndroid Build Coastguard Worker FILETIME ft;
1809*f6dc9357SAndroid Build Coastguard Worker
1810*f6dc9357SAndroid Build Coastguard Worker unsigned timePrec = 0;
1811*f6dc9357SAndroid Build Coastguard Worker unsigned ns100 = 0;
1812*f6dc9357SAndroid Build Coastguard Worker
1813*f6dc9357SAndroid Build Coastguard Worker if ((flags & NTimeRecord::NFlags::kUnixTime) != 0)
1814*f6dc9357SAndroid Build Coastguard Worker {
1815*f6dc9357SAndroid Build Coastguard Worker curStamp *= 4;
1816*f6dc9357SAndroid Build Coastguard Worker if (curStamp + 4 > size)
1817*f6dc9357SAndroid Build Coastguard Worker return;
1818*f6dc9357SAndroid Build Coastguard Worker p += curStamp;
1819*f6dc9357SAndroid Build Coastguard Worker UInt64 val = NTime::UnixTime_To_FileTime64(Get32(p));
1820*f6dc9357SAndroid Build Coastguard Worker numStamps *= 4;
1821*f6dc9357SAndroid Build Coastguard Worker timePrec = k_PropVar_TimePrec_Unix;
1822*f6dc9357SAndroid Build Coastguard Worker if ((flags & NTimeRecord::NFlags::kUnixNs) != 0 && numStamps * 2 <= size)
1823*f6dc9357SAndroid Build Coastguard Worker {
1824*f6dc9357SAndroid Build Coastguard Worker const UInt32 ns = Get32(p + numStamps) & 0x3FFFFFFF;
1825*f6dc9357SAndroid Build Coastguard Worker if (ns < 1000000000)
1826*f6dc9357SAndroid Build Coastguard Worker {
1827*f6dc9357SAndroid Build Coastguard Worker val += ns / 100;
1828*f6dc9357SAndroid Build Coastguard Worker ns100 = (unsigned)(ns % 100);
1829*f6dc9357SAndroid Build Coastguard Worker timePrec = k_PropVar_TimePrec_1ns;
1830*f6dc9357SAndroid Build Coastguard Worker }
1831*f6dc9357SAndroid Build Coastguard Worker }
1832*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (DWORD)val;
1833*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (DWORD)(val >> 32);
1834*f6dc9357SAndroid Build Coastguard Worker }
1835*f6dc9357SAndroid Build Coastguard Worker else
1836*f6dc9357SAndroid Build Coastguard Worker {
1837*f6dc9357SAndroid Build Coastguard Worker curStamp *= 8;
1838*f6dc9357SAndroid Build Coastguard Worker if (curStamp + 8 > size)
1839*f6dc9357SAndroid Build Coastguard Worker return;
1840*f6dc9357SAndroid Build Coastguard Worker p += curStamp;
1841*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = Get32(p);
1842*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = Get32(p + 4);
1843*f6dc9357SAndroid Build Coastguard Worker }
1844*f6dc9357SAndroid Build Coastguard Worker
1845*f6dc9357SAndroid Build Coastguard Worker prop.SetAsTimeFrom_FT_Prec_Ns100(ft, timePrec, ns100);
1846*f6dc9357SAndroid Build Coastguard Worker }
1847*f6dc9357SAndroid Build Coastguard Worker
1848*f6dc9357SAndroid Build Coastguard Worker
1849*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
1850*f6dc9357SAndroid Build Coastguard Worker {
1851*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1852*f6dc9357SAndroid Build Coastguard Worker
1853*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
1854*f6dc9357SAndroid Build Coastguard Worker const CRefItem &ref = _refs[index];
1855*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[ref.Item];
1856*f6dc9357SAndroid Build Coastguard Worker const CItem &lastItem = _items[ref.Last];
1857*f6dc9357SAndroid Build Coastguard Worker
1858*f6dc9357SAndroid Build Coastguard Worker switch (propID)
1859*f6dc9357SAndroid Build Coastguard Worker {
1860*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
1861*f6dc9357SAndroid Build Coastguard Worker {
1862*f6dc9357SAndroid Build Coastguard Worker UString unicodeName;
1863*f6dc9357SAndroid Build Coastguard Worker
1864*f6dc9357SAndroid Build Coastguard Worker if (item.Is_STM())
1865*f6dc9357SAndroid Build Coastguard Worker {
1866*f6dc9357SAndroid Build Coastguard Worker AString s;
1867*f6dc9357SAndroid Build Coastguard Worker if (ref.Parent >= 0)
1868*f6dc9357SAndroid Build Coastguard Worker {
1869*f6dc9357SAndroid Build Coastguard Worker const CItem &mainItem = _items[_refs[ref.Parent].Item];
1870*f6dc9357SAndroid Build Coastguard Worker s = mainItem.Name;
1871*f6dc9357SAndroid Build Coastguard Worker }
1872*f6dc9357SAndroid Build Coastguard Worker
1873*f6dc9357SAndroid Build Coastguard Worker AString name;
1874*f6dc9357SAndroid Build Coastguard Worker item.GetAltStreamName(name);
1875*f6dc9357SAndroid Build Coastguard Worker if (name[0] != ':')
1876*f6dc9357SAndroid Build Coastguard Worker s.Add_Colon();
1877*f6dc9357SAndroid Build Coastguard Worker s += name;
1878*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(s, unicodeName);
1879*f6dc9357SAndroid Build Coastguard Worker }
1880*f6dc9357SAndroid Build Coastguard Worker else
1881*f6dc9357SAndroid Build Coastguard Worker {
1882*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(item.Name, unicodeName);
1883*f6dc9357SAndroid Build Coastguard Worker
1884*f6dc9357SAndroid Build Coastguard Worker if (item.Version_Defined)
1885*f6dc9357SAndroid Build Coastguard Worker {
1886*f6dc9357SAndroid Build Coastguard Worker char temp[32];
1887*f6dc9357SAndroid Build Coastguard Worker // temp[0] = ';';
1888*f6dc9357SAndroid Build Coastguard Worker // ConvertUInt64ToString(item.Version, temp + 1);
1889*f6dc9357SAndroid Build Coastguard Worker // unicodeName += temp;
1890*f6dc9357SAndroid Build Coastguard Worker ConvertUInt64ToString(item.Version, temp);
1891*f6dc9357SAndroid Build Coastguard Worker UString s2 ("[VER]" STRING_PATH_SEPARATOR);
1892*f6dc9357SAndroid Build Coastguard Worker s2 += temp;
1893*f6dc9357SAndroid Build Coastguard Worker s2.Add_PathSepar();
1894*f6dc9357SAndroid Build Coastguard Worker unicodeName.Insert(0, s2);
1895*f6dc9357SAndroid Build Coastguard Worker }
1896*f6dc9357SAndroid Build Coastguard Worker }
1897*f6dc9357SAndroid Build Coastguard Worker
1898*f6dc9357SAndroid Build Coastguard Worker NItemName::ReplaceToOsSlashes_Remove_TailSlash(unicodeName);
1899*f6dc9357SAndroid Build Coastguard Worker prop = unicodeName;
1900*f6dc9357SAndroid Build Coastguard Worker
1901*f6dc9357SAndroid Build Coastguard Worker break;
1902*f6dc9357SAndroid Build Coastguard Worker }
1903*f6dc9357SAndroid Build Coastguard Worker
1904*f6dc9357SAndroid Build Coastguard Worker case kpidIsDir: prop = item.IsDir(); break;
1905*f6dc9357SAndroid Build Coastguard Worker case kpidSize: if (!lastItem.Is_UnknownSize()) prop = lastItem.Size; break;
1906*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: prop = GetPackSize((unsigned)index); break;
1907*f6dc9357SAndroid Build Coastguard Worker
1908*f6dc9357SAndroid Build Coastguard Worker case kpidMTime:
1909*f6dc9357SAndroid Build Coastguard Worker {
1910*f6dc9357SAndroid Build Coastguard Worker TimeRecordToProp(item, NTimeRecord::k_Index_MTime, prop);
1911*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_EMPTY && item.Has_UnixMTime())
1912*f6dc9357SAndroid Build Coastguard Worker PropVariant_SetFrom_UnixTime(prop, item.UnixMTime);
1913*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_EMPTY && ref.Parent >= 0)
1914*f6dc9357SAndroid Build Coastguard Worker {
1915*f6dc9357SAndroid Build Coastguard Worker const CItem &baseItem = _items[_refs[ref.Parent].Item];
1916*f6dc9357SAndroid Build Coastguard Worker TimeRecordToProp(baseItem, NTimeRecord::k_Index_MTime, prop);
1917*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_EMPTY && baseItem.Has_UnixMTime())
1918*f6dc9357SAndroid Build Coastguard Worker PropVariant_SetFrom_UnixTime(prop, baseItem.UnixMTime);
1919*f6dc9357SAndroid Build Coastguard Worker }
1920*f6dc9357SAndroid Build Coastguard Worker break;
1921*f6dc9357SAndroid Build Coastguard Worker }
1922*f6dc9357SAndroid Build Coastguard Worker case kpidCTime: TimeRecordToProp(item, NTimeRecord::k_Index_CTime, prop); break;
1923*f6dc9357SAndroid Build Coastguard Worker case kpidATime: TimeRecordToProp(item, NTimeRecord::k_Index_ATime, prop); break;
1924*f6dc9357SAndroid Build Coastguard Worker
1925*f6dc9357SAndroid Build Coastguard Worker case kpidName:
1926*f6dc9357SAndroid Build Coastguard Worker {
1927*f6dc9357SAndroid Build Coastguard Worker if (item.Is_STM())
1928*f6dc9357SAndroid Build Coastguard Worker {
1929*f6dc9357SAndroid Build Coastguard Worker AString name;
1930*f6dc9357SAndroid Build Coastguard Worker item.GetAltStreamName(name);
1931*f6dc9357SAndroid Build Coastguard Worker if (name[0] == ':')
1932*f6dc9357SAndroid Build Coastguard Worker {
1933*f6dc9357SAndroid Build Coastguard Worker name.DeleteFrontal(1);
1934*f6dc9357SAndroid Build Coastguard Worker UString unicodeName;
1935*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(name, unicodeName);
1936*f6dc9357SAndroid Build Coastguard Worker prop = unicodeName;
1937*f6dc9357SAndroid Build Coastguard Worker }
1938*f6dc9357SAndroid Build Coastguard Worker }
1939*f6dc9357SAndroid Build Coastguard Worker break;
1940*f6dc9357SAndroid Build Coastguard Worker }
1941*f6dc9357SAndroid Build Coastguard Worker
1942*f6dc9357SAndroid Build Coastguard Worker case kpidIsAltStream: prop = item.Is_STM(); break;
1943*f6dc9357SAndroid Build Coastguard Worker
1944*f6dc9357SAndroid Build Coastguard Worker case kpidSymLink: item.Link_to_Prop(NLinkType::kUnixSymLink, prop); break;
1945*f6dc9357SAndroid Build Coastguard Worker case kpidHardLink: item.Link_to_Prop(NLinkType::kHardLink, prop); break;
1946*f6dc9357SAndroid Build Coastguard Worker case kpidCopyLink: item.Link_to_Prop(NLinkType::kFileCopy, prop); break;
1947*f6dc9357SAndroid Build Coastguard Worker
1948*f6dc9357SAndroid Build Coastguard Worker case kpidAttrib: prop = item.GetWinAttrib(); break;
1949*f6dc9357SAndroid Build Coastguard Worker case kpidPosixAttrib:
1950*f6dc9357SAndroid Build Coastguard Worker if (item.HostOS == kHost_Unix)
1951*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)item.Attrib;
1952*f6dc9357SAndroid Build Coastguard Worker break;
1953*f6dc9357SAndroid Build Coastguard Worker
1954*f6dc9357SAndroid Build Coastguard Worker case kpidEncrypted: prop = item.IsEncrypted(); break;
1955*f6dc9357SAndroid Build Coastguard Worker case kpidSolid: prop = item.IsSolid(); break;
1956*f6dc9357SAndroid Build Coastguard Worker
1957*f6dc9357SAndroid Build Coastguard Worker case kpidSplitBefore: prop = item.IsSplitBefore(); break;
1958*f6dc9357SAndroid Build Coastguard Worker case kpidSplitAfter: prop = lastItem.IsSplitAfter(); break;
1959*f6dc9357SAndroid Build Coastguard Worker
1960*f6dc9357SAndroid Build Coastguard Worker case kpidVolumeIndex:
1961*f6dc9357SAndroid Build Coastguard Worker {
1962*f6dc9357SAndroid Build Coastguard Worker if (item.VolIndex < _arcs.Size())
1963*f6dc9357SAndroid Build Coastguard Worker {
1964*f6dc9357SAndroid Build Coastguard Worker const CInArcInfo &arcInfo = _arcs[item.VolIndex].Info;
1965*f6dc9357SAndroid Build Coastguard Worker if (arcInfo.IsVolume())
1966*f6dc9357SAndroid Build Coastguard Worker prop = (UInt64)arcInfo.GetVolIndex();
1967*f6dc9357SAndroid Build Coastguard Worker }
1968*f6dc9357SAndroid Build Coastguard Worker break;
1969*f6dc9357SAndroid Build Coastguard Worker }
1970*f6dc9357SAndroid Build Coastguard Worker
1971*f6dc9357SAndroid Build Coastguard Worker case kpidCRC:
1972*f6dc9357SAndroid Build Coastguard Worker {
1973*f6dc9357SAndroid Build Coastguard Worker const CItem *item2 = (lastItem.IsSplitAfter() ? &item : &lastItem);
1974*f6dc9357SAndroid Build Coastguard Worker // we don't want to show crc for encrypted file here,
1975*f6dc9357SAndroid Build Coastguard Worker // because crc is also encrrypted.
1976*f6dc9357SAndroid Build Coastguard Worker if (item2->Has_CRC() && !item2->IsEncrypted())
1977*f6dc9357SAndroid Build Coastguard Worker prop = item2->CRC;
1978*f6dc9357SAndroid Build Coastguard Worker break;
1979*f6dc9357SAndroid Build Coastguard Worker }
1980*f6dc9357SAndroid Build Coastguard Worker
1981*f6dc9357SAndroid Build Coastguard Worker case kpidMethod:
1982*f6dc9357SAndroid Build Coastguard Worker {
1983*f6dc9357SAndroid Build Coastguard Worker char temp[128];
1984*f6dc9357SAndroid Build Coastguard Worker const unsigned algo = item.Get_AlgoVersion_RawBits();
1985*f6dc9357SAndroid Build Coastguard Worker char *s = temp;
1986*f6dc9357SAndroid Build Coastguard Worker // if (algo != 0)
1987*f6dc9357SAndroid Build Coastguard Worker {
1988*f6dc9357SAndroid Build Coastguard Worker *s++ = 'v';
1989*f6dc9357SAndroid Build Coastguard Worker s = ConvertUInt32ToString((UInt32)algo + 6, s);
1990*f6dc9357SAndroid Build Coastguard Worker if (item.Is_Rar5_Compat())
1991*f6dc9357SAndroid Build Coastguard Worker *s++ = 'c';
1992*f6dc9357SAndroid Build Coastguard Worker *s++ = ':';
1993*f6dc9357SAndroid Build Coastguard Worker }
1994*f6dc9357SAndroid Build Coastguard Worker {
1995*f6dc9357SAndroid Build Coastguard Worker const unsigned m = item.Get_Method();
1996*f6dc9357SAndroid Build Coastguard Worker *s++ = 'm';
1997*f6dc9357SAndroid Build Coastguard Worker *s++ = (char)(m + '0');
1998*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDir())
1999*f6dc9357SAndroid Build Coastguard Worker {
2000*f6dc9357SAndroid Build Coastguard Worker *s++ = ':';
2001*f6dc9357SAndroid Build Coastguard Worker const unsigned dictMain = item.Get_DictSize_Main();
2002*f6dc9357SAndroid Build Coastguard Worker const unsigned frac = item.Get_DictSize_Frac();
2003*f6dc9357SAndroid Build Coastguard Worker /*
2004*f6dc9357SAndroid Build Coastguard Worker if (frac == 0 && algo == 0)
2005*f6dc9357SAndroid Build Coastguard Worker s = ConvertUInt32ToString(dictMain + 17, s);
2006*f6dc9357SAndroid Build Coastguard Worker else
2007*f6dc9357SAndroid Build Coastguard Worker */
2008*f6dc9357SAndroid Build Coastguard Worker s = PrintDictSize(s, (UInt64)(32 + frac) << (12 + dictMain));
2009*f6dc9357SAndroid Build Coastguard Worker if (item.Is_Rar5_Compat())
2010*f6dc9357SAndroid Build Coastguard Worker {
2011*f6dc9357SAndroid Build Coastguard Worker *s++ = ':';
2012*f6dc9357SAndroid Build Coastguard Worker *s++ = 'c';
2013*f6dc9357SAndroid Build Coastguard Worker }
2014*f6dc9357SAndroid Build Coastguard Worker }
2015*f6dc9357SAndroid Build Coastguard Worker }
2016*f6dc9357SAndroid Build Coastguard Worker unsigned cryptoSize = 0;
2017*f6dc9357SAndroid Build Coastguard Worker const int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize);
2018*f6dc9357SAndroid Build Coastguard Worker if (cryptoOffset >= 0)
2019*f6dc9357SAndroid Build Coastguard Worker {
2020*f6dc9357SAndroid Build Coastguard Worker *s++ = ' ';
2021*f6dc9357SAndroid Build Coastguard Worker CCryptoInfo cryptoInfo;
2022*f6dc9357SAndroid Build Coastguard Worker const bool isOK = cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize);
2023*f6dc9357SAndroid Build Coastguard Worker if (cryptoInfo.Algo == 0)
2024*f6dc9357SAndroid Build Coastguard Worker s = MyStpCpy(s, "AES");
2025*f6dc9357SAndroid Build Coastguard Worker else
2026*f6dc9357SAndroid Build Coastguard Worker {
2027*f6dc9357SAndroid Build Coastguard Worker s = MyStpCpy(s, "Crypto_");
2028*f6dc9357SAndroid Build Coastguard Worker s = ConvertUInt64ToString(cryptoInfo.Algo, s);
2029*f6dc9357SAndroid Build Coastguard Worker }
2030*f6dc9357SAndroid Build Coastguard Worker if (isOK)
2031*f6dc9357SAndroid Build Coastguard Worker {
2032*f6dc9357SAndroid Build Coastguard Worker *s++ = ':';
2033*f6dc9357SAndroid Build Coastguard Worker s = ConvertUInt32ToString(cryptoInfo.Cnt, s);
2034*f6dc9357SAndroid Build Coastguard Worker *s++ = ':';
2035*f6dc9357SAndroid Build Coastguard Worker s = ConvertUInt64ToString(cryptoInfo.Flags, s);
2036*f6dc9357SAndroid Build Coastguard Worker }
2037*f6dc9357SAndroid Build Coastguard Worker }
2038*f6dc9357SAndroid Build Coastguard Worker *s = 0;
2039*f6dc9357SAndroid Build Coastguard Worker prop = temp;
2040*f6dc9357SAndroid Build Coastguard Worker break;
2041*f6dc9357SAndroid Build Coastguard Worker }
2042*f6dc9357SAndroid Build Coastguard Worker
2043*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts:
2044*f6dc9357SAndroid Build Coastguard Worker {
2045*f6dc9357SAndroid Build Coastguard Worker AString s;
2046*f6dc9357SAndroid Build Coastguard Worker
2047*f6dc9357SAndroid Build Coastguard Worker if (item.ACL >= 0)
2048*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("ACL");
2049*f6dc9357SAndroid Build Coastguard Worker
2050*f6dc9357SAndroid Build Coastguard Worker const UInt32 flags = item.Flags;
2051*f6dc9357SAndroid Build Coastguard Worker if (flags != 0)
2052*f6dc9357SAndroid Build Coastguard Worker {
2053*f6dc9357SAndroid Build Coastguard Worker const AString s2 = FlagsToString(k_FileFlags, Z7_ARRAY_SIZE(k_FileFlags), flags);
2054*f6dc9357SAndroid Build Coastguard Worker if (!s2.IsEmpty())
2055*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced(s2);
2056*f6dc9357SAndroid Build Coastguard Worker }
2057*f6dc9357SAndroid Build Coastguard Worker
2058*f6dc9357SAndroid Build Coastguard Worker item.PrintInfo(s);
2059*f6dc9357SAndroid Build Coastguard Worker
2060*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
2061*f6dc9357SAndroid Build Coastguard Worker prop = s;
2062*f6dc9357SAndroid Build Coastguard Worker break;
2063*f6dc9357SAndroid Build Coastguard Worker }
2064*f6dc9357SAndroid Build Coastguard Worker
2065*f6dc9357SAndroid Build Coastguard Worker
2066*f6dc9357SAndroid Build Coastguard Worker case kpidHostOS:
2067*f6dc9357SAndroid Build Coastguard Worker if (item.HostOS < Z7_ARRAY_SIZE(kHostOS))
2068*f6dc9357SAndroid Build Coastguard Worker prop = kHostOS[(size_t)item.HostOS];
2069*f6dc9357SAndroid Build Coastguard Worker else
2070*f6dc9357SAndroid Build Coastguard Worker prop = (UInt64)item.HostOS;
2071*f6dc9357SAndroid Build Coastguard Worker break;
2072*f6dc9357SAndroid Build Coastguard Worker }
2073*f6dc9357SAndroid Build Coastguard Worker
2074*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
2075*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2076*f6dc9357SAndroid Build Coastguard Worker
2077*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2078*f6dc9357SAndroid Build Coastguard Worker }
2079*f6dc9357SAndroid Build Coastguard Worker
2080*f6dc9357SAndroid Build Coastguard Worker
2081*f6dc9357SAndroid Build Coastguard Worker
2082*f6dc9357SAndroid Build Coastguard Worker // ---------- Copy Links ----------
2083*f6dc9357SAndroid Build Coastguard Worker
2084*f6dc9357SAndroid Build Coastguard Worker static int CompareItemsPaths(const CHandler &handler, unsigned p1, unsigned p2, const AString *name1)
2085*f6dc9357SAndroid Build Coastguard Worker {
2086*f6dc9357SAndroid Build Coastguard Worker const CItem &item1 = handler._items[handler._refs[p1].Item];
2087*f6dc9357SAndroid Build Coastguard Worker const CItem &item2 = handler._items[handler._refs[p2].Item];
2088*f6dc9357SAndroid Build Coastguard Worker
2089*f6dc9357SAndroid Build Coastguard Worker if (item1.Version_Defined)
2090*f6dc9357SAndroid Build Coastguard Worker {
2091*f6dc9357SAndroid Build Coastguard Worker if (!item2.Version_Defined)
2092*f6dc9357SAndroid Build Coastguard Worker return -1;
2093*f6dc9357SAndroid Build Coastguard Worker const int res = MyCompare(item1.Version, item2.Version);
2094*f6dc9357SAndroid Build Coastguard Worker if (res != 0)
2095*f6dc9357SAndroid Build Coastguard Worker return res;
2096*f6dc9357SAndroid Build Coastguard Worker }
2097*f6dc9357SAndroid Build Coastguard Worker else if (item2.Version_Defined)
2098*f6dc9357SAndroid Build Coastguard Worker return 1;
2099*f6dc9357SAndroid Build Coastguard Worker
2100*f6dc9357SAndroid Build Coastguard Worker if (!name1)
2101*f6dc9357SAndroid Build Coastguard Worker name1 = &item1.Name;
2102*f6dc9357SAndroid Build Coastguard Worker return strcmp(*name1, item2.Name);
2103*f6dc9357SAndroid Build Coastguard Worker }
2104*f6dc9357SAndroid Build Coastguard Worker
2105*f6dc9357SAndroid Build Coastguard Worker static int CompareItemsPaths2(const CHandler &handler, unsigned p1, unsigned p2, const AString *name1)
2106*f6dc9357SAndroid Build Coastguard Worker {
2107*f6dc9357SAndroid Build Coastguard Worker const int res = CompareItemsPaths(handler, p1, p2, name1);
2108*f6dc9357SAndroid Build Coastguard Worker if (res != 0)
2109*f6dc9357SAndroid Build Coastguard Worker return res;
2110*f6dc9357SAndroid Build Coastguard Worker return MyCompare(p1, p2);
2111*f6dc9357SAndroid Build Coastguard Worker }
2112*f6dc9357SAndroid Build Coastguard Worker
2113*f6dc9357SAndroid Build Coastguard Worker static int CompareItemsPaths_Sort(const unsigned *p1, const unsigned *p2, void *param)
2114*f6dc9357SAndroid Build Coastguard Worker {
2115*f6dc9357SAndroid Build Coastguard Worker return CompareItemsPaths2(*(const CHandler *)param, *p1, *p2, NULL);
2116*f6dc9357SAndroid Build Coastguard Worker }
2117*f6dc9357SAndroid Build Coastguard Worker
2118*f6dc9357SAndroid Build Coastguard Worker static int FindLink(const CHandler &handler, const CUIntVector &sorted,
2119*f6dc9357SAndroid Build Coastguard Worker const AString &s, unsigned index)
2120*f6dc9357SAndroid Build Coastguard Worker {
2121*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = sorted.Size();
2122*f6dc9357SAndroid Build Coastguard Worker for (;;)
2123*f6dc9357SAndroid Build Coastguard Worker {
2124*f6dc9357SAndroid Build Coastguard Worker if (left == right)
2125*f6dc9357SAndroid Build Coastguard Worker {
2126*f6dc9357SAndroid Build Coastguard Worker if (left > 0)
2127*f6dc9357SAndroid Build Coastguard Worker {
2128*f6dc9357SAndroid Build Coastguard Worker const unsigned refIndex = sorted[left - 1];
2129*f6dc9357SAndroid Build Coastguard Worker if (CompareItemsPaths(handler, index, refIndex, &s) == 0)
2130*f6dc9357SAndroid Build Coastguard Worker return (int)refIndex;
2131*f6dc9357SAndroid Build Coastguard Worker }
2132*f6dc9357SAndroid Build Coastguard Worker if (right < sorted.Size())
2133*f6dc9357SAndroid Build Coastguard Worker {
2134*f6dc9357SAndroid Build Coastguard Worker const unsigned refIndex = sorted[right];
2135*f6dc9357SAndroid Build Coastguard Worker if (CompareItemsPaths(handler, index, refIndex, &s) == 0)
2136*f6dc9357SAndroid Build Coastguard Worker return (int)refIndex;
2137*f6dc9357SAndroid Build Coastguard Worker }
2138*f6dc9357SAndroid Build Coastguard Worker return -1;
2139*f6dc9357SAndroid Build Coastguard Worker }
2140*f6dc9357SAndroid Build Coastguard Worker
2141*f6dc9357SAndroid Build Coastguard Worker const unsigned mid = (left + right) / 2;
2142*f6dc9357SAndroid Build Coastguard Worker const unsigned refIndex = sorted[mid];
2143*f6dc9357SAndroid Build Coastguard Worker const int compare = CompareItemsPaths2(handler, index, refIndex, &s);
2144*f6dc9357SAndroid Build Coastguard Worker if (compare == 0)
2145*f6dc9357SAndroid Build Coastguard Worker return (int)refIndex;
2146*f6dc9357SAndroid Build Coastguard Worker if (compare < 0)
2147*f6dc9357SAndroid Build Coastguard Worker right = mid;
2148*f6dc9357SAndroid Build Coastguard Worker else
2149*f6dc9357SAndroid Build Coastguard Worker left = mid + 1;
2150*f6dc9357SAndroid Build Coastguard Worker }
2151*f6dc9357SAndroid Build Coastguard Worker }
2152*f6dc9357SAndroid Build Coastguard Worker
2153*f6dc9357SAndroid Build Coastguard Worker void CHandler::FillLinks()
2154*f6dc9357SAndroid Build Coastguard Worker {
2155*f6dc9357SAndroid Build Coastguard Worker unsigned i;
2156*f6dc9357SAndroid Build Coastguard Worker
2157*f6dc9357SAndroid Build Coastguard Worker bool need_FillLinks = false;
2158*f6dc9357SAndroid Build Coastguard Worker
2159*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _refs.Size(); i++)
2160*f6dc9357SAndroid Build Coastguard Worker {
2161*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[_refs[i].Item];
2162*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDir()
2163*f6dc9357SAndroid Build Coastguard Worker && !item.IsService()
2164*f6dc9357SAndroid Build Coastguard Worker && item.NeedUse_as_CopyLink())
2165*f6dc9357SAndroid Build Coastguard Worker need_FillLinks = true;
2166*f6dc9357SAndroid Build Coastguard Worker
2167*f6dc9357SAndroid Build Coastguard Worker if (!item.IsSolid())
2168*f6dc9357SAndroid Build Coastguard Worker _numBlocks++;
2169*f6dc9357SAndroid Build Coastguard Worker
2170*f6dc9357SAndroid Build Coastguard Worker const unsigned algo = item.Get_AlgoVersion_RawBits();
2171*f6dc9357SAndroid Build Coastguard Worker _algo_Mask |= (UInt64)1 << algo;
2172*f6dc9357SAndroid Build Coastguard Worker _rar5comapt_mask |= 1u << item.Get_Rar5_CompatBit();
2173*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDir() && algo < Z7_ARRAY_SIZE(_methodMasks))
2174*f6dc9357SAndroid Build Coastguard Worker {
2175*f6dc9357SAndroid Build Coastguard Worker _methodMasks[algo] |= 1u << (item.Get_Method());
2176*f6dc9357SAndroid Build Coastguard Worker UInt64 d = 32 + item.Get_DictSize_Frac();
2177*f6dc9357SAndroid Build Coastguard Worker d <<= (12 + item.Get_DictSize_Main());
2178*f6dc9357SAndroid Build Coastguard Worker if (_dictMaxSizes[algo] < d)
2179*f6dc9357SAndroid Build Coastguard Worker _dictMaxSizes[algo] = d;
2180*f6dc9357SAndroid Build Coastguard Worker }
2181*f6dc9357SAndroid Build Coastguard Worker }
2182*f6dc9357SAndroid Build Coastguard Worker
2183*f6dc9357SAndroid Build Coastguard Worker if (!need_FillLinks)
2184*f6dc9357SAndroid Build Coastguard Worker return;
2185*f6dc9357SAndroid Build Coastguard Worker
2186*f6dc9357SAndroid Build Coastguard Worker CUIntVector sorted;
2187*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _refs.Size(); i++)
2188*f6dc9357SAndroid Build Coastguard Worker {
2189*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[_refs[i].Item];
2190*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDir() && !item.IsService())
2191*f6dc9357SAndroid Build Coastguard Worker sorted.Add(i);
2192*f6dc9357SAndroid Build Coastguard Worker }
2193*f6dc9357SAndroid Build Coastguard Worker
2194*f6dc9357SAndroid Build Coastguard Worker if (sorted.IsEmpty())
2195*f6dc9357SAndroid Build Coastguard Worker return;
2196*f6dc9357SAndroid Build Coastguard Worker
2197*f6dc9357SAndroid Build Coastguard Worker sorted.Sort(CompareItemsPaths_Sort, (void *)this);
2198*f6dc9357SAndroid Build Coastguard Worker
2199*f6dc9357SAndroid Build Coastguard Worker AString link;
2200*f6dc9357SAndroid Build Coastguard Worker
2201*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _refs.Size(); i++)
2202*f6dc9357SAndroid Build Coastguard Worker {
2203*f6dc9357SAndroid Build Coastguard Worker CRefItem &ref = _refs[i];
2204*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[ref.Item];
2205*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir() || item.IsService() || item.PackSize != 0)
2206*f6dc9357SAndroid Build Coastguard Worker continue;
2207*f6dc9357SAndroid Build Coastguard Worker CLinkInfo linkInfo;
2208*f6dc9357SAndroid Build Coastguard Worker if (!item.FindExtra_Link(linkInfo) || linkInfo.Type != NLinkType::kFileCopy)
2209*f6dc9357SAndroid Build Coastguard Worker continue;
2210*f6dc9357SAndroid Build Coastguard Worker link.SetFrom_CalcLen((const char *)(item.Extra + linkInfo.NameOffset), linkInfo.NameLen);
2211*f6dc9357SAndroid Build Coastguard Worker const int linkIndex = FindLink(*this, sorted, link, i);
2212*f6dc9357SAndroid Build Coastguard Worker if (linkIndex < 0)
2213*f6dc9357SAndroid Build Coastguard Worker continue;
2214*f6dc9357SAndroid Build Coastguard Worker if ((unsigned)linkIndex >= i)
2215*f6dc9357SAndroid Build Coastguard Worker continue; // we don't support forward links that can lead to loops
2216*f6dc9357SAndroid Build Coastguard Worker const CRefItem &linkRef = _refs[linkIndex];
2217*f6dc9357SAndroid Build Coastguard Worker const CItem &linkItem = _items[linkRef.Item];
2218*f6dc9357SAndroid Build Coastguard Worker if (linkItem.Size == item.Size)
2219*f6dc9357SAndroid Build Coastguard Worker {
2220*f6dc9357SAndroid Build Coastguard Worker if (linkRef.Link >= 0)
2221*f6dc9357SAndroid Build Coastguard Worker ref.Link = linkRef.Link;
2222*f6dc9357SAndroid Build Coastguard Worker else if (!linkItem.NeedUse_as_CopyLink())
2223*f6dc9357SAndroid Build Coastguard Worker ref.Link = linkIndex;
2224*f6dc9357SAndroid Build Coastguard Worker }
2225*f6dc9357SAndroid Build Coastguard Worker }
2226*f6dc9357SAndroid Build Coastguard Worker }
2227*f6dc9357SAndroid Build Coastguard Worker
2228*f6dc9357SAndroid Build Coastguard Worker
2229*f6dc9357SAndroid Build Coastguard Worker
2230*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream,
2231*f6dc9357SAndroid Build Coastguard Worker const UInt64 *maxCheckStartPosition,
2232*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback *openCallback)
2233*f6dc9357SAndroid Build Coastguard Worker {
2234*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
2235*f6dc9357SAndroid Build Coastguard Worker // CMyComPtr<ICryptoGetTextPassword> getTextPassword;
2236*f6dc9357SAndroid Build Coastguard Worker NRar::CVolumeName seqName;
2237*f6dc9357SAndroid Build Coastguard Worker CTempBuf tempBuf;
2238*f6dc9357SAndroid Build Coastguard Worker CUnpacker unpacker;
2239*f6dc9357SAndroid Build Coastguard Worker
2240*f6dc9357SAndroid Build Coastguard Worker if (openCallback)
2241*f6dc9357SAndroid Build Coastguard Worker {
2242*f6dc9357SAndroid Build Coastguard Worker openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
2243*f6dc9357SAndroid Build Coastguard Worker openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&unpacker.getTextPassword);
2244*f6dc9357SAndroid Build Coastguard Worker }
2245*f6dc9357SAndroid Build Coastguard Worker // unpacker.getTextPassword = getTextPassword;
2246*f6dc9357SAndroid Build Coastguard Worker
2247*f6dc9357SAndroid Build Coastguard Worker CInArchive arch;
2248*f6dc9357SAndroid Build Coastguard Worker int prevSplitFile = -1;
2249*f6dc9357SAndroid Build Coastguard Worker int prevMainFile = -1;
2250*f6dc9357SAndroid Build Coastguard Worker UInt64 totalBytes = 0;
2251*f6dc9357SAndroid Build Coastguard Worker UInt64 curBytes = 0;
2252*f6dc9357SAndroid Build Coastguard Worker bool nextVol_is_Required = false;
2253*f6dc9357SAndroid Build Coastguard Worker
2254*f6dc9357SAndroid Build Coastguard Worker for (;;)
2255*f6dc9357SAndroid Build Coastguard Worker {
2256*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> inStream;
2257*f6dc9357SAndroid Build Coastguard Worker
2258*f6dc9357SAndroid Build Coastguard Worker if (_arcs.IsEmpty())
2259*f6dc9357SAndroid Build Coastguard Worker inStream = stream;
2260*f6dc9357SAndroid Build Coastguard Worker else
2261*f6dc9357SAndroid Build Coastguard Worker {
2262*f6dc9357SAndroid Build Coastguard Worker if (!openVolumeCallback)
2263*f6dc9357SAndroid Build Coastguard Worker break;
2264*f6dc9357SAndroid Build Coastguard Worker if (_arcs.Size() == 1)
2265*f6dc9357SAndroid Build Coastguard Worker {
2266*f6dc9357SAndroid Build Coastguard Worker UString baseName;
2267*f6dc9357SAndroid Build Coastguard Worker {
2268*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
2269*f6dc9357SAndroid Build Coastguard Worker RINOK(openVolumeCallback->GetProperty(kpidName, &prop))
2270*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_BSTR)
2271*f6dc9357SAndroid Build Coastguard Worker break;
2272*f6dc9357SAndroid Build Coastguard Worker baseName = prop.bstrVal;
2273*f6dc9357SAndroid Build Coastguard Worker }
2274*f6dc9357SAndroid Build Coastguard Worker if (!seqName.InitName(baseName))
2275*f6dc9357SAndroid Build Coastguard Worker break;
2276*f6dc9357SAndroid Build Coastguard Worker }
2277*f6dc9357SAndroid Build Coastguard Worker const UString volName = seqName.GetNextName();
2278*f6dc9357SAndroid Build Coastguard Worker const HRESULT result = openVolumeCallback->GetStream(volName, &inStream);
2279*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK && result != S_FALSE)
2280*f6dc9357SAndroid Build Coastguard Worker return result;
2281*f6dc9357SAndroid Build Coastguard Worker if (!inStream || result != S_OK)
2282*f6dc9357SAndroid Build Coastguard Worker {
2283*f6dc9357SAndroid Build Coastguard Worker if (nextVol_is_Required)
2284*f6dc9357SAndroid Build Coastguard Worker _missingVolName = volName;
2285*f6dc9357SAndroid Build Coastguard Worker break;
2286*f6dc9357SAndroid Build Coastguard Worker }
2287*f6dc9357SAndroid Build Coastguard Worker }
2288*f6dc9357SAndroid Build Coastguard Worker
2289*f6dc9357SAndroid Build Coastguard Worker UInt64 endPos = 0;
2290*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetPos_GetSize(inStream, arch.StreamStartPosition, endPos))
2291*f6dc9357SAndroid Build Coastguard Worker
2292*f6dc9357SAndroid Build Coastguard Worker if (openCallback)
2293*f6dc9357SAndroid Build Coastguard Worker {
2294*f6dc9357SAndroid Build Coastguard Worker totalBytes += endPos;
2295*f6dc9357SAndroid Build Coastguard Worker RINOK(openCallback->SetTotal(NULL, &totalBytes))
2296*f6dc9357SAndroid Build Coastguard Worker }
2297*f6dc9357SAndroid Build Coastguard Worker
2298*f6dc9357SAndroid Build Coastguard Worker CInArcInfo arcInfo_Open;
2299*f6dc9357SAndroid Build Coastguard Worker {
2300*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = arch.Open(inStream, maxCheckStartPosition, unpacker.getTextPassword, arcInfo_Open);
2301*f6dc9357SAndroid Build Coastguard Worker if (arch.IsArc && arch.UnexpectedEnd)
2302*f6dc9357SAndroid Build Coastguard Worker _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
2303*f6dc9357SAndroid Build Coastguard Worker if (_arcs.IsEmpty())
2304*f6dc9357SAndroid Build Coastguard Worker _isArc = arch.IsArc;
2305*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
2306*f6dc9357SAndroid Build Coastguard Worker {
2307*f6dc9357SAndroid Build Coastguard Worker if (res != S_FALSE)
2308*f6dc9357SAndroid Build Coastguard Worker return res;
2309*f6dc9357SAndroid Build Coastguard Worker if (_arcs.IsEmpty())
2310*f6dc9357SAndroid Build Coastguard Worker return res;
2311*f6dc9357SAndroid Build Coastguard Worker break;
2312*f6dc9357SAndroid Build Coastguard Worker }
2313*f6dc9357SAndroid Build Coastguard Worker }
2314*f6dc9357SAndroid Build Coastguard Worker
2315*f6dc9357SAndroid Build Coastguard Worker CArc &arc = _arcs.AddNew();
2316*f6dc9357SAndroid Build Coastguard Worker CInArcInfo &arcInfo = arc.Info;
2317*f6dc9357SAndroid Build Coastguard Worker arcInfo = arcInfo_Open;
2318*f6dc9357SAndroid Build Coastguard Worker arc.Stream = inStream;
2319*f6dc9357SAndroid Build Coastguard Worker
2320*f6dc9357SAndroid Build Coastguard Worker CItem item;
2321*f6dc9357SAndroid Build Coastguard Worker
2322*f6dc9357SAndroid Build Coastguard Worker for (;;)
2323*f6dc9357SAndroid Build Coastguard Worker {
2324*f6dc9357SAndroid Build Coastguard Worker item.Clear();
2325*f6dc9357SAndroid Build Coastguard Worker
2326*f6dc9357SAndroid Build Coastguard Worker arcInfo.EndPos = arch.Position;
2327*f6dc9357SAndroid Build Coastguard Worker if (arch.Position > endPos)
2328*f6dc9357SAndroid Build Coastguard Worker {
2329*f6dc9357SAndroid Build Coastguard Worker _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
2330*f6dc9357SAndroid Build Coastguard Worker break;
2331*f6dc9357SAndroid Build Coastguard Worker }
2332*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(inStream, arch.Position))
2333*f6dc9357SAndroid Build Coastguard Worker
2334*f6dc9357SAndroid Build Coastguard Worker {
2335*f6dc9357SAndroid Build Coastguard Worker CInArchive::CHeader h;
2336*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = arch.ReadBlockHeader(h);
2337*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
2338*f6dc9357SAndroid Build Coastguard Worker {
2339*f6dc9357SAndroid Build Coastguard Worker if (res != S_FALSE)
2340*f6dc9357SAndroid Build Coastguard Worker return res;
2341*f6dc9357SAndroid Build Coastguard Worker if (arch.UnexpectedEnd)
2342*f6dc9357SAndroid Build Coastguard Worker {
2343*f6dc9357SAndroid Build Coastguard Worker _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
2344*f6dc9357SAndroid Build Coastguard Worker if (arcInfo.EndPos < arch.Position)
2345*f6dc9357SAndroid Build Coastguard Worker arcInfo.EndPos = arch.Position;
2346*f6dc9357SAndroid Build Coastguard Worker if (arcInfo.EndPos < endPos)
2347*f6dc9357SAndroid Build Coastguard Worker arcInfo.EndPos = endPos;
2348*f6dc9357SAndroid Build Coastguard Worker }
2349*f6dc9357SAndroid Build Coastguard Worker else
2350*f6dc9357SAndroid Build Coastguard Worker _errorFlags |= kpv_ErrorFlags_HeadersError;
2351*f6dc9357SAndroid Build Coastguard Worker break;
2352*f6dc9357SAndroid Build Coastguard Worker }
2353*f6dc9357SAndroid Build Coastguard Worker
2354*f6dc9357SAndroid Build Coastguard Worker if (h.Type == NHeaderType::kEndOfArc)
2355*f6dc9357SAndroid Build Coastguard Worker {
2356*f6dc9357SAndroid Build Coastguard Worker arcInfo.EndPos = arch.Position;
2357*f6dc9357SAndroid Build Coastguard Worker arcInfo.EndOfArchive_was_Read = true;
2358*f6dc9357SAndroid Build Coastguard Worker if (!arch.ReadVar(arcInfo.EndFlags))
2359*f6dc9357SAndroid Build Coastguard Worker _errorFlags |= kpv_ErrorFlags_HeadersError;
2360*f6dc9357SAndroid Build Coastguard Worker if (!arch.Is_Buf_Finished() || h.ExtraSize || h.DataSize)
2361*f6dc9357SAndroid Build Coastguard Worker arcInfo.UnsupportedFeature = true;
2362*f6dc9357SAndroid Build Coastguard Worker if (arcInfo.IsVolume())
2363*f6dc9357SAndroid Build Coastguard Worker {
2364*f6dc9357SAndroid Build Coastguard Worker // for multivolume archives RAR can add ZERO bytes at the end for alignment.
2365*f6dc9357SAndroid Build Coastguard Worker // We must skip these bytes to prevent phySize warning.
2366*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(inStream, arcInfo.EndPos))
2367*f6dc9357SAndroid Build Coastguard Worker bool areThereNonZeros;
2368*f6dc9357SAndroid Build Coastguard Worker UInt64 numZeros;
2369*f6dc9357SAndroid Build Coastguard Worker const UInt64 maxSize = 1 << 12;
2370*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize))
2371*f6dc9357SAndroid Build Coastguard Worker if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize)
2372*f6dc9357SAndroid Build Coastguard Worker arcInfo.EndPos += numZeros;
2373*f6dc9357SAndroid Build Coastguard Worker }
2374*f6dc9357SAndroid Build Coastguard Worker break;
2375*f6dc9357SAndroid Build Coastguard Worker }
2376*f6dc9357SAndroid Build Coastguard Worker
2377*f6dc9357SAndroid Build Coastguard Worker if (h.Type != NHeaderType::kFile &&
2378*f6dc9357SAndroid Build Coastguard Worker h.Type != NHeaderType::kService)
2379*f6dc9357SAndroid Build Coastguard Worker {
2380*f6dc9357SAndroid Build Coastguard Worker _errorFlags |= kpv_ErrorFlags_UnsupportedFeature;
2381*f6dc9357SAndroid Build Coastguard Worker break;
2382*f6dc9357SAndroid Build Coastguard Worker }
2383*f6dc9357SAndroid Build Coastguard Worker
2384*f6dc9357SAndroid Build Coastguard Worker item.RecordType = (Byte)h.Type;
2385*f6dc9357SAndroid Build Coastguard Worker if (!arch.ReadFileHeader(h, item))
2386*f6dc9357SAndroid Build Coastguard Worker {
2387*f6dc9357SAndroid Build Coastguard Worker _errorFlags |= kpv_ErrorFlags_HeadersError;
2388*f6dc9357SAndroid Build Coastguard Worker break;
2389*f6dc9357SAndroid Build Coastguard Worker }
2390*f6dc9357SAndroid Build Coastguard Worker item.DataPos = arch.Position;
2391*f6dc9357SAndroid Build Coastguard Worker }
2392*f6dc9357SAndroid Build Coastguard Worker
2393*f6dc9357SAndroid Build Coastguard Worker bool isOk_packSize = true;
2394*f6dc9357SAndroid Build Coastguard Worker {
2395*f6dc9357SAndroid Build Coastguard Worker arcInfo.EndPos = arch.Position;
2396*f6dc9357SAndroid Build Coastguard Worker if (arch.Position + item.PackSize < arch.Position)
2397*f6dc9357SAndroid Build Coastguard Worker {
2398*f6dc9357SAndroid Build Coastguard Worker isOk_packSize = false;
2399*f6dc9357SAndroid Build Coastguard Worker _errorFlags |= kpv_ErrorFlags_HeadersError;
2400*f6dc9357SAndroid Build Coastguard Worker if (arcInfo.EndPos < endPos)
2401*f6dc9357SAndroid Build Coastguard Worker arcInfo.EndPos = endPos;
2402*f6dc9357SAndroid Build Coastguard Worker }
2403*f6dc9357SAndroid Build Coastguard Worker else
2404*f6dc9357SAndroid Build Coastguard Worker {
2405*f6dc9357SAndroid Build Coastguard Worker arch.AddToSeekValue(item.PackSize); // Position points to next header;
2406*f6dc9357SAndroid Build Coastguard Worker arcInfo.EndPos = arch.Position;
2407*f6dc9357SAndroid Build Coastguard Worker }
2408*f6dc9357SAndroid Build Coastguard Worker }
2409*f6dc9357SAndroid Build Coastguard Worker
2410*f6dc9357SAndroid Build Coastguard Worker bool needAdd = true;
2411*f6dc9357SAndroid Build Coastguard Worker
2412*f6dc9357SAndroid Build Coastguard Worker if (!_comment_WasUsedInArc
2413*f6dc9357SAndroid Build Coastguard Worker && _comment.Size() == 0
2414*f6dc9357SAndroid Build Coastguard Worker && item.Is_CMT())
2415*f6dc9357SAndroid Build Coastguard Worker {
2416*f6dc9357SAndroid Build Coastguard Worker _comment_WasUsedInArc = true;
2417*f6dc9357SAndroid Build Coastguard Worker if ( item.PackSize <= kCommentSize_Max
2418*f6dc9357SAndroid Build Coastguard Worker && item.PackSize == item.Size
2419*f6dc9357SAndroid Build Coastguard Worker && item.PackSize != 0
2420*f6dc9357SAndroid Build Coastguard Worker && item.Get_Method() == 0
2421*f6dc9357SAndroid Build Coastguard Worker && !item.IsSplit())
2422*f6dc9357SAndroid Build Coastguard Worker {
2423*f6dc9357SAndroid Build Coastguard Worker RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_VARS item, item.PackSize, inStream, _comment))
2424*f6dc9357SAndroid Build Coastguard Worker needAdd = false;
2425*f6dc9357SAndroid Build Coastguard Worker // item.RecordType = (Byte)NHeaderType::kFile; // for debug
2426*f6dc9357SAndroid Build Coastguard Worker }
2427*f6dc9357SAndroid Build Coastguard Worker }
2428*f6dc9357SAndroid Build Coastguard Worker
2429*f6dc9357SAndroid Build Coastguard Worker CRefItem ref;
2430*f6dc9357SAndroid Build Coastguard Worker ref.Item = _items.Size();
2431*f6dc9357SAndroid Build Coastguard Worker ref.Last = ref.Item;
2432*f6dc9357SAndroid Build Coastguard Worker ref.Parent = -1;
2433*f6dc9357SAndroid Build Coastguard Worker ref.Link = -1;
2434*f6dc9357SAndroid Build Coastguard Worker
2435*f6dc9357SAndroid Build Coastguard Worker if (needAdd)
2436*f6dc9357SAndroid Build Coastguard Worker {
2437*f6dc9357SAndroid Build Coastguard Worker if (item.IsService())
2438*f6dc9357SAndroid Build Coastguard Worker {
2439*f6dc9357SAndroid Build Coastguard Worker if (item.Is_STM())
2440*f6dc9357SAndroid Build Coastguard Worker {
2441*f6dc9357SAndroid Build Coastguard Worker if (prevMainFile >= 0)
2442*f6dc9357SAndroid Build Coastguard Worker ref.Parent = prevMainFile;
2443*f6dc9357SAndroid Build Coastguard Worker }
2444*f6dc9357SAndroid Build Coastguard Worker else
2445*f6dc9357SAndroid Build Coastguard Worker {
2446*f6dc9357SAndroid Build Coastguard Worker needAdd = false;
2447*f6dc9357SAndroid Build Coastguard Worker if (item.Is_ACL())
2448*f6dc9357SAndroid Build Coastguard Worker {
2449*f6dc9357SAndroid Build Coastguard Worker _acl_Used = true;
2450*f6dc9357SAndroid Build Coastguard Worker if (item.IsEncrypted() && !arch.m_CryptoMode)
2451*f6dc9357SAndroid Build Coastguard Worker _error_in_ACL = true;
2452*f6dc9357SAndroid Build Coastguard Worker else if (item.IsSolid()
2453*f6dc9357SAndroid Build Coastguard Worker || prevMainFile < 0
2454*f6dc9357SAndroid Build Coastguard Worker || item.Size >= (1 << 24)
2455*f6dc9357SAndroid Build Coastguard Worker || item.Size == 0)
2456*f6dc9357SAndroid Build Coastguard Worker _error_in_ACL = true;
2457*f6dc9357SAndroid Build Coastguard Worker if (prevMainFile >= 0 && item.Size < (1 << 24) && item.Size != 0)
2458*f6dc9357SAndroid Build Coastguard Worker {
2459*f6dc9357SAndroid Build Coastguard Worker CItem &mainItem = _items[_refs[prevMainFile].Item];
2460*f6dc9357SAndroid Build Coastguard Worker
2461*f6dc9357SAndroid Build Coastguard Worker if (mainItem.ACL < 0)
2462*f6dc9357SAndroid Build Coastguard Worker {
2463*f6dc9357SAndroid Build Coastguard Worker CByteBuffer acl;
2464*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = tempBuf.Decode(EXTERNAL_CODECS_VARS item, inStream, unpacker, acl);
2465*f6dc9357SAndroid Build Coastguard Worker if (!item.IsSplitAfter())
2466*f6dc9357SAndroid Build Coastguard Worker tempBuf.Clear();
2467*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
2468*f6dc9357SAndroid Build Coastguard Worker {
2469*f6dc9357SAndroid Build Coastguard Worker tempBuf.Clear();
2470*f6dc9357SAndroid Build Coastguard Worker if (res != S_FALSE && res != E_NOTIMPL)
2471*f6dc9357SAndroid Build Coastguard Worker return res;
2472*f6dc9357SAndroid Build Coastguard Worker _error_in_ACL = true;
2473*f6dc9357SAndroid Build Coastguard Worker }
2474*f6dc9357SAndroid Build Coastguard Worker else if (acl.Size() != 0)
2475*f6dc9357SAndroid Build Coastguard Worker {
2476*f6dc9357SAndroid Build Coastguard Worker if (_acls.IsEmpty() || acl != _acls.Back())
2477*f6dc9357SAndroid Build Coastguard Worker _acls.Add(acl);
2478*f6dc9357SAndroid Build Coastguard Worker mainItem.ACL = (int)_acls.Size() - 1;
2479*f6dc9357SAndroid Build Coastguard Worker }
2480*f6dc9357SAndroid Build Coastguard Worker }
2481*f6dc9357SAndroid Build Coastguard Worker }
2482*f6dc9357SAndroid Build Coastguard Worker }
2483*f6dc9357SAndroid Build Coastguard Worker }
2484*f6dc9357SAndroid Build Coastguard Worker } // item.IsService()
2485*f6dc9357SAndroid Build Coastguard Worker
2486*f6dc9357SAndroid Build Coastguard Worker if (needAdd)
2487*f6dc9357SAndroid Build Coastguard Worker {
2488*f6dc9357SAndroid Build Coastguard Worker if (item.IsSplitBefore())
2489*f6dc9357SAndroid Build Coastguard Worker {
2490*f6dc9357SAndroid Build Coastguard Worker if (prevSplitFile >= 0)
2491*f6dc9357SAndroid Build Coastguard Worker {
2492*f6dc9357SAndroid Build Coastguard Worker CRefItem &ref2 = _refs[prevSplitFile];
2493*f6dc9357SAndroid Build Coastguard Worker CItem &prevItem = _items[ref2.Last];
2494*f6dc9357SAndroid Build Coastguard Worker if (item.IsNextForItem(prevItem))
2495*f6dc9357SAndroid Build Coastguard Worker {
2496*f6dc9357SAndroid Build Coastguard Worker ref2.Last = _items.Size();
2497*f6dc9357SAndroid Build Coastguard Worker prevItem.NextItem = (int)ref2.Last;
2498*f6dc9357SAndroid Build Coastguard Worker needAdd = false;
2499*f6dc9357SAndroid Build Coastguard Worker }
2500*f6dc9357SAndroid Build Coastguard Worker }
2501*f6dc9357SAndroid Build Coastguard Worker else
2502*f6dc9357SAndroid Build Coastguard Worker _split_Error = true;
2503*f6dc9357SAndroid Build Coastguard Worker }
2504*f6dc9357SAndroid Build Coastguard Worker }
2505*f6dc9357SAndroid Build Coastguard Worker
2506*f6dc9357SAndroid Build Coastguard Worker if (needAdd)
2507*f6dc9357SAndroid Build Coastguard Worker {
2508*f6dc9357SAndroid Build Coastguard Worker if (item.IsSplitAfter())
2509*f6dc9357SAndroid Build Coastguard Worker prevSplitFile = (int)_refs.Size();
2510*f6dc9357SAndroid Build Coastguard Worker if (!item.IsService())
2511*f6dc9357SAndroid Build Coastguard Worker prevMainFile = (int)_refs.Size();
2512*f6dc9357SAndroid Build Coastguard Worker }
2513*f6dc9357SAndroid Build Coastguard Worker }
2514*f6dc9357SAndroid Build Coastguard Worker
2515*f6dc9357SAndroid Build Coastguard Worker {
2516*f6dc9357SAndroid Build Coastguard Worker UInt64 version;
2517*f6dc9357SAndroid Build Coastguard Worker if (item.FindExtra_Version(version))
2518*f6dc9357SAndroid Build Coastguard Worker {
2519*f6dc9357SAndroid Build Coastguard Worker item.Version_Defined = true;
2520*f6dc9357SAndroid Build Coastguard Worker item.Version = version;
2521*f6dc9357SAndroid Build Coastguard Worker }
2522*f6dc9357SAndroid Build Coastguard Worker }
2523*f6dc9357SAndroid Build Coastguard Worker
2524*f6dc9357SAndroid Build Coastguard Worker item.VolIndex = _arcs.Size() - 1;
2525*f6dc9357SAndroid Build Coastguard Worker _items.Add(item);
2526*f6dc9357SAndroid Build Coastguard Worker if (needAdd)
2527*f6dc9357SAndroid Build Coastguard Worker _refs.Add(ref);
2528*f6dc9357SAndroid Build Coastguard Worker
2529*f6dc9357SAndroid Build Coastguard Worker if (openCallback && (_items.Size() & 0xFF) == 0)
2530*f6dc9357SAndroid Build Coastguard Worker {
2531*f6dc9357SAndroid Build Coastguard Worker const UInt64 numFiles = _refs.Size(); // _items.Size()
2532*f6dc9357SAndroid Build Coastguard Worker const UInt64 numBytes = curBytes + item.DataPos;
2533*f6dc9357SAndroid Build Coastguard Worker RINOK(openCallback->SetCompleted(&numFiles, &numBytes))
2534*f6dc9357SAndroid Build Coastguard Worker }
2535*f6dc9357SAndroid Build Coastguard Worker
2536*f6dc9357SAndroid Build Coastguard Worker if (!isOk_packSize)
2537*f6dc9357SAndroid Build Coastguard Worker break;
2538*f6dc9357SAndroid Build Coastguard Worker }
2539*f6dc9357SAndroid Build Coastguard Worker
2540*f6dc9357SAndroid Build Coastguard Worker curBytes += endPos;
2541*f6dc9357SAndroid Build Coastguard Worker
2542*f6dc9357SAndroid Build Coastguard Worker nextVol_is_Required = false;
2543*f6dc9357SAndroid Build Coastguard Worker
2544*f6dc9357SAndroid Build Coastguard Worker if (!arcInfo.IsVolume())
2545*f6dc9357SAndroid Build Coastguard Worker break;
2546*f6dc9357SAndroid Build Coastguard Worker
2547*f6dc9357SAndroid Build Coastguard Worker if (arcInfo.EndOfArchive_was_Read)
2548*f6dc9357SAndroid Build Coastguard Worker {
2549*f6dc9357SAndroid Build Coastguard Worker if (!arcInfo.AreMoreVolumes())
2550*f6dc9357SAndroid Build Coastguard Worker break;
2551*f6dc9357SAndroid Build Coastguard Worker nextVol_is_Required = true;
2552*f6dc9357SAndroid Build Coastguard Worker }
2553*f6dc9357SAndroid Build Coastguard Worker }
2554*f6dc9357SAndroid Build Coastguard Worker
2555*f6dc9357SAndroid Build Coastguard Worker FillLinks();
2556*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2557*f6dc9357SAndroid Build Coastguard Worker }
2558*f6dc9357SAndroid Build Coastguard Worker
2559*f6dc9357SAndroid Build Coastguard Worker
2560*f6dc9357SAndroid Build Coastguard Worker
2561*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
2562*f6dc9357SAndroid Build Coastguard Worker const UInt64 *maxCheckStartPosition,
2563*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback *openCallback))
2564*f6dc9357SAndroid Build Coastguard Worker {
2565*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2566*f6dc9357SAndroid Build Coastguard Worker Close();
2567*f6dc9357SAndroid Build Coastguard Worker return Open2(stream, maxCheckStartPosition, openCallback);
2568*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2569*f6dc9357SAndroid Build Coastguard Worker }
2570*f6dc9357SAndroid Build Coastguard Worker
2571*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
2572*f6dc9357SAndroid Build Coastguard Worker {
2573*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2574*f6dc9357SAndroid Build Coastguard Worker _missingVolName.Empty();
2575*f6dc9357SAndroid Build Coastguard Worker _errorFlags = 0;
2576*f6dc9357SAndroid Build Coastguard Worker // _warningFlags = 0;
2577*f6dc9357SAndroid Build Coastguard Worker _isArc = false;
2578*f6dc9357SAndroid Build Coastguard Worker _comment_WasUsedInArc = false;
2579*f6dc9357SAndroid Build Coastguard Worker _acl_Used = false;
2580*f6dc9357SAndroid Build Coastguard Worker _error_in_ACL = false;
2581*f6dc9357SAndroid Build Coastguard Worker _split_Error = false;
2582*f6dc9357SAndroid Build Coastguard Worker _numBlocks = 0;
2583*f6dc9357SAndroid Build Coastguard Worker _rar5comapt_mask = 0;
2584*f6dc9357SAndroid Build Coastguard Worker _algo_Mask = 0; // (UInt64)0u - 1;
2585*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < Z7_ARRAY_SIZE(_methodMasks); i++)
2586*f6dc9357SAndroid Build Coastguard Worker {
2587*f6dc9357SAndroid Build Coastguard Worker _methodMasks[i] = 0;
2588*f6dc9357SAndroid Build Coastguard Worker _dictMaxSizes[i] = 0;
2589*f6dc9357SAndroid Build Coastguard Worker }
2590*f6dc9357SAndroid Build Coastguard Worker
2591*f6dc9357SAndroid Build Coastguard Worker _refs.Clear();
2592*f6dc9357SAndroid Build Coastguard Worker _items.Clear();
2593*f6dc9357SAndroid Build Coastguard Worker _arcs.Clear();
2594*f6dc9357SAndroid Build Coastguard Worker _acls.Clear();
2595*f6dc9357SAndroid Build Coastguard Worker _comment.Free();
2596*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2597*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2598*f6dc9357SAndroid Build Coastguard Worker }
2599*f6dc9357SAndroid Build Coastguard Worker
2600*f6dc9357SAndroid Build Coastguard Worker
2601*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_1(
2602*f6dc9357SAndroid Build Coastguard Worker CVolsInStream
2603*f6dc9357SAndroid Build Coastguard Worker , ISequentialInStream
2604*f6dc9357SAndroid Build Coastguard Worker )
2605*f6dc9357SAndroid Build Coastguard Worker UInt64 _rem;
2606*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *_stream;
2607*f6dc9357SAndroid Build Coastguard Worker const CObjectVector<CArc> *_arcs;
2608*f6dc9357SAndroid Build Coastguard Worker const CObjectVector<CItem> *_items;
2609*f6dc9357SAndroid Build Coastguard Worker int _itemIndex;
2610*f6dc9357SAndroid Build Coastguard Worker public:
2611*f6dc9357SAndroid Build Coastguard Worker bool CrcIsOK;
2612*f6dc9357SAndroid Build Coastguard Worker private:
2613*f6dc9357SAndroid Build Coastguard Worker CHash _hash;
2614*f6dc9357SAndroid Build Coastguard Worker public:
2615*f6dc9357SAndroid Build Coastguard Worker void Init(const CObjectVector<CArc> *arcs,
2616*f6dc9357SAndroid Build Coastguard Worker const CObjectVector<CItem> *items,
2617*f6dc9357SAndroid Build Coastguard Worker unsigned itemIndex)
2618*f6dc9357SAndroid Build Coastguard Worker {
2619*f6dc9357SAndroid Build Coastguard Worker _arcs = arcs;
2620*f6dc9357SAndroid Build Coastguard Worker _items = items;
2621*f6dc9357SAndroid Build Coastguard Worker _itemIndex = (int)itemIndex;
2622*f6dc9357SAndroid Build Coastguard Worker _stream = NULL;
2623*f6dc9357SAndroid Build Coastguard Worker CrcIsOK = true;
2624*f6dc9357SAndroid Build Coastguard Worker }
2625*f6dc9357SAndroid Build Coastguard Worker };
2626*f6dc9357SAndroid Build Coastguard Worker
2627*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
2628*f6dc9357SAndroid Build Coastguard Worker {
2629*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
2630*f6dc9357SAndroid Build Coastguard Worker *processedSize = 0;
2631*f6dc9357SAndroid Build Coastguard Worker UInt32 realProcessedSize = 0;
2632*f6dc9357SAndroid Build Coastguard Worker
2633*f6dc9357SAndroid Build Coastguard Worker while (size != 0)
2634*f6dc9357SAndroid Build Coastguard Worker {
2635*f6dc9357SAndroid Build Coastguard Worker if (!_stream)
2636*f6dc9357SAndroid Build Coastguard Worker {
2637*f6dc9357SAndroid Build Coastguard Worker if (_itemIndex < 0)
2638*f6dc9357SAndroid Build Coastguard Worker break;
2639*f6dc9357SAndroid Build Coastguard Worker const CItem &item = (*_items)[_itemIndex];
2640*f6dc9357SAndroid Build Coastguard Worker IInStream *s = (*_arcs)[item.VolIndex].Stream;
2641*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(s, item.GetDataPosition()))
2642*f6dc9357SAndroid Build Coastguard Worker _stream = s;
2643*f6dc9357SAndroid Build Coastguard Worker if (CrcIsOK && item.IsSplitAfter())
2644*f6dc9357SAndroid Build Coastguard Worker _hash.Init(item);
2645*f6dc9357SAndroid Build Coastguard Worker else
2646*f6dc9357SAndroid Build Coastguard Worker _hash.Init_NoCalc();
2647*f6dc9357SAndroid Build Coastguard Worker _rem = item.PackSize;
2648*f6dc9357SAndroid Build Coastguard Worker }
2649*f6dc9357SAndroid Build Coastguard Worker {
2650*f6dc9357SAndroid Build Coastguard Worker UInt32 cur = size;
2651*f6dc9357SAndroid Build Coastguard Worker if (cur > _rem)
2652*f6dc9357SAndroid Build Coastguard Worker cur = (UInt32)_rem;
2653*f6dc9357SAndroid Build Coastguard Worker const UInt32 num = cur;
2654*f6dc9357SAndroid Build Coastguard Worker HRESULT res = _stream->Read(data, cur, &cur);
2655*f6dc9357SAndroid Build Coastguard Worker _hash.Update(data, cur);
2656*f6dc9357SAndroid Build Coastguard Worker realProcessedSize += cur;
2657*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
2658*f6dc9357SAndroid Build Coastguard Worker *processedSize = realProcessedSize;
2659*f6dc9357SAndroid Build Coastguard Worker data = (Byte *)data + cur;
2660*f6dc9357SAndroid Build Coastguard Worker size -= cur;
2661*f6dc9357SAndroid Build Coastguard Worker _rem -= cur;
2662*f6dc9357SAndroid Build Coastguard Worker if (_rem == 0)
2663*f6dc9357SAndroid Build Coastguard Worker {
2664*f6dc9357SAndroid Build Coastguard Worker const CItem &item = (*_items)[_itemIndex];
2665*f6dc9357SAndroid Build Coastguard Worker _itemIndex = item.NextItem;
2666*f6dc9357SAndroid Build Coastguard Worker if (!_hash.Check(item, NULL)) // RAR doesn't use MAC here
2667*f6dc9357SAndroid Build Coastguard Worker CrcIsOK = false;
2668*f6dc9357SAndroid Build Coastguard Worker _stream = NULL;
2669*f6dc9357SAndroid Build Coastguard Worker }
2670*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
2671*f6dc9357SAndroid Build Coastguard Worker return res;
2672*f6dc9357SAndroid Build Coastguard Worker if (realProcessedSize != 0)
2673*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2674*f6dc9357SAndroid Build Coastguard Worker if (cur == 0 && num != 0)
2675*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2676*f6dc9357SAndroid Build Coastguard Worker }
2677*f6dc9357SAndroid Build Coastguard Worker }
2678*f6dc9357SAndroid Build Coastguard Worker
2679*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2680*f6dc9357SAndroid Build Coastguard Worker }
2681*f6dc9357SAndroid Build Coastguard Worker
2682*f6dc9357SAndroid Build Coastguard Worker
2683*f6dc9357SAndroid Build Coastguard Worker static int FindLinkBuf(CObjectVector<CLinkFile> &linkFiles, unsigned index)
2684*f6dc9357SAndroid Build Coastguard Worker {
2685*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = linkFiles.Size();
2686*f6dc9357SAndroid Build Coastguard Worker for (;;)
2687*f6dc9357SAndroid Build Coastguard Worker {
2688*f6dc9357SAndroid Build Coastguard Worker if (left == right)
2689*f6dc9357SAndroid Build Coastguard Worker return -1;
2690*f6dc9357SAndroid Build Coastguard Worker const unsigned mid = (left + right) / 2;
2691*f6dc9357SAndroid Build Coastguard Worker const unsigned linkIndex = linkFiles[mid].Index;
2692*f6dc9357SAndroid Build Coastguard Worker if (index == linkIndex)
2693*f6dc9357SAndroid Build Coastguard Worker return (int)mid;
2694*f6dc9357SAndroid Build Coastguard Worker if (index < linkIndex)
2695*f6dc9357SAndroid Build Coastguard Worker right = mid;
2696*f6dc9357SAndroid Build Coastguard Worker else
2697*f6dc9357SAndroid Build Coastguard Worker left = mid + 1;
2698*f6dc9357SAndroid Build Coastguard Worker }
2699*f6dc9357SAndroid Build Coastguard Worker }
2700*f6dc9357SAndroid Build Coastguard Worker
2701*f6dc9357SAndroid Build Coastguard Worker
2702*f6dc9357SAndroid Build Coastguard Worker static inline int DecoderRes_to_OpRes(HRESULT res, bool crcOK)
2703*f6dc9357SAndroid Build Coastguard Worker {
2704*f6dc9357SAndroid Build Coastguard Worker if (res == E_NOTIMPL)
2705*f6dc9357SAndroid Build Coastguard Worker return NExtract::NOperationResult::kUnsupportedMethod;
2706*f6dc9357SAndroid Build Coastguard Worker // if (res == S_FALSE)
2707*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
2708*f6dc9357SAndroid Build Coastguard Worker return NExtract::NOperationResult::kDataError;
2709*f6dc9357SAndroid Build Coastguard Worker return crcOK ?
2710*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kOK :
2711*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kCRCError;
2712*f6dc9357SAndroid Build Coastguard Worker }
2713*f6dc9357SAndroid Build Coastguard Worker
2714*f6dc9357SAndroid Build Coastguard Worker
2715*f6dc9357SAndroid Build Coastguard Worker static HRESULT CopyData_with_Progress(const Byte *data, size_t size,
2716*f6dc9357SAndroid Build Coastguard Worker ISequentialOutStream *outStream, ICompressProgressInfo *progress)
2717*f6dc9357SAndroid Build Coastguard Worker {
2718*f6dc9357SAndroid Build Coastguard Worker UInt64 pos64 = 0;
2719*f6dc9357SAndroid Build Coastguard Worker while (size)
2720*f6dc9357SAndroid Build Coastguard Worker {
2721*f6dc9357SAndroid Build Coastguard Worker const UInt32 kStepSize = (UInt32)1 << 24;
2722*f6dc9357SAndroid Build Coastguard Worker UInt32 cur = kStepSize;
2723*f6dc9357SAndroid Build Coastguard Worker if (cur > size)
2724*f6dc9357SAndroid Build Coastguard Worker cur = (UInt32)size;
2725*f6dc9357SAndroid Build Coastguard Worker RINOK(outStream->Write(data, cur, &cur))
2726*f6dc9357SAndroid Build Coastguard Worker if (cur == 0)
2727*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
2728*f6dc9357SAndroid Build Coastguard Worker size -= cur;
2729*f6dc9357SAndroid Build Coastguard Worker data += cur;
2730*f6dc9357SAndroid Build Coastguard Worker pos64 += cur;
2731*f6dc9357SAndroid Build Coastguard Worker if (progress)
2732*f6dc9357SAndroid Build Coastguard Worker {
2733*f6dc9357SAndroid Build Coastguard Worker RINOK(progress->SetRatioInfo(&pos64, &pos64))
2734*f6dc9357SAndroid Build Coastguard Worker }
2735*f6dc9357SAndroid Build Coastguard Worker }
2736*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2737*f6dc9357SAndroid Build Coastguard Worker }
2738*f6dc9357SAndroid Build Coastguard Worker
2739*f6dc9357SAndroid Build Coastguard Worker
2740*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2741*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
2742*f6dc9357SAndroid Build Coastguard Worker {
2743*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2744*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
2745*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
2746*f6dc9357SAndroid Build Coastguard Worker numItems = (UInt32)_refs.Size();
2747*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
2748*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2749*f6dc9357SAndroid Build Coastguard Worker
2750*f6dc9357SAndroid Build Coastguard Worker CByteArr extractStatuses(_refs.Size());
2751*f6dc9357SAndroid Build Coastguard Worker memset(extractStatuses, 0, _refs.Size());
2752*f6dc9357SAndroid Build Coastguard Worker
2753*f6dc9357SAndroid Build Coastguard Worker // we don't want to use temp buffer for big link files.
2754*f6dc9357SAndroid Build Coastguard Worker const size_t k_CopyLinkFile_MaxSize = (size_t)1 << (28 + sizeof(size_t) / 2);
2755*f6dc9357SAndroid Build Coastguard Worker
2756*f6dc9357SAndroid Build Coastguard Worker const Byte kStatus_Extract = 1 << 0;
2757*f6dc9357SAndroid Build Coastguard Worker const Byte kStatus_Skip = 1 << 1;
2758*f6dc9357SAndroid Build Coastguard Worker const Byte kStatus_Link = 1 << 2;
2759*f6dc9357SAndroid Build Coastguard Worker
2760*f6dc9357SAndroid Build Coastguard Worker /*
2761*f6dc9357SAndroid Build Coastguard Worker In original RAR:
2762*f6dc9357SAndroid Build Coastguard Worker 1) service streams are not allowed to be solid,
2763*f6dc9357SAndroid Build Coastguard Worker and solid flag must be ignored for service streams.
2764*f6dc9357SAndroid Build Coastguard Worker 2) If RAR creates new solid block and first file in solid block is Link file,
2765*f6dc9357SAndroid Build Coastguard Worker then it can clear solid flag for Link file and
2766*f6dc9357SAndroid Build Coastguard Worker clear solid flag for first non-Link file after Link file.
2767*f6dc9357SAndroid Build Coastguard Worker */
2768*f6dc9357SAndroid Build Coastguard Worker
2769*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CLinkFile> linkFiles;
2770*f6dc9357SAndroid Build Coastguard Worker
2771*f6dc9357SAndroid Build Coastguard Worker {
2772*f6dc9357SAndroid Build Coastguard Worker UInt64 total = 0;
2773*f6dc9357SAndroid Build Coastguard Worker bool isThereUndefinedSize = false;
2774*f6dc9357SAndroid Build Coastguard Worker bool thereAreLinks = false;
2775*f6dc9357SAndroid Build Coastguard Worker {
2776*f6dc9357SAndroid Build Coastguard Worker unsigned solidLimit = 0;
2777*f6dc9357SAndroid Build Coastguard Worker for (UInt32 t = 0; t < numItems; t++)
2778*f6dc9357SAndroid Build Coastguard Worker {
2779*f6dc9357SAndroid Build Coastguard Worker const unsigned index = (unsigned)(allFilesMode ? t : indices[t]);
2780*f6dc9357SAndroid Build Coastguard Worker const CRefItem &ref = _refs[index];
2781*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[ref.Item];
2782*f6dc9357SAndroid Build Coastguard Worker const CItem &lastItem = _items[ref.Last];
2783*f6dc9357SAndroid Build Coastguard Worker
2784*f6dc9357SAndroid Build Coastguard Worker extractStatuses[index] |= kStatus_Extract;
2785*f6dc9357SAndroid Build Coastguard Worker
2786*f6dc9357SAndroid Build Coastguard Worker if (!lastItem.Is_UnknownSize())
2787*f6dc9357SAndroid Build Coastguard Worker total += lastItem.Size;
2788*f6dc9357SAndroid Build Coastguard Worker else
2789*f6dc9357SAndroid Build Coastguard Worker isThereUndefinedSize = true;
2790*f6dc9357SAndroid Build Coastguard Worker
2791*f6dc9357SAndroid Build Coastguard Worker if (ref.Link >= 0)
2792*f6dc9357SAndroid Build Coastguard Worker {
2793*f6dc9357SAndroid Build Coastguard Worker // 18.06 fixed: we use links for Test mode too
2794*f6dc9357SAndroid Build Coastguard Worker // if (!testMode)
2795*f6dc9357SAndroid Build Coastguard Worker {
2796*f6dc9357SAndroid Build Coastguard Worker if ((unsigned)ref.Link < index)
2797*f6dc9357SAndroid Build Coastguard Worker {
2798*f6dc9357SAndroid Build Coastguard Worker const CRefItem &linkRef = _refs[(unsigned)ref.Link];
2799*f6dc9357SAndroid Build Coastguard Worker const CItem &linkItem = _items[linkRef.Item];
2800*f6dc9357SAndroid Build Coastguard Worker if (linkItem.IsSolid())
2801*f6dc9357SAndroid Build Coastguard Worker if (testMode || linkItem.Size <= k_CopyLinkFile_MaxSize)
2802*f6dc9357SAndroid Build Coastguard Worker {
2803*f6dc9357SAndroid Build Coastguard Worker if (extractStatuses[(unsigned)ref.Link] == 0)
2804*f6dc9357SAndroid Build Coastguard Worker {
2805*f6dc9357SAndroid Build Coastguard Worker const CItem &lastLinkItem = _items[linkRef.Last];
2806*f6dc9357SAndroid Build Coastguard Worker if (!lastLinkItem.Is_UnknownSize())
2807*f6dc9357SAndroid Build Coastguard Worker total += lastLinkItem.Size;
2808*f6dc9357SAndroid Build Coastguard Worker else
2809*f6dc9357SAndroid Build Coastguard Worker isThereUndefinedSize = true;
2810*f6dc9357SAndroid Build Coastguard Worker }
2811*f6dc9357SAndroid Build Coastguard Worker extractStatuses[(unsigned)ref.Link] |= kStatus_Link;
2812*f6dc9357SAndroid Build Coastguard Worker thereAreLinks = true;
2813*f6dc9357SAndroid Build Coastguard Worker }
2814*f6dc9357SAndroid Build Coastguard Worker }
2815*f6dc9357SAndroid Build Coastguard Worker }
2816*f6dc9357SAndroid Build Coastguard Worker continue;
2817*f6dc9357SAndroid Build Coastguard Worker }
2818*f6dc9357SAndroid Build Coastguard Worker
2819*f6dc9357SAndroid Build Coastguard Worker if (item.IsService())
2820*f6dc9357SAndroid Build Coastguard Worker continue;
2821*f6dc9357SAndroid Build Coastguard Worker
2822*f6dc9357SAndroid Build Coastguard Worker if (item.IsSolid())
2823*f6dc9357SAndroid Build Coastguard Worker {
2824*f6dc9357SAndroid Build Coastguard Worker unsigned j = index;
2825*f6dc9357SAndroid Build Coastguard Worker
2826*f6dc9357SAndroid Build Coastguard Worker while (j > solidLimit)
2827*f6dc9357SAndroid Build Coastguard Worker {
2828*f6dc9357SAndroid Build Coastguard Worker j--;
2829*f6dc9357SAndroid Build Coastguard Worker const CRefItem &ref2 = _refs[j];
2830*f6dc9357SAndroid Build Coastguard Worker const CItem &item2 = _items[ref2.Item];
2831*f6dc9357SAndroid Build Coastguard Worker if (!item2.IsService())
2832*f6dc9357SAndroid Build Coastguard Worker {
2833*f6dc9357SAndroid Build Coastguard Worker if (extractStatuses[j] == 0)
2834*f6dc9357SAndroid Build Coastguard Worker {
2835*f6dc9357SAndroid Build Coastguard Worker const CItem &lastItem2 = _items[ref2.Last];
2836*f6dc9357SAndroid Build Coastguard Worker if (!lastItem2.Is_UnknownSize())
2837*f6dc9357SAndroid Build Coastguard Worker total += lastItem2.Size;
2838*f6dc9357SAndroid Build Coastguard Worker else
2839*f6dc9357SAndroid Build Coastguard Worker isThereUndefinedSize = true;
2840*f6dc9357SAndroid Build Coastguard Worker }
2841*f6dc9357SAndroid Build Coastguard Worker extractStatuses[j] |= kStatus_Skip;
2842*f6dc9357SAndroid Build Coastguard Worker if (!item2.IsSolid())
2843*f6dc9357SAndroid Build Coastguard Worker break;
2844*f6dc9357SAndroid Build Coastguard Worker }
2845*f6dc9357SAndroid Build Coastguard Worker }
2846*f6dc9357SAndroid Build Coastguard Worker }
2847*f6dc9357SAndroid Build Coastguard Worker
2848*f6dc9357SAndroid Build Coastguard Worker solidLimit = index + 1;
2849*f6dc9357SAndroid Build Coastguard Worker }
2850*f6dc9357SAndroid Build Coastguard Worker }
2851*f6dc9357SAndroid Build Coastguard Worker
2852*f6dc9357SAndroid Build Coastguard Worker if (thereAreLinks)
2853*f6dc9357SAndroid Build Coastguard Worker {
2854*f6dc9357SAndroid Build Coastguard Worker unsigned solidLimit = 0;
2855*f6dc9357SAndroid Build Coastguard Worker
2856*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, _refs)
2857*f6dc9357SAndroid Build Coastguard Worker {
2858*f6dc9357SAndroid Build Coastguard Worker if ((extractStatuses[i] & kStatus_Link) == 0)
2859*f6dc9357SAndroid Build Coastguard Worker continue;
2860*f6dc9357SAndroid Build Coastguard Worker
2861*f6dc9357SAndroid Build Coastguard Worker // We use CLinkFile for testMode too.
2862*f6dc9357SAndroid Build Coastguard Worker // So we can show errors for copy files.
2863*f6dc9357SAndroid Build Coastguard Worker // if (!testMode)
2864*f6dc9357SAndroid Build Coastguard Worker {
2865*f6dc9357SAndroid Build Coastguard Worker CLinkFile &linkFile = linkFiles.AddNew();
2866*f6dc9357SAndroid Build Coastguard Worker linkFile.Index = i;
2867*f6dc9357SAndroid Build Coastguard Worker }
2868*f6dc9357SAndroid Build Coastguard Worker
2869*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[_refs[i].Item];
2870*f6dc9357SAndroid Build Coastguard Worker /*
2871*f6dc9357SAndroid Build Coastguard Worker if (item.IsService())
2872*f6dc9357SAndroid Build Coastguard Worker continue;
2873*f6dc9357SAndroid Build Coastguard Worker */
2874*f6dc9357SAndroid Build Coastguard Worker
2875*f6dc9357SAndroid Build Coastguard Worker if (item.IsSolid())
2876*f6dc9357SAndroid Build Coastguard Worker {
2877*f6dc9357SAndroid Build Coastguard Worker unsigned j = i;
2878*f6dc9357SAndroid Build Coastguard Worker
2879*f6dc9357SAndroid Build Coastguard Worker while (j > solidLimit)
2880*f6dc9357SAndroid Build Coastguard Worker {
2881*f6dc9357SAndroid Build Coastguard Worker j--;
2882*f6dc9357SAndroid Build Coastguard Worker const CRefItem &ref2 = _refs[j];
2883*f6dc9357SAndroid Build Coastguard Worker const CItem &item2 = _items[ref2.Item];
2884*f6dc9357SAndroid Build Coastguard Worker if (!item2.IsService())
2885*f6dc9357SAndroid Build Coastguard Worker {
2886*f6dc9357SAndroid Build Coastguard Worker if (extractStatuses[j] != 0)
2887*f6dc9357SAndroid Build Coastguard Worker break;
2888*f6dc9357SAndroid Build Coastguard Worker extractStatuses[j] = kStatus_Skip;
2889*f6dc9357SAndroid Build Coastguard Worker {
2890*f6dc9357SAndroid Build Coastguard Worker const CItem &lastItem2 = _items[ref2.Last];
2891*f6dc9357SAndroid Build Coastguard Worker if (!lastItem2.Is_UnknownSize())
2892*f6dc9357SAndroid Build Coastguard Worker total += lastItem2.Size;
2893*f6dc9357SAndroid Build Coastguard Worker else
2894*f6dc9357SAndroid Build Coastguard Worker isThereUndefinedSize = true;
2895*f6dc9357SAndroid Build Coastguard Worker }
2896*f6dc9357SAndroid Build Coastguard Worker if (!item2.IsSolid())
2897*f6dc9357SAndroid Build Coastguard Worker break;
2898*f6dc9357SAndroid Build Coastguard Worker }
2899*f6dc9357SAndroid Build Coastguard Worker }
2900*f6dc9357SAndroid Build Coastguard Worker }
2901*f6dc9357SAndroid Build Coastguard Worker
2902*f6dc9357SAndroid Build Coastguard Worker solidLimit = i + 1;
2903*f6dc9357SAndroid Build Coastguard Worker }
2904*f6dc9357SAndroid Build Coastguard Worker
2905*f6dc9357SAndroid Build Coastguard Worker if (!testMode)
2906*f6dc9357SAndroid Build Coastguard Worker for (UInt32 t = 0; t < numItems; t++)
2907*f6dc9357SAndroid Build Coastguard Worker {
2908*f6dc9357SAndroid Build Coastguard Worker const unsigned index = (unsigned)(allFilesMode ? t : indices[t]);
2909*f6dc9357SAndroid Build Coastguard Worker const CRefItem &ref = _refs[index];
2910*f6dc9357SAndroid Build Coastguard Worker
2911*f6dc9357SAndroid Build Coastguard Worker const int linkIndex = ref.Link;
2912*f6dc9357SAndroid Build Coastguard Worker if (linkIndex < 0 || (unsigned)linkIndex >= index)
2913*f6dc9357SAndroid Build Coastguard Worker continue;
2914*f6dc9357SAndroid Build Coastguard Worker const CItem &linkItem = _items[_refs[(unsigned)linkIndex].Item];
2915*f6dc9357SAndroid Build Coastguard Worker if (!linkItem.IsSolid() || linkItem.Size > k_CopyLinkFile_MaxSize)
2916*f6dc9357SAndroid Build Coastguard Worker continue;
2917*f6dc9357SAndroid Build Coastguard Worker const int bufIndex = FindLinkBuf(linkFiles, (unsigned)linkIndex);
2918*f6dc9357SAndroid Build Coastguard Worker if (bufIndex < 0)
2919*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
2920*f6dc9357SAndroid Build Coastguard Worker linkFiles[bufIndex].NumLinks++;
2921*f6dc9357SAndroid Build Coastguard Worker }
2922*f6dc9357SAndroid Build Coastguard Worker }
2923*f6dc9357SAndroid Build Coastguard Worker
2924*f6dc9357SAndroid Build Coastguard Worker if (total != 0 || !isThereUndefinedSize)
2925*f6dc9357SAndroid Build Coastguard Worker {
2926*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(total))
2927*f6dc9357SAndroid Build Coastguard Worker }
2928*f6dc9357SAndroid Build Coastguard Worker }
2929*f6dc9357SAndroid Build Coastguard Worker
2930*f6dc9357SAndroid Build Coastguard Worker
2931*f6dc9357SAndroid Build Coastguard Worker
2932*f6dc9357SAndroid Build Coastguard Worker // ---------- MEMORY REQUEST ----------
2933*f6dc9357SAndroid Build Coastguard Worker {
2934*f6dc9357SAndroid Build Coastguard Worker UInt64 dictMaxSize = 0;
2935*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < _refs.Size(); i++)
2936*f6dc9357SAndroid Build Coastguard Worker {
2937*f6dc9357SAndroid Build Coastguard Worker if (extractStatuses[i] == 0)
2938*f6dc9357SAndroid Build Coastguard Worker continue;
2939*f6dc9357SAndroid Build Coastguard Worker const CRefItem &ref = _refs[i];
2940*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[ref.Item];
2941*f6dc9357SAndroid Build Coastguard Worker /*
2942*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDir() && !item.IsService() && item.NeedUse_as_CopyLink())
2943*f6dc9357SAndroid Build Coastguard Worker {
2944*f6dc9357SAndroid Build Coastguard Worker }
2945*f6dc9357SAndroid Build Coastguard Worker */
2946*f6dc9357SAndroid Build Coastguard Worker const unsigned algo = item.Get_AlgoVersion_RawBits();
2947*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDir() && algo < Z7_ARRAY_SIZE(_methodMasks))
2948*f6dc9357SAndroid Build Coastguard Worker {
2949*f6dc9357SAndroid Build Coastguard Worker const UInt64 d = item.Get_DictSize64();
2950*f6dc9357SAndroid Build Coastguard Worker if (dictMaxSize < d)
2951*f6dc9357SAndroid Build Coastguard Worker dictMaxSize = d;
2952*f6dc9357SAndroid Build Coastguard Worker }
2953*f6dc9357SAndroid Build Coastguard Worker }
2954*f6dc9357SAndroid Build Coastguard Worker // we use callback, if dict exceeds (1 GB), because
2955*f6dc9357SAndroid Build Coastguard Worker // client code can set low limit (1 GB) for allowed memory usage.
2956*f6dc9357SAndroid Build Coastguard Worker const UInt64 k_MemLimit_for_Callback = (UInt64)1 << 30;
2957*f6dc9357SAndroid Build Coastguard Worker if (dictMaxSize > (_memUsage_WasSet ?
2958*f6dc9357SAndroid Build Coastguard Worker _memUsage_Decompress : k_MemLimit_for_Callback))
2959*f6dc9357SAndroid Build Coastguard Worker {
2960*f6dc9357SAndroid Build Coastguard Worker {
2961*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IArchiveRequestMemoryUseCallback> requestMem;
2962*f6dc9357SAndroid Build Coastguard Worker extractCallback->QueryInterface(IID_IArchiveRequestMemoryUseCallback, (void **)&requestMem);
2963*f6dc9357SAndroid Build Coastguard Worker if (!requestMem)
2964*f6dc9357SAndroid Build Coastguard Worker {
2965*f6dc9357SAndroid Build Coastguard Worker if (_memUsage_WasSet)
2966*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
2967*f6dc9357SAndroid Build Coastguard Worker }
2968*f6dc9357SAndroid Build Coastguard Worker else
2969*f6dc9357SAndroid Build Coastguard Worker {
2970*f6dc9357SAndroid Build Coastguard Worker UInt64 allowedSize = _memUsage_WasSet ?
2971*f6dc9357SAndroid Build Coastguard Worker _memUsage_Decompress :
2972*f6dc9357SAndroid Build Coastguard Worker (UInt64)1 << 32; // 4 GB is default allowed limit for RAR7
2973*f6dc9357SAndroid Build Coastguard Worker
2974*f6dc9357SAndroid Build Coastguard Worker const UInt32 flags = (_memUsage_WasSet ?
2975*f6dc9357SAndroid Build Coastguard Worker NRequestMemoryUseFlags::k_AllowedSize_WasForced |
2976*f6dc9357SAndroid Build Coastguard Worker NRequestMemoryUseFlags::k_MLimit_Exceeded :
2977*f6dc9357SAndroid Build Coastguard Worker (dictMaxSize > allowedSize) ?
2978*f6dc9357SAndroid Build Coastguard Worker NRequestMemoryUseFlags::k_DefaultLimit_Exceeded:
2979*f6dc9357SAndroid Build Coastguard Worker 0)
2980*f6dc9357SAndroid Build Coastguard Worker | NRequestMemoryUseFlags::k_SkipArc_IsExpected
2981*f6dc9357SAndroid Build Coastguard Worker // | NRequestMemoryUseFlags::k_NoErrorMessage // for debug
2982*f6dc9357SAndroid Build Coastguard Worker ;
2983*f6dc9357SAndroid Build Coastguard Worker
2984*f6dc9357SAndroid Build Coastguard Worker // we set "Allow" for default case, if requestMem doesn't process anything.
2985*f6dc9357SAndroid Build Coastguard Worker UInt32 answerFlags =
2986*f6dc9357SAndroid Build Coastguard Worker (_memUsage_WasSet && dictMaxSize > allowedSize) ?
2987*f6dc9357SAndroid Build Coastguard Worker NRequestMemoryAnswerFlags::k_Limit_Exceeded
2988*f6dc9357SAndroid Build Coastguard Worker | NRequestMemoryAnswerFlags::k_SkipArc
2989*f6dc9357SAndroid Build Coastguard Worker : NRequestMemoryAnswerFlags::k_Allow;
2990*f6dc9357SAndroid Build Coastguard Worker
2991*f6dc9357SAndroid Build Coastguard Worker RINOK(requestMem->RequestMemoryUse(
2992*f6dc9357SAndroid Build Coastguard Worker flags,
2993*f6dc9357SAndroid Build Coastguard Worker NEventIndexType::kNoIndex,
2994*f6dc9357SAndroid Build Coastguard Worker // NEventIndexType::kInArcIndex, // for debug
2995*f6dc9357SAndroid Build Coastguard Worker 0, // index
2996*f6dc9357SAndroid Build Coastguard Worker NULL, // path
2997*f6dc9357SAndroid Build Coastguard Worker dictMaxSize, &allowedSize, &answerFlags))
2998*f6dc9357SAndroid Build Coastguard Worker if ( (answerFlags & NRequestMemoryAnswerFlags::k_Allow) == 0
2999*f6dc9357SAndroid Build Coastguard Worker || (answerFlags & NRequestMemoryAnswerFlags::k_Stop)
3000*f6dc9357SAndroid Build Coastguard Worker || (answerFlags & NRequestMemoryAnswerFlags::k_SkipArc)
3001*f6dc9357SAndroid Build Coastguard Worker )
3002*f6dc9357SAndroid Build Coastguard Worker {
3003*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
3004*f6dc9357SAndroid Build Coastguard Worker }
3005*f6dc9357SAndroid Build Coastguard Worker /*
3006*f6dc9357SAndroid Build Coastguard Worker if ((answerFlags & NRequestMemoryAnswerFlags::k_AskForBigFile) == 0 &&
3007*f6dc9357SAndroid Build Coastguard Worker (answerFlags & NRequestMemoryAnswerFlags::k_ReportForBigFile) == 0)
3008*f6dc9357SAndroid Build Coastguard Worker {
3009*f6dc9357SAndroid Build Coastguard Worker // requestMem.Release();
3010*f6dc9357SAndroid Build Coastguard Worker }
3011*f6dc9357SAndroid Build Coastguard Worker */
3012*f6dc9357SAndroid Build Coastguard Worker }
3013*f6dc9357SAndroid Build Coastguard Worker }
3014*f6dc9357SAndroid Build Coastguard Worker }
3015*f6dc9357SAndroid Build Coastguard Worker }
3016*f6dc9357SAndroid Build Coastguard Worker
3017*f6dc9357SAndroid Build Coastguard Worker
3018*f6dc9357SAndroid Build Coastguard Worker
3019*f6dc9357SAndroid Build Coastguard Worker // ---------- UNPACK ----------
3020*f6dc9357SAndroid Build Coastguard Worker
3021*f6dc9357SAndroid Build Coastguard Worker UInt64 totalUnpacked = 0;
3022*f6dc9357SAndroid Build Coastguard Worker UInt64 totalPacked = 0;
3023*f6dc9357SAndroid Build Coastguard Worker UInt64 curUnpackSize;
3024*f6dc9357SAndroid Build Coastguard Worker UInt64 curPackSize;
3025*f6dc9357SAndroid Build Coastguard Worker
3026*f6dc9357SAndroid Build Coastguard Worker CUnpacker unpacker;
3027*f6dc9357SAndroid Build Coastguard Worker unpacker.NeedCrc = _needChecksumCheck;
3028*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CVolsInStream> volsInStream;
3029*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
3030*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
3031*f6dc9357SAndroid Build Coastguard Worker
3032*f6dc9357SAndroid Build Coastguard Worker /*
3033*f6dc9357SAndroid Build Coastguard Worker bool prevSolidWasSkipped = false;
3034*f6dc9357SAndroid Build Coastguard Worker UInt64 solidDictSize_Skip = 0;
3035*f6dc9357SAndroid Build Coastguard Worker */
3036*f6dc9357SAndroid Build Coastguard Worker
3037*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0;; i++,
3038*f6dc9357SAndroid Build Coastguard Worker totalUnpacked += curUnpackSize,
3039*f6dc9357SAndroid Build Coastguard Worker totalPacked += curPackSize)
3040*f6dc9357SAndroid Build Coastguard Worker {
3041*f6dc9357SAndroid Build Coastguard Worker lps->InSize = totalPacked;
3042*f6dc9357SAndroid Build Coastguard Worker lps->OutSize = totalUnpacked;
3043*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
3044*f6dc9357SAndroid Build Coastguard Worker {
3045*f6dc9357SAndroid Build Coastguard Worker const unsigned num = _refs.Size();
3046*f6dc9357SAndroid Build Coastguard Worker if (i >= num)
3047*f6dc9357SAndroid Build Coastguard Worker break;
3048*f6dc9357SAndroid Build Coastguard Worker for (;;)
3049*f6dc9357SAndroid Build Coastguard Worker {
3050*f6dc9357SAndroid Build Coastguard Worker if (extractStatuses[i] != 0)
3051*f6dc9357SAndroid Build Coastguard Worker break;
3052*f6dc9357SAndroid Build Coastguard Worker i++;
3053*f6dc9357SAndroid Build Coastguard Worker if (i >= num)
3054*f6dc9357SAndroid Build Coastguard Worker break;
3055*f6dc9357SAndroid Build Coastguard Worker }
3056*f6dc9357SAndroid Build Coastguard Worker if (i >= num)
3057*f6dc9357SAndroid Build Coastguard Worker break;
3058*f6dc9357SAndroid Build Coastguard Worker }
3059*f6dc9357SAndroid Build Coastguard Worker curUnpackSize = 0;
3060*f6dc9357SAndroid Build Coastguard Worker curPackSize = 0;
3061*f6dc9357SAndroid Build Coastguard Worker
3062*f6dc9357SAndroid Build Coastguard Worker // isExtract means that we don't skip that item. So we need read data.
3063*f6dc9357SAndroid Build Coastguard Worker const bool isExtract = ((extractStatuses[i] & kStatus_Extract) != 0);
3064*f6dc9357SAndroid Build Coastguard Worker Int32 askMode =
3065*f6dc9357SAndroid Build Coastguard Worker isExtract ? (testMode ?
3066*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
3067*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract) :
3068*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kSkip;
3069*f6dc9357SAndroid Build Coastguard Worker
3070*f6dc9357SAndroid Build Coastguard Worker unpacker.linkFile = NULL;
3071*f6dc9357SAndroid Build Coastguard Worker
3072*f6dc9357SAndroid Build Coastguard Worker // if (!testMode)
3073*f6dc9357SAndroid Build Coastguard Worker if ((extractStatuses[i] & kStatus_Link) != 0)
3074*f6dc9357SAndroid Build Coastguard Worker {
3075*f6dc9357SAndroid Build Coastguard Worker const int bufIndex = FindLinkBuf(linkFiles, i);
3076*f6dc9357SAndroid Build Coastguard Worker if (bufIndex < 0)
3077*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
3078*f6dc9357SAndroid Build Coastguard Worker unpacker.linkFile = &linkFiles[bufIndex];
3079*f6dc9357SAndroid Build Coastguard Worker }
3080*f6dc9357SAndroid Build Coastguard Worker
3081*f6dc9357SAndroid Build Coastguard Worker const unsigned index = i;
3082*f6dc9357SAndroid Build Coastguard Worker const CRefItem *ref = &_refs[index];
3083*f6dc9357SAndroid Build Coastguard Worker const CItem *item = &_items[ref->Item];
3084*f6dc9357SAndroid Build Coastguard Worker const CItem &lastItem = _items[ref->Last];
3085*f6dc9357SAndroid Build Coastguard Worker
3086*f6dc9357SAndroid Build Coastguard Worker curUnpackSize = 0;
3087*f6dc9357SAndroid Build Coastguard Worker if (!lastItem.Is_UnknownSize())
3088*f6dc9357SAndroid Build Coastguard Worker curUnpackSize = lastItem.Size;
3089*f6dc9357SAndroid Build Coastguard Worker
3090*f6dc9357SAndroid Build Coastguard Worker curPackSize = GetPackSize(index);
3091*f6dc9357SAndroid Build Coastguard Worker
3092*f6dc9357SAndroid Build Coastguard Worker bool isSolid = false;
3093*f6dc9357SAndroid Build Coastguard Worker if (!item->IsService())
3094*f6dc9357SAndroid Build Coastguard Worker {
3095*f6dc9357SAndroid Build Coastguard Worker if (item->IsSolid())
3096*f6dc9357SAndroid Build Coastguard Worker isSolid = unpacker.SolidAllowed;
3097*f6dc9357SAndroid Build Coastguard Worker unpacker.SolidAllowed = isSolid;
3098*f6dc9357SAndroid Build Coastguard Worker }
3099*f6dc9357SAndroid Build Coastguard Worker
3100*f6dc9357SAndroid Build Coastguard Worker
3101*f6dc9357SAndroid Build Coastguard Worker // ----- request mem -----
3102*f6dc9357SAndroid Build Coastguard Worker /*
3103*f6dc9357SAndroid Build Coastguard Worker // link files are complicated cases. (ref->Link >= 0)
3104*f6dc9357SAndroid Build Coastguard Worker // link file can refer to non-solid file that can have big dictionary
3105*f6dc9357SAndroid Build Coastguard Worker // link file can refer to solid files that requres buffer
3106*f6dc9357SAndroid Build Coastguard Worker if (!item->IsDir() && requestMem && ref->Link < 0)
3107*f6dc9357SAndroid Build Coastguard Worker {
3108*f6dc9357SAndroid Build Coastguard Worker bool needSkip = false;
3109*f6dc9357SAndroid Build Coastguard Worker if (isSolid)
3110*f6dc9357SAndroid Build Coastguard Worker needSkip = prevSolidWasSkipped;
3111*f6dc9357SAndroid Build Coastguard Worker else
3112*f6dc9357SAndroid Build Coastguard Worker {
3113*f6dc9357SAndroid Build Coastguard Worker // isSolid == false
3114*f6dc9357SAndroid Build Coastguard Worker const unsigned algo = item->Get_AlgoVersion_RawBits();
3115*f6dc9357SAndroid Build Coastguard Worker // const unsigned m = item.Get_Method();
3116*f6dc9357SAndroid Build Coastguard Worker if (algo < Z7_ARRAY_SIZE(_methodMasks))
3117*f6dc9357SAndroid Build Coastguard Worker {
3118*f6dc9357SAndroid Build Coastguard Worker solidDictSize_Skip = item->Get_DictSize64();
3119*f6dc9357SAndroid Build Coastguard Worker if (solidDictSize_Skip > allowedSize)
3120*f6dc9357SAndroid Build Coastguard Worker needSkip = true;
3121*f6dc9357SAndroid Build Coastguard Worker }
3122*f6dc9357SAndroid Build Coastguard Worker }
3123*f6dc9357SAndroid Build Coastguard Worker if (needSkip)
3124*f6dc9357SAndroid Build Coastguard Worker {
3125*f6dc9357SAndroid Build Coastguard Worker UInt32 answerFlags = 0;
3126*f6dc9357SAndroid Build Coastguard Worker UInt64 allowedSize_File = allowedSize;
3127*f6dc9357SAndroid Build Coastguard Worker RINOK(requestMem->RequestMemoryUse(
3128*f6dc9357SAndroid Build Coastguard Worker NRequestMemoryUseFlags::k_Limit_Exceeded |
3129*f6dc9357SAndroid Build Coastguard Worker NRequestMemoryUseFlags::k_IsReport,
3130*f6dc9357SAndroid Build Coastguard Worker NEventIndexType::kInArcIndex,
3131*f6dc9357SAndroid Build Coastguard Worker index,
3132*f6dc9357SAndroid Build Coastguard Worker NULL, // path
3133*f6dc9357SAndroid Build Coastguard Worker solidDictSize_Skip, &allowedSize_File, &answerFlags))
3134*f6dc9357SAndroid Build Coastguard Worker if (!item->IsService())
3135*f6dc9357SAndroid Build Coastguard Worker prevSolidWasSkipped = true;
3136*f6dc9357SAndroid Build Coastguard Worker continue;
3137*f6dc9357SAndroid Build Coastguard Worker }
3138*f6dc9357SAndroid Build Coastguard Worker }
3139*f6dc9357SAndroid Build Coastguard Worker if (!item->IsService() && item->IsDir())
3140*f6dc9357SAndroid Build Coastguard Worker prevSolidWasSkipped = false;
3141*f6dc9357SAndroid Build Coastguard Worker */
3142*f6dc9357SAndroid Build Coastguard Worker
3143*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
3144*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream((UInt32)index, &realOutStream, askMode))
3145*f6dc9357SAndroid Build Coastguard Worker
3146*f6dc9357SAndroid Build Coastguard Worker if (item->IsDir())
3147*f6dc9357SAndroid Build Coastguard Worker {
3148*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
3149*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
3150*f6dc9357SAndroid Build Coastguard Worker continue;
3151*f6dc9357SAndroid Build Coastguard Worker }
3152*f6dc9357SAndroid Build Coastguard Worker
3153*f6dc9357SAndroid Build Coastguard Worker const int index2 = ref->Link;
3154*f6dc9357SAndroid Build Coastguard Worker
3155*f6dc9357SAndroid Build Coastguard Worker int bufIndex = -1;
3156*f6dc9357SAndroid Build Coastguard Worker
3157*f6dc9357SAndroid Build Coastguard Worker if (index2 >= 0)
3158*f6dc9357SAndroid Build Coastguard Worker {
3159*f6dc9357SAndroid Build Coastguard Worker const CRefItem &ref2 = _refs[index2];
3160*f6dc9357SAndroid Build Coastguard Worker const CItem &item2 = _items[ref2.Item];
3161*f6dc9357SAndroid Build Coastguard Worker const CItem &lastItem2 = _items[ref2.Last];
3162*f6dc9357SAndroid Build Coastguard Worker if (!item2.IsSolid())
3163*f6dc9357SAndroid Build Coastguard Worker {
3164*f6dc9357SAndroid Build Coastguard Worker item = &item2;
3165*f6dc9357SAndroid Build Coastguard Worker ref = &ref2;
3166*f6dc9357SAndroid Build Coastguard Worker if (!lastItem2.Is_UnknownSize())
3167*f6dc9357SAndroid Build Coastguard Worker curUnpackSize = lastItem2.Size;
3168*f6dc9357SAndroid Build Coastguard Worker else
3169*f6dc9357SAndroid Build Coastguard Worker curUnpackSize = 0;
3170*f6dc9357SAndroid Build Coastguard Worker curPackSize = GetPackSize((unsigned)index2);
3171*f6dc9357SAndroid Build Coastguard Worker }
3172*f6dc9357SAndroid Build Coastguard Worker else
3173*f6dc9357SAndroid Build Coastguard Worker {
3174*f6dc9357SAndroid Build Coastguard Worker if ((unsigned)index2 < index)
3175*f6dc9357SAndroid Build Coastguard Worker bufIndex = FindLinkBuf(linkFiles, (unsigned)index2);
3176*f6dc9357SAndroid Build Coastguard Worker }
3177*f6dc9357SAndroid Build Coastguard Worker }
3178*f6dc9357SAndroid Build Coastguard Worker
3179*f6dc9357SAndroid Build Coastguard Worker bool needCallback = true;
3180*f6dc9357SAndroid Build Coastguard Worker
3181*f6dc9357SAndroid Build Coastguard Worker if (!realOutStream)
3182*f6dc9357SAndroid Build Coastguard Worker {
3183*f6dc9357SAndroid Build Coastguard Worker if (testMode)
3184*f6dc9357SAndroid Build Coastguard Worker {
3185*f6dc9357SAndroid Build Coastguard Worker if (item->NeedUse_as_CopyLink_or_HardLink())
3186*f6dc9357SAndroid Build Coastguard Worker {
3187*f6dc9357SAndroid Build Coastguard Worker Int32 opRes = NExtract::NOperationResult::kOK;
3188*f6dc9357SAndroid Build Coastguard Worker if (bufIndex >= 0)
3189*f6dc9357SAndroid Build Coastguard Worker {
3190*f6dc9357SAndroid Build Coastguard Worker const CLinkFile &linkFile = linkFiles[bufIndex];
3191*f6dc9357SAndroid Build Coastguard Worker opRes = DecoderRes_to_OpRes(linkFile.Res, linkFile.crcOK);
3192*f6dc9357SAndroid Build Coastguard Worker }
3193*f6dc9357SAndroid Build Coastguard Worker
3194*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
3195*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(opRes))
3196*f6dc9357SAndroid Build Coastguard Worker continue;
3197*f6dc9357SAndroid Build Coastguard Worker }
3198*f6dc9357SAndroid Build Coastguard Worker }
3199*f6dc9357SAndroid Build Coastguard Worker else
3200*f6dc9357SAndroid Build Coastguard Worker {
3201*f6dc9357SAndroid Build Coastguard Worker if (item->IsService())
3202*f6dc9357SAndroid Build Coastguard Worker continue;
3203*f6dc9357SAndroid Build Coastguard Worker
3204*f6dc9357SAndroid Build Coastguard Worker needCallback = false;
3205*f6dc9357SAndroid Build Coastguard Worker
3206*f6dc9357SAndroid Build Coastguard Worker if (!item->NeedUse_as_HardLink())
3207*f6dc9357SAndroid Build Coastguard Worker if (index2 < 0)
3208*f6dc9357SAndroid Build Coastguard Worker
3209*f6dc9357SAndroid Build Coastguard Worker for (unsigned n = i + 1; n < _refs.Size(); n++)
3210*f6dc9357SAndroid Build Coastguard Worker {
3211*f6dc9357SAndroid Build Coastguard Worker const CItem &nextItem = _items[_refs[n].Item];
3212*f6dc9357SAndroid Build Coastguard Worker if (nextItem.IsService())
3213*f6dc9357SAndroid Build Coastguard Worker continue;
3214*f6dc9357SAndroid Build Coastguard Worker if (!nextItem.IsSolid())
3215*f6dc9357SAndroid Build Coastguard Worker break;
3216*f6dc9357SAndroid Build Coastguard Worker if (extractStatuses[i] != 0)
3217*f6dc9357SAndroid Build Coastguard Worker {
3218*f6dc9357SAndroid Build Coastguard Worker needCallback = true;
3219*f6dc9357SAndroid Build Coastguard Worker break;
3220*f6dc9357SAndroid Build Coastguard Worker }
3221*f6dc9357SAndroid Build Coastguard Worker }
3222*f6dc9357SAndroid Build Coastguard Worker
3223*f6dc9357SAndroid Build Coastguard Worker askMode = NExtract::NAskMode::kSkip;
3224*f6dc9357SAndroid Build Coastguard Worker }
3225*f6dc9357SAndroid Build Coastguard Worker }
3226*f6dc9357SAndroid Build Coastguard Worker
3227*f6dc9357SAndroid Build Coastguard Worker if (needCallback)
3228*f6dc9357SAndroid Build Coastguard Worker {
3229*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
3230*f6dc9357SAndroid Build Coastguard Worker }
3231*f6dc9357SAndroid Build Coastguard Worker
3232*f6dc9357SAndroid Build Coastguard Worker if (bufIndex >= 0)
3233*f6dc9357SAndroid Build Coastguard Worker {
3234*f6dc9357SAndroid Build Coastguard Worker CLinkFile &linkFile = linkFiles[bufIndex];
3235*f6dc9357SAndroid Build Coastguard Worker
3236*f6dc9357SAndroid Build Coastguard Worker if (isExtract)
3237*f6dc9357SAndroid Build Coastguard Worker {
3238*f6dc9357SAndroid Build Coastguard Worker if (linkFile.NumLinks == 0)
3239*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
3240*f6dc9357SAndroid Build Coastguard Worker
3241*f6dc9357SAndroid Build Coastguard Worker if (needCallback)
3242*f6dc9357SAndroid Build Coastguard Worker if (realOutStream)
3243*f6dc9357SAndroid Build Coastguard Worker {
3244*f6dc9357SAndroid Build Coastguard Worker RINOK(CopyData_with_Progress(linkFile.Data, linkFile.Data.Size(), realOutStream, lps))
3245*f6dc9357SAndroid Build Coastguard Worker }
3246*f6dc9357SAndroid Build Coastguard Worker
3247*f6dc9357SAndroid Build Coastguard Worker if (--linkFile.NumLinks == 0)
3248*f6dc9357SAndroid Build Coastguard Worker linkFile.Data.Free();
3249*f6dc9357SAndroid Build Coastguard Worker }
3250*f6dc9357SAndroid Build Coastguard Worker
3251*f6dc9357SAndroid Build Coastguard Worker if (needCallback)
3252*f6dc9357SAndroid Build Coastguard Worker {
3253*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(DecoderRes_to_OpRes(linkFile.Res, linkFile.crcOK)))
3254*f6dc9357SAndroid Build Coastguard Worker }
3255*f6dc9357SAndroid Build Coastguard Worker continue;
3256*f6dc9357SAndroid Build Coastguard Worker }
3257*f6dc9357SAndroid Build Coastguard Worker
3258*f6dc9357SAndroid Build Coastguard Worker if (!needCallback)
3259*f6dc9357SAndroid Build Coastguard Worker continue;
3260*f6dc9357SAndroid Build Coastguard Worker
3261*f6dc9357SAndroid Build Coastguard Worker if (item->NeedUse_as_CopyLink())
3262*f6dc9357SAndroid Build Coastguard Worker {
3263*f6dc9357SAndroid Build Coastguard Worker const int opRes = realOutStream ?
3264*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kUnsupportedMethod:
3265*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kOK;
3266*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release();
3267*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(opRes))
3268*f6dc9357SAndroid Build Coastguard Worker continue;
3269*f6dc9357SAndroid Build Coastguard Worker }
3270*f6dc9357SAndroid Build Coastguard Worker
3271*f6dc9357SAndroid Build Coastguard Worker volsInStream->Init(&_arcs, &_items, ref->Item);
3272*f6dc9357SAndroid Build Coastguard Worker
3273*f6dc9357SAndroid Build Coastguard Worker const UInt64 packSize = curPackSize;
3274*f6dc9357SAndroid Build Coastguard Worker
3275*f6dc9357SAndroid Build Coastguard Worker if (item->IsEncrypted())
3276*f6dc9357SAndroid Build Coastguard Worker if (!unpacker.getTextPassword)
3277*f6dc9357SAndroid Build Coastguard Worker extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&unpacker.getTextPassword);
3278*f6dc9357SAndroid Build Coastguard Worker
3279*f6dc9357SAndroid Build Coastguard Worker bool wrongPassword;
3280*f6dc9357SAndroid Build Coastguard Worker HRESULT result = unpacker.Create(EXTERNAL_CODECS_VARS *item, isSolid, wrongPassword);
3281*f6dc9357SAndroid Build Coastguard Worker
3282*f6dc9357SAndroid Build Coastguard Worker if (wrongPassword)
3283*f6dc9357SAndroid Build Coastguard Worker {
3284*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release();
3285*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kWrongPassword))
3286*f6dc9357SAndroid Build Coastguard Worker continue;
3287*f6dc9357SAndroid Build Coastguard Worker }
3288*f6dc9357SAndroid Build Coastguard Worker
3289*f6dc9357SAndroid Build Coastguard Worker bool crcOK = true;
3290*f6dc9357SAndroid Build Coastguard Worker if (result == S_OK)
3291*f6dc9357SAndroid Build Coastguard Worker result = unpacker.Code(*item, _items[ref->Last], packSize, volsInStream, realOutStream, lps, crcOK);
3292*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release();
3293*f6dc9357SAndroid Build Coastguard Worker if (!volsInStream->CrcIsOK)
3294*f6dc9357SAndroid Build Coastguard Worker crcOK = false;
3295*f6dc9357SAndroid Build Coastguard Worker
3296*f6dc9357SAndroid Build Coastguard Worker int opRes = crcOK ?
3297*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kOK:
3298*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kCRCError;
3299*f6dc9357SAndroid Build Coastguard Worker
3300*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK)
3301*f6dc9357SAndroid Build Coastguard Worker {
3302*f6dc9357SAndroid Build Coastguard Worker if (result == S_FALSE)
3303*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError;
3304*f6dc9357SAndroid Build Coastguard Worker else if (result == E_NOTIMPL)
3305*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kUnsupportedMethod;
3306*f6dc9357SAndroid Build Coastguard Worker else
3307*f6dc9357SAndroid Build Coastguard Worker return result;
3308*f6dc9357SAndroid Build Coastguard Worker }
3309*f6dc9357SAndroid Build Coastguard Worker
3310*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(opRes))
3311*f6dc9357SAndroid Build Coastguard Worker }
3312*f6dc9357SAndroid Build Coastguard Worker
3313*f6dc9357SAndroid Build Coastguard Worker {
3314*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (k, linkFiles)
3315*f6dc9357SAndroid Build Coastguard Worker if (linkFiles[k].NumLinks != 0)
3316*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
3317*f6dc9357SAndroid Build Coastguard Worker }
3318*f6dc9357SAndroid Build Coastguard Worker
3319*f6dc9357SAndroid Build Coastguard Worker return S_OK;
3320*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
3321*f6dc9357SAndroid Build Coastguard Worker }
3322*f6dc9357SAndroid Build Coastguard Worker
3323*f6dc9357SAndroid Build Coastguard Worker
3324*f6dc9357SAndroid Build Coastguard Worker CHandler::CHandler()
3325*f6dc9357SAndroid Build Coastguard Worker {
3326*f6dc9357SAndroid Build Coastguard Worker InitDefaults();
3327*f6dc9357SAndroid Build Coastguard Worker }
3328*f6dc9357SAndroid Build Coastguard Worker
3329*f6dc9357SAndroid Build Coastguard Worker void CHandler::InitDefaults()
3330*f6dc9357SAndroid Build Coastguard Worker {
3331*f6dc9357SAndroid Build Coastguard Worker _needChecksumCheck = true;
3332*f6dc9357SAndroid Build Coastguard Worker _memUsage_WasSet = false;
3333*f6dc9357SAndroid Build Coastguard Worker _memUsage_Decompress = (UInt64)1 << 32;
3334*f6dc9357SAndroid Build Coastguard Worker }
3335*f6dc9357SAndroid Build Coastguard Worker
3336*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
3337*f6dc9357SAndroid Build Coastguard Worker {
3338*f6dc9357SAndroid Build Coastguard Worker InitDefaults();
3339*f6dc9357SAndroid Build Coastguard Worker
3340*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numProps; i++)
3341*f6dc9357SAndroid Build Coastguard Worker {
3342*f6dc9357SAndroid Build Coastguard Worker UString name = names[i];
3343*f6dc9357SAndroid Build Coastguard Worker name.MakeLower_Ascii();
3344*f6dc9357SAndroid Build Coastguard Worker if (name.IsEmpty())
3345*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
3346*f6dc9357SAndroid Build Coastguard Worker
3347*f6dc9357SAndroid Build Coastguard Worker const PROPVARIANT &prop = values[i];
3348*f6dc9357SAndroid Build Coastguard Worker
3349*f6dc9357SAndroid Build Coastguard Worker if (name.IsPrefixedBy_Ascii_NoCase("mt"))
3350*f6dc9357SAndroid Build Coastguard Worker {
3351*f6dc9357SAndroid Build Coastguard Worker }
3352*f6dc9357SAndroid Build Coastguard Worker else if (name.IsPrefixedBy_Ascii_NoCase("memx"))
3353*f6dc9357SAndroid Build Coastguard Worker {
3354*f6dc9357SAndroid Build Coastguard Worker size_t memAvail;
3355*f6dc9357SAndroid Build Coastguard Worker if (!NWindows::NSystem::GetRamSize(memAvail))
3356*f6dc9357SAndroid Build Coastguard Worker memAvail = (size_t)sizeof(size_t) << 28;
3357*f6dc9357SAndroid Build Coastguard Worker UInt64 v;
3358*f6dc9357SAndroid Build Coastguard Worker if (!ParseSizeString(name.Ptr(4), prop, memAvail, v))
3359*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
3360*f6dc9357SAndroid Build Coastguard Worker _memUsage_Decompress = v;
3361*f6dc9357SAndroid Build Coastguard Worker _memUsage_WasSet = true;
3362*f6dc9357SAndroid Build Coastguard Worker }
3363*f6dc9357SAndroid Build Coastguard Worker else if (name.IsPrefixedBy_Ascii_NoCase("crc"))
3364*f6dc9357SAndroid Build Coastguard Worker {
3365*f6dc9357SAndroid Build Coastguard Worker name.Delete(0, 3);
3366*f6dc9357SAndroid Build Coastguard Worker UInt32 crcSize = 1;
3367*f6dc9357SAndroid Build Coastguard Worker RINOK(ParsePropToUInt32(name, prop, crcSize))
3368*f6dc9357SAndroid Build Coastguard Worker _needChecksumCheck = (crcSize != 0);
3369*f6dc9357SAndroid Build Coastguard Worker }
3370*f6dc9357SAndroid Build Coastguard Worker else
3371*f6dc9357SAndroid Build Coastguard Worker {
3372*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
3373*f6dc9357SAndroid Build Coastguard Worker }
3374*f6dc9357SAndroid Build Coastguard Worker }
3375*f6dc9357SAndroid Build Coastguard Worker return S_OK;
3376*f6dc9357SAndroid Build Coastguard Worker }
3377*f6dc9357SAndroid Build Coastguard Worker
3378*f6dc9357SAndroid Build Coastguard Worker
3379*f6dc9357SAndroid Build Coastguard Worker IMPL_ISetCompressCodecsInfo
3380*f6dc9357SAndroid Build Coastguard Worker
3381*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
3382*f6dc9357SAndroid Build Coastguard Worker "Rar5", "rar r00", NULL, 0xCC,
3383*f6dc9357SAndroid Build Coastguard Worker kMarker,
3384*f6dc9357SAndroid Build Coastguard Worker 0,
3385*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kFindSignature,
3386*f6dc9357SAndroid Build Coastguard Worker NULL)
3387*f6dc9357SAndroid Build Coastguard Worker
3388*f6dc9357SAndroid Build Coastguard Worker }}
3389*f6dc9357SAndroid Build Coastguard Worker
3390*f6dc9357SAndroid Build Coastguard Worker
3391*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_2(
3392*f6dc9357SAndroid Build Coastguard Worker CBlake2spHasher
3393*f6dc9357SAndroid Build Coastguard Worker , IHasher
3394*f6dc9357SAndroid Build Coastguard Worker , ICompressSetCoderProperties
3395*f6dc9357SAndroid Build Coastguard Worker )
3396*f6dc9357SAndroid Build Coastguard Worker CAlignedBuffer1 _buf;
3397*f6dc9357SAndroid Build Coastguard Worker // CBlake2sp _blake;
3398*f6dc9357SAndroid Build Coastguard Worker #define Z7_BLACK2S_ALIGN_OBJECT_OFFSET 0
3399*f6dc9357SAndroid Build Coastguard Worker CBlake2sp *Obj() { return (CBlake2sp *)(void *)((Byte *)_buf + Z7_BLACK2S_ALIGN_OBJECT_OFFSET); }
3400*f6dc9357SAndroid Build Coastguard Worker public:
3401*f6dc9357SAndroid Build Coastguard Worker Byte _mtDummy[1 << 7]; // it's public to eliminate clang warning: unused private field
3402*f6dc9357SAndroid Build Coastguard Worker CBlake2spHasher():
3403*f6dc9357SAndroid Build Coastguard Worker _buf(sizeof(CBlake2sp) + Z7_BLACK2S_ALIGN_OBJECT_OFFSET)
3404*f6dc9357SAndroid Build Coastguard Worker {
3405*f6dc9357SAndroid Build Coastguard Worker Blake2sp_SetFunction(Obj(), 0);
3406*f6dc9357SAndroid Build Coastguard Worker Blake2sp_InitState(Obj());
3407*f6dc9357SAndroid Build Coastguard Worker }
3408*f6dc9357SAndroid Build Coastguard Worker };
3409*f6dc9357SAndroid Build Coastguard Worker
3410*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF2(void, CBlake2spHasher::Init())
3411*f6dc9357SAndroid Build Coastguard Worker {
3412*f6dc9357SAndroid Build Coastguard Worker Blake2sp_InitState(Obj());
3413*f6dc9357SAndroid Build Coastguard Worker }
3414*f6dc9357SAndroid Build Coastguard Worker
3415*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF2(void, CBlake2spHasher::Update(const void *data, UInt32 size))
3416*f6dc9357SAndroid Build Coastguard Worker {
3417*f6dc9357SAndroid Build Coastguard Worker #if 1
3418*f6dc9357SAndroid Build Coastguard Worker Blake2sp_Update(Obj(), (const Byte *)data, (size_t)size);
3419*f6dc9357SAndroid Build Coastguard Worker #else
3420*f6dc9357SAndroid Build Coastguard Worker // for debug:
3421*f6dc9357SAndroid Build Coastguard Worker for (;;)
3422*f6dc9357SAndroid Build Coastguard Worker {
3423*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
3424*f6dc9357SAndroid Build Coastguard Worker return;
3425*f6dc9357SAndroid Build Coastguard Worker UInt32 size2 = (size * 0x85EBCA87) % size / 800;
3426*f6dc9357SAndroid Build Coastguard Worker // UInt32 size2 = size / 2;
3427*f6dc9357SAndroid Build Coastguard Worker if (size2 == 0)
3428*f6dc9357SAndroid Build Coastguard Worker size2 = 1;
3429*f6dc9357SAndroid Build Coastguard Worker Blake2sp_Update(Obj(), (const Byte *)data, size2);
3430*f6dc9357SAndroid Build Coastguard Worker data = (const void *)((const Byte *)data + size2);
3431*f6dc9357SAndroid Build Coastguard Worker size -= size2;
3432*f6dc9357SAndroid Build Coastguard Worker }
3433*f6dc9357SAndroid Build Coastguard Worker #endif
3434*f6dc9357SAndroid Build Coastguard Worker }
3435*f6dc9357SAndroid Build Coastguard Worker
3436*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF2(void, CBlake2spHasher::Final(Byte *digest))
3437*f6dc9357SAndroid Build Coastguard Worker {
3438*f6dc9357SAndroid Build Coastguard Worker Blake2sp_Final(Obj(), digest);
3439*f6dc9357SAndroid Build Coastguard Worker }
3440*f6dc9357SAndroid Build Coastguard Worker
3441*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CBlake2spHasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))
3442*f6dc9357SAndroid Build Coastguard Worker {
3443*f6dc9357SAndroid Build Coastguard Worker unsigned algo = 0;
3444*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numProps; i++)
3445*f6dc9357SAndroid Build Coastguard Worker {
3446*f6dc9357SAndroid Build Coastguard Worker if (propIDs[i] == NCoderPropID::kDefaultProp)
3447*f6dc9357SAndroid Build Coastguard Worker {
3448*f6dc9357SAndroid Build Coastguard Worker const PROPVARIANT &prop = coderProps[i];
3449*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_UI4)
3450*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
3451*f6dc9357SAndroid Build Coastguard Worker /*
3452*f6dc9357SAndroid Build Coastguard Worker if (prop.ulVal > Z7_BLAKE2S_ALGO_MAX)
3453*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
3454*f6dc9357SAndroid Build Coastguard Worker */
3455*f6dc9357SAndroid Build Coastguard Worker algo = (unsigned)prop.ulVal;
3456*f6dc9357SAndroid Build Coastguard Worker }
3457*f6dc9357SAndroid Build Coastguard Worker }
3458*f6dc9357SAndroid Build Coastguard Worker if (!Blake2sp_SetFunction(Obj(), algo))
3459*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
3460*f6dc9357SAndroid Build Coastguard Worker return S_OK;
3461*f6dc9357SAndroid Build Coastguard Worker }
3462*f6dc9357SAndroid Build Coastguard Worker
3463*f6dc9357SAndroid Build Coastguard Worker REGISTER_HASHER(CBlake2spHasher, 0x202, "BLAKE2sp", Z7_BLAKE2S_DIGEST_SIZE)
3464*f6dc9357SAndroid Build Coastguard Worker
3465*f6dc9357SAndroid Build Coastguard Worker static struct CBlake2sp_Prepare { CBlake2sp_Prepare() { z7_Black2sp_Prepare(); } } g_Blake2sp_Prepare;
3466