xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Rar/RarHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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