1*f6dc9357SAndroid Build Coastguard Worker // RarHandler.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/ComTry.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/IntToString.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/MyBuffer2.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/UTFConvert.h"
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariantUtils.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/TimeUtils.h"
14*f6dc9357SAndroid Build Coastguard Worker
15*f6dc9357SAndroid Build Coastguard Worker #include "../../IPassword.h"
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/CreateCoder.h"
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/MethodId.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/StreamUtils.h"
24*f6dc9357SAndroid Build Coastguard Worker
25*f6dc9357SAndroid Build Coastguard Worker #include "../../Compress/CopyCoder.h"
26*f6dc9357SAndroid Build Coastguard Worker
27*f6dc9357SAndroid Build Coastguard Worker #include "../../Crypto/Rar20Crypto.h"
28*f6dc9357SAndroid Build Coastguard Worker #include "../../Crypto/RarAes.h"
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker #include "../Common/FindSignature.h"
31*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ItemNameUtils.h"
32*f6dc9357SAndroid Build Coastguard Worker #include "../Common/OutStreamWithCRC.h"
33*f6dc9357SAndroid Build Coastguard Worker
34*f6dc9357SAndroid Build Coastguard Worker #include "../HandlerCont.h"
35*f6dc9357SAndroid Build Coastguard Worker
36*f6dc9357SAndroid Build Coastguard Worker #include "RarVol.h"
37*f6dc9357SAndroid Build Coastguard Worker #include "RarHandler.h"
38*f6dc9357SAndroid Build Coastguard Worker
39*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
40*f6dc9357SAndroid Build Coastguard Worker
41*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
42*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
43*f6dc9357SAndroid Build Coastguard Worker
44*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
45*f6dc9357SAndroid Build Coastguard Worker namespace NRar {
46*f6dc9357SAndroid Build Coastguard Worker
47*f6dc9357SAndroid Build Coastguard Worker static const Byte kMarker[NHeader::kMarkerSize] =
48*f6dc9357SAndroid Build Coastguard Worker { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 };
49*f6dc9357SAndroid Build Coastguard Worker
50*f6dc9357SAndroid Build Coastguard Worker const unsigned kPasswordLen_MAX = 127;
51*f6dc9357SAndroid Build Coastguard Worker
IgnoreItem() const52*f6dc9357SAndroid Build Coastguard Worker bool CItem::IgnoreItem() const
53*f6dc9357SAndroid Build Coastguard Worker {
54*f6dc9357SAndroid Build Coastguard Worker switch (HostOS)
55*f6dc9357SAndroid Build Coastguard Worker {
56*f6dc9357SAndroid Build Coastguard Worker case NHeader::NFile::kHostMSDOS:
57*f6dc9357SAndroid Build Coastguard Worker case NHeader::NFile::kHostOS2:
58*f6dc9357SAndroid Build Coastguard Worker case NHeader::NFile::kHostWin32:
59*f6dc9357SAndroid Build Coastguard Worker return ((Attrib & NHeader::NFile::kLabelFileAttribute) != 0);
60*f6dc9357SAndroid Build Coastguard Worker }
61*f6dc9357SAndroid Build Coastguard Worker return false;
62*f6dc9357SAndroid Build Coastguard Worker }
63*f6dc9357SAndroid Build Coastguard Worker
IsDir() const64*f6dc9357SAndroid Build Coastguard Worker bool CItem::IsDir() const
65*f6dc9357SAndroid Build Coastguard Worker {
66*f6dc9357SAndroid Build Coastguard Worker if (GetDictSize() == NHeader::NFile::kDictDirectoryValue)
67*f6dc9357SAndroid Build Coastguard Worker return true;
68*f6dc9357SAndroid Build Coastguard Worker switch (HostOS)
69*f6dc9357SAndroid Build Coastguard Worker {
70*f6dc9357SAndroid Build Coastguard Worker case NHeader::NFile::kHostMSDOS:
71*f6dc9357SAndroid Build Coastguard Worker case NHeader::NFile::kHostOS2:
72*f6dc9357SAndroid Build Coastguard Worker case NHeader::NFile::kHostWin32:
73*f6dc9357SAndroid Build Coastguard Worker if ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
74*f6dc9357SAndroid Build Coastguard Worker return true;
75*f6dc9357SAndroid Build Coastguard Worker }
76*f6dc9357SAndroid Build Coastguard Worker return false;
77*f6dc9357SAndroid Build Coastguard Worker }
78*f6dc9357SAndroid Build Coastguard Worker
GetWinAttrib() const79*f6dc9357SAndroid Build Coastguard Worker UInt32 CItem::GetWinAttrib() const
80*f6dc9357SAndroid Build Coastguard Worker {
81*f6dc9357SAndroid Build Coastguard Worker UInt32 a;
82*f6dc9357SAndroid Build Coastguard Worker switch (HostOS)
83*f6dc9357SAndroid Build Coastguard Worker {
84*f6dc9357SAndroid Build Coastguard Worker case NHeader::NFile::kHostMSDOS:
85*f6dc9357SAndroid Build Coastguard Worker case NHeader::NFile::kHostOS2:
86*f6dc9357SAndroid Build Coastguard Worker case NHeader::NFile::kHostWin32:
87*f6dc9357SAndroid Build Coastguard Worker a = Attrib;
88*f6dc9357SAndroid Build Coastguard Worker break;
89*f6dc9357SAndroid Build Coastguard Worker default:
90*f6dc9357SAndroid Build Coastguard Worker a = 0; // must be converted from unix value;
91*f6dc9357SAndroid Build Coastguard Worker }
92*f6dc9357SAndroid Build Coastguard Worker if (IsDir())
93*f6dc9357SAndroid Build Coastguard Worker a |= NHeader::NFile::kWinFileDirectoryAttributeMask;
94*f6dc9357SAndroid Build Coastguard Worker return a;
95*f6dc9357SAndroid Build Coastguard Worker }
96*f6dc9357SAndroid Build Coastguard Worker
97*f6dc9357SAndroid Build Coastguard Worker static const char * const kHostOS[] =
98*f6dc9357SAndroid Build Coastguard Worker {
99*f6dc9357SAndroid Build Coastguard Worker "MS DOS"
100*f6dc9357SAndroid Build Coastguard Worker , "OS/2"
101*f6dc9357SAndroid Build Coastguard Worker , "Win32"
102*f6dc9357SAndroid Build Coastguard Worker , "Unix"
103*f6dc9357SAndroid Build Coastguard Worker , "Mac OS"
104*f6dc9357SAndroid Build Coastguard Worker , "BeOS"
105*f6dc9357SAndroid Build Coastguard Worker };
106*f6dc9357SAndroid Build Coastguard Worker
107*f6dc9357SAndroid Build Coastguard Worker static const char * const k_Flags[] =
108*f6dc9357SAndroid Build Coastguard Worker {
109*f6dc9357SAndroid Build Coastguard Worker "Volume"
110*f6dc9357SAndroid Build Coastguard Worker , "Comment"
111*f6dc9357SAndroid Build Coastguard Worker , "Lock"
112*f6dc9357SAndroid Build Coastguard Worker , "Solid"
113*f6dc9357SAndroid Build Coastguard Worker , "NewVolName" // pack_comment in old versuons
114*f6dc9357SAndroid Build Coastguard Worker , "Authenticity"
115*f6dc9357SAndroid Build Coastguard Worker , "Recovery"
116*f6dc9357SAndroid Build Coastguard Worker , "BlockEncryption"
117*f6dc9357SAndroid Build Coastguard Worker , "FirstVolume"
118*f6dc9357SAndroid Build Coastguard Worker , "EncryptVer" // 9
119*f6dc9357SAndroid Build Coastguard Worker };
120*f6dc9357SAndroid Build Coastguard Worker
121*f6dc9357SAndroid Build Coastguard Worker enum EErrorType
122*f6dc9357SAndroid Build Coastguard Worker {
123*f6dc9357SAndroid Build Coastguard Worker k_ErrorType_OK,
124*f6dc9357SAndroid Build Coastguard Worker k_ErrorType_Corrupted,
125*f6dc9357SAndroid Build Coastguard Worker k_ErrorType_UnexpectedEnd,
126*f6dc9357SAndroid Build Coastguard Worker k_ErrorType_DecryptionError
127*f6dc9357SAndroid Build Coastguard Worker };
128*f6dc9357SAndroid Build Coastguard Worker
129*f6dc9357SAndroid Build Coastguard Worker class CInArchive
130*f6dc9357SAndroid Build Coastguard Worker {
131*f6dc9357SAndroid Build Coastguard Worker IInStream *m_Stream;
132*f6dc9357SAndroid Build Coastguard Worker UInt64 m_StreamStartPosition;
133*f6dc9357SAndroid Build Coastguard Worker UString _unicodeNameBuffer;
134*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _comment;
135*f6dc9357SAndroid Build Coastguard Worker CByteBuffer m_FileHeaderData;
136*f6dc9357SAndroid Build Coastguard Worker NHeader::NBlock::CBlock m_BlockHeader;
137*f6dc9357SAndroid Build Coastguard Worker NCrypto::NRar3::CDecoder *m_RarAESSpec;
138*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressFilter> m_RarAES;
139*f6dc9357SAndroid Build Coastguard Worker CAlignedBuffer m_DecryptedDataAligned;
140*f6dc9357SAndroid Build Coastguard Worker UInt32 m_DecryptedDataSize;
141*f6dc9357SAndroid Build Coastguard Worker bool m_CryptoMode;
142*f6dc9357SAndroid Build Coastguard Worker UInt32 m_CryptoPos;
143*f6dc9357SAndroid Build Coastguard Worker
144*f6dc9357SAndroid Build Coastguard Worker
145*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadBytesSpec(void *data, size_t *size);
146*f6dc9357SAndroid Build Coastguard Worker bool ReadBytesAndTestSize(void *data, UInt32 size);
147*f6dc9357SAndroid Build Coastguard Worker void ReadName(const Byte *p, unsigned nameSize, CItem &item);
148*f6dc9357SAndroid Build Coastguard Worker bool ReadHeaderReal(const Byte *p, unsigned size, CItem &item);
149*f6dc9357SAndroid Build Coastguard Worker
150*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
151*f6dc9357SAndroid Build Coastguard Worker
AddToSeekValue(UInt64 addValue)152*f6dc9357SAndroid Build Coastguard Worker void AddToSeekValue(UInt64 addValue)
153*f6dc9357SAndroid Build Coastguard Worker {
154*f6dc9357SAndroid Build Coastguard Worker m_Position += addValue;
155*f6dc9357SAndroid Build Coastguard Worker }
156*f6dc9357SAndroid Build Coastguard Worker
FinishCryptoBlock()157*f6dc9357SAndroid Build Coastguard Worker void FinishCryptoBlock()
158*f6dc9357SAndroid Build Coastguard Worker {
159*f6dc9357SAndroid Build Coastguard Worker if (m_CryptoMode)
160*f6dc9357SAndroid Build Coastguard Worker while ((m_CryptoPos & 0xF) != 0)
161*f6dc9357SAndroid Build Coastguard Worker {
162*f6dc9357SAndroid Build Coastguard Worker m_CryptoPos++;
163*f6dc9357SAndroid Build Coastguard Worker m_Position++;
164*f6dc9357SAndroid Build Coastguard Worker }
165*f6dc9357SAndroid Build Coastguard Worker }
166*f6dc9357SAndroid Build Coastguard Worker
167*f6dc9357SAndroid Build Coastguard Worker public:
168*f6dc9357SAndroid Build Coastguard Worker UInt64 m_Position;
169*f6dc9357SAndroid Build Coastguard Worker CInArcInfo ArcInfo;
170*f6dc9357SAndroid Build Coastguard Worker bool HeaderErrorWarning;
171*f6dc9357SAndroid Build Coastguard Worker
172*f6dc9357SAndroid Build Coastguard Worker HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit);
173*f6dc9357SAndroid Build Coastguard Worker HRESULT GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPassword,
174*f6dc9357SAndroid Build Coastguard Worker bool &filled, EErrorType &error);
175*f6dc9357SAndroid Build Coastguard Worker };
176*f6dc9357SAndroid Build Coastguard Worker
CheckHeaderCrc(const Byte * header,size_t headerSize)177*f6dc9357SAndroid Build Coastguard Worker static bool CheckHeaderCrc(const Byte *header, size_t headerSize)
178*f6dc9357SAndroid Build Coastguard Worker {
179*f6dc9357SAndroid Build Coastguard Worker return Get16(header) == (UInt16)(CrcCalc(header + 2, headerSize - 2) & 0xFFFF);
180*f6dc9357SAndroid Build Coastguard Worker }
181*f6dc9357SAndroid Build Coastguard Worker
Open(IInStream * stream,const UInt64 * searchHeaderSizeLimit)182*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
183*f6dc9357SAndroid Build Coastguard Worker {
184*f6dc9357SAndroid Build Coastguard Worker HeaderErrorWarning = false;
185*f6dc9357SAndroid Build Coastguard Worker m_CryptoMode = false;
186*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetPos_GetSize(stream, m_StreamStartPosition, ArcInfo.FileSize))
187*f6dc9357SAndroid Build Coastguard Worker m_Position = m_StreamStartPosition;
188*f6dc9357SAndroid Build Coastguard Worker
189*f6dc9357SAndroid Build Coastguard Worker UInt64 arcStartPos = m_StreamStartPosition;
190*f6dc9357SAndroid Build Coastguard Worker {
191*f6dc9357SAndroid Build Coastguard Worker Byte marker[NHeader::kMarkerSize];
192*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, marker, NHeader::kMarkerSize))
193*f6dc9357SAndroid Build Coastguard Worker if (memcmp(marker, kMarker, NHeader::kMarkerSize) == 0)
194*f6dc9357SAndroid Build Coastguard Worker m_Position += NHeader::kMarkerSize;
195*f6dc9357SAndroid Build Coastguard Worker else
196*f6dc9357SAndroid Build Coastguard Worker {
197*f6dc9357SAndroid Build Coastguard Worker if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)
198*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
199*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, m_StreamStartPosition))
200*f6dc9357SAndroid Build Coastguard Worker RINOK(FindSignatureInStream(stream, kMarker, NHeader::kMarkerSize,
201*f6dc9357SAndroid Build Coastguard Worker searchHeaderSizeLimit, arcStartPos))
202*f6dc9357SAndroid Build Coastguard Worker m_Position = arcStartPos + NHeader::kMarkerSize;
203*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, m_Position))
204*f6dc9357SAndroid Build Coastguard Worker }
205*f6dc9357SAndroid Build Coastguard Worker }
206*f6dc9357SAndroid Build Coastguard Worker Byte buf[NHeader::NArchive::kArchiveHeaderSize + 1];
207*f6dc9357SAndroid Build Coastguard Worker
208*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buf, NHeader::NArchive::kArchiveHeaderSize))
209*f6dc9357SAndroid Build Coastguard Worker AddToSeekValue(NHeader::NArchive::kArchiveHeaderSize);
210*f6dc9357SAndroid Build Coastguard Worker
211*f6dc9357SAndroid Build Coastguard Worker
212*f6dc9357SAndroid Build Coastguard Worker const UInt32 blockSize = Get16(buf + 5);
213*f6dc9357SAndroid Build Coastguard Worker
214*f6dc9357SAndroid Build Coastguard Worker ArcInfo.EncryptVersion = 0;
215*f6dc9357SAndroid Build Coastguard Worker ArcInfo.Flags = Get16(buf + 3);
216*f6dc9357SAndroid Build Coastguard Worker
217*f6dc9357SAndroid Build Coastguard Worker UInt32 headerSize = NHeader::NArchive::kArchiveHeaderSize;
218*f6dc9357SAndroid Build Coastguard Worker
219*f6dc9357SAndroid Build Coastguard Worker /*
220*f6dc9357SAndroid Build Coastguard Worker if (ArcInfo.IsThereEncryptVer())
221*f6dc9357SAndroid Build Coastguard Worker {
222*f6dc9357SAndroid Build Coastguard Worker if (blockSize <= headerSize)
223*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
224*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buf + NHeader::NArchive::kArchiveHeaderSize, 1));
225*f6dc9357SAndroid Build Coastguard Worker AddToSeekValue(1);
226*f6dc9357SAndroid Build Coastguard Worker ArcInfo.EncryptVersion = buf[NHeader::NArchive::kArchiveHeaderSize];
227*f6dc9357SAndroid Build Coastguard Worker headerSize += 1;
228*f6dc9357SAndroid Build Coastguard Worker }
229*f6dc9357SAndroid Build Coastguard Worker */
230*f6dc9357SAndroid Build Coastguard Worker
231*f6dc9357SAndroid Build Coastguard Worker if (blockSize < headerSize
232*f6dc9357SAndroid Build Coastguard Worker || buf[2] != NHeader::NBlockType::kArchiveHeader
233*f6dc9357SAndroid Build Coastguard Worker || !CheckHeaderCrc(buf, headerSize))
234*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
235*f6dc9357SAndroid Build Coastguard Worker
236*f6dc9357SAndroid Build Coastguard Worker size_t commentSize = blockSize - headerSize;
237*f6dc9357SAndroid Build Coastguard Worker _comment.Alloc(commentSize);
238*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, _comment, commentSize))
239*f6dc9357SAndroid Build Coastguard Worker AddToSeekValue(commentSize);
240*f6dc9357SAndroid Build Coastguard Worker m_Stream = stream;
241*f6dc9357SAndroid Build Coastguard Worker ArcInfo.StartPos = arcStartPos;
242*f6dc9357SAndroid Build Coastguard Worker return S_OK;
243*f6dc9357SAndroid Build Coastguard Worker }
244*f6dc9357SAndroid Build Coastguard Worker
ReadBytesSpec(void * data,size_t * resSize)245*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::ReadBytesSpec(void *data, size_t *resSize)
246*f6dc9357SAndroid Build Coastguard Worker {
247*f6dc9357SAndroid Build Coastguard Worker if (m_CryptoMode)
248*f6dc9357SAndroid Build Coastguard Worker {
249*f6dc9357SAndroid Build Coastguard Worker size_t size = *resSize;
250*f6dc9357SAndroid Build Coastguard Worker *resSize = 0;
251*f6dc9357SAndroid Build Coastguard Worker const Byte *bufData = m_DecryptedDataAligned;
252*f6dc9357SAndroid Build Coastguard Worker UInt32 bufSize = m_DecryptedDataSize;
253*f6dc9357SAndroid Build Coastguard Worker size_t i;
254*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < size && m_CryptoPos < bufSize; i++)
255*f6dc9357SAndroid Build Coastguard Worker ((Byte *)data)[i] = bufData[m_CryptoPos++];
256*f6dc9357SAndroid Build Coastguard Worker *resSize = i;
257*f6dc9357SAndroid Build Coastguard Worker return S_OK;
258*f6dc9357SAndroid Build Coastguard Worker }
259*f6dc9357SAndroid Build Coastguard Worker return ReadStream(m_Stream, data, resSize);
260*f6dc9357SAndroid Build Coastguard Worker }
261*f6dc9357SAndroid Build Coastguard Worker
ReadBytesAndTestSize(void * data,UInt32 size)262*f6dc9357SAndroid Build Coastguard Worker bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
263*f6dc9357SAndroid Build Coastguard Worker {
264*f6dc9357SAndroid Build Coastguard Worker size_t processed = size;
265*f6dc9357SAndroid Build Coastguard Worker if (ReadBytesSpec(data, &processed) != S_OK)
266*f6dc9357SAndroid Build Coastguard Worker return false;
267*f6dc9357SAndroid Build Coastguard Worker return processed == size;
268*f6dc9357SAndroid Build Coastguard Worker }
269*f6dc9357SAndroid Build Coastguard Worker
270*f6dc9357SAndroid Build Coastguard Worker
DecodeUnicodeFileName(const Byte * name,const Byte * encName,unsigned encSize,wchar_t * unicodeName,unsigned maxDecSize)271*f6dc9357SAndroid Build Coastguard Worker static unsigned DecodeUnicodeFileName(const Byte *name, const Byte *encName,
272*f6dc9357SAndroid Build Coastguard Worker unsigned encSize, wchar_t *unicodeName, unsigned maxDecSize)
273*f6dc9357SAndroid Build Coastguard Worker {
274*f6dc9357SAndroid Build Coastguard Worker unsigned encPos = 0;
275*f6dc9357SAndroid Build Coastguard Worker unsigned decPos = 0;
276*f6dc9357SAndroid Build Coastguard Worker unsigned flagBits = 0;
277*f6dc9357SAndroid Build Coastguard Worker Byte flags = 0;
278*f6dc9357SAndroid Build Coastguard Worker
279*f6dc9357SAndroid Build Coastguard Worker if (encPos >= encSize)
280*f6dc9357SAndroid Build Coastguard Worker return 0; // error
281*f6dc9357SAndroid Build Coastguard Worker const unsigned highBits = ((unsigned)encName[encPos++]) << 8;
282*f6dc9357SAndroid Build Coastguard Worker
283*f6dc9357SAndroid Build Coastguard Worker while (encPos < encSize && decPos < maxDecSize)
284*f6dc9357SAndroid Build Coastguard Worker {
285*f6dc9357SAndroid Build Coastguard Worker if (flagBits == 0)
286*f6dc9357SAndroid Build Coastguard Worker {
287*f6dc9357SAndroid Build Coastguard Worker flags = encName[encPos++];
288*f6dc9357SAndroid Build Coastguard Worker flagBits = 8;
289*f6dc9357SAndroid Build Coastguard Worker }
290*f6dc9357SAndroid Build Coastguard Worker
291*f6dc9357SAndroid Build Coastguard Worker if (encPos >= encSize)
292*f6dc9357SAndroid Build Coastguard Worker break; // error
293*f6dc9357SAndroid Build Coastguard Worker unsigned len = encName[encPos++];
294*f6dc9357SAndroid Build Coastguard Worker
295*f6dc9357SAndroid Build Coastguard Worker flagBits -= 2;
296*f6dc9357SAndroid Build Coastguard Worker const unsigned mode = (flags >> flagBits) & 3;
297*f6dc9357SAndroid Build Coastguard Worker
298*f6dc9357SAndroid Build Coastguard Worker if (mode != 3)
299*f6dc9357SAndroid Build Coastguard Worker {
300*f6dc9357SAndroid Build Coastguard Worker if (mode == 1)
301*f6dc9357SAndroid Build Coastguard Worker len += highBits;
302*f6dc9357SAndroid Build Coastguard Worker else if (mode == 2)
303*f6dc9357SAndroid Build Coastguard Worker {
304*f6dc9357SAndroid Build Coastguard Worker if (encPos >= encSize)
305*f6dc9357SAndroid Build Coastguard Worker break; // error
306*f6dc9357SAndroid Build Coastguard Worker len += ((unsigned)encName[encPos++] << 8);
307*f6dc9357SAndroid Build Coastguard Worker }
308*f6dc9357SAndroid Build Coastguard Worker unicodeName[decPos++] = (wchar_t)len;
309*f6dc9357SAndroid Build Coastguard Worker }
310*f6dc9357SAndroid Build Coastguard Worker else
311*f6dc9357SAndroid Build Coastguard Worker {
312*f6dc9357SAndroid Build Coastguard Worker if (len & 0x80)
313*f6dc9357SAndroid Build Coastguard Worker {
314*f6dc9357SAndroid Build Coastguard Worker if (encPos >= encSize)
315*f6dc9357SAndroid Build Coastguard Worker break; // error
316*f6dc9357SAndroid Build Coastguard Worker Byte correction = encName[encPos++];
317*f6dc9357SAndroid Build Coastguard Worker for (len = (len & 0x7f) + 2; len > 0 && decPos < maxDecSize; len--, decPos++)
318*f6dc9357SAndroid Build Coastguard Worker unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + highBits);
319*f6dc9357SAndroid Build Coastguard Worker }
320*f6dc9357SAndroid Build Coastguard Worker else
321*f6dc9357SAndroid Build Coastguard Worker for (len += 2; len > 0 && decPos < maxDecSize; len--, decPos++)
322*f6dc9357SAndroid Build Coastguard Worker unicodeName[decPos] = name[decPos];
323*f6dc9357SAndroid Build Coastguard Worker }
324*f6dc9357SAndroid Build Coastguard Worker }
325*f6dc9357SAndroid Build Coastguard Worker
326*f6dc9357SAndroid Build Coastguard Worker return decPos < maxDecSize ? decPos : maxDecSize - 1;
327*f6dc9357SAndroid Build Coastguard Worker }
328*f6dc9357SAndroid Build Coastguard Worker
329*f6dc9357SAndroid Build Coastguard Worker
ReadName(const Byte * p,unsigned nameSize,CItem & item)330*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadName(const Byte *p, unsigned nameSize, CItem &item)
331*f6dc9357SAndroid Build Coastguard Worker {
332*f6dc9357SAndroid Build Coastguard Worker item.UnicodeName.Empty();
333*f6dc9357SAndroid Build Coastguard Worker if (nameSize > 0)
334*f6dc9357SAndroid Build Coastguard Worker {
335*f6dc9357SAndroid Build Coastguard Worker unsigned i;
336*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < nameSize && p[i] != 0; i++);
337*f6dc9357SAndroid Build Coastguard Worker item.Name.SetFrom((const char *)p, i);
338*f6dc9357SAndroid Build Coastguard Worker
339*f6dc9357SAndroid Build Coastguard Worker if (item.HasUnicodeName())
340*f6dc9357SAndroid Build Coastguard Worker {
341*f6dc9357SAndroid Build Coastguard Worker if (i < nameSize)
342*f6dc9357SAndroid Build Coastguard Worker {
343*f6dc9357SAndroid Build Coastguard Worker i++;
344*f6dc9357SAndroid Build Coastguard Worker unsigned uNameSizeMax = MyMin(nameSize, (unsigned)0x400);
345*f6dc9357SAndroid Build Coastguard Worker unsigned len = DecodeUnicodeFileName(p, p + i, nameSize - i, _unicodeNameBuffer.GetBuf(uNameSizeMax), uNameSizeMax);
346*f6dc9357SAndroid Build Coastguard Worker _unicodeNameBuffer.ReleaseBuf_SetEnd(len);
347*f6dc9357SAndroid Build Coastguard Worker item.UnicodeName = _unicodeNameBuffer;
348*f6dc9357SAndroid Build Coastguard Worker }
349*f6dc9357SAndroid Build Coastguard Worker else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName))
350*f6dc9357SAndroid Build Coastguard Worker item.UnicodeName.Empty();
351*f6dc9357SAndroid Build Coastguard Worker }
352*f6dc9357SAndroid Build Coastguard Worker }
353*f6dc9357SAndroid Build Coastguard Worker else
354*f6dc9357SAndroid Build Coastguard Worker item.Name.Empty();
355*f6dc9357SAndroid Build Coastguard Worker }
356*f6dc9357SAndroid Build Coastguard Worker
ReadTime(const Byte * p,unsigned size,Byte mask,CRarTime & rarTime)357*f6dc9357SAndroid Build Coastguard Worker static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime)
358*f6dc9357SAndroid Build Coastguard Worker {
359*f6dc9357SAndroid Build Coastguard Worker rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0);
360*f6dc9357SAndroid Build Coastguard Worker const unsigned numDigits = (mask & 3);
361*f6dc9357SAndroid Build Coastguard Worker rarTime.SubTime[0] =
362*f6dc9357SAndroid Build Coastguard Worker rarTime.SubTime[1] =
363*f6dc9357SAndroid Build Coastguard Worker rarTime.SubTime[2] = 0;
364*f6dc9357SAndroid Build Coastguard Worker if (numDigits > size)
365*f6dc9357SAndroid Build Coastguard Worker return -1;
366*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < numDigits; i++)
367*f6dc9357SAndroid Build Coastguard Worker rarTime.SubTime[3 - numDigits + i] = p[i];
368*f6dc9357SAndroid Build Coastguard Worker return (int)numDigits;
369*f6dc9357SAndroid Build Coastguard Worker }
370*f6dc9357SAndroid Build Coastguard Worker
371*f6dc9357SAndroid Build Coastguard Worker #define READ_TIME(_mask_, _ttt_) \
372*f6dc9357SAndroid Build Coastguard Worker { int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += (unsigned)size2, size -= (unsigned)size2; }
373*f6dc9357SAndroid Build Coastguard Worker
374*f6dc9357SAndroid Build Coastguard Worker #define READ_TIME_2(_mask_, _def_, _ttt_) \
375*f6dc9357SAndroid Build Coastguard Worker _def_ = ((_mask_ & 8) != 0); if (_def_) \
376*f6dc9357SAndroid Build Coastguard Worker { if (size < 4) return false; \
377*f6dc9357SAndroid Build Coastguard Worker _ttt_ .DosTime = Get32(p); p += 4; size -= 4; \
378*f6dc9357SAndroid Build Coastguard Worker READ_TIME(_mask_, _ttt_); } \
379*f6dc9357SAndroid Build Coastguard Worker
380*f6dc9357SAndroid Build Coastguard Worker
ReadHeaderReal(const Byte * p,unsigned size,CItem & item)381*f6dc9357SAndroid Build Coastguard Worker bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
382*f6dc9357SAndroid Build Coastguard Worker {
383*f6dc9357SAndroid Build Coastguard Worker const Byte *pStart = p;
384*f6dc9357SAndroid Build Coastguard Worker
385*f6dc9357SAndroid Build Coastguard Worker item.Clear();
386*f6dc9357SAndroid Build Coastguard Worker item.Flags = m_BlockHeader.Flags;
387*f6dc9357SAndroid Build Coastguard Worker
388*f6dc9357SAndroid Build Coastguard Worker const unsigned kFileHeaderSize = 25;
389*f6dc9357SAndroid Build Coastguard Worker
390*f6dc9357SAndroid Build Coastguard Worker if (size < kFileHeaderSize)
391*f6dc9357SAndroid Build Coastguard Worker return false;
392*f6dc9357SAndroid Build Coastguard Worker
393*f6dc9357SAndroid Build Coastguard Worker item.PackSize = Get32(p);
394*f6dc9357SAndroid Build Coastguard Worker item.Size = Get32(p + 4);
395*f6dc9357SAndroid Build Coastguard Worker item.HostOS = p[8];
396*f6dc9357SAndroid Build Coastguard Worker item.FileCRC = Get32(p + 9);
397*f6dc9357SAndroid Build Coastguard Worker item.MTime.DosTime = Get32(p + 13);
398*f6dc9357SAndroid Build Coastguard Worker item.UnPackVersion = p[17];
399*f6dc9357SAndroid Build Coastguard Worker item.Method = p[18];
400*f6dc9357SAndroid Build Coastguard Worker unsigned nameSize = Get16(p + 19);
401*f6dc9357SAndroid Build Coastguard Worker item.Attrib = Get32(p + 21);
402*f6dc9357SAndroid Build Coastguard Worker
403*f6dc9357SAndroid Build Coastguard Worker item.MTime.LowSecond = 0;
404*f6dc9357SAndroid Build Coastguard Worker item.MTime.SubTime[0] =
405*f6dc9357SAndroid Build Coastguard Worker item.MTime.SubTime[1] =
406*f6dc9357SAndroid Build Coastguard Worker item.MTime.SubTime[2] = 0;
407*f6dc9357SAndroid Build Coastguard Worker
408*f6dc9357SAndroid Build Coastguard Worker p += kFileHeaderSize;
409*f6dc9357SAndroid Build Coastguard Worker size -= kFileHeaderSize;
410*f6dc9357SAndroid Build Coastguard Worker if ((item.Flags & NHeader::NFile::kSize64Bits) != 0)
411*f6dc9357SAndroid Build Coastguard Worker {
412*f6dc9357SAndroid Build Coastguard Worker if (size < 8)
413*f6dc9357SAndroid Build Coastguard Worker return false;
414*f6dc9357SAndroid Build Coastguard Worker item.PackSize |= ((UInt64)Get32(p) << 32);
415*f6dc9357SAndroid Build Coastguard Worker if (item.PackSize >= ((UInt64)1 << 63))
416*f6dc9357SAndroid Build Coastguard Worker return false;
417*f6dc9357SAndroid Build Coastguard Worker item.Size |= ((UInt64)Get32(p + 4) << 32);
418*f6dc9357SAndroid Build Coastguard Worker p += 8;
419*f6dc9357SAndroid Build Coastguard Worker size -= 8;
420*f6dc9357SAndroid Build Coastguard Worker }
421*f6dc9357SAndroid Build Coastguard Worker if (nameSize > size)
422*f6dc9357SAndroid Build Coastguard Worker return false;
423*f6dc9357SAndroid Build Coastguard Worker ReadName(p, nameSize, item);
424*f6dc9357SAndroid Build Coastguard Worker p += nameSize;
425*f6dc9357SAndroid Build Coastguard Worker size -= nameSize;
426*f6dc9357SAndroid Build Coastguard Worker
427*f6dc9357SAndroid Build Coastguard Worker /*
428*f6dc9357SAndroid Build Coastguard Worker // It was commented, since it's difficult to support alt Streams for solid archives.
429*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.Type == NHeader::NBlockType::kSubBlock)
430*f6dc9357SAndroid Build Coastguard Worker {
431*f6dc9357SAndroid Build Coastguard Worker if (item.HasSalt())
432*f6dc9357SAndroid Build Coastguard Worker {
433*f6dc9357SAndroid Build Coastguard Worker if (size < sizeof(item.Salt))
434*f6dc9357SAndroid Build Coastguard Worker return false;
435*f6dc9357SAndroid Build Coastguard Worker size -= sizeof(item.Salt);
436*f6dc9357SAndroid Build Coastguard Worker p += sizeof(item.Salt);
437*f6dc9357SAndroid Build Coastguard Worker }
438*f6dc9357SAndroid Build Coastguard Worker if (item.Name == "ACL" && size == 0)
439*f6dc9357SAndroid Build Coastguard Worker {
440*f6dc9357SAndroid Build Coastguard Worker item.IsAltStream = true;
441*f6dc9357SAndroid Build Coastguard Worker item.Name.Empty();
442*f6dc9357SAndroid Build Coastguard Worker item.UnicodeName.SetFromAscii(".ACL");
443*f6dc9357SAndroid Build Coastguard Worker }
444*f6dc9357SAndroid Build Coastguard Worker else if (item.Name == "STM" && size != 0 && (size & 1) == 0)
445*f6dc9357SAndroid Build Coastguard Worker {
446*f6dc9357SAndroid Build Coastguard Worker item.IsAltStream = true;
447*f6dc9357SAndroid Build Coastguard Worker item.Name.Empty();
448*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < size; i += 2)
449*f6dc9357SAndroid Build Coastguard Worker {
450*f6dc9357SAndroid Build Coastguard Worker wchar_t c = Get16(p + i);
451*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
452*f6dc9357SAndroid Build Coastguard Worker return false;
453*f6dc9357SAndroid Build Coastguard Worker item.UnicodeName += c;
454*f6dc9357SAndroid Build Coastguard Worker }
455*f6dc9357SAndroid Build Coastguard Worker }
456*f6dc9357SAndroid Build Coastguard Worker }
457*f6dc9357SAndroid Build Coastguard Worker */
458*f6dc9357SAndroid Build Coastguard Worker
459*f6dc9357SAndroid Build Coastguard Worker if (item.HasSalt())
460*f6dc9357SAndroid Build Coastguard Worker {
461*f6dc9357SAndroid Build Coastguard Worker if (size < sizeof(item.Salt))
462*f6dc9357SAndroid Build Coastguard Worker return false;
463*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < sizeof(item.Salt); i++)
464*f6dc9357SAndroid Build Coastguard Worker item.Salt[i] = p[i];
465*f6dc9357SAndroid Build Coastguard Worker p += sizeof(item.Salt);
466*f6dc9357SAndroid Build Coastguard Worker size -= (unsigned)sizeof(item.Salt);
467*f6dc9357SAndroid Build Coastguard Worker }
468*f6dc9357SAndroid Build Coastguard Worker
469*f6dc9357SAndroid Build Coastguard Worker // some rar archives have HasExtTime flag without field.
470*f6dc9357SAndroid Build Coastguard Worker if (size >= 2 && item.HasExtTime())
471*f6dc9357SAndroid Build Coastguard Worker {
472*f6dc9357SAndroid Build Coastguard Worker Byte aMask = (Byte)(p[0] >> 4);
473*f6dc9357SAndroid Build Coastguard Worker Byte b = p[1];
474*f6dc9357SAndroid Build Coastguard Worker p += 2;
475*f6dc9357SAndroid Build Coastguard Worker size -= 2;
476*f6dc9357SAndroid Build Coastguard Worker Byte mMask = (Byte)(b >> 4);
477*f6dc9357SAndroid Build Coastguard Worker Byte cMask = (Byte)(b & 0xF);
478*f6dc9357SAndroid Build Coastguard Worker if ((mMask & 8) != 0)
479*f6dc9357SAndroid Build Coastguard Worker {
480*f6dc9357SAndroid Build Coastguard Worker READ_TIME(mMask, item.MTime)
481*f6dc9357SAndroid Build Coastguard Worker }
482*f6dc9357SAndroid Build Coastguard Worker READ_TIME_2(cMask, item.CTimeDefined, item.CTime)
483*f6dc9357SAndroid Build Coastguard Worker READ_TIME_2(aMask, item.ATimeDefined, item.ATime)
484*f6dc9357SAndroid Build Coastguard Worker }
485*f6dc9357SAndroid Build Coastguard Worker
486*f6dc9357SAndroid Build Coastguard Worker unsigned fileHeaderWithNameSize = 7 + (unsigned)(p - pStart);
487*f6dc9357SAndroid Build Coastguard Worker
488*f6dc9357SAndroid Build Coastguard Worker item.Position = m_Position;
489*f6dc9357SAndroid Build Coastguard Worker item.MainPartSize = fileHeaderWithNameSize;
490*f6dc9357SAndroid Build Coastguard Worker item.CommentSize = (UInt16)(m_BlockHeader.HeadSize - fileHeaderWithNameSize);
491*f6dc9357SAndroid Build Coastguard Worker
492*f6dc9357SAndroid Build Coastguard Worker if (m_CryptoMode)
493*f6dc9357SAndroid Build Coastguard Worker item.AlignSize = (UInt16)((16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF);
494*f6dc9357SAndroid Build Coastguard Worker else
495*f6dc9357SAndroid Build Coastguard Worker item.AlignSize = 0;
496*f6dc9357SAndroid Build Coastguard Worker AddToSeekValue(m_BlockHeader.HeadSize);
497*f6dc9357SAndroid Build Coastguard Worker
498*f6dc9357SAndroid Build Coastguard Worker // return (m_BlockHeader.Type != NHeader::NBlockType::kSubBlock || item.IsAltStream);
499*f6dc9357SAndroid Build Coastguard Worker return true;
500*f6dc9357SAndroid Build Coastguard Worker }
501*f6dc9357SAndroid Build Coastguard Worker
GetNextItem(CItem & item,ICryptoGetTextPassword * getTextPassword,bool & filled,EErrorType & error)502*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPassword, bool &filled, EErrorType &error)
503*f6dc9357SAndroid Build Coastguard Worker {
504*f6dc9357SAndroid Build Coastguard Worker filled = false;
505*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_OK;
506*f6dc9357SAndroid Build Coastguard Worker for (;;)
507*f6dc9357SAndroid Build Coastguard Worker {
508*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(m_Stream, m_Position))
509*f6dc9357SAndroid Build Coastguard Worker ArcInfo.EndPos = m_Position;
510*f6dc9357SAndroid Build Coastguard Worker if (!m_CryptoMode && (ArcInfo.Flags &
511*f6dc9357SAndroid Build Coastguard Worker NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)
512*f6dc9357SAndroid Build Coastguard Worker {
513*f6dc9357SAndroid Build Coastguard Worker m_CryptoMode = false;
514*f6dc9357SAndroid Build Coastguard Worker if (!getTextPassword)
515*f6dc9357SAndroid Build Coastguard Worker {
516*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_DecryptionError;
517*f6dc9357SAndroid Build Coastguard Worker return S_OK; // return S_FALSE;
518*f6dc9357SAndroid Build Coastguard Worker }
519*f6dc9357SAndroid Build Coastguard Worker if (!m_RarAES)
520*f6dc9357SAndroid Build Coastguard Worker {
521*f6dc9357SAndroid Build Coastguard Worker m_RarAESSpec = new NCrypto::NRar3::CDecoder;
522*f6dc9357SAndroid Build Coastguard Worker m_RarAES = m_RarAESSpec;
523*f6dc9357SAndroid Build Coastguard Worker }
524*f6dc9357SAndroid Build Coastguard Worker // m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld());
525*f6dc9357SAndroid Build Coastguard Worker
526*f6dc9357SAndroid Build Coastguard Worker {
527*f6dc9357SAndroid Build Coastguard Worker // Salt
528*f6dc9357SAndroid Build Coastguard Worker const UInt32 kSaltSize = 8;
529*f6dc9357SAndroid Build Coastguard Worker Byte salt[kSaltSize];
530*f6dc9357SAndroid Build Coastguard Worker if (!ReadBytesAndTestSize(salt, kSaltSize))
531*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
532*f6dc9357SAndroid Build Coastguard Worker m_Position += kSaltSize;
533*f6dc9357SAndroid Build Coastguard Worker RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize))
534*f6dc9357SAndroid Build Coastguard Worker }
535*f6dc9357SAndroid Build Coastguard Worker
536*f6dc9357SAndroid Build Coastguard Worker {
537*f6dc9357SAndroid Build Coastguard Worker // Password
538*f6dc9357SAndroid Build Coastguard Worker CMyComBSTR_Wipe password;
539*f6dc9357SAndroid Build Coastguard Worker RINOK(getTextPassword->CryptoGetTextPassword(&password))
540*f6dc9357SAndroid Build Coastguard Worker unsigned len = 0;
541*f6dc9357SAndroid Build Coastguard Worker if (password)
542*f6dc9357SAndroid Build Coastguard Worker len = MyStringLen(password);
543*f6dc9357SAndroid Build Coastguard Worker if (len > kPasswordLen_MAX)
544*f6dc9357SAndroid Build Coastguard Worker len = kPasswordLen_MAX;
545*f6dc9357SAndroid Build Coastguard Worker
546*f6dc9357SAndroid Build Coastguard Worker CByteBuffer_Wipe buffer(len * 2);
547*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < len; i++)
548*f6dc9357SAndroid Build Coastguard Worker {
549*f6dc9357SAndroid Build Coastguard Worker wchar_t c = password[i];
550*f6dc9357SAndroid Build Coastguard Worker ((Byte *)buffer)[i * 2] = (Byte)c;
551*f6dc9357SAndroid Build Coastguard Worker ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
552*f6dc9357SAndroid Build Coastguard Worker }
553*f6dc9357SAndroid Build Coastguard Worker
554*f6dc9357SAndroid Build Coastguard Worker m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2);
555*f6dc9357SAndroid Build Coastguard Worker }
556*f6dc9357SAndroid Build Coastguard Worker
557*f6dc9357SAndroid Build Coastguard Worker const UInt32 kDecryptedBufferSize = (1 << 12);
558*f6dc9357SAndroid Build Coastguard Worker if (m_DecryptedDataAligned.Size() == 0)
559*f6dc9357SAndroid Build Coastguard Worker {
560*f6dc9357SAndroid Build Coastguard Worker // const UInt32 kAlign = 16;
561*f6dc9357SAndroid Build Coastguard Worker m_DecryptedDataAligned.AllocAtLeast(kDecryptedBufferSize);
562*f6dc9357SAndroid Build Coastguard Worker if (!m_DecryptedDataAligned.IsAllocated())
563*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
564*f6dc9357SAndroid Build Coastguard Worker }
565*f6dc9357SAndroid Build Coastguard Worker RINOK(m_RarAES->Init())
566*f6dc9357SAndroid Build Coastguard Worker size_t decryptedDataSizeT = kDecryptedBufferSize;
567*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(m_Stream, m_DecryptedDataAligned, &decryptedDataSizeT))
568*f6dc9357SAndroid Build Coastguard Worker m_DecryptedDataSize = (UInt32)decryptedDataSizeT;
569*f6dc9357SAndroid Build Coastguard Worker m_DecryptedDataSize = m_RarAES->Filter(m_DecryptedDataAligned, m_DecryptedDataSize);
570*f6dc9357SAndroid Build Coastguard Worker
571*f6dc9357SAndroid Build Coastguard Worker m_CryptoMode = true;
572*f6dc9357SAndroid Build Coastguard Worker m_CryptoPos = 0;
573*f6dc9357SAndroid Build Coastguard Worker }
574*f6dc9357SAndroid Build Coastguard Worker
575*f6dc9357SAndroid Build Coastguard Worker m_FileHeaderData.AllocAtLeast(7);
576*f6dc9357SAndroid Build Coastguard Worker size_t processed = 7;
577*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadBytesSpec((Byte *)m_FileHeaderData, &processed))
578*f6dc9357SAndroid Build Coastguard Worker if (processed != 7)
579*f6dc9357SAndroid Build Coastguard Worker {
580*f6dc9357SAndroid Build Coastguard Worker if (processed != 0)
581*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_UnexpectedEnd;
582*f6dc9357SAndroid Build Coastguard Worker ArcInfo.EndPos = m_Position + processed; // test it
583*f6dc9357SAndroid Build Coastguard Worker return S_OK;
584*f6dc9357SAndroid Build Coastguard Worker }
585*f6dc9357SAndroid Build Coastguard Worker
586*f6dc9357SAndroid Build Coastguard Worker const Byte *p = m_FileHeaderData;
587*f6dc9357SAndroid Build Coastguard Worker m_BlockHeader.CRC = Get16(p + 0);
588*f6dc9357SAndroid Build Coastguard Worker m_BlockHeader.Type = p[2];
589*f6dc9357SAndroid Build Coastguard Worker m_BlockHeader.Flags = Get16(p + 3);
590*f6dc9357SAndroid Build Coastguard Worker m_BlockHeader.HeadSize = Get16(p + 5);
591*f6dc9357SAndroid Build Coastguard Worker
592*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.HeadSize < 7)
593*f6dc9357SAndroid Build Coastguard Worker {
594*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_Corrupted;
595*f6dc9357SAndroid Build Coastguard Worker return S_OK;
596*f6dc9357SAndroid Build Coastguard Worker // ThrowExceptionWithCode(CInArchiveException::kIncorrectArchive);
597*f6dc9357SAndroid Build Coastguard Worker }
598*f6dc9357SAndroid Build Coastguard Worker
599*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.Type < NHeader::NBlockType::kFileHeader ||
600*f6dc9357SAndroid Build Coastguard Worker m_BlockHeader.Type > NHeader::NBlockType::kEndOfArchive)
601*f6dc9357SAndroid Build Coastguard Worker {
602*f6dc9357SAndroid Build Coastguard Worker error = m_CryptoMode ?
603*f6dc9357SAndroid Build Coastguard Worker k_ErrorType_DecryptionError :
604*f6dc9357SAndroid Build Coastguard Worker k_ErrorType_Corrupted;
605*f6dc9357SAndroid Build Coastguard Worker return S_OK;
606*f6dc9357SAndroid Build Coastguard Worker }
607*f6dc9357SAndroid Build Coastguard Worker
608*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.Type == NHeader::NBlockType::kEndOfArchive)
609*f6dc9357SAndroid Build Coastguard Worker {
610*f6dc9357SAndroid Build Coastguard Worker bool footerError = false;
611*f6dc9357SAndroid Build Coastguard Worker
612*f6dc9357SAndroid Build Coastguard Worker unsigned expectHeadLen = 7;
613*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_DataCRC)
614*f6dc9357SAndroid Build Coastguard Worker expectHeadLen += 4;
615*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_VolNumber)
616*f6dc9357SAndroid Build Coastguard Worker expectHeadLen += 2;
617*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_RevSpace)
618*f6dc9357SAndroid Build Coastguard Worker expectHeadLen += 7;
619*f6dc9357SAndroid Build Coastguard Worker
620*f6dc9357SAndroid Build Coastguard Worker // rar 5.0 beta 1 writes incorrect RevSpace and headSize
621*f6dc9357SAndroid Build Coastguard Worker
622*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.HeadSize < expectHeadLen)
623*f6dc9357SAndroid Build Coastguard Worker HeaderErrorWarning = true;
624*f6dc9357SAndroid Build Coastguard Worker
625*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.HeadSize > 7)
626*f6dc9357SAndroid Build Coastguard Worker {
627*f6dc9357SAndroid Build Coastguard Worker /* We suppose that EndOfArchive header is always small.
628*f6dc9357SAndroid Build Coastguard Worker It's only 20 bytes for multivolume
629*f6dc9357SAndroid Build Coastguard Worker Fix the limit, if larger footers are possible */
630*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.HeadSize > (1 << 8))
631*f6dc9357SAndroid Build Coastguard Worker footerError = true;
632*f6dc9357SAndroid Build Coastguard Worker else
633*f6dc9357SAndroid Build Coastguard Worker {
634*f6dc9357SAndroid Build Coastguard Worker if (m_FileHeaderData.Size() < m_BlockHeader.HeadSize)
635*f6dc9357SAndroid Build Coastguard Worker m_FileHeaderData.ChangeSize_KeepData(m_BlockHeader.HeadSize, 7);
636*f6dc9357SAndroid Build Coastguard Worker UInt32 afterSize = m_BlockHeader.HeadSize - 7;
637*f6dc9357SAndroid Build Coastguard Worker if (ReadBytesAndTestSize(m_FileHeaderData + 7, afterSize))
638*f6dc9357SAndroid Build Coastguard Worker processed += afterSize;
639*f6dc9357SAndroid Build Coastguard Worker else
640*f6dc9357SAndroid Build Coastguard Worker {
641*f6dc9357SAndroid Build Coastguard Worker if (!m_CryptoMode)
642*f6dc9357SAndroid Build Coastguard Worker {
643*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_UnexpectedEnd;
644*f6dc9357SAndroid Build Coastguard Worker return S_OK;
645*f6dc9357SAndroid Build Coastguard Worker }
646*f6dc9357SAndroid Build Coastguard Worker footerError = true;
647*f6dc9357SAndroid Build Coastguard Worker }
648*f6dc9357SAndroid Build Coastguard Worker }
649*f6dc9357SAndroid Build Coastguard Worker }
650*f6dc9357SAndroid Build Coastguard Worker
651*f6dc9357SAndroid Build Coastguard Worker if (footerError || !CheckHeaderCrc(m_FileHeaderData, m_BlockHeader.HeadSize))
652*f6dc9357SAndroid Build Coastguard Worker {
653*f6dc9357SAndroid Build Coastguard Worker error = m_CryptoMode ?
654*f6dc9357SAndroid Build Coastguard Worker k_ErrorType_DecryptionError :
655*f6dc9357SAndroid Build Coastguard Worker k_ErrorType_Corrupted;
656*f6dc9357SAndroid Build Coastguard Worker }
657*f6dc9357SAndroid Build Coastguard Worker else
658*f6dc9357SAndroid Build Coastguard Worker {
659*f6dc9357SAndroid Build Coastguard Worker ArcInfo.EndFlags = m_BlockHeader.Flags;
660*f6dc9357SAndroid Build Coastguard Worker UInt32 offset = 7;
661*f6dc9357SAndroid Build Coastguard Worker
662*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_DataCRC)
663*f6dc9357SAndroid Build Coastguard Worker {
664*f6dc9357SAndroid Build Coastguard Worker if (processed < offset + 4)
665*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_Corrupted;
666*f6dc9357SAndroid Build Coastguard Worker else
667*f6dc9357SAndroid Build Coastguard Worker ArcInfo.DataCRC = Get32(m_FileHeaderData + offset);
668*f6dc9357SAndroid Build Coastguard Worker offset += 4;
669*f6dc9357SAndroid Build Coastguard Worker }
670*f6dc9357SAndroid Build Coastguard Worker
671*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_VolNumber)
672*f6dc9357SAndroid Build Coastguard Worker {
673*f6dc9357SAndroid Build Coastguard Worker if (processed < offset + 2)
674*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_Corrupted;
675*f6dc9357SAndroid Build Coastguard Worker else
676*f6dc9357SAndroid Build Coastguard Worker ArcInfo.VolNumber = (UInt32)Get16(m_FileHeaderData + offset);
677*f6dc9357SAndroid Build Coastguard Worker }
678*f6dc9357SAndroid Build Coastguard Worker
679*f6dc9357SAndroid Build Coastguard Worker ArcInfo.EndOfArchive_was_Read = true;
680*f6dc9357SAndroid Build Coastguard Worker }
681*f6dc9357SAndroid Build Coastguard Worker
682*f6dc9357SAndroid Build Coastguard Worker m_Position += processed;
683*f6dc9357SAndroid Build Coastguard Worker FinishCryptoBlock();
684*f6dc9357SAndroid Build Coastguard Worker ArcInfo.EndPos = m_Position;
685*f6dc9357SAndroid Build Coastguard Worker return S_OK;
686*f6dc9357SAndroid Build Coastguard Worker }
687*f6dc9357SAndroid Build Coastguard Worker
688*f6dc9357SAndroid Build Coastguard Worker if (m_BlockHeader.Type == NHeader::NBlockType::kFileHeader
689*f6dc9357SAndroid Build Coastguard Worker /* || m_BlockHeader.Type == NHeader::NBlockType::kSubBlock */)
690*f6dc9357SAndroid Build Coastguard Worker {
691*f6dc9357SAndroid Build Coastguard Worker if (m_FileHeaderData.Size() < m_BlockHeader.HeadSize)
692*f6dc9357SAndroid Build Coastguard Worker m_FileHeaderData.ChangeSize_KeepData(m_BlockHeader.HeadSize, 7);
693*f6dc9357SAndroid Build Coastguard Worker // m_CurData = (Byte *)m_FileHeaderData;
694*f6dc9357SAndroid Build Coastguard Worker // m_PosLimit = m_BlockHeader.HeadSize;
695*f6dc9357SAndroid Build Coastguard Worker if (!ReadBytesAndTestSize(m_FileHeaderData + 7, m_BlockHeader.HeadSize - 7))
696*f6dc9357SAndroid Build Coastguard Worker {
697*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_UnexpectedEnd;
698*f6dc9357SAndroid Build Coastguard Worker return S_OK;
699*f6dc9357SAndroid Build Coastguard Worker }
700*f6dc9357SAndroid Build Coastguard Worker
701*f6dc9357SAndroid Build Coastguard Worker bool okItem = ReadHeaderReal(m_FileHeaderData + 7, m_BlockHeader.HeadSize - 7, item);
702*f6dc9357SAndroid Build Coastguard Worker if (okItem)
703*f6dc9357SAndroid Build Coastguard Worker {
704*f6dc9357SAndroid Build Coastguard Worker if (!CheckHeaderCrc(m_FileHeaderData, (unsigned)m_BlockHeader.HeadSize - item.CommentSize))
705*f6dc9357SAndroid Build Coastguard Worker {
706*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_Corrupted; // ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError);
707*f6dc9357SAndroid Build Coastguard Worker return S_OK;
708*f6dc9357SAndroid Build Coastguard Worker }
709*f6dc9357SAndroid Build Coastguard Worker filled = true;
710*f6dc9357SAndroid Build Coastguard Worker }
711*f6dc9357SAndroid Build Coastguard Worker
712*f6dc9357SAndroid Build Coastguard Worker FinishCryptoBlock();
713*f6dc9357SAndroid Build Coastguard Worker m_CryptoMode = false;
714*f6dc9357SAndroid Build Coastguard Worker // Move Position to compressed Data;
715*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(m_Stream, m_Position))
716*f6dc9357SAndroid Build Coastguard Worker AddToSeekValue(item.PackSize); // m_Position points to next header;
717*f6dc9357SAndroid Build Coastguard Worker // if (okItem)
718*f6dc9357SAndroid Build Coastguard Worker return S_OK;
719*f6dc9357SAndroid Build Coastguard Worker /*
720*f6dc9357SAndroid Build Coastguard Worker else
721*f6dc9357SAndroid Build Coastguard Worker continue;
722*f6dc9357SAndroid Build Coastguard Worker */
723*f6dc9357SAndroid Build Coastguard Worker }
724*f6dc9357SAndroid Build Coastguard Worker
725*f6dc9357SAndroid Build Coastguard Worker if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 10))
726*f6dc9357SAndroid Build Coastguard Worker {
727*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_DecryptionError;
728*f6dc9357SAndroid Build Coastguard Worker return S_OK;
729*f6dc9357SAndroid Build Coastguard Worker }
730*f6dc9357SAndroid Build Coastguard Worker
731*f6dc9357SAndroid Build Coastguard Worker if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0)
732*f6dc9357SAndroid Build Coastguard Worker {
733*f6dc9357SAndroid Build Coastguard Worker if (m_FileHeaderData.Size() < 7 + 4)
734*f6dc9357SAndroid Build Coastguard Worker m_FileHeaderData.ChangeSize_KeepData(7 + 4, 7);
735*f6dc9357SAndroid Build Coastguard Worker if (!ReadBytesAndTestSize(m_FileHeaderData + 7, 4))
736*f6dc9357SAndroid Build Coastguard Worker {
737*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_UnexpectedEnd;
738*f6dc9357SAndroid Build Coastguard Worker return S_OK;
739*f6dc9357SAndroid Build Coastguard Worker }
740*f6dc9357SAndroid Build Coastguard Worker UInt32 dataSize = Get32(m_FileHeaderData + 7);
741*f6dc9357SAndroid Build Coastguard Worker AddToSeekValue(dataSize);
742*f6dc9357SAndroid Build Coastguard Worker if (m_CryptoMode && dataSize > (1 << 27))
743*f6dc9357SAndroid Build Coastguard Worker {
744*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_DecryptionError;
745*f6dc9357SAndroid Build Coastguard Worker return S_OK;
746*f6dc9357SAndroid Build Coastguard Worker }
747*f6dc9357SAndroid Build Coastguard Worker m_CryptoPos = m_BlockHeader.HeadSize;
748*f6dc9357SAndroid Build Coastguard Worker }
749*f6dc9357SAndroid Build Coastguard Worker else
750*f6dc9357SAndroid Build Coastguard Worker m_CryptoPos = 0;
751*f6dc9357SAndroid Build Coastguard Worker
752*f6dc9357SAndroid Build Coastguard Worker {
753*f6dc9357SAndroid Build Coastguard Worker UInt64 newPos = m_Position + m_BlockHeader.HeadSize;
754*f6dc9357SAndroid Build Coastguard Worker if (newPos > ArcInfo.FileSize)
755*f6dc9357SAndroid Build Coastguard Worker {
756*f6dc9357SAndroid Build Coastguard Worker error = k_ErrorType_UnexpectedEnd;
757*f6dc9357SAndroid Build Coastguard Worker return S_OK;
758*f6dc9357SAndroid Build Coastguard Worker }
759*f6dc9357SAndroid Build Coastguard Worker }
760*f6dc9357SAndroid Build Coastguard Worker AddToSeekValue(m_BlockHeader.HeadSize);
761*f6dc9357SAndroid Build Coastguard Worker FinishCryptoBlock();
762*f6dc9357SAndroid Build Coastguard Worker m_CryptoMode = false;
763*f6dc9357SAndroid Build Coastguard Worker }
764*f6dc9357SAndroid Build Coastguard Worker }
765*f6dc9357SAndroid Build Coastguard Worker
766*f6dc9357SAndroid Build Coastguard Worker
767*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
768*f6dc9357SAndroid Build Coastguard Worker {
769*f6dc9357SAndroid Build Coastguard Worker kpidPath,
770*f6dc9357SAndroid Build Coastguard Worker kpidIsDir,
771*f6dc9357SAndroid Build Coastguard Worker kpidSize,
772*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
773*f6dc9357SAndroid Build Coastguard Worker kpidMTime,
774*f6dc9357SAndroid Build Coastguard Worker kpidCTime,
775*f6dc9357SAndroid Build Coastguard Worker kpidATime,
776*f6dc9357SAndroid Build Coastguard Worker kpidAttrib,
777*f6dc9357SAndroid Build Coastguard Worker
778*f6dc9357SAndroid Build Coastguard Worker kpidEncrypted,
779*f6dc9357SAndroid Build Coastguard Worker kpidSolid,
780*f6dc9357SAndroid Build Coastguard Worker kpidCommented,
781*f6dc9357SAndroid Build Coastguard Worker kpidSplitBefore,
782*f6dc9357SAndroid Build Coastguard Worker kpidSplitAfter,
783*f6dc9357SAndroid Build Coastguard Worker kpidCRC,
784*f6dc9357SAndroid Build Coastguard Worker kpidHostOS,
785*f6dc9357SAndroid Build Coastguard Worker kpidMethod,
786*f6dc9357SAndroid Build Coastguard Worker kpidUnpackVer,
787*f6dc9357SAndroid Build Coastguard Worker
788*f6dc9357SAndroid Build Coastguard Worker kpidVolumeIndex
789*f6dc9357SAndroid Build Coastguard Worker };
790*f6dc9357SAndroid Build Coastguard Worker
791*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
792*f6dc9357SAndroid Build Coastguard Worker {
793*f6dc9357SAndroid Build Coastguard Worker kpidTotalPhySize,
794*f6dc9357SAndroid Build Coastguard Worker kpidCharacts,
795*f6dc9357SAndroid Build Coastguard Worker kpidSolid,
796*f6dc9357SAndroid Build Coastguard Worker kpidNumBlocks,
797*f6dc9357SAndroid Build Coastguard Worker // kpidEncrypted,
798*f6dc9357SAndroid Build Coastguard Worker kpidIsVolume,
799*f6dc9357SAndroid Build Coastguard Worker kpidVolumeIndex,
800*f6dc9357SAndroid Build Coastguard Worker kpidNumVolumes
801*f6dc9357SAndroid Build Coastguard Worker // kpidCommented
802*f6dc9357SAndroid Build Coastguard Worker };
803*f6dc9357SAndroid Build Coastguard Worker
804*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
805*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
806*f6dc9357SAndroid Build Coastguard Worker
GetPackSize(unsigned refIndex) const807*f6dc9357SAndroid Build Coastguard Worker UInt64 CHandler::GetPackSize(unsigned refIndex) const
808*f6dc9357SAndroid Build Coastguard Worker {
809*f6dc9357SAndroid Build Coastguard Worker const CRefItem &refItem = _refItems[refIndex];
810*f6dc9357SAndroid Build Coastguard Worker UInt64 totalPackSize = 0;
811*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < refItem.NumItems; i++)
812*f6dc9357SAndroid Build Coastguard Worker totalPackSize += _items[refItem.ItemIndex + i].PackSize;
813*f6dc9357SAndroid Build Coastguard Worker return totalPackSize;
814*f6dc9357SAndroid Build Coastguard Worker }
815*f6dc9357SAndroid Build Coastguard Worker
IsSolid(unsigned refIndex) const816*f6dc9357SAndroid Build Coastguard Worker bool CHandler::IsSolid(unsigned refIndex) const
817*f6dc9357SAndroid Build Coastguard Worker {
818*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[_refItems[refIndex].ItemIndex];
819*f6dc9357SAndroid Build Coastguard Worker if (item.UnPackVersion < 20)
820*f6dc9357SAndroid Build Coastguard Worker {
821*f6dc9357SAndroid Build Coastguard Worker if (_arcInfo.IsSolid())
822*f6dc9357SAndroid Build Coastguard Worker return (refIndex > 0);
823*f6dc9357SAndroid Build Coastguard Worker return false;
824*f6dc9357SAndroid Build Coastguard Worker }
825*f6dc9357SAndroid Build Coastguard Worker return item.IsSolid();
826*f6dc9357SAndroid Build Coastguard Worker }
827*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetArchiveProperty (PROPID propID,PROPVARIANT * value))828*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
829*f6dc9357SAndroid Build Coastguard Worker {
830*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
831*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
832*f6dc9357SAndroid Build Coastguard Worker switch (propID)
833*f6dc9357SAndroid Build Coastguard Worker {
834*f6dc9357SAndroid Build Coastguard Worker case kpidVolumeIndex: if (_arcInfo.Is_VolNumber_Defined()) prop = (UInt32)_arcInfo.VolNumber; break;
835*f6dc9357SAndroid Build Coastguard Worker case kpidSolid: prop = _arcInfo.IsSolid(); break;
836*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts:
837*f6dc9357SAndroid Build Coastguard Worker {
838*f6dc9357SAndroid Build Coastguard Worker AString s (FlagsToString(k_Flags, Z7_ARRAY_SIZE(k_Flags), _arcInfo.Flags));
839*f6dc9357SAndroid Build Coastguard Worker // FLAGS_TO_PROP(k_Flags, _arcInfo.Flags, prop);
840*f6dc9357SAndroid Build Coastguard Worker if (_arcInfo.Is_DataCRC_Defined())
841*f6dc9357SAndroid Build Coastguard Worker {
842*f6dc9357SAndroid Build Coastguard Worker s.Add_Space_if_NotEmpty();
843*f6dc9357SAndroid Build Coastguard Worker s += "VolCRC";
844*f6dc9357SAndroid Build Coastguard Worker }
845*f6dc9357SAndroid Build Coastguard Worker prop = s;
846*f6dc9357SAndroid Build Coastguard Worker break;
847*f6dc9357SAndroid Build Coastguard Worker }
848*f6dc9357SAndroid Build Coastguard Worker // case kpidEncrypted: prop = _arcInfo.IsEncrypted(); break; // it's for encrypted names.
849*f6dc9357SAndroid Build Coastguard Worker case kpidIsVolume: prop = _arcInfo.IsVolume(); break;
850*f6dc9357SAndroid Build Coastguard Worker case kpidNumVolumes: prop = (UInt32)_arcs.Size(); break;
851*f6dc9357SAndroid Build Coastguard Worker case kpidOffset: if (_arcs.Size() == 1 && _arcInfo.StartPos != 0) prop = _arcInfo.StartPos; break;
852*f6dc9357SAndroid Build Coastguard Worker
853*f6dc9357SAndroid Build Coastguard Worker case kpidTotalPhySize:
854*f6dc9357SAndroid Build Coastguard Worker {
855*f6dc9357SAndroid Build Coastguard Worker if (_arcs.Size() > 1)
856*f6dc9357SAndroid Build Coastguard Worker {
857*f6dc9357SAndroid Build Coastguard Worker UInt64 sum = 0;
858*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (v, _arcs)
859*f6dc9357SAndroid Build Coastguard Worker sum += _arcs[v].PhySize;
860*f6dc9357SAndroid Build Coastguard Worker prop = sum;
861*f6dc9357SAndroid Build Coastguard Worker }
862*f6dc9357SAndroid Build Coastguard Worker break;
863*f6dc9357SAndroid Build Coastguard Worker }
864*f6dc9357SAndroid Build Coastguard Worker
865*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize:
866*f6dc9357SAndroid Build Coastguard Worker {
867*f6dc9357SAndroid Build Coastguard Worker if (_arcs.Size() != 0)
868*f6dc9357SAndroid Build Coastguard Worker prop = _arcInfo.GetPhySize();
869*f6dc9357SAndroid Build Coastguard Worker break;
870*f6dc9357SAndroid Build Coastguard Worker }
871*f6dc9357SAndroid Build Coastguard Worker
872*f6dc9357SAndroid Build Coastguard Worker // case kpidCommented: prop = _arcInfo.IsCommented(); break;
873*f6dc9357SAndroid Build Coastguard Worker
874*f6dc9357SAndroid Build Coastguard Worker case kpidNumBlocks:
875*f6dc9357SAndroid Build Coastguard Worker {
876*f6dc9357SAndroid Build Coastguard Worker UInt32 numBlocks = 0;
877*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, _refItems)
878*f6dc9357SAndroid Build Coastguard Worker if (!IsSolid(i))
879*f6dc9357SAndroid Build Coastguard Worker numBlocks++;
880*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)numBlocks;
881*f6dc9357SAndroid Build Coastguard Worker break;
882*f6dc9357SAndroid Build Coastguard Worker }
883*f6dc9357SAndroid Build Coastguard Worker
884*f6dc9357SAndroid Build Coastguard Worker
885*f6dc9357SAndroid Build Coastguard Worker case kpidError:
886*f6dc9357SAndroid Build Coastguard Worker {
887*f6dc9357SAndroid Build Coastguard Worker // if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
888*f6dc9357SAndroid Build Coastguard Worker
889*f6dc9357SAndroid Build Coastguard Worker if (/* &_missingVol || */ !_missingVolName.IsEmpty())
890*f6dc9357SAndroid Build Coastguard Worker {
891*f6dc9357SAndroid Build Coastguard Worker UString s ("Missing volume : ");
892*f6dc9357SAndroid Build Coastguard Worker s += _missingVolName;
893*f6dc9357SAndroid Build Coastguard Worker prop = s;
894*f6dc9357SAndroid Build Coastguard Worker }
895*f6dc9357SAndroid Build Coastguard Worker break;
896*f6dc9357SAndroid Build Coastguard Worker }
897*f6dc9357SAndroid Build Coastguard Worker
898*f6dc9357SAndroid Build Coastguard Worker case kpidErrorFlags:
899*f6dc9357SAndroid Build Coastguard Worker {
900*f6dc9357SAndroid Build Coastguard Worker UInt32 v = _errorFlags;
901*f6dc9357SAndroid Build Coastguard Worker if (!_isArc)
902*f6dc9357SAndroid Build Coastguard Worker v |= kpv_ErrorFlags_IsNotArc;
903*f6dc9357SAndroid Build Coastguard Worker prop = v;
904*f6dc9357SAndroid Build Coastguard Worker break;
905*f6dc9357SAndroid Build Coastguard Worker }
906*f6dc9357SAndroid Build Coastguard Worker
907*f6dc9357SAndroid Build Coastguard Worker case kpidWarningFlags:
908*f6dc9357SAndroid Build Coastguard Worker {
909*f6dc9357SAndroid Build Coastguard Worker if (_warningFlags != 0)
910*f6dc9357SAndroid Build Coastguard Worker prop = _warningFlags;
911*f6dc9357SAndroid Build Coastguard Worker break;
912*f6dc9357SAndroid Build Coastguard Worker }
913*f6dc9357SAndroid Build Coastguard Worker
914*f6dc9357SAndroid Build Coastguard Worker case kpidExtension:
915*f6dc9357SAndroid Build Coastguard Worker if (_arcs.Size() == 1)
916*f6dc9357SAndroid Build Coastguard Worker {
917*f6dc9357SAndroid Build Coastguard Worker if (_arcInfo.Is_VolNumber_Defined())
918*f6dc9357SAndroid Build Coastguard Worker {
919*f6dc9357SAndroid Build Coastguard Worker AString s ("part");
920*f6dc9357SAndroid Build Coastguard Worker UInt32 v = (UInt32)_arcInfo.VolNumber + 1;
921*f6dc9357SAndroid Build Coastguard Worker if (v < 10)
922*f6dc9357SAndroid Build Coastguard Worker s += '0';
923*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(v);
924*f6dc9357SAndroid Build Coastguard Worker s += ".rar";
925*f6dc9357SAndroid Build Coastguard Worker prop = s;
926*f6dc9357SAndroid Build Coastguard Worker }
927*f6dc9357SAndroid Build Coastguard Worker }
928*f6dc9357SAndroid Build Coastguard Worker break;
929*f6dc9357SAndroid Build Coastguard Worker }
930*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
931*f6dc9357SAndroid Build Coastguard Worker return S_OK;
932*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
933*f6dc9357SAndroid Build Coastguard Worker }
934*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetNumberOfItems (UInt32 * numItems))935*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
936*f6dc9357SAndroid Build Coastguard Worker {
937*f6dc9357SAndroid Build Coastguard Worker *numItems = _refItems.Size();
938*f6dc9357SAndroid Build Coastguard Worker return S_OK;
939*f6dc9357SAndroid Build Coastguard Worker }
940*f6dc9357SAndroid Build Coastguard Worker
RarTimeToFileTime(const CRarTime & rarTime,FILETIME & ft)941*f6dc9357SAndroid Build Coastguard Worker static bool RarTimeToFileTime(const CRarTime &rarTime, FILETIME &ft)
942*f6dc9357SAndroid Build Coastguard Worker {
943*f6dc9357SAndroid Build Coastguard Worker if (!NTime::DosTime_To_FileTime(rarTime.DosTime, ft))
944*f6dc9357SAndroid Build Coastguard Worker return false;
945*f6dc9357SAndroid Build Coastguard Worker UInt64 v = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
946*f6dc9357SAndroid Build Coastguard Worker v += (UInt32)rarTime.LowSecond * 10000000;
947*f6dc9357SAndroid Build Coastguard Worker v +=
948*f6dc9357SAndroid Build Coastguard Worker ((UInt32)rarTime.SubTime[2] << 16) +
949*f6dc9357SAndroid Build Coastguard Worker ((UInt32)rarTime.SubTime[1] << 8) +
950*f6dc9357SAndroid Build Coastguard Worker ((UInt32)rarTime.SubTime[0]);
951*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (DWORD)v;
952*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (DWORD)(v >> 32);
953*f6dc9357SAndroid Build Coastguard Worker return true;
954*f6dc9357SAndroid Build Coastguard Worker }
955*f6dc9357SAndroid Build Coastguard Worker
RarTimeToProp(const CRarTime & rarTime,NCOM::CPropVariant & prop)956*f6dc9357SAndroid Build Coastguard Worker static void RarTimeToProp(const CRarTime &rarTime, NCOM::CPropVariant &prop)
957*f6dc9357SAndroid Build Coastguard Worker {
958*f6dc9357SAndroid Build Coastguard Worker FILETIME localFileTime, utc;
959*f6dc9357SAndroid Build Coastguard Worker if (RarTimeToFileTime(rarTime, localFileTime)
960*f6dc9357SAndroid Build Coastguard Worker && LocalFileTimeToFileTime(&localFileTime, &utc))
961*f6dc9357SAndroid Build Coastguard Worker prop.SetAsTimeFrom_FT_Prec(utc, k_PropVar_TimePrec_100ns);
962*f6dc9357SAndroid Build Coastguard Worker /*
963*f6dc9357SAndroid Build Coastguard Worker else
964*f6dc9357SAndroid Build Coastguard Worker utc.dwHighDateTime = utc.dwLowDateTime = 0;
965*f6dc9357SAndroid Build Coastguard Worker // prop.SetAsTimeFrom_FT_Prec(utc, k_PropVar_TimePrec_100ns);
966*f6dc9357SAndroid Build Coastguard Worker */
967*f6dc9357SAndroid Build Coastguard Worker }
968*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetProperty (UInt32 index,PROPID propID,PROPVARIANT * value))969*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
970*f6dc9357SAndroid Build Coastguard Worker {
971*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
972*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
973*f6dc9357SAndroid Build Coastguard Worker const CRefItem &refItem = _refItems[index];
974*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[refItem.ItemIndex];
975*f6dc9357SAndroid Build Coastguard Worker const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
976*f6dc9357SAndroid Build Coastguard Worker
977*f6dc9357SAndroid Build Coastguard Worker /*
978*f6dc9357SAndroid Build Coastguard Worker const CItem *mainItem = &item;
979*f6dc9357SAndroid Build Coastguard Worker if (item.BaseFileIndex >= 0)
980*f6dc9357SAndroid Build Coastguard Worker mainItem = &_items[_refItems[item.BaseFileIndex].ItemIndex];
981*f6dc9357SAndroid Build Coastguard Worker */
982*f6dc9357SAndroid Build Coastguard Worker switch (propID)
983*f6dc9357SAndroid Build Coastguard Worker {
984*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
985*f6dc9357SAndroid Build Coastguard Worker {
986*f6dc9357SAndroid Build Coastguard Worker /*
987*f6dc9357SAndroid Build Coastguard Worker UString u;
988*f6dc9357SAndroid Build Coastguard Worker if (item.BaseFileIndex >= 0)
989*f6dc9357SAndroid Build Coastguard Worker u = mainItem->GetName();
990*f6dc9357SAndroid Build Coastguard Worker u += item.GetName();
991*f6dc9357SAndroid Build Coastguard Worker */
992*f6dc9357SAndroid Build Coastguard Worker prop = (const wchar_t *)NItemName::WinPathToOsPath(item.GetName());
993*f6dc9357SAndroid Build Coastguard Worker break;
994*f6dc9357SAndroid Build Coastguard Worker }
995*f6dc9357SAndroid Build Coastguard Worker case kpidIsDir: prop = item.IsDir(); break;
996*f6dc9357SAndroid Build Coastguard Worker case kpidSize: if (lastItem.Is_Size_Defined()) prop = lastItem.Size; break;
997*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: prop = GetPackSize(index); break;
998*f6dc9357SAndroid Build Coastguard Worker case kpidMTime: RarTimeToProp(item.MTime, prop); break;
999*f6dc9357SAndroid Build Coastguard Worker case kpidCTime: if (item.CTimeDefined) RarTimeToProp(item.CTime, prop); break;
1000*f6dc9357SAndroid Build Coastguard Worker case kpidATime: if (item.ATimeDefined) RarTimeToProp(item.ATime, prop); break;
1001*f6dc9357SAndroid Build Coastguard Worker case kpidAttrib: prop = item.GetWinAttrib(); break;
1002*f6dc9357SAndroid Build Coastguard Worker case kpidEncrypted: prop = item.IsEncrypted(); break;
1003*f6dc9357SAndroid Build Coastguard Worker case kpidSolid: prop = IsSolid(index); break;
1004*f6dc9357SAndroid Build Coastguard Worker case kpidCommented: prop = item.IsCommented(); break;
1005*f6dc9357SAndroid Build Coastguard Worker case kpidSplitBefore: prop = item.IsSplitBefore(); break;
1006*f6dc9357SAndroid Build Coastguard Worker case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter(); break;
1007*f6dc9357SAndroid Build Coastguard Worker
1008*f6dc9357SAndroid Build Coastguard Worker case kpidVolumeIndex:
1009*f6dc9357SAndroid Build Coastguard Worker if (_arcInfo.Is_VolNumber_Defined())
1010*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)(_arcInfo.VolNumber + refItem.VolumeIndex);
1011*f6dc9357SAndroid Build Coastguard Worker break;
1012*f6dc9357SAndroid Build Coastguard Worker
1013*f6dc9357SAndroid Build Coastguard Worker case kpidCRC:
1014*f6dc9357SAndroid Build Coastguard Worker {
1015*f6dc9357SAndroid Build Coastguard Worker prop = ((lastItem.IsSplitAfter()) ? item.FileCRC : lastItem.FileCRC);
1016*f6dc9357SAndroid Build Coastguard Worker break;
1017*f6dc9357SAndroid Build Coastguard Worker }
1018*f6dc9357SAndroid Build Coastguard Worker case kpidUnpackVer: prop = item.UnPackVersion; break;
1019*f6dc9357SAndroid Build Coastguard Worker case kpidMethod:
1020*f6dc9357SAndroid Build Coastguard Worker {
1021*f6dc9357SAndroid Build Coastguard Worker char s[16];
1022*f6dc9357SAndroid Build Coastguard Worker Byte m = item.Method;
1023*f6dc9357SAndroid Build Coastguard Worker if (m < (Byte)'0' || m > (Byte)'5')
1024*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(m, s);
1025*f6dc9357SAndroid Build Coastguard Worker else
1026*f6dc9357SAndroid Build Coastguard Worker {
1027*f6dc9357SAndroid Build Coastguard Worker s[0] = 'm';
1028*f6dc9357SAndroid Build Coastguard Worker s[1] = (char)m;
1029*f6dc9357SAndroid Build Coastguard Worker s[2] = 0;
1030*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDir())
1031*f6dc9357SAndroid Build Coastguard Worker {
1032*f6dc9357SAndroid Build Coastguard Worker s[2] = ':';
1033*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(16 + item.GetDictSize(), &s[3]);
1034*f6dc9357SAndroid Build Coastguard Worker }
1035*f6dc9357SAndroid Build Coastguard Worker }
1036*f6dc9357SAndroid Build Coastguard Worker prop = s;
1037*f6dc9357SAndroid Build Coastguard Worker break;
1038*f6dc9357SAndroid Build Coastguard Worker }
1039*f6dc9357SAndroid Build Coastguard Worker case kpidHostOS:
1040*f6dc9357SAndroid Build Coastguard Worker TYPE_TO_PROP(kHostOS, item.HostOS, prop);
1041*f6dc9357SAndroid Build Coastguard Worker break;
1042*f6dc9357SAndroid Build Coastguard Worker }
1043*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
1044*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1045*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1046*f6dc9357SAndroid Build Coastguard Worker }
1047*f6dc9357SAndroid Build Coastguard Worker
1048*f6dc9357SAndroid Build Coastguard Worker
Open2(IInStream * stream,const UInt64 * maxCheckStartPosition,IArchiveOpenCallback * openCallback)1049*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream,
1050*f6dc9357SAndroid Build Coastguard Worker const UInt64 *maxCheckStartPosition,
1051*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback *openCallback)
1052*f6dc9357SAndroid Build Coastguard Worker {
1053*f6dc9357SAndroid Build Coastguard Worker {
1054*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
1055*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICryptoGetTextPassword> getTextPassword;
1056*f6dc9357SAndroid Build Coastguard Worker
1057*f6dc9357SAndroid Build Coastguard Worker CVolumeName seqName;
1058*f6dc9357SAndroid Build Coastguard Worker
1059*f6dc9357SAndroid Build Coastguard Worker UInt64 totalBytes = 0;
1060*f6dc9357SAndroid Build Coastguard Worker UInt64 curBytes = 0;
1061*f6dc9357SAndroid Build Coastguard Worker
1062*f6dc9357SAndroid Build Coastguard Worker if (openCallback)
1063*f6dc9357SAndroid Build Coastguard Worker {
1064*f6dc9357SAndroid Build Coastguard Worker openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
1065*f6dc9357SAndroid Build Coastguard Worker openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
1066*f6dc9357SAndroid Build Coastguard Worker }
1067*f6dc9357SAndroid Build Coastguard Worker
1068*f6dc9357SAndroid Build Coastguard Worker bool nextVol_is_Required = false;
1069*f6dc9357SAndroid Build Coastguard Worker
1070*f6dc9357SAndroid Build Coastguard Worker CInArchive archive;
1071*f6dc9357SAndroid Build Coastguard Worker
1072*f6dc9357SAndroid Build Coastguard Worker for (;;)
1073*f6dc9357SAndroid Build Coastguard Worker {
1074*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> inStream;
1075*f6dc9357SAndroid Build Coastguard Worker if (!_arcs.IsEmpty())
1076*f6dc9357SAndroid Build Coastguard Worker {
1077*f6dc9357SAndroid Build Coastguard Worker if (!openVolumeCallback)
1078*f6dc9357SAndroid Build Coastguard Worker break;
1079*f6dc9357SAndroid Build Coastguard Worker
1080*f6dc9357SAndroid Build Coastguard Worker if (_arcs.Size() == 1)
1081*f6dc9357SAndroid Build Coastguard Worker {
1082*f6dc9357SAndroid Build Coastguard Worker if (!_arcInfo.IsVolume())
1083*f6dc9357SAndroid Build Coastguard Worker break;
1084*f6dc9357SAndroid Build Coastguard Worker UString baseName;
1085*f6dc9357SAndroid Build Coastguard Worker {
1086*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
1087*f6dc9357SAndroid Build Coastguard Worker RINOK(openVolumeCallback->GetProperty(kpidName, &prop))
1088*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_BSTR)
1089*f6dc9357SAndroid Build Coastguard Worker break;
1090*f6dc9357SAndroid Build Coastguard Worker baseName = prop.bstrVal;
1091*f6dc9357SAndroid Build Coastguard Worker }
1092*f6dc9357SAndroid Build Coastguard Worker if (!seqName.InitName(baseName, _arcInfo.HaveNewVolumeName()))
1093*f6dc9357SAndroid Build Coastguard Worker break;
1094*f6dc9357SAndroid Build Coastguard Worker /*
1095*f6dc9357SAndroid Build Coastguard Worker if (_arcInfo.HaveNewVolumeName() && !_arcInfo.IsFirstVolume())
1096*f6dc9357SAndroid Build Coastguard Worker {
1097*f6dc9357SAndroid Build Coastguard Worker seqName.MakeBeforeFirstName();
1098*f6dc9357SAndroid Build Coastguard Worker }
1099*f6dc9357SAndroid Build Coastguard Worker */
1100*f6dc9357SAndroid Build Coastguard Worker }
1101*f6dc9357SAndroid Build Coastguard Worker
1102*f6dc9357SAndroid Build Coastguard Worker const UString volName = seqName.GetNextName();
1103*f6dc9357SAndroid Build Coastguard Worker
1104*f6dc9357SAndroid Build Coastguard Worker HRESULT result = openVolumeCallback->GetStream(volName, &inStream);
1105*f6dc9357SAndroid Build Coastguard Worker
1106*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK && result != S_FALSE)
1107*f6dc9357SAndroid Build Coastguard Worker return result;
1108*f6dc9357SAndroid Build Coastguard Worker
1109*f6dc9357SAndroid Build Coastguard Worker if (!inStream || result != S_OK)
1110*f6dc9357SAndroid Build Coastguard Worker {
1111*f6dc9357SAndroid Build Coastguard Worker if (nextVol_is_Required)
1112*f6dc9357SAndroid Build Coastguard Worker _missingVolName = volName;
1113*f6dc9357SAndroid Build Coastguard Worker break;
1114*f6dc9357SAndroid Build Coastguard Worker }
1115*f6dc9357SAndroid Build Coastguard Worker }
1116*f6dc9357SAndroid Build Coastguard Worker else
1117*f6dc9357SAndroid Build Coastguard Worker inStream = stream;
1118*f6dc9357SAndroid Build Coastguard Worker
1119*f6dc9357SAndroid Build Coastguard Worker UInt64 endPos;
1120*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_AtBegin_GetSize(inStream, endPos))
1121*f6dc9357SAndroid Build Coastguard Worker if (openCallback)
1122*f6dc9357SAndroid Build Coastguard Worker {
1123*f6dc9357SAndroid Build Coastguard Worker totalBytes += endPos;
1124*f6dc9357SAndroid Build Coastguard Worker RINOK(openCallback->SetTotal(NULL, &totalBytes))
1125*f6dc9357SAndroid Build Coastguard Worker }
1126*f6dc9357SAndroid Build Coastguard Worker
1127*f6dc9357SAndroid Build Coastguard Worker RINOK(archive.Open(inStream, maxCheckStartPosition))
1128*f6dc9357SAndroid Build Coastguard Worker _isArc = true;
1129*f6dc9357SAndroid Build Coastguard Worker CItem item;
1130*f6dc9357SAndroid Build Coastguard Worker
1131*f6dc9357SAndroid Build Coastguard Worker for (;;)
1132*f6dc9357SAndroid Build Coastguard Worker {
1133*f6dc9357SAndroid Build Coastguard Worker if (archive.m_Position > endPos)
1134*f6dc9357SAndroid Build Coastguard Worker {
1135*f6dc9357SAndroid Build Coastguard Worker _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
1136*f6dc9357SAndroid Build Coastguard Worker break;
1137*f6dc9357SAndroid Build Coastguard Worker }
1138*f6dc9357SAndroid Build Coastguard Worker
1139*f6dc9357SAndroid Build Coastguard Worker EErrorType error;
1140*f6dc9357SAndroid Build Coastguard Worker // bool decryptionError;
1141*f6dc9357SAndroid Build Coastguard Worker // AString errorMessageLoc;
1142*f6dc9357SAndroid Build Coastguard Worker bool filled;
1143*f6dc9357SAndroid Build Coastguard Worker HRESULT result = archive.GetNextItem(item, getTextPassword, filled, error);
1144*f6dc9357SAndroid Build Coastguard Worker
1145*f6dc9357SAndroid Build Coastguard Worker if (error != k_ErrorType_OK)
1146*f6dc9357SAndroid Build Coastguard Worker {
1147*f6dc9357SAndroid Build Coastguard Worker if (error == k_ErrorType_UnexpectedEnd)
1148*f6dc9357SAndroid Build Coastguard Worker _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
1149*f6dc9357SAndroid Build Coastguard Worker else if (error == k_ErrorType_Corrupted)
1150*f6dc9357SAndroid Build Coastguard Worker _errorFlags |= kpv_ErrorFlags_HeadersError;
1151*f6dc9357SAndroid Build Coastguard Worker else if (error == k_ErrorType_DecryptionError)
1152*f6dc9357SAndroid Build Coastguard Worker _errorFlags |= kpv_ErrorFlags_EncryptedHeadersError;
1153*f6dc9357SAndroid Build Coastguard Worker
1154*f6dc9357SAndroid Build Coastguard Worker // AddErrorMessage(errorMessageLoc);
1155*f6dc9357SAndroid Build Coastguard Worker }
1156*f6dc9357SAndroid Build Coastguard Worker RINOK(result)
1157*f6dc9357SAndroid Build Coastguard Worker
1158*f6dc9357SAndroid Build Coastguard Worker if (!filled)
1159*f6dc9357SAndroid Build Coastguard Worker {
1160*f6dc9357SAndroid Build Coastguard Worker if (error == k_ErrorType_DecryptionError && _items.IsEmpty())
1161*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1162*f6dc9357SAndroid Build Coastguard Worker
1163*f6dc9357SAndroid Build Coastguard Worker if (archive.ArcInfo.ExtraZeroTail_is_Possible())
1164*f6dc9357SAndroid Build Coastguard Worker {
1165*f6dc9357SAndroid Build Coastguard Worker /* if there is recovery record for multivolume archive,
1166*f6dc9357SAndroid Build Coastguard Worker RAR adds 18 bytes (ZERO bytes) at the end for alignment.
1167*f6dc9357SAndroid Build Coastguard Worker We must skip these bytes to prevent phySize warning. */
1168*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(inStream, archive.ArcInfo.EndPos))
1169*f6dc9357SAndroid Build Coastguard Worker bool areThereNonZeros;
1170*f6dc9357SAndroid Build Coastguard Worker UInt64 numZeros;
1171*f6dc9357SAndroid Build Coastguard Worker const UInt64 maxSize = 1 << 12;
1172*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize))
1173*f6dc9357SAndroid Build Coastguard Worker if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize)
1174*f6dc9357SAndroid Build Coastguard Worker archive.ArcInfo.EndPos += numZeros;
1175*f6dc9357SAndroid Build Coastguard Worker }
1176*f6dc9357SAndroid Build Coastguard Worker break;
1177*f6dc9357SAndroid Build Coastguard Worker }
1178*f6dc9357SAndroid Build Coastguard Worker
1179*f6dc9357SAndroid Build Coastguard Worker if (item.IgnoreItem())
1180*f6dc9357SAndroid Build Coastguard Worker continue;
1181*f6dc9357SAndroid Build Coastguard Worker
1182*f6dc9357SAndroid Build Coastguard Worker bool needAdd = true;
1183*f6dc9357SAndroid Build Coastguard Worker
1184*f6dc9357SAndroid Build Coastguard Worker if (item.IsSplitBefore())
1185*f6dc9357SAndroid Build Coastguard Worker {
1186*f6dc9357SAndroid Build Coastguard Worker if (!_refItems.IsEmpty())
1187*f6dc9357SAndroid Build Coastguard Worker {
1188*f6dc9357SAndroid Build Coastguard Worker CRefItem &refItem = _refItems.Back();
1189*f6dc9357SAndroid Build Coastguard Worker refItem.NumItems++;
1190*f6dc9357SAndroid Build Coastguard Worker needAdd = false;
1191*f6dc9357SAndroid Build Coastguard Worker }
1192*f6dc9357SAndroid Build Coastguard Worker }
1193*f6dc9357SAndroid Build Coastguard Worker
1194*f6dc9357SAndroid Build Coastguard Worker if (needAdd)
1195*f6dc9357SAndroid Build Coastguard Worker {
1196*f6dc9357SAndroid Build Coastguard Worker CRefItem refItem;
1197*f6dc9357SAndroid Build Coastguard Worker refItem.ItemIndex = _items.Size();
1198*f6dc9357SAndroid Build Coastguard Worker refItem.NumItems = 1;
1199*f6dc9357SAndroid Build Coastguard Worker refItem.VolumeIndex = _arcs.Size();
1200*f6dc9357SAndroid Build Coastguard Worker _refItems.Add(refItem);
1201*f6dc9357SAndroid Build Coastguard Worker }
1202*f6dc9357SAndroid Build Coastguard Worker
1203*f6dc9357SAndroid Build Coastguard Worker _items.Add(item);
1204*f6dc9357SAndroid Build Coastguard Worker
1205*f6dc9357SAndroid Build Coastguard Worker if (openCallback && _items.Size() % 100 == 0)
1206*f6dc9357SAndroid Build Coastguard Worker {
1207*f6dc9357SAndroid Build Coastguard Worker UInt64 numFiles = _items.Size();
1208*f6dc9357SAndroid Build Coastguard Worker UInt64 numBytes = curBytes + item.Position;
1209*f6dc9357SAndroid Build Coastguard Worker RINOK(openCallback->SetCompleted(&numFiles, &numBytes))
1210*f6dc9357SAndroid Build Coastguard Worker }
1211*f6dc9357SAndroid Build Coastguard Worker }
1212*f6dc9357SAndroid Build Coastguard Worker
1213*f6dc9357SAndroid Build Coastguard Worker if (archive.HeaderErrorWarning)
1214*f6dc9357SAndroid Build Coastguard Worker _warningFlags |= kpv_ErrorFlags_HeadersError;
1215*f6dc9357SAndroid Build Coastguard Worker
1216*f6dc9357SAndroid Build Coastguard Worker /*
1217*f6dc9357SAndroid Build Coastguard Worker if (archive.m_Position < endPos)
1218*f6dc9357SAndroid Build Coastguard Worker _warningFlags |= kpv_ErrorFlags_DataAfterEnd;
1219*f6dc9357SAndroid Build Coastguard Worker */
1220*f6dc9357SAndroid Build Coastguard Worker if (_arcs.IsEmpty())
1221*f6dc9357SAndroid Build Coastguard Worker _arcInfo = archive.ArcInfo;
1222*f6dc9357SAndroid Build Coastguard Worker // _arcInfo.EndPos = archive.EndPos;
1223*f6dc9357SAndroid Build Coastguard Worker
1224*f6dc9357SAndroid Build Coastguard Worker curBytes += endPos;
1225*f6dc9357SAndroid Build Coastguard Worker {
1226*f6dc9357SAndroid Build Coastguard Worker CArc &arc = _arcs.AddNew();
1227*f6dc9357SAndroid Build Coastguard Worker arc.PhySize = archive.ArcInfo.GetPhySize();
1228*f6dc9357SAndroid Build Coastguard Worker arc.Stream = inStream;
1229*f6dc9357SAndroid Build Coastguard Worker }
1230*f6dc9357SAndroid Build Coastguard Worker
1231*f6dc9357SAndroid Build Coastguard Worker nextVol_is_Required = false;
1232*f6dc9357SAndroid Build Coastguard Worker
1233*f6dc9357SAndroid Build Coastguard Worker if (!archive.ArcInfo.IsVolume())
1234*f6dc9357SAndroid Build Coastguard Worker break;
1235*f6dc9357SAndroid Build Coastguard Worker
1236*f6dc9357SAndroid Build Coastguard Worker if (archive.ArcInfo.EndOfArchive_was_Read)
1237*f6dc9357SAndroid Build Coastguard Worker {
1238*f6dc9357SAndroid Build Coastguard Worker if (!archive.ArcInfo.AreMoreVolumes())
1239*f6dc9357SAndroid Build Coastguard Worker break;
1240*f6dc9357SAndroid Build Coastguard Worker nextVol_is_Required = true;
1241*f6dc9357SAndroid Build Coastguard Worker }
1242*f6dc9357SAndroid Build Coastguard Worker }
1243*f6dc9357SAndroid Build Coastguard Worker }
1244*f6dc9357SAndroid Build Coastguard Worker
1245*f6dc9357SAndroid Build Coastguard Worker /*
1246*f6dc9357SAndroid Build Coastguard Worker int baseFileIndex = -1;
1247*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < _refItems.Size(); i++)
1248*f6dc9357SAndroid Build Coastguard Worker {
1249*f6dc9357SAndroid Build Coastguard Worker CItem &item = _items[_refItems[i].ItemIndex];
1250*f6dc9357SAndroid Build Coastguard Worker if (item.IsAltStream)
1251*f6dc9357SAndroid Build Coastguard Worker item.BaseFileIndex = baseFileIndex;
1252*f6dc9357SAndroid Build Coastguard Worker else
1253*f6dc9357SAndroid Build Coastguard Worker baseFileIndex = i;
1254*f6dc9357SAndroid Build Coastguard Worker }
1255*f6dc9357SAndroid Build Coastguard Worker */
1256*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1257*f6dc9357SAndroid Build Coastguard Worker }
1258*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Open (IInStream * stream,const UInt64 * maxCheckStartPosition,IArchiveOpenCallback * openCallback))1259*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
1260*f6dc9357SAndroid Build Coastguard Worker const UInt64 *maxCheckStartPosition,
1261*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback *openCallback))
1262*f6dc9357SAndroid Build Coastguard Worker {
1263*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1264*f6dc9357SAndroid Build Coastguard Worker Close();
1265*f6dc9357SAndroid Build Coastguard Worker // try
1266*f6dc9357SAndroid Build Coastguard Worker {
1267*f6dc9357SAndroid Build Coastguard Worker HRESULT res = Open2(stream, maxCheckStartPosition, openCallback);
1268*f6dc9357SAndroid Build Coastguard Worker /*
1269*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
1270*f6dc9357SAndroid Build Coastguard Worker Close();
1271*f6dc9357SAndroid Build Coastguard Worker */
1272*f6dc9357SAndroid Build Coastguard Worker
1273*f6dc9357SAndroid Build Coastguard Worker return res;
1274*f6dc9357SAndroid Build Coastguard Worker }
1275*f6dc9357SAndroid Build Coastguard Worker // catch(const CInArchiveException &) { Close(); return S_FALSE; }
1276*f6dc9357SAndroid Build Coastguard Worker // catch(...) { Close(); throw; }
1277*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1278*f6dc9357SAndroid Build Coastguard Worker }
1279*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Close ())1280*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
1281*f6dc9357SAndroid Build Coastguard Worker {
1282*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1283*f6dc9357SAndroid Build Coastguard Worker // _errorMessage.Empty();
1284*f6dc9357SAndroid Build Coastguard Worker _missingVolName.Empty();
1285*f6dc9357SAndroid Build Coastguard Worker _errorFlags = 0;
1286*f6dc9357SAndroid Build Coastguard Worker _warningFlags = 0;
1287*f6dc9357SAndroid Build Coastguard Worker _isArc = false;
1288*f6dc9357SAndroid Build Coastguard Worker _refItems.Clear();
1289*f6dc9357SAndroid Build Coastguard Worker _items.Clear();
1290*f6dc9357SAndroid Build Coastguard Worker _arcs.Clear();
1291*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1292*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1293*f6dc9357SAndroid Build Coastguard Worker }
1294*f6dc9357SAndroid Build Coastguard Worker
1295*f6dc9357SAndroid Build Coastguard Worker struct CMethodItem
1296*f6dc9357SAndroid Build Coastguard Worker {
1297*f6dc9357SAndroid Build Coastguard Worker Byte RarUnPackVersion;
1298*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressCoder> Coder;
1299*f6dc9357SAndroid Build Coastguard Worker };
1300*f6dc9357SAndroid Build Coastguard Worker
1301*f6dc9357SAndroid Build Coastguard Worker
1302*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_1(
1303*f6dc9357SAndroid Build Coastguard Worker CVolsInStream
1304*f6dc9357SAndroid Build Coastguard Worker , ISequentialInStream
1305*f6dc9357SAndroid Build Coastguard Worker )
1306*f6dc9357SAndroid Build Coastguard Worker UInt64 _rem;
1307*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *_stream;
1308*f6dc9357SAndroid Build Coastguard Worker const CObjectVector<CArc> *_arcs;
1309*f6dc9357SAndroid Build Coastguard Worker const CObjectVector<CItem> *_items;
1310*f6dc9357SAndroid Build Coastguard Worker CRefItem _refItem;
1311*f6dc9357SAndroid Build Coastguard Worker unsigned _curIndex;
1312*f6dc9357SAndroid Build Coastguard Worker UInt32 _crc;
1313*f6dc9357SAndroid Build Coastguard Worker bool _calcCrc;
1314*f6dc9357SAndroid Build Coastguard Worker
1315*f6dc9357SAndroid Build Coastguard Worker public:
1316*f6dc9357SAndroid Build Coastguard Worker void Init(const CObjectVector<CArc> *arcs,
1317*f6dc9357SAndroid Build Coastguard Worker const CObjectVector<CItem> *items,
1318*f6dc9357SAndroid Build Coastguard Worker const CRefItem &refItem)
1319*f6dc9357SAndroid Build Coastguard Worker {
1320*f6dc9357SAndroid Build Coastguard Worker _arcs = arcs;
1321*f6dc9357SAndroid Build Coastguard Worker _items = items;
1322*f6dc9357SAndroid Build Coastguard Worker _refItem = refItem;
1323*f6dc9357SAndroid Build Coastguard Worker _curIndex = 0;
1324*f6dc9357SAndroid Build Coastguard Worker _stream = NULL;
1325*f6dc9357SAndroid Build Coastguard Worker CrcIsOK = true;
1326*f6dc9357SAndroid Build Coastguard Worker }
1327*f6dc9357SAndroid Build Coastguard Worker
1328*f6dc9357SAndroid Build Coastguard Worker bool CrcIsOK;
1329*f6dc9357SAndroid Build Coastguard Worker };
1330*f6dc9357SAndroid Build Coastguard Worker
1331*f6dc9357SAndroid Build Coastguard Worker
1332*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
1333*f6dc9357SAndroid Build Coastguard Worker {
1334*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
1335*f6dc9357SAndroid Build Coastguard Worker *processedSize = 0;
1336*f6dc9357SAndroid Build Coastguard Worker UInt32 realProcessedSize = 0;
1337*f6dc9357SAndroid Build Coastguard Worker
1338*f6dc9357SAndroid Build Coastguard Worker while (size != 0)
1339*f6dc9357SAndroid Build Coastguard Worker {
1340*f6dc9357SAndroid Build Coastguard Worker if (!_stream)
1341*f6dc9357SAndroid Build Coastguard Worker {
1342*f6dc9357SAndroid Build Coastguard Worker if (_curIndex >= _refItem.NumItems)
1343*f6dc9357SAndroid Build Coastguard Worker break;
1344*f6dc9357SAndroid Build Coastguard Worker const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
1345*f6dc9357SAndroid Build Coastguard Worker unsigned volIndex = _refItem.VolumeIndex + _curIndex;
1346*f6dc9357SAndroid Build Coastguard Worker if (volIndex >= _arcs->Size())
1347*f6dc9357SAndroid Build Coastguard Worker {
1348*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1349*f6dc9357SAndroid Build Coastguard Worker // return S_FALSE;
1350*f6dc9357SAndroid Build Coastguard Worker }
1351*f6dc9357SAndroid Build Coastguard Worker IInStream *s = (*_arcs)[volIndex].Stream;
1352*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(s, item.GetDataPosition()))
1353*f6dc9357SAndroid Build Coastguard Worker _stream = s;
1354*f6dc9357SAndroid Build Coastguard Worker _calcCrc = (CrcIsOK && item.IsSplitAfter());
1355*f6dc9357SAndroid Build Coastguard Worker _crc = CRC_INIT_VAL;
1356*f6dc9357SAndroid Build Coastguard Worker _rem = item.PackSize;
1357*f6dc9357SAndroid Build Coastguard Worker }
1358*f6dc9357SAndroid Build Coastguard Worker {
1359*f6dc9357SAndroid Build Coastguard Worker UInt32 cur = size;
1360*f6dc9357SAndroid Build Coastguard Worker if (cur > _rem)
1361*f6dc9357SAndroid Build Coastguard Worker cur = (UInt32)_rem;
1362*f6dc9357SAndroid Build Coastguard Worker UInt32 num = cur;
1363*f6dc9357SAndroid Build Coastguard Worker HRESULT res = _stream->Read(data, cur, &cur);
1364*f6dc9357SAndroid Build Coastguard Worker if (_calcCrc)
1365*f6dc9357SAndroid Build Coastguard Worker _crc = CrcUpdate(_crc, data, cur);
1366*f6dc9357SAndroid Build Coastguard Worker realProcessedSize += cur;
1367*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
1368*f6dc9357SAndroid Build Coastguard Worker *processedSize = realProcessedSize;
1369*f6dc9357SAndroid Build Coastguard Worker data = (Byte *)data + cur;
1370*f6dc9357SAndroid Build Coastguard Worker size -= cur;
1371*f6dc9357SAndroid Build Coastguard Worker _rem -= cur;
1372*f6dc9357SAndroid Build Coastguard Worker if (_rem == 0)
1373*f6dc9357SAndroid Build Coastguard Worker {
1374*f6dc9357SAndroid Build Coastguard Worker const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
1375*f6dc9357SAndroid Build Coastguard Worker _curIndex++;
1376*f6dc9357SAndroid Build Coastguard Worker if (_calcCrc && CRC_GET_DIGEST(_crc) != item.FileCRC)
1377*f6dc9357SAndroid Build Coastguard Worker CrcIsOK = false;
1378*f6dc9357SAndroid Build Coastguard Worker _stream = NULL;
1379*f6dc9357SAndroid Build Coastguard Worker }
1380*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
1381*f6dc9357SAndroid Build Coastguard Worker return res;
1382*f6dc9357SAndroid Build Coastguard Worker if (realProcessedSize != 0)
1383*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1384*f6dc9357SAndroid Build Coastguard Worker if (cur == 0 && num != 0)
1385*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1386*f6dc9357SAndroid Build Coastguard Worker }
1387*f6dc9357SAndroid Build Coastguard Worker }
1388*f6dc9357SAndroid Build Coastguard Worker
1389*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1390*f6dc9357SAndroid Build Coastguard Worker }
1391*f6dc9357SAndroid Build Coastguard Worker
1392*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1393*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
1394*f6dc9357SAndroid Build Coastguard Worker {
1395*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1396*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICryptoGetTextPassword> getTextPassword;
1397*f6dc9357SAndroid Build Coastguard Worker UInt64 // censoredTotalUnPacked = 0,
1398*f6dc9357SAndroid Build Coastguard Worker // censoredTotalPacked = 0,
1399*f6dc9357SAndroid Build Coastguard Worker importantTotalUnPacked = 0;
1400*f6dc9357SAndroid Build Coastguard Worker // importantTotalPacked = 0;
1401*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
1402*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
1403*f6dc9357SAndroid Build Coastguard Worker numItems = _refItems.Size();
1404*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
1405*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1406*f6dc9357SAndroid Build Coastguard Worker unsigned lastIndex = 0;
1407*f6dc9357SAndroid Build Coastguard Worker CRecordVector<unsigned> importantIndexes;
1408*f6dc9357SAndroid Build Coastguard Worker CRecordVector<bool> extractStatuses;
1409*f6dc9357SAndroid Build Coastguard Worker
1410*f6dc9357SAndroid Build Coastguard Worker bool isThereUndefinedSize = false;
1411*f6dc9357SAndroid Build Coastguard Worker
1412*f6dc9357SAndroid Build Coastguard Worker for (UInt32 t = 0; t < numItems; t++)
1413*f6dc9357SAndroid Build Coastguard Worker {
1414*f6dc9357SAndroid Build Coastguard Worker unsigned index = allFilesMode ? t : indices[t];
1415*f6dc9357SAndroid Build Coastguard Worker
1416*f6dc9357SAndroid Build Coastguard Worker {
1417*f6dc9357SAndroid Build Coastguard Worker const CRefItem &refItem = _refItems[index];
1418*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[refItem.ItemIndex + refItem.NumItems - 1];
1419*f6dc9357SAndroid Build Coastguard Worker
1420*f6dc9357SAndroid Build Coastguard Worker if (item.Is_Size_Defined())
1421*f6dc9357SAndroid Build Coastguard Worker {
1422*f6dc9357SAndroid Build Coastguard Worker // censoredTotalUnPacked += item.Size;
1423*f6dc9357SAndroid Build Coastguard Worker }
1424*f6dc9357SAndroid Build Coastguard Worker else
1425*f6dc9357SAndroid Build Coastguard Worker isThereUndefinedSize = true;
1426*f6dc9357SAndroid Build Coastguard Worker
1427*f6dc9357SAndroid Build Coastguard Worker // censoredTotalPacked += item.PackSize;
1428*f6dc9357SAndroid Build Coastguard Worker }
1429*f6dc9357SAndroid Build Coastguard Worker
1430*f6dc9357SAndroid Build Coastguard Worker unsigned j;
1431*f6dc9357SAndroid Build Coastguard Worker for (j = lastIndex; j <= index; j++)
1432*f6dc9357SAndroid Build Coastguard Worker // if (!_items[_refItems[j].ItemIndex].IsSolid())
1433*f6dc9357SAndroid Build Coastguard Worker if (!IsSolid(j))
1434*f6dc9357SAndroid Build Coastguard Worker lastIndex = j;
1435*f6dc9357SAndroid Build Coastguard Worker
1436*f6dc9357SAndroid Build Coastguard Worker for (j = lastIndex; j <= index; j++)
1437*f6dc9357SAndroid Build Coastguard Worker {
1438*f6dc9357SAndroid Build Coastguard Worker const CRefItem &refItem = _refItems[j];
1439*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[refItem.ItemIndex + refItem.NumItems - 1];
1440*f6dc9357SAndroid Build Coastguard Worker
1441*f6dc9357SAndroid Build Coastguard Worker if (item.Is_Size_Defined())
1442*f6dc9357SAndroid Build Coastguard Worker importantTotalUnPacked += item.Size;
1443*f6dc9357SAndroid Build Coastguard Worker else
1444*f6dc9357SAndroid Build Coastguard Worker isThereUndefinedSize = true;
1445*f6dc9357SAndroid Build Coastguard Worker // importantTotalPacked += item.PackSize;
1446*f6dc9357SAndroid Build Coastguard Worker importantIndexes.Add(j);
1447*f6dc9357SAndroid Build Coastguard Worker extractStatuses.Add(j == index);
1448*f6dc9357SAndroid Build Coastguard Worker }
1449*f6dc9357SAndroid Build Coastguard Worker
1450*f6dc9357SAndroid Build Coastguard Worker lastIndex = index + 1;
1451*f6dc9357SAndroid Build Coastguard Worker }
1452*f6dc9357SAndroid Build Coastguard Worker
1453*f6dc9357SAndroid Build Coastguard Worker if (importantTotalUnPacked != 0 || !isThereUndefinedSize)
1454*f6dc9357SAndroid Build Coastguard Worker {
1455*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(importantTotalUnPacked))
1456*f6dc9357SAndroid Build Coastguard Worker }
1457*f6dc9357SAndroid Build Coastguard Worker
1458*f6dc9357SAndroid Build Coastguard Worker UInt64 currentImportantTotalUnPacked = 0;
1459*f6dc9357SAndroid Build Coastguard Worker UInt64 currentImportantTotalPacked = 0;
1460*f6dc9357SAndroid Build Coastguard Worker UInt64 currentUnPackSize, currentPackSize;
1461*f6dc9357SAndroid Build Coastguard Worker
1462*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CMethodItem> methodItems;
1463*f6dc9357SAndroid Build Coastguard Worker
1464*f6dc9357SAndroid Build Coastguard Worker NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
1465*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
1466*f6dc9357SAndroid Build Coastguard Worker
1467*f6dc9357SAndroid Build Coastguard Worker CFilterCoder *filterStreamSpec = new CFilterCoder(false);
1468*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
1469*f6dc9357SAndroid Build Coastguard Worker
1470*f6dc9357SAndroid Build Coastguard Worker NCrypto::NRar2::CDecoder *rar20CryptoDecoderSpec = NULL;
1471*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressFilter> rar20CryptoDecoder;
1472*f6dc9357SAndroid Build Coastguard Worker NCrypto::NRar3::CDecoder *rar3CryptoDecoderSpec = NULL;
1473*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressFilter> rar3CryptoDecoder;
1474*f6dc9357SAndroid Build Coastguard Worker
1475*f6dc9357SAndroid Build Coastguard Worker CVolsInStream *volsInStreamSpec = NULL;
1476*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> volsInStream;
1477*f6dc9357SAndroid Build Coastguard Worker
1478*f6dc9357SAndroid Build Coastguard Worker CLocalProgress *lps = new CLocalProgress;
1479*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressProgressInfo> progress = lps;
1480*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
1481*f6dc9357SAndroid Build Coastguard Worker
1482*f6dc9357SAndroid Build Coastguard Worker bool solidStart = true;
1483*f6dc9357SAndroid Build Coastguard Worker
1484*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0;;
1485*f6dc9357SAndroid Build Coastguard Worker i++,
1486*f6dc9357SAndroid Build Coastguard Worker currentImportantTotalUnPacked += currentUnPackSize,
1487*f6dc9357SAndroid Build Coastguard Worker currentImportantTotalPacked += currentPackSize)
1488*f6dc9357SAndroid Build Coastguard Worker {
1489*f6dc9357SAndroid Build Coastguard Worker lps->InSize = currentImportantTotalPacked;
1490*f6dc9357SAndroid Build Coastguard Worker lps->OutSize = currentImportantTotalUnPacked;
1491*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
1492*f6dc9357SAndroid Build Coastguard Worker
1493*f6dc9357SAndroid Build Coastguard Worker if (i >= importantIndexes.Size())
1494*f6dc9357SAndroid Build Coastguard Worker break;
1495*f6dc9357SAndroid Build Coastguard Worker
1496*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
1497*f6dc9357SAndroid Build Coastguard Worker
1498*f6dc9357SAndroid Build Coastguard Worker Int32 askMode;
1499*f6dc9357SAndroid Build Coastguard Worker if (extractStatuses[i])
1500*f6dc9357SAndroid Build Coastguard Worker askMode = testMode ?
1501*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
1502*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
1503*f6dc9357SAndroid Build Coastguard Worker else
1504*f6dc9357SAndroid Build Coastguard Worker askMode = NExtract::NAskMode::kSkip;
1505*f6dc9357SAndroid Build Coastguard Worker
1506*f6dc9357SAndroid Build Coastguard Worker UInt32 index = importantIndexes[i];
1507*f6dc9357SAndroid Build Coastguard Worker
1508*f6dc9357SAndroid Build Coastguard Worker const CRefItem &refItem = _refItems[index];
1509*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[refItem.ItemIndex];
1510*f6dc9357SAndroid Build Coastguard Worker const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
1511*f6dc9357SAndroid Build Coastguard Worker
1512*f6dc9357SAndroid Build Coastguard Worker UInt64 outSize = (UInt64)(Int64)-1;
1513*f6dc9357SAndroid Build Coastguard Worker currentUnPackSize = 0;
1514*f6dc9357SAndroid Build Coastguard Worker if (lastItem.Is_Size_Defined())
1515*f6dc9357SAndroid Build Coastguard Worker {
1516*f6dc9357SAndroid Build Coastguard Worker outSize = lastItem.Size;
1517*f6dc9357SAndroid Build Coastguard Worker currentUnPackSize = outSize;
1518*f6dc9357SAndroid Build Coastguard Worker }
1519*f6dc9357SAndroid Build Coastguard Worker
1520*f6dc9357SAndroid Build Coastguard Worker currentPackSize = GetPackSize(index);
1521*f6dc9357SAndroid Build Coastguard Worker
1522*f6dc9357SAndroid Build Coastguard Worker if (item.IgnoreItem())
1523*f6dc9357SAndroid Build Coastguard Worker continue;
1524*f6dc9357SAndroid Build Coastguard Worker
1525*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
1526*f6dc9357SAndroid Build Coastguard Worker
1527*f6dc9357SAndroid Build Coastguard Worker if (!IsSolid(index))
1528*f6dc9357SAndroid Build Coastguard Worker solidStart = true;
1529*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir())
1530*f6dc9357SAndroid Build Coastguard Worker {
1531*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
1532*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
1533*f6dc9357SAndroid Build Coastguard Worker continue;
1534*f6dc9357SAndroid Build Coastguard Worker }
1535*f6dc9357SAndroid Build Coastguard Worker
1536*f6dc9357SAndroid Build Coastguard Worker bool mustBeProcessedAnywhere = false;
1537*f6dc9357SAndroid Build Coastguard Worker if (i < importantIndexes.Size() - 1)
1538*f6dc9357SAndroid Build Coastguard Worker {
1539*f6dc9357SAndroid Build Coastguard Worker // const CRefItem &nextRefItem = _refItems[importantIndexes[i + 1]];
1540*f6dc9357SAndroid Build Coastguard Worker // const CItem &nextItemInfo = _items[nextRefItem.ItemIndex];
1541*f6dc9357SAndroid Build Coastguard Worker // mustBeProcessedAnywhere = nextItemInfo.IsSolid();
1542*f6dc9357SAndroid Build Coastguard Worker mustBeProcessedAnywhere = IsSolid(importantIndexes[i + 1]);
1543*f6dc9357SAndroid Build Coastguard Worker }
1544*f6dc9357SAndroid Build Coastguard Worker
1545*f6dc9357SAndroid Build Coastguard Worker if (!mustBeProcessedAnywhere && !testMode && !realOutStream)
1546*f6dc9357SAndroid Build Coastguard Worker continue;
1547*f6dc9357SAndroid Build Coastguard Worker
1548*f6dc9357SAndroid Build Coastguard Worker if (!realOutStream && !testMode)
1549*f6dc9357SAndroid Build Coastguard Worker askMode = NExtract::NAskMode::kSkip;
1550*f6dc9357SAndroid Build Coastguard Worker
1551*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
1552*f6dc9357SAndroid Build Coastguard Worker
1553*f6dc9357SAndroid Build Coastguard Worker COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
1554*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
1555*f6dc9357SAndroid Build Coastguard Worker outStreamSpec->SetStream(realOutStream);
1556*f6dc9357SAndroid Build Coastguard Worker outStreamSpec->Init();
1557*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release();
1558*f6dc9357SAndroid Build Coastguard Worker
1559*f6dc9357SAndroid Build Coastguard Worker if (!volsInStream)
1560*f6dc9357SAndroid Build Coastguard Worker {
1561*f6dc9357SAndroid Build Coastguard Worker volsInStreamSpec = new CVolsInStream;
1562*f6dc9357SAndroid Build Coastguard Worker volsInStream = volsInStreamSpec;
1563*f6dc9357SAndroid Build Coastguard Worker }
1564*f6dc9357SAndroid Build Coastguard Worker
1565*f6dc9357SAndroid Build Coastguard Worker volsInStreamSpec->Init(&_arcs, &_items, refItem);
1566*f6dc9357SAndroid Build Coastguard Worker
1567*f6dc9357SAndroid Build Coastguard Worker UInt64 packSize = currentPackSize;
1568*f6dc9357SAndroid Build Coastguard Worker
1569*f6dc9357SAndroid Build Coastguard Worker // packedPos += item.PackSize;
1570*f6dc9357SAndroid Build Coastguard Worker // unpackedPos += 0;
1571*f6dc9357SAndroid Build Coastguard Worker
1572*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> inStream;
1573*f6dc9357SAndroid Build Coastguard Worker
1574*f6dc9357SAndroid Build Coastguard Worker if (item.IsEncrypted())
1575*f6dc9357SAndroid Build Coastguard Worker {
1576*f6dc9357SAndroid Build Coastguard Worker // CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
1577*f6dc9357SAndroid Build Coastguard Worker
1578*f6dc9357SAndroid Build Coastguard Worker if (item.UnPackVersion >= 29)
1579*f6dc9357SAndroid Build Coastguard Worker {
1580*f6dc9357SAndroid Build Coastguard Worker if (!rar3CryptoDecoder)
1581*f6dc9357SAndroid Build Coastguard Worker {
1582*f6dc9357SAndroid Build Coastguard Worker rar3CryptoDecoderSpec = new NCrypto::NRar3::CDecoder;
1583*f6dc9357SAndroid Build Coastguard Worker rar3CryptoDecoder = rar3CryptoDecoderSpec;
1584*f6dc9357SAndroid Build Coastguard Worker }
1585*f6dc9357SAndroid Build Coastguard Worker // rar3CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
1586*f6dc9357SAndroid Build Coastguard Worker /*
1587*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
1588*f6dc9357SAndroid Build Coastguard Worker RINOK(rar3CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
1589*f6dc9357SAndroid Build Coastguard Worker &cryptoProperties));
1590*f6dc9357SAndroid Build Coastguard Worker */
1591*f6dc9357SAndroid Build Coastguard Worker RINOK(rar3CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0))
1592*f6dc9357SAndroid Build Coastguard Worker filterStreamSpec->Filter = rar3CryptoDecoder;
1593*f6dc9357SAndroid Build Coastguard Worker }
1594*f6dc9357SAndroid Build Coastguard Worker else if (item.UnPackVersion >= 20)
1595*f6dc9357SAndroid Build Coastguard Worker {
1596*f6dc9357SAndroid Build Coastguard Worker if (!rar20CryptoDecoder)
1597*f6dc9357SAndroid Build Coastguard Worker {
1598*f6dc9357SAndroid Build Coastguard Worker rar20CryptoDecoderSpec = new NCrypto::NRar2::CDecoder;
1599*f6dc9357SAndroid Build Coastguard Worker rar20CryptoDecoder = rar20CryptoDecoderSpec;
1600*f6dc9357SAndroid Build Coastguard Worker }
1601*f6dc9357SAndroid Build Coastguard Worker filterStreamSpec->Filter = rar20CryptoDecoder;
1602*f6dc9357SAndroid Build Coastguard Worker }
1603*f6dc9357SAndroid Build Coastguard Worker else
1604*f6dc9357SAndroid Build Coastguard Worker {
1605*f6dc9357SAndroid Build Coastguard Worker outStream.Release();
1606*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))
1607*f6dc9357SAndroid Build Coastguard Worker continue;
1608*f6dc9357SAndroid Build Coastguard Worker }
1609*f6dc9357SAndroid Build Coastguard Worker
1610*f6dc9357SAndroid Build Coastguard Worker // RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
1611*f6dc9357SAndroid Build Coastguard Worker
1612*f6dc9357SAndroid Build Coastguard Worker if (!getTextPassword)
1613*f6dc9357SAndroid Build Coastguard Worker extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
1614*f6dc9357SAndroid Build Coastguard Worker
1615*f6dc9357SAndroid Build Coastguard Worker if (!getTextPassword)
1616*f6dc9357SAndroid Build Coastguard Worker {
1617*f6dc9357SAndroid Build Coastguard Worker outStream.Release();
1618*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))
1619*f6dc9357SAndroid Build Coastguard Worker continue;
1620*f6dc9357SAndroid Build Coastguard Worker }
1621*f6dc9357SAndroid Build Coastguard Worker
1622*f6dc9357SAndroid Build Coastguard Worker // if (getTextPassword)
1623*f6dc9357SAndroid Build Coastguard Worker {
1624*f6dc9357SAndroid Build Coastguard Worker CMyComBSTR_Wipe password;
1625*f6dc9357SAndroid Build Coastguard Worker RINOK(getTextPassword->CryptoGetTextPassword(&password))
1626*f6dc9357SAndroid Build Coastguard Worker
1627*f6dc9357SAndroid Build Coastguard Worker if (item.UnPackVersion >= 29)
1628*f6dc9357SAndroid Build Coastguard Worker {
1629*f6dc9357SAndroid Build Coastguard Worker unsigned len = 0;
1630*f6dc9357SAndroid Build Coastguard Worker if (password)
1631*f6dc9357SAndroid Build Coastguard Worker len = MyStringLen(password);
1632*f6dc9357SAndroid Build Coastguard Worker if (len > kPasswordLen_MAX)
1633*f6dc9357SAndroid Build Coastguard Worker len = kPasswordLen_MAX;
1634*f6dc9357SAndroid Build Coastguard Worker CByteBuffer_Wipe buffer(len * 2);
1635*f6dc9357SAndroid Build Coastguard Worker for (unsigned k = 0; k < len; k++)
1636*f6dc9357SAndroid Build Coastguard Worker {
1637*f6dc9357SAndroid Build Coastguard Worker wchar_t c = password[k];
1638*f6dc9357SAndroid Build Coastguard Worker ((Byte *)buffer)[k * 2] = (Byte)c;
1639*f6dc9357SAndroid Build Coastguard Worker ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8);
1640*f6dc9357SAndroid Build Coastguard Worker }
1641*f6dc9357SAndroid Build Coastguard Worker rar3CryptoDecoderSpec->SetPassword((const Byte *)buffer, len * 2);
1642*f6dc9357SAndroid Build Coastguard Worker }
1643*f6dc9357SAndroid Build Coastguard Worker else
1644*f6dc9357SAndroid Build Coastguard Worker {
1645*f6dc9357SAndroid Build Coastguard Worker AString_Wipe oemPassword;
1646*f6dc9357SAndroid Build Coastguard Worker if (password)
1647*f6dc9357SAndroid Build Coastguard Worker {
1648*f6dc9357SAndroid Build Coastguard Worker UString_Wipe unicode;
1649*f6dc9357SAndroid Build Coastguard Worker unicode.SetFromBstr(password);
1650*f6dc9357SAndroid Build Coastguard Worker if (unicode.Len() > kPasswordLen_MAX)
1651*f6dc9357SAndroid Build Coastguard Worker unicode.DeleteFrom(kPasswordLen_MAX);
1652*f6dc9357SAndroid Build Coastguard Worker UnicodeStringToMultiByte2(oemPassword, unicode, CP_OEMCP);
1653*f6dc9357SAndroid Build Coastguard Worker }
1654*f6dc9357SAndroid Build Coastguard Worker rar20CryptoDecoderSpec->SetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len());
1655*f6dc9357SAndroid Build Coastguard Worker }
1656*f6dc9357SAndroid Build Coastguard Worker }
1657*f6dc9357SAndroid Build Coastguard Worker /*
1658*f6dc9357SAndroid Build Coastguard Worker else
1659*f6dc9357SAndroid Build Coastguard Worker {
1660*f6dc9357SAndroid Build Coastguard Worker RINOK(cryptoSetPassword->CryptoSetPassword(NULL, 0));
1661*f6dc9357SAndroid Build Coastguard Worker }
1662*f6dc9357SAndroid Build Coastguard Worker */
1663*f6dc9357SAndroid Build Coastguard Worker
1664*f6dc9357SAndroid Build Coastguard Worker filterStreamSpec->SetInStream(volsInStream);
1665*f6dc9357SAndroid Build Coastguard Worker filterStreamSpec->SetOutStreamSize(NULL);
1666*f6dc9357SAndroid Build Coastguard Worker inStream = filterStream;
1667*f6dc9357SAndroid Build Coastguard Worker }
1668*f6dc9357SAndroid Build Coastguard Worker else
1669*f6dc9357SAndroid Build Coastguard Worker {
1670*f6dc9357SAndroid Build Coastguard Worker inStream = volsInStream;
1671*f6dc9357SAndroid Build Coastguard Worker }
1672*f6dc9357SAndroid Build Coastguard Worker
1673*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressCoder> commonCoder;
1674*f6dc9357SAndroid Build Coastguard Worker
1675*f6dc9357SAndroid Build Coastguard Worker switch (item.Method)
1676*f6dc9357SAndroid Build Coastguard Worker {
1677*f6dc9357SAndroid Build Coastguard Worker case '0':
1678*f6dc9357SAndroid Build Coastguard Worker {
1679*f6dc9357SAndroid Build Coastguard Worker commonCoder = copyCoder;
1680*f6dc9357SAndroid Build Coastguard Worker break;
1681*f6dc9357SAndroid Build Coastguard Worker }
1682*f6dc9357SAndroid Build Coastguard Worker case '1':
1683*f6dc9357SAndroid Build Coastguard Worker case '2':
1684*f6dc9357SAndroid Build Coastguard Worker case '3':
1685*f6dc9357SAndroid Build Coastguard Worker case '4':
1686*f6dc9357SAndroid Build Coastguard Worker case '5':
1687*f6dc9357SAndroid Build Coastguard Worker {
1688*f6dc9357SAndroid Build Coastguard Worker unsigned m;
1689*f6dc9357SAndroid Build Coastguard Worker for (m = 0; m < methodItems.Size(); m++)
1690*f6dc9357SAndroid Build Coastguard Worker if (methodItems[m].RarUnPackVersion == item.UnPackVersion)
1691*f6dc9357SAndroid Build Coastguard Worker break;
1692*f6dc9357SAndroid Build Coastguard Worker if (m == methodItems.Size())
1693*f6dc9357SAndroid Build Coastguard Worker {
1694*f6dc9357SAndroid Build Coastguard Worker CMethodItem mi;
1695*f6dc9357SAndroid Build Coastguard Worker mi.RarUnPackVersion = item.UnPackVersion;
1696*f6dc9357SAndroid Build Coastguard Worker
1697*f6dc9357SAndroid Build Coastguard Worker mi.Coder.Release();
1698*f6dc9357SAndroid Build Coastguard Worker if (item.UnPackVersion <= 40)
1699*f6dc9357SAndroid Build Coastguard Worker {
1700*f6dc9357SAndroid Build Coastguard Worker UInt32 methodID = 0x40300;
1701*f6dc9357SAndroid Build Coastguard Worker if (item.UnPackVersion < 20)
1702*f6dc9357SAndroid Build Coastguard Worker methodID += 1;
1703*f6dc9357SAndroid Build Coastguard Worker else if (item.UnPackVersion < 29)
1704*f6dc9357SAndroid Build Coastguard Worker methodID += 2;
1705*f6dc9357SAndroid Build Coastguard Worker else
1706*f6dc9357SAndroid Build Coastguard Worker methodID += 3;
1707*f6dc9357SAndroid Build Coastguard Worker RINOK(CreateCoder_Id(EXTERNAL_CODECS_VARS methodID, false, mi.Coder))
1708*f6dc9357SAndroid Build Coastguard Worker }
1709*f6dc9357SAndroid Build Coastguard Worker
1710*f6dc9357SAndroid Build Coastguard Worker if (!mi.Coder)
1711*f6dc9357SAndroid Build Coastguard Worker {
1712*f6dc9357SAndroid Build Coastguard Worker outStream.Release();
1713*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))
1714*f6dc9357SAndroid Build Coastguard Worker continue;
1715*f6dc9357SAndroid Build Coastguard Worker }
1716*f6dc9357SAndroid Build Coastguard Worker
1717*f6dc9357SAndroid Build Coastguard Worker m = methodItems.Add(mi);
1718*f6dc9357SAndroid Build Coastguard Worker }
1719*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressCoder> decoder = methodItems[m].Coder;
1720*f6dc9357SAndroid Build Coastguard Worker
1721*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;
1722*f6dc9357SAndroid Build Coastguard Worker RINOK(decoder.QueryInterface(IID_ICompressSetDecoderProperties2,
1723*f6dc9357SAndroid Build Coastguard Worker &compressSetDecoderProperties))
1724*f6dc9357SAndroid Build Coastguard Worker
1725*f6dc9357SAndroid Build Coastguard Worker Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);
1726*f6dc9357SAndroid Build Coastguard Worker if (solidStart)
1727*f6dc9357SAndroid Build Coastguard Worker {
1728*f6dc9357SAndroid Build Coastguard Worker isSolid = 0;
1729*f6dc9357SAndroid Build Coastguard Worker solidStart = false;
1730*f6dc9357SAndroid Build Coastguard Worker }
1731*f6dc9357SAndroid Build Coastguard Worker
1732*f6dc9357SAndroid Build Coastguard Worker
1733*f6dc9357SAndroid Build Coastguard Worker RINOK(compressSetDecoderProperties->SetDecoderProperties2(&isSolid, 1))
1734*f6dc9357SAndroid Build Coastguard Worker
1735*f6dc9357SAndroid Build Coastguard Worker commonCoder = decoder;
1736*f6dc9357SAndroid Build Coastguard Worker break;
1737*f6dc9357SAndroid Build Coastguard Worker }
1738*f6dc9357SAndroid Build Coastguard Worker default:
1739*f6dc9357SAndroid Build Coastguard Worker outStream.Release();
1740*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))
1741*f6dc9357SAndroid Build Coastguard Worker continue;
1742*f6dc9357SAndroid Build Coastguard Worker }
1743*f6dc9357SAndroid Build Coastguard Worker
1744*f6dc9357SAndroid Build Coastguard Worker HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &outSize, progress);
1745*f6dc9357SAndroid Build Coastguard Worker
1746*f6dc9357SAndroid Build Coastguard Worker if (item.IsEncrypted())
1747*f6dc9357SAndroid Build Coastguard Worker filterStreamSpec->ReleaseInStream();
1748*f6dc9357SAndroid Build Coastguard Worker
1749*f6dc9357SAndroid Build Coastguard Worker if (outSize == (UInt64)(Int64)-1)
1750*f6dc9357SAndroid Build Coastguard Worker currentUnPackSize = outStreamSpec->GetSize();
1751*f6dc9357SAndroid Build Coastguard Worker
1752*f6dc9357SAndroid Build Coastguard Worker int opRes = (volsInStreamSpec->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ?
1753*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kOK:
1754*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kCRCError;
1755*f6dc9357SAndroid Build Coastguard Worker outStream.Release();
1756*f6dc9357SAndroid Build Coastguard Worker
1757*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK)
1758*f6dc9357SAndroid Build Coastguard Worker {
1759*f6dc9357SAndroid Build Coastguard Worker if (result == S_FALSE)
1760*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError;
1761*f6dc9357SAndroid Build Coastguard Worker else if (result == E_NOTIMPL)
1762*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kUnsupportedMethod;
1763*f6dc9357SAndroid Build Coastguard Worker else
1764*f6dc9357SAndroid Build Coastguard Worker return result;
1765*f6dc9357SAndroid Build Coastguard Worker }
1766*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(opRes))
1767*f6dc9357SAndroid Build Coastguard Worker }
1768*f6dc9357SAndroid Build Coastguard Worker
1769*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1770*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1771*f6dc9357SAndroid Build Coastguard Worker }
1772*f6dc9357SAndroid Build Coastguard Worker
1773*f6dc9357SAndroid Build Coastguard Worker IMPL_ISetCompressCodecsInfo
1774*f6dc9357SAndroid Build Coastguard Worker
1775*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
1776*f6dc9357SAndroid Build Coastguard Worker "Rar", "rar r00", NULL, 3,
1777*f6dc9357SAndroid Build Coastguard Worker kMarker,
1778*f6dc9357SAndroid Build Coastguard Worker 0,
1779*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kFindSignature,
1780*f6dc9357SAndroid Build Coastguard Worker NULL)
1781*f6dc9357SAndroid Build Coastguard Worker
1782*f6dc9357SAndroid Build Coastguard Worker }}
1783