xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/Common/HashCalc.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // HashCalc.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/Alloc.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/DynLimBuf.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/IntToString.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringToInt.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/FileStreams.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ProgressUtils.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamObjects.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
16*f6dc9357SAndroid Build Coastguard Worker 
17*f6dc9357SAndroid Build Coastguard Worker #include "../../Archive/Common/ItemNameUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../../Archive/IArchive.h"
19*f6dc9357SAndroid Build Coastguard Worker 
20*f6dc9357SAndroid Build Coastguard Worker #include "EnumDirItems.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "HashCalc.h"
22*f6dc9357SAndroid Build Coastguard Worker 
23*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
24*f6dc9357SAndroid Build Coastguard Worker 
25*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_EXTERNAL_CODECS
26*f6dc9357SAndroid Build Coastguard Worker extern const CExternalCodecs *g_ExternalCodecs_Ptr;
27*f6dc9357SAndroid Build Coastguard Worker #endif
28*f6dc9357SAndroid Build Coastguard Worker 
29*f6dc9357SAndroid Build Coastguard Worker class CHashMidBuf
30*f6dc9357SAndroid Build Coastguard Worker {
31*f6dc9357SAndroid Build Coastguard Worker   void *_data;
32*f6dc9357SAndroid Build Coastguard Worker public:
CHashMidBuf()33*f6dc9357SAndroid Build Coastguard Worker   CHashMidBuf(): _data(NULL) {}
operator void*()34*f6dc9357SAndroid Build Coastguard Worker   operator void *() { return _data; }
Alloc(size_t size)35*f6dc9357SAndroid Build Coastguard Worker   bool Alloc(size_t size)
36*f6dc9357SAndroid Build Coastguard Worker   {
37*f6dc9357SAndroid Build Coastguard Worker     if (_data)
38*f6dc9357SAndroid Build Coastguard Worker       return false;
39*f6dc9357SAndroid Build Coastguard Worker     _data = ::MidAlloc(size);
40*f6dc9357SAndroid Build Coastguard Worker     return _data != NULL;
41*f6dc9357SAndroid Build Coastguard Worker   }
~CHashMidBuf()42*f6dc9357SAndroid Build Coastguard Worker   ~CHashMidBuf() { ::MidFree(_data); }
43*f6dc9357SAndroid Build Coastguard Worker };
44*f6dc9357SAndroid Build Coastguard Worker 
45*f6dc9357SAndroid Build Coastguard Worker static const char * const k_DefaultHashMethod = "CRC32";
46*f6dc9357SAndroid Build Coastguard Worker 
SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector & hashMethods)47*f6dc9357SAndroid Build Coastguard Worker HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods)
48*f6dc9357SAndroid Build Coastguard Worker {
49*f6dc9357SAndroid Build Coastguard Worker   UStringVector names = hashMethods;
50*f6dc9357SAndroid Build Coastguard Worker   if (names.IsEmpty())
51*f6dc9357SAndroid Build Coastguard Worker     names.Add(UString(k_DefaultHashMethod));
52*f6dc9357SAndroid Build Coastguard Worker 
53*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<CMethodId> ids;
54*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<COneMethodInfo> methods;
55*f6dc9357SAndroid Build Coastguard Worker 
56*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
57*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < names.Size(); i++)
58*f6dc9357SAndroid Build Coastguard Worker   {
59*f6dc9357SAndroid Build Coastguard Worker     COneMethodInfo m;
60*f6dc9357SAndroid Build Coastguard Worker     RINOK(m.ParseMethodFromString(names[i]))
61*f6dc9357SAndroid Build Coastguard Worker 
62*f6dc9357SAndroid Build Coastguard Worker     if (m.MethodName.IsEmpty())
63*f6dc9357SAndroid Build Coastguard Worker       m.MethodName = k_DefaultHashMethod;
64*f6dc9357SAndroid Build Coastguard Worker 
65*f6dc9357SAndroid Build Coastguard Worker     if (m.MethodName == "*")
66*f6dc9357SAndroid Build Coastguard Worker     {
67*f6dc9357SAndroid Build Coastguard Worker       CRecordVector<CMethodId> tempMethods;
68*f6dc9357SAndroid Build Coastguard Worker       GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods);
69*f6dc9357SAndroid Build Coastguard Worker       methods.Clear();
70*f6dc9357SAndroid Build Coastguard Worker       ids.Clear();
71*f6dc9357SAndroid Build Coastguard Worker       FOR_VECTOR (t, tempMethods)
72*f6dc9357SAndroid Build Coastguard Worker       {
73*f6dc9357SAndroid Build Coastguard Worker         unsigned index = ids.AddToUniqueSorted(tempMethods[t]);
74*f6dc9357SAndroid Build Coastguard Worker         if (ids.Size() != methods.Size())
75*f6dc9357SAndroid Build Coastguard Worker           methods.Insert(index, m);
76*f6dc9357SAndroid Build Coastguard Worker       }
77*f6dc9357SAndroid Build Coastguard Worker       break;
78*f6dc9357SAndroid Build Coastguard Worker     }
79*f6dc9357SAndroid Build Coastguard Worker     else
80*f6dc9357SAndroid Build Coastguard Worker     {
81*f6dc9357SAndroid Build Coastguard Worker       // m.MethodName.RemoveChar(L'-');
82*f6dc9357SAndroid Build Coastguard Worker       CMethodId id;
83*f6dc9357SAndroid Build Coastguard Worker       if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id))
84*f6dc9357SAndroid Build Coastguard Worker         return E_NOTIMPL;
85*f6dc9357SAndroid Build Coastguard Worker       unsigned index = ids.AddToUniqueSorted(id);
86*f6dc9357SAndroid Build Coastguard Worker       if (ids.Size() != methods.Size())
87*f6dc9357SAndroid Build Coastguard Worker         methods.Insert(index, m);
88*f6dc9357SAndroid Build Coastguard Worker     }
89*f6dc9357SAndroid Build Coastguard Worker   }
90*f6dc9357SAndroid Build Coastguard Worker 
91*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < ids.Size(); i++)
92*f6dc9357SAndroid Build Coastguard Worker   {
93*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<IHasher> hasher;
94*f6dc9357SAndroid Build Coastguard Worker     AString name;
95*f6dc9357SAndroid Build Coastguard Worker     RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher))
96*f6dc9357SAndroid Build Coastguard Worker     if (!hasher)
97*f6dc9357SAndroid Build Coastguard Worker       throw "Can't create hasher";
98*f6dc9357SAndroid Build Coastguard Worker     const COneMethodInfo &m = methods[i];
99*f6dc9357SAndroid Build Coastguard Worker     {
100*f6dc9357SAndroid Build Coastguard Worker       CMyComPtr<ICompressSetCoderProperties> scp;
101*f6dc9357SAndroid Build Coastguard Worker       hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp);
102*f6dc9357SAndroid Build Coastguard Worker       if (scp)
103*f6dc9357SAndroid Build Coastguard Worker         RINOK(m.SetCoderProps(scp, NULL))
104*f6dc9357SAndroid Build Coastguard Worker     }
105*f6dc9357SAndroid Build Coastguard Worker     const UInt32 digestSize = hasher->GetDigestSize();
106*f6dc9357SAndroid Build Coastguard Worker     if (digestSize > k_HashCalc_DigestSize_Max)
107*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
108*f6dc9357SAndroid Build Coastguard Worker     CHasherState &h = Hashers.AddNew();
109*f6dc9357SAndroid Build Coastguard Worker     h.DigestSize = digestSize;
110*f6dc9357SAndroid Build Coastguard Worker     h.Hasher = hasher;
111*f6dc9357SAndroid Build Coastguard Worker     h.Name = name;
112*f6dc9357SAndroid Build Coastguard Worker     for (unsigned k = 0; k < k_HashCalc_NumGroups; k++)
113*f6dc9357SAndroid Build Coastguard Worker       h.InitDigestGroup(k);
114*f6dc9357SAndroid Build Coastguard Worker   }
115*f6dc9357SAndroid Build Coastguard Worker 
116*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
117*f6dc9357SAndroid Build Coastguard Worker }
118*f6dc9357SAndroid Build Coastguard Worker 
InitForNewFile()119*f6dc9357SAndroid Build Coastguard Worker void CHashBundle::InitForNewFile()
120*f6dc9357SAndroid Build Coastguard Worker {
121*f6dc9357SAndroid Build Coastguard Worker   CurSize = 0;
122*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, Hashers)
123*f6dc9357SAndroid Build Coastguard Worker   {
124*f6dc9357SAndroid Build Coastguard Worker     CHasherState &h = Hashers[i];
125*f6dc9357SAndroid Build Coastguard Worker     h.Hasher->Init();
126*f6dc9357SAndroid Build Coastguard Worker     h.InitDigestGroup(k_HashCalc_Index_Current);
127*f6dc9357SAndroid Build Coastguard Worker   }
128*f6dc9357SAndroid Build Coastguard Worker }
129*f6dc9357SAndroid Build Coastguard Worker 
Update(const void * data,UInt32 size)130*f6dc9357SAndroid Build Coastguard Worker void CHashBundle::Update(const void *data, UInt32 size)
131*f6dc9357SAndroid Build Coastguard Worker {
132*f6dc9357SAndroid Build Coastguard Worker   CurSize += size;
133*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, Hashers)
134*f6dc9357SAndroid Build Coastguard Worker     Hashers[i].Hasher->Update(data, size);
135*f6dc9357SAndroid Build Coastguard Worker }
136*f6dc9357SAndroid Build Coastguard Worker 
SetSize(UInt64 size)137*f6dc9357SAndroid Build Coastguard Worker void CHashBundle::SetSize(UInt64 size)
138*f6dc9357SAndroid Build Coastguard Worker {
139*f6dc9357SAndroid Build Coastguard Worker   CurSize = size;
140*f6dc9357SAndroid Build Coastguard Worker }
141*f6dc9357SAndroid Build Coastguard Worker 
AddDigests(Byte * dest,const Byte * src,UInt32 size)142*f6dc9357SAndroid Build Coastguard Worker static void AddDigests(Byte *dest, const Byte *src, UInt32 size)
143*f6dc9357SAndroid Build Coastguard Worker {
144*f6dc9357SAndroid Build Coastguard Worker   unsigned next = 0;
145*f6dc9357SAndroid Build Coastguard Worker   /*
146*f6dc9357SAndroid Build Coastguard Worker   // we could use big-endian addition for sha-1 and sha-256
147*f6dc9357SAndroid Build Coastguard Worker   // but another hashers are little-endian
148*f6dc9357SAndroid Build Coastguard Worker   if (size > 8)
149*f6dc9357SAndroid Build Coastguard Worker   {
150*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = size; i != 0;)
151*f6dc9357SAndroid Build Coastguard Worker     {
152*f6dc9357SAndroid Build Coastguard Worker       i--;
153*f6dc9357SAndroid Build Coastguard Worker       next += (unsigned)dest[i] + (unsigned)src[i];
154*f6dc9357SAndroid Build Coastguard Worker       dest[i] = (Byte)next;
155*f6dc9357SAndroid Build Coastguard Worker       next >>= 8;
156*f6dc9357SAndroid Build Coastguard Worker     }
157*f6dc9357SAndroid Build Coastguard Worker   }
158*f6dc9357SAndroid Build Coastguard Worker   else
159*f6dc9357SAndroid Build Coastguard Worker   */
160*f6dc9357SAndroid Build Coastguard Worker   {
161*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < size; i++)
162*f6dc9357SAndroid Build Coastguard Worker     {
163*f6dc9357SAndroid Build Coastguard Worker       next += (unsigned)dest[i] + (unsigned)src[i];
164*f6dc9357SAndroid Build Coastguard Worker       dest[i] = (Byte)next;
165*f6dc9357SAndroid Build Coastguard Worker       next >>= 8;
166*f6dc9357SAndroid Build Coastguard Worker     }
167*f6dc9357SAndroid Build Coastguard Worker   }
168*f6dc9357SAndroid Build Coastguard Worker 
169*f6dc9357SAndroid Build Coastguard Worker   // we use little-endian to store extra bytes
170*f6dc9357SAndroid Build Coastguard Worker   dest += k_HashCalc_DigestSize_Max;
171*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < k_HashCalc_ExtraSize; i++)
172*f6dc9357SAndroid Build Coastguard Worker   {
173*f6dc9357SAndroid Build Coastguard Worker     next += (unsigned)dest[i];
174*f6dc9357SAndroid Build Coastguard Worker     dest[i] = (Byte)next;
175*f6dc9357SAndroid Build Coastguard Worker     next >>= 8;
176*f6dc9357SAndroid Build Coastguard Worker   }
177*f6dc9357SAndroid Build Coastguard Worker }
178*f6dc9357SAndroid Build Coastguard Worker 
AddDigest(unsigned groupIndex,const Byte * data)179*f6dc9357SAndroid Build Coastguard Worker void CHasherState::AddDigest(unsigned groupIndex, const Byte *data)
180*f6dc9357SAndroid Build Coastguard Worker {
181*f6dc9357SAndroid Build Coastguard Worker   NumSums[groupIndex]++;
182*f6dc9357SAndroid Build Coastguard Worker   AddDigests(Digests[groupIndex], data, DigestSize);
183*f6dc9357SAndroid Build Coastguard Worker }
184*f6dc9357SAndroid Build Coastguard Worker 
Final(bool isDir,bool isAltStream,const UString & path)185*f6dc9357SAndroid Build Coastguard Worker void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path)
186*f6dc9357SAndroid Build Coastguard Worker {
187*f6dc9357SAndroid Build Coastguard Worker   if (isDir)
188*f6dc9357SAndroid Build Coastguard Worker     NumDirs++;
189*f6dc9357SAndroid Build Coastguard Worker   else if (isAltStream)
190*f6dc9357SAndroid Build Coastguard Worker   {
191*f6dc9357SAndroid Build Coastguard Worker     NumAltStreams++;
192*f6dc9357SAndroid Build Coastguard Worker     AltStreamsSize += CurSize;
193*f6dc9357SAndroid Build Coastguard Worker   }
194*f6dc9357SAndroid Build Coastguard Worker   else
195*f6dc9357SAndroid Build Coastguard Worker   {
196*f6dc9357SAndroid Build Coastguard Worker     NumFiles++;
197*f6dc9357SAndroid Build Coastguard Worker     FilesSize += CurSize;
198*f6dc9357SAndroid Build Coastguard Worker   }
199*f6dc9357SAndroid Build Coastguard Worker 
200*f6dc9357SAndroid Build Coastguard Worker   Byte pre[16];
201*f6dc9357SAndroid Build Coastguard Worker   memset(pre, 0, sizeof(pre));
202*f6dc9357SAndroid Build Coastguard Worker   if (isDir)
203*f6dc9357SAndroid Build Coastguard Worker     pre[0] = 1;
204*f6dc9357SAndroid Build Coastguard Worker 
205*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, Hashers)
206*f6dc9357SAndroid Build Coastguard Worker   {
207*f6dc9357SAndroid Build Coastguard Worker     CHasherState &h = Hashers[i];
208*f6dc9357SAndroid Build Coastguard Worker     if (!isDir)
209*f6dc9357SAndroid Build Coastguard Worker     {
210*f6dc9357SAndroid Build Coastguard Worker       h.Hasher->Final(h.Digests[0]); // k_HashCalc_Index_Current
211*f6dc9357SAndroid Build Coastguard Worker       if (!isAltStream)
212*f6dc9357SAndroid Build Coastguard Worker         h.AddDigest(k_HashCalc_Index_DataSum, h.Digests[0]);
213*f6dc9357SAndroid Build Coastguard Worker     }
214*f6dc9357SAndroid Build Coastguard Worker 
215*f6dc9357SAndroid Build Coastguard Worker     h.Hasher->Init();
216*f6dc9357SAndroid Build Coastguard Worker     h.Hasher->Update(pre, sizeof(pre));
217*f6dc9357SAndroid Build Coastguard Worker     h.Hasher->Update(h.Digests[0], h.DigestSize);
218*f6dc9357SAndroid Build Coastguard Worker 
219*f6dc9357SAndroid Build Coastguard Worker     for (unsigned k = 0; k < path.Len(); k++)
220*f6dc9357SAndroid Build Coastguard Worker     {
221*f6dc9357SAndroid Build Coastguard Worker       wchar_t c = path[k];
222*f6dc9357SAndroid Build Coastguard Worker 
223*f6dc9357SAndroid Build Coastguard Worker       // 21.04: we want same hash for linux and windows paths
224*f6dc9357SAndroid Build Coastguard Worker       #if CHAR_PATH_SEPARATOR != '/'
225*f6dc9357SAndroid Build Coastguard Worker       if (c == CHAR_PATH_SEPARATOR)
226*f6dc9357SAndroid Build Coastguard Worker         c = '/';
227*f6dc9357SAndroid Build Coastguard Worker       // if (c == (wchar_t)('\\' + 0xf000)) c = '\\'; // to debug WSL
228*f6dc9357SAndroid Build Coastguard Worker       // if (c > 0xf000 && c < 0xf080) c -= 0xf000; // to debug WSL
229*f6dc9357SAndroid Build Coastguard Worker       #endif
230*f6dc9357SAndroid Build Coastguard Worker 
231*f6dc9357SAndroid Build Coastguard Worker       Byte temp[2] = { (Byte)(c & 0xFF), (Byte)((c >> 8) & 0xFF) };
232*f6dc9357SAndroid Build Coastguard Worker       h.Hasher->Update(temp, 2);
233*f6dc9357SAndroid Build Coastguard Worker     }
234*f6dc9357SAndroid Build Coastguard Worker 
235*f6dc9357SAndroid Build Coastguard Worker     Byte tempDigest[k_HashCalc_DigestSize_Max];
236*f6dc9357SAndroid Build Coastguard Worker     h.Hasher->Final(tempDigest);
237*f6dc9357SAndroid Build Coastguard Worker     if (!isAltStream)
238*f6dc9357SAndroid Build Coastguard Worker       h.AddDigest(k_HashCalc_Index_NamesSum, tempDigest);
239*f6dc9357SAndroid Build Coastguard Worker     h.AddDigest(k_HashCalc_Index_StreamsSum, tempDigest);
240*f6dc9357SAndroid Build Coastguard Worker   }
241*f6dc9357SAndroid Build Coastguard Worker }
242*f6dc9357SAndroid Build Coastguard Worker 
243*f6dc9357SAndroid Build Coastguard Worker 
CSum_Name_OriginalToEscape(const AString & src,AString & dest)244*f6dc9357SAndroid Build Coastguard Worker static void CSum_Name_OriginalToEscape(const AString &src, AString &dest)
245*f6dc9357SAndroid Build Coastguard Worker {
246*f6dc9357SAndroid Build Coastguard Worker   dest.Empty();
247*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < src.Len();)
248*f6dc9357SAndroid Build Coastguard Worker   {
249*f6dc9357SAndroid Build Coastguard Worker     char c = src[i++];
250*f6dc9357SAndroid Build Coastguard Worker     if (c == '\n')
251*f6dc9357SAndroid Build Coastguard Worker     {
252*f6dc9357SAndroid Build Coastguard Worker       dest.Add_Char('\\');
253*f6dc9357SAndroid Build Coastguard Worker       c = 'n';
254*f6dc9357SAndroid Build Coastguard Worker     }
255*f6dc9357SAndroid Build Coastguard Worker     else if (c == '\\')
256*f6dc9357SAndroid Build Coastguard Worker       dest.Add_Char('\\');
257*f6dc9357SAndroid Build Coastguard Worker     dest.Add_Char(c);
258*f6dc9357SAndroid Build Coastguard Worker   }
259*f6dc9357SAndroid Build Coastguard Worker }
260*f6dc9357SAndroid Build Coastguard Worker 
261*f6dc9357SAndroid Build Coastguard Worker 
CSum_Name_EscapeToOriginal(const char * s,AString & dest)262*f6dc9357SAndroid Build Coastguard Worker static bool CSum_Name_EscapeToOriginal(const char *s, AString &dest)
263*f6dc9357SAndroid Build Coastguard Worker {
264*f6dc9357SAndroid Build Coastguard Worker   bool isOK = true;
265*f6dc9357SAndroid Build Coastguard Worker   dest.Empty();
266*f6dc9357SAndroid Build Coastguard Worker   for (;;)
267*f6dc9357SAndroid Build Coastguard Worker   {
268*f6dc9357SAndroid Build Coastguard Worker     char c = *s++;
269*f6dc9357SAndroid Build Coastguard Worker     if (c == 0)
270*f6dc9357SAndroid Build Coastguard Worker       break;
271*f6dc9357SAndroid Build Coastguard Worker     if (c == '\\')
272*f6dc9357SAndroid Build Coastguard Worker     {
273*f6dc9357SAndroid Build Coastguard Worker       const char c1 = *s;
274*f6dc9357SAndroid Build Coastguard Worker       if (c1 == 'n')
275*f6dc9357SAndroid Build Coastguard Worker       {
276*f6dc9357SAndroid Build Coastguard Worker         c = '\n';
277*f6dc9357SAndroid Build Coastguard Worker         s++;
278*f6dc9357SAndroid Build Coastguard Worker       }
279*f6dc9357SAndroid Build Coastguard Worker       else if (c1 == '\\')
280*f6dc9357SAndroid Build Coastguard Worker       {
281*f6dc9357SAndroid Build Coastguard Worker         c = c1;
282*f6dc9357SAndroid Build Coastguard Worker         s++;
283*f6dc9357SAndroid Build Coastguard Worker       }
284*f6dc9357SAndroid Build Coastguard Worker       else
285*f6dc9357SAndroid Build Coastguard Worker       {
286*f6dc9357SAndroid Build Coastguard Worker         // original md5sum returns NULL for such bad strings
287*f6dc9357SAndroid Build Coastguard Worker         isOK = false;
288*f6dc9357SAndroid Build Coastguard Worker       }
289*f6dc9357SAndroid Build Coastguard Worker     }
290*f6dc9357SAndroid Build Coastguard Worker     dest.Add_Char(c);
291*f6dc9357SAndroid Build Coastguard Worker   }
292*f6dc9357SAndroid Build Coastguard Worker   return isOK;
293*f6dc9357SAndroid Build Coastguard Worker }
294*f6dc9357SAndroid Build Coastguard Worker 
295*f6dc9357SAndroid Build Coastguard Worker 
296*f6dc9357SAndroid Build Coastguard Worker 
SetSpacesAndNul(char * s,unsigned num)297*f6dc9357SAndroid Build Coastguard Worker static void SetSpacesAndNul(char *s, unsigned num)
298*f6dc9357SAndroid Build Coastguard Worker {
299*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < num; i++)
300*f6dc9357SAndroid Build Coastguard Worker     s[i] = ' ';
301*f6dc9357SAndroid Build Coastguard Worker   s[num] = 0;
302*f6dc9357SAndroid Build Coastguard Worker }
303*f6dc9357SAndroid Build Coastguard Worker 
304*f6dc9357SAndroid Build Coastguard Worker static const unsigned kHashColumnWidth_Min = 4 * 2;
305*f6dc9357SAndroid Build Coastguard Worker 
GetColumnWidth(unsigned digestSize)306*f6dc9357SAndroid Build Coastguard Worker static unsigned GetColumnWidth(unsigned digestSize)
307*f6dc9357SAndroid Build Coastguard Worker {
308*f6dc9357SAndroid Build Coastguard Worker   const unsigned width = digestSize * 2;
309*f6dc9357SAndroid Build Coastguard Worker   return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width;
310*f6dc9357SAndroid Build Coastguard Worker }
311*f6dc9357SAndroid Build Coastguard Worker 
312*f6dc9357SAndroid Build Coastguard Worker 
AddHashResultLine(AString & _s,const CObjectVector<CHasherState> & hashers)313*f6dc9357SAndroid Build Coastguard Worker static void AddHashResultLine(
314*f6dc9357SAndroid Build Coastguard Worker     AString &_s,
315*f6dc9357SAndroid Build Coastguard Worker     // bool showHash,
316*f6dc9357SAndroid Build Coastguard Worker     // UInt64 fileSize, bool showSize,
317*f6dc9357SAndroid Build Coastguard Worker     const CObjectVector<CHasherState> &hashers
318*f6dc9357SAndroid Build Coastguard Worker     // unsigned digestIndex, = k_HashCalc_Index_Current
319*f6dc9357SAndroid Build Coastguard Worker     )
320*f6dc9357SAndroid Build Coastguard Worker {
321*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, hashers)
322*f6dc9357SAndroid Build Coastguard Worker   {
323*f6dc9357SAndroid Build Coastguard Worker     const CHasherState &h = hashers[i];
324*f6dc9357SAndroid Build Coastguard Worker     char s[k_HashCalc_DigestSize_Max * 2 + 64];
325*f6dc9357SAndroid Build Coastguard Worker     s[0] = 0;
326*f6dc9357SAndroid Build Coastguard Worker     // if (showHash)
327*f6dc9357SAndroid Build Coastguard Worker       HashHexToString(s, h.Digests[k_HashCalc_Index_Current], h.DigestSize);
328*f6dc9357SAndroid Build Coastguard Worker     const unsigned pos = (unsigned)strlen(s);
329*f6dc9357SAndroid Build Coastguard Worker     const int numSpaces = (int)GetColumnWidth(h.DigestSize) - (int)pos;
330*f6dc9357SAndroid Build Coastguard Worker     if (numSpaces > 0)
331*f6dc9357SAndroid Build Coastguard Worker       SetSpacesAndNul(s + pos, (unsigned)numSpaces);
332*f6dc9357SAndroid Build Coastguard Worker     if (i != 0)
333*f6dc9357SAndroid Build Coastguard Worker       _s.Add_Space();
334*f6dc9357SAndroid Build Coastguard Worker     _s += s;
335*f6dc9357SAndroid Build Coastguard Worker   }
336*f6dc9357SAndroid Build Coastguard Worker 
337*f6dc9357SAndroid Build Coastguard Worker   /*
338*f6dc9357SAndroid Build Coastguard Worker   if (showSize)
339*f6dc9357SAndroid Build Coastguard Worker   {
340*f6dc9357SAndroid Build Coastguard Worker     _s.Add_Space();
341*f6dc9357SAndroid Build Coastguard Worker     static const unsigned kSizeField_Len = 13; // same as in HashCon.cpp
342*f6dc9357SAndroid Build Coastguard Worker     char s[kSizeField_Len + 32];
343*f6dc9357SAndroid Build Coastguard Worker     char *p = s;
344*f6dc9357SAndroid Build Coastguard Worker     SetSpacesAndNul(s, kSizeField_Len);
345*f6dc9357SAndroid Build Coastguard Worker     p = s + kSizeField_Len;
346*f6dc9357SAndroid Build Coastguard Worker     ConvertUInt64ToString(fileSize, p);
347*f6dc9357SAndroid Build Coastguard Worker     int numSpaces = (int)kSizeField_Len - (int)strlen(p);
348*f6dc9357SAndroid Build Coastguard Worker     if (numSpaces > 0)
349*f6dc9357SAndroid Build Coastguard Worker       p -= (unsigned)numSpaces;
350*f6dc9357SAndroid Build Coastguard Worker     _s += p;
351*f6dc9357SAndroid Build Coastguard Worker   }
352*f6dc9357SAndroid Build Coastguard Worker   */
353*f6dc9357SAndroid Build Coastguard Worker }
354*f6dc9357SAndroid Build Coastguard Worker 
355*f6dc9357SAndroid Build Coastguard Worker 
Add_LF(CDynLimBuf & hashFileString,const CHashOptionsLocal & options)356*f6dc9357SAndroid Build Coastguard Worker static void Add_LF(CDynLimBuf &hashFileString, const CHashOptionsLocal &options)
357*f6dc9357SAndroid Build Coastguard Worker {
358*f6dc9357SAndroid Build Coastguard Worker   hashFileString += (char)(options.HashMode_Zero.Val ? 0 : '\n');
359*f6dc9357SAndroid Build Coastguard Worker }
360*f6dc9357SAndroid Build Coastguard Worker 
361*f6dc9357SAndroid Build Coastguard Worker 
362*f6dc9357SAndroid Build Coastguard Worker 
363*f6dc9357SAndroid Build Coastguard Worker 
WriteLine(CDynLimBuf & hashFileString,const CHashOptionsLocal & options,const UString & path2,bool isDir,const AString & methodName,const AString & hashesString)364*f6dc9357SAndroid Build Coastguard Worker static void WriteLine(CDynLimBuf &hashFileString,
365*f6dc9357SAndroid Build Coastguard Worker     const CHashOptionsLocal &options,
366*f6dc9357SAndroid Build Coastguard Worker     const UString &path2,
367*f6dc9357SAndroid Build Coastguard Worker     bool isDir,
368*f6dc9357SAndroid Build Coastguard Worker     const AString &methodName,
369*f6dc9357SAndroid Build Coastguard Worker     const AString &hashesString)
370*f6dc9357SAndroid Build Coastguard Worker {
371*f6dc9357SAndroid Build Coastguard Worker   if (options.HashMode_OnlyHash.Val)
372*f6dc9357SAndroid Build Coastguard Worker   {
373*f6dc9357SAndroid Build Coastguard Worker     hashFileString += hashesString;
374*f6dc9357SAndroid Build Coastguard Worker     Add_LF(hashFileString, options);
375*f6dc9357SAndroid Build Coastguard Worker     return;
376*f6dc9357SAndroid Build Coastguard Worker   }
377*f6dc9357SAndroid Build Coastguard Worker 
378*f6dc9357SAndroid Build Coastguard Worker   UString path = path2;
379*f6dc9357SAndroid Build Coastguard Worker 
380*f6dc9357SAndroid Build Coastguard Worker   bool isBin = false;
381*f6dc9357SAndroid Build Coastguard Worker   const bool zeroMode = options.HashMode_Zero.Val;
382*f6dc9357SAndroid Build Coastguard Worker   const bool tagMode = options.HashMode_Tag.Val;
383*f6dc9357SAndroid Build Coastguard Worker 
384*f6dc9357SAndroid Build Coastguard Worker #if CHAR_PATH_SEPARATOR != '/'
385*f6dc9357SAndroid Build Coastguard Worker   path.Replace(WCHAR_PATH_SEPARATOR, L'/');
386*f6dc9357SAndroid Build Coastguard Worker   // path.Replace((wchar_t)('\\' + 0xf000), L'\\'); // to debug WSL
387*f6dc9357SAndroid Build Coastguard Worker #endif
388*f6dc9357SAndroid Build Coastguard Worker 
389*f6dc9357SAndroid Build Coastguard Worker   AString utf8;
390*f6dc9357SAndroid Build Coastguard Worker   ConvertUnicodeToUTF8(path, utf8);
391*f6dc9357SAndroid Build Coastguard Worker 
392*f6dc9357SAndroid Build Coastguard Worker   AString esc;
393*f6dc9357SAndroid Build Coastguard Worker   CSum_Name_OriginalToEscape(utf8, esc);
394*f6dc9357SAndroid Build Coastguard Worker 
395*f6dc9357SAndroid Build Coastguard Worker   if (!zeroMode)
396*f6dc9357SAndroid Build Coastguard Worker   {
397*f6dc9357SAndroid Build Coastguard Worker     if (esc != utf8)
398*f6dc9357SAndroid Build Coastguard Worker     {
399*f6dc9357SAndroid Build Coastguard Worker       /* Original md5sum writes escape in that case.
400*f6dc9357SAndroid Build Coastguard Worker       We do same for compatibility with original md5sum. */
401*f6dc9357SAndroid Build Coastguard Worker       hashFileString += '\\';
402*f6dc9357SAndroid Build Coastguard Worker     }
403*f6dc9357SAndroid Build Coastguard Worker   }
404*f6dc9357SAndroid Build Coastguard Worker 
405*f6dc9357SAndroid Build Coastguard Worker   if (isDir && !esc.IsEmpty() && esc.Back() != '/')
406*f6dc9357SAndroid Build Coastguard Worker     esc.Add_Slash();
407*f6dc9357SAndroid Build Coastguard Worker 
408*f6dc9357SAndroid Build Coastguard Worker   if (tagMode)
409*f6dc9357SAndroid Build Coastguard Worker   {
410*f6dc9357SAndroid Build Coastguard Worker     if (!methodName.IsEmpty())
411*f6dc9357SAndroid Build Coastguard Worker     {
412*f6dc9357SAndroid Build Coastguard Worker       hashFileString += methodName;
413*f6dc9357SAndroid Build Coastguard Worker       hashFileString += ' ';
414*f6dc9357SAndroid Build Coastguard Worker     }
415*f6dc9357SAndroid Build Coastguard Worker     hashFileString += '(';
416*f6dc9357SAndroid Build Coastguard Worker     hashFileString += esc;
417*f6dc9357SAndroid Build Coastguard Worker     hashFileString += ')';
418*f6dc9357SAndroid Build Coastguard Worker     hashFileString += " = ";
419*f6dc9357SAndroid Build Coastguard Worker   }
420*f6dc9357SAndroid Build Coastguard Worker 
421*f6dc9357SAndroid Build Coastguard Worker   hashFileString += hashesString;
422*f6dc9357SAndroid Build Coastguard Worker 
423*f6dc9357SAndroid Build Coastguard Worker   if (!tagMode)
424*f6dc9357SAndroid Build Coastguard Worker   {
425*f6dc9357SAndroid Build Coastguard Worker     hashFileString += ' ';
426*f6dc9357SAndroid Build Coastguard Worker     hashFileString += (char)(isBin ? '*' : ' ');
427*f6dc9357SAndroid Build Coastguard Worker     hashFileString += esc;
428*f6dc9357SAndroid Build Coastguard Worker   }
429*f6dc9357SAndroid Build Coastguard Worker 
430*f6dc9357SAndroid Build Coastguard Worker   Add_LF(hashFileString, options);
431*f6dc9357SAndroid Build Coastguard Worker }
432*f6dc9357SAndroid Build Coastguard Worker 
433*f6dc9357SAndroid Build Coastguard Worker 
434*f6dc9357SAndroid Build Coastguard Worker 
WriteLine(CDynLimBuf & hashFileString,const CHashOptionsLocal & options,const UString & path,bool isDir,const CHashBundle & hb)435*f6dc9357SAndroid Build Coastguard Worker static void WriteLine(CDynLimBuf &hashFileString,
436*f6dc9357SAndroid Build Coastguard Worker     const CHashOptionsLocal &options,
437*f6dc9357SAndroid Build Coastguard Worker     const UString &path,
438*f6dc9357SAndroid Build Coastguard Worker     bool isDir,
439*f6dc9357SAndroid Build Coastguard Worker     const CHashBundle &hb)
440*f6dc9357SAndroid Build Coastguard Worker {
441*f6dc9357SAndroid Build Coastguard Worker   AString methodName;
442*f6dc9357SAndroid Build Coastguard Worker   if (!hb.Hashers.IsEmpty())
443*f6dc9357SAndroid Build Coastguard Worker     methodName = hb.Hashers[0].Name;
444*f6dc9357SAndroid Build Coastguard Worker 
445*f6dc9357SAndroid Build Coastguard Worker   AString hashesString;
446*f6dc9357SAndroid Build Coastguard Worker   AddHashResultLine(hashesString, hb.Hashers);
447*f6dc9357SAndroid Build Coastguard Worker   WriteLine(hashFileString, options, path, isDir, methodName, hashesString);
448*f6dc9357SAndroid Build Coastguard Worker }
449*f6dc9357SAndroid Build Coastguard Worker 
450*f6dc9357SAndroid Build Coastguard Worker 
HashCalc(DECL_EXTERNAL_CODECS_LOC_VARS const NWildcard::CCensor & censor,const CHashOptions & options,AString & errorInfo,IHashCallbackUI * callback)451*f6dc9357SAndroid Build Coastguard Worker HRESULT HashCalc(
452*f6dc9357SAndroid Build Coastguard Worker     DECL_EXTERNAL_CODECS_LOC_VARS
453*f6dc9357SAndroid Build Coastguard Worker     const NWildcard::CCensor &censor,
454*f6dc9357SAndroid Build Coastguard Worker     const CHashOptions &options,
455*f6dc9357SAndroid Build Coastguard Worker     AString &errorInfo,
456*f6dc9357SAndroid Build Coastguard Worker     IHashCallbackUI *callback)
457*f6dc9357SAndroid Build Coastguard Worker {
458*f6dc9357SAndroid Build Coastguard Worker   CDirItems dirItems;
459*f6dc9357SAndroid Build Coastguard Worker   dirItems.Callback = callback;
460*f6dc9357SAndroid Build Coastguard Worker 
461*f6dc9357SAndroid Build Coastguard Worker   if (options.StdInMode)
462*f6dc9357SAndroid Build Coastguard Worker   {
463*f6dc9357SAndroid Build Coastguard Worker     CDirItem di;
464*f6dc9357SAndroid Build Coastguard Worker     if (!di.SetAs_StdInFile())
465*f6dc9357SAndroid Build Coastguard Worker       return GetLastError_noZero_HRESULT();
466*f6dc9357SAndroid Build Coastguard Worker     dirItems.Items.Add(di);
467*f6dc9357SAndroid Build Coastguard Worker   }
468*f6dc9357SAndroid Build Coastguard Worker   else
469*f6dc9357SAndroid Build Coastguard Worker   {
470*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->StartScanning())
471*f6dc9357SAndroid Build Coastguard Worker 
472*f6dc9357SAndroid Build Coastguard Worker     dirItems.SymLinks = options.SymLinks.Val;
473*f6dc9357SAndroid Build Coastguard Worker     dirItems.ScanAltStreams = options.AltStreamsMode;
474*f6dc9357SAndroid Build Coastguard Worker     dirItems.ExcludeDirItems = censor.ExcludeDirItems;
475*f6dc9357SAndroid Build Coastguard Worker     dirItems.ExcludeFileItems = censor.ExcludeFileItems;
476*f6dc9357SAndroid Build Coastguard Worker 
477*f6dc9357SAndroid Build Coastguard Worker     dirItems.ShareForWrite = options.OpenShareForWrite;
478*f6dc9357SAndroid Build Coastguard Worker 
479*f6dc9357SAndroid Build Coastguard Worker     HRESULT res = EnumerateItems(censor,
480*f6dc9357SAndroid Build Coastguard Worker         options.PathMode,
481*f6dc9357SAndroid Build Coastguard Worker         UString(),
482*f6dc9357SAndroid Build Coastguard Worker         dirItems);
483*f6dc9357SAndroid Build Coastguard Worker 
484*f6dc9357SAndroid Build Coastguard Worker     if (res != S_OK)
485*f6dc9357SAndroid Build Coastguard Worker     {
486*f6dc9357SAndroid Build Coastguard Worker       if (res != E_ABORT)
487*f6dc9357SAndroid Build Coastguard Worker         errorInfo = "Scanning error";
488*f6dc9357SAndroid Build Coastguard Worker       return res;
489*f6dc9357SAndroid Build Coastguard Worker     }
490*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->FinishScanning(dirItems.Stat))
491*f6dc9357SAndroid Build Coastguard Worker   }
492*f6dc9357SAndroid Build Coastguard Worker 
493*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
494*f6dc9357SAndroid Build Coastguard Worker   CHashBundle hb;
495*f6dc9357SAndroid Build Coastguard Worker   RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods))
496*f6dc9357SAndroid Build Coastguard Worker   // hb.Init();
497*f6dc9357SAndroid Build Coastguard Worker 
498*f6dc9357SAndroid Build Coastguard Worker   hb.NumErrors = dirItems.Stat.NumErrors;
499*f6dc9357SAndroid Build Coastguard Worker 
500*f6dc9357SAndroid Build Coastguard Worker   UInt64 totalSize = 0;
501*f6dc9357SAndroid Build Coastguard Worker   if (options.StdInMode)
502*f6dc9357SAndroid Build Coastguard Worker   {
503*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->SetNumFiles(1))
504*f6dc9357SAndroid Build Coastguard Worker   }
505*f6dc9357SAndroid Build Coastguard Worker   else
506*f6dc9357SAndroid Build Coastguard Worker   {
507*f6dc9357SAndroid Build Coastguard Worker     totalSize = dirItems.Stat.GetTotalBytes();
508*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->SetTotal(totalSize))
509*f6dc9357SAndroid Build Coastguard Worker   }
510*f6dc9357SAndroid Build Coastguard Worker 
511*f6dc9357SAndroid Build Coastguard Worker   const UInt32 kBufSize = 1 << 15;
512*f6dc9357SAndroid Build Coastguard Worker   CHashMidBuf buf;
513*f6dc9357SAndroid Build Coastguard Worker   if (!buf.Alloc(kBufSize))
514*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
515*f6dc9357SAndroid Build Coastguard Worker 
516*f6dc9357SAndroid Build Coastguard Worker   UInt64 completeValue = 0;
517*f6dc9357SAndroid Build Coastguard Worker 
518*f6dc9357SAndroid Build Coastguard Worker   RINOK(callback->BeforeFirstFile(hb))
519*f6dc9357SAndroid Build Coastguard Worker 
520*f6dc9357SAndroid Build Coastguard Worker   /*
521*f6dc9357SAndroid Build Coastguard Worker   CDynLimBuf hashFileString((size_t)1 << 31);
522*f6dc9357SAndroid Build Coastguard Worker   const bool needGenerate = !options.HashFilePath.IsEmpty();
523*f6dc9357SAndroid Build Coastguard Worker   */
524*f6dc9357SAndroid Build Coastguard Worker 
525*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < dirItems.Items.Size(); i++)
526*f6dc9357SAndroid Build Coastguard Worker   {
527*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ISequentialInStream> inStream;
528*f6dc9357SAndroid Build Coastguard Worker     UString path;
529*f6dc9357SAndroid Build Coastguard Worker     bool isDir = false;
530*f6dc9357SAndroid Build Coastguard Worker     bool isAltStream = false;
531*f6dc9357SAndroid Build Coastguard Worker 
532*f6dc9357SAndroid Build Coastguard Worker     if (options.StdInMode)
533*f6dc9357SAndroid Build Coastguard Worker     {
534*f6dc9357SAndroid Build Coastguard Worker #if 1
535*f6dc9357SAndroid Build Coastguard Worker       inStream = new CStdInFileStream;
536*f6dc9357SAndroid Build Coastguard Worker #else
537*f6dc9357SAndroid Build Coastguard Worker       if (!CreateStdInStream(inStream))
538*f6dc9357SAndroid Build Coastguard Worker       {
539*f6dc9357SAndroid Build Coastguard Worker         const DWORD lastError = ::GetLastError();
540*f6dc9357SAndroid Build Coastguard Worker         const HRESULT res = callback->OpenFileError(FString("stdin"), lastError);
541*f6dc9357SAndroid Build Coastguard Worker         hb.NumErrors++;
542*f6dc9357SAndroid Build Coastguard Worker         if (res != S_FALSE && res != S_OK)
543*f6dc9357SAndroid Build Coastguard Worker           return res;
544*f6dc9357SAndroid Build Coastguard Worker         continue;
545*f6dc9357SAndroid Build Coastguard Worker       }
546*f6dc9357SAndroid Build Coastguard Worker #endif
547*f6dc9357SAndroid Build Coastguard Worker     }
548*f6dc9357SAndroid Build Coastguard Worker     else
549*f6dc9357SAndroid Build Coastguard Worker     {
550*f6dc9357SAndroid Build Coastguard Worker       path = dirItems.GetLogPath(i);
551*f6dc9357SAndroid Build Coastguard Worker       const CDirItem &di = dirItems.Items[i];
552*f6dc9357SAndroid Build Coastguard Worker      #ifdef _WIN32
553*f6dc9357SAndroid Build Coastguard Worker       isAltStream = di.IsAltStream;
554*f6dc9357SAndroid Build Coastguard Worker      #endif
555*f6dc9357SAndroid Build Coastguard Worker 
556*f6dc9357SAndroid Build Coastguard Worker       #ifndef UNDER_CE
557*f6dc9357SAndroid Build Coastguard Worker       // if (di.AreReparseData())
558*f6dc9357SAndroid Build Coastguard Worker       if (di.ReparseData.Size() != 0)
559*f6dc9357SAndroid Build Coastguard Worker       {
560*f6dc9357SAndroid Build Coastguard Worker         CBufInStream *inStreamSpec = new CBufInStream();
561*f6dc9357SAndroid Build Coastguard Worker         inStream = inStreamSpec;
562*f6dc9357SAndroid Build Coastguard Worker         inStreamSpec->Init(di.ReparseData, di.ReparseData.Size());
563*f6dc9357SAndroid Build Coastguard Worker       }
564*f6dc9357SAndroid Build Coastguard Worker       else
565*f6dc9357SAndroid Build Coastguard Worker       #endif
566*f6dc9357SAndroid Build Coastguard Worker       {
567*f6dc9357SAndroid Build Coastguard Worker         CInFileStream *inStreamSpec = new CInFileStream;
568*f6dc9357SAndroid Build Coastguard Worker         inStreamSpec->Set_PreserveATime(options.PreserveATime);
569*f6dc9357SAndroid Build Coastguard Worker         inStream = inStreamSpec;
570*f6dc9357SAndroid Build Coastguard Worker         isDir = di.IsDir();
571*f6dc9357SAndroid Build Coastguard Worker         if (!isDir)
572*f6dc9357SAndroid Build Coastguard Worker         {
573*f6dc9357SAndroid Build Coastguard Worker           const FString phyPath = dirItems.GetPhyPath(i);
574*f6dc9357SAndroid Build Coastguard Worker           if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite))
575*f6dc9357SAndroid Build Coastguard Worker           {
576*f6dc9357SAndroid Build Coastguard Worker             const HRESULT res = callback->OpenFileError(phyPath, ::GetLastError());
577*f6dc9357SAndroid Build Coastguard Worker             hb.NumErrors++;
578*f6dc9357SAndroid Build Coastguard Worker             if (res != S_FALSE)
579*f6dc9357SAndroid Build Coastguard Worker               return res;
580*f6dc9357SAndroid Build Coastguard Worker             continue;
581*f6dc9357SAndroid Build Coastguard Worker           }
582*f6dc9357SAndroid Build Coastguard Worker           if (!options.StdInMode)
583*f6dc9357SAndroid Build Coastguard Worker           {
584*f6dc9357SAndroid Build Coastguard Worker             UInt64 curSize = 0;
585*f6dc9357SAndroid Build Coastguard Worker             if (inStreamSpec->GetSize(&curSize) == S_OK)
586*f6dc9357SAndroid Build Coastguard Worker             {
587*f6dc9357SAndroid Build Coastguard Worker               if (curSize > di.Size)
588*f6dc9357SAndroid Build Coastguard Worker               {
589*f6dc9357SAndroid Build Coastguard Worker                 totalSize += curSize - di.Size;
590*f6dc9357SAndroid Build Coastguard Worker                 RINOK(callback->SetTotal(totalSize))
591*f6dc9357SAndroid Build Coastguard Worker                 // printf("\ntotal = %d MiB\n", (unsigned)(totalSize >> 20));
592*f6dc9357SAndroid Build Coastguard Worker               }
593*f6dc9357SAndroid Build Coastguard Worker             }
594*f6dc9357SAndroid Build Coastguard Worker           }
595*f6dc9357SAndroid Build Coastguard Worker           // inStreamSpec->ReloadProps();
596*f6dc9357SAndroid Build Coastguard Worker         }
597*f6dc9357SAndroid Build Coastguard Worker       }
598*f6dc9357SAndroid Build Coastguard Worker     }
599*f6dc9357SAndroid Build Coastguard Worker 
600*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->GetStream(path, isDir))
601*f6dc9357SAndroid Build Coastguard Worker     UInt64 fileSize = 0;
602*f6dc9357SAndroid Build Coastguard Worker 
603*f6dc9357SAndroid Build Coastguard Worker     hb.InitForNewFile();
604*f6dc9357SAndroid Build Coastguard Worker 
605*f6dc9357SAndroid Build Coastguard Worker     if (!isDir)
606*f6dc9357SAndroid Build Coastguard Worker     {
607*f6dc9357SAndroid Build Coastguard Worker       for (UInt32 step = 0;; step++)
608*f6dc9357SAndroid Build Coastguard Worker       {
609*f6dc9357SAndroid Build Coastguard Worker         if ((step & 0xFF) == 0)
610*f6dc9357SAndroid Build Coastguard Worker         {
611*f6dc9357SAndroid Build Coastguard Worker           // printf("\ncompl = %d\n", (unsigned)(completeValue >> 20));
612*f6dc9357SAndroid Build Coastguard Worker           RINOK(callback->SetCompleted(&completeValue))
613*f6dc9357SAndroid Build Coastguard Worker         }
614*f6dc9357SAndroid Build Coastguard Worker         UInt32 size;
615*f6dc9357SAndroid Build Coastguard Worker         RINOK(inStream->Read(buf, kBufSize, &size))
616*f6dc9357SAndroid Build Coastguard Worker         if (size == 0)
617*f6dc9357SAndroid Build Coastguard Worker           break;
618*f6dc9357SAndroid Build Coastguard Worker         hb.Update(buf, size);
619*f6dc9357SAndroid Build Coastguard Worker         fileSize += size;
620*f6dc9357SAndroid Build Coastguard Worker         completeValue += size;
621*f6dc9357SAndroid Build Coastguard Worker       }
622*f6dc9357SAndroid Build Coastguard Worker     }
623*f6dc9357SAndroid Build Coastguard Worker 
624*f6dc9357SAndroid Build Coastguard Worker     hb.Final(isDir, isAltStream, path);
625*f6dc9357SAndroid Build Coastguard Worker 
626*f6dc9357SAndroid Build Coastguard Worker     /*
627*f6dc9357SAndroid Build Coastguard Worker     if (needGenerate
628*f6dc9357SAndroid Build Coastguard Worker         && (options.HashMode_Dirs.Val || !isDir))
629*f6dc9357SAndroid Build Coastguard Worker     {
630*f6dc9357SAndroid Build Coastguard Worker       WriteLine(hashFileString,
631*f6dc9357SAndroid Build Coastguard Worker           options,
632*f6dc9357SAndroid Build Coastguard Worker           path, // change it
633*f6dc9357SAndroid Build Coastguard Worker           isDir,
634*f6dc9357SAndroid Build Coastguard Worker           hb);
635*f6dc9357SAndroid Build Coastguard Worker 
636*f6dc9357SAndroid Build Coastguard Worker       if (hashFileString.IsError())
637*f6dc9357SAndroid Build Coastguard Worker         return E_OUTOFMEMORY;
638*f6dc9357SAndroid Build Coastguard Worker     }
639*f6dc9357SAndroid Build Coastguard Worker     */
640*f6dc9357SAndroid Build Coastguard Worker 
641*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->SetOperationResult(fileSize, hb, !isDir))
642*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->SetCompleted(&completeValue))
643*f6dc9357SAndroid Build Coastguard Worker   }
644*f6dc9357SAndroid Build Coastguard Worker 
645*f6dc9357SAndroid Build Coastguard Worker   /*
646*f6dc9357SAndroid Build Coastguard Worker   if (needGenerate)
647*f6dc9357SAndroid Build Coastguard Worker   {
648*f6dc9357SAndroid Build Coastguard Worker     NFile::NIO::COutFile file;
649*f6dc9357SAndroid Build Coastguard Worker     if (!file.Create(us2fs(options.HashFilePath), true)) // createAlways
650*f6dc9357SAndroid Build Coastguard Worker       return GetLastError_noZero_HRESULT();
651*f6dc9357SAndroid Build Coastguard Worker     if (!file.WriteFull(hashFileString, hashFileString.Len()))
652*f6dc9357SAndroid Build Coastguard Worker       return GetLastError_noZero_HRESULT();
653*f6dc9357SAndroid Build Coastguard Worker   }
654*f6dc9357SAndroid Build Coastguard Worker   */
655*f6dc9357SAndroid Build Coastguard Worker 
656*f6dc9357SAndroid Build Coastguard Worker   return callback->AfterLastFile(hb);
657*f6dc9357SAndroid Build Coastguard Worker }
658*f6dc9357SAndroid Build Coastguard Worker 
659*f6dc9357SAndroid Build Coastguard Worker 
HashHexToString(char * dest,const Byte * data,size_t size)660*f6dc9357SAndroid Build Coastguard Worker void HashHexToString(char *dest, const Byte *data, size_t size)
661*f6dc9357SAndroid Build Coastguard Worker {
662*f6dc9357SAndroid Build Coastguard Worker   if (!data)
663*f6dc9357SAndroid Build Coastguard Worker   {
664*f6dc9357SAndroid Build Coastguard Worker     for (size_t i = 0; i < size; i++)
665*f6dc9357SAndroid Build Coastguard Worker     {
666*f6dc9357SAndroid Build Coastguard Worker       dest[0] = ' ';
667*f6dc9357SAndroid Build Coastguard Worker       dest[1] = ' ';
668*f6dc9357SAndroid Build Coastguard Worker       dest += 2;
669*f6dc9357SAndroid Build Coastguard Worker     }
670*f6dc9357SAndroid Build Coastguard Worker     *dest = 0;
671*f6dc9357SAndroid Build Coastguard Worker     return;
672*f6dc9357SAndroid Build Coastguard Worker   }
673*f6dc9357SAndroid Build Coastguard Worker 
674*f6dc9357SAndroid Build Coastguard Worker   if (size > 8)
675*f6dc9357SAndroid Build Coastguard Worker     ConvertDataToHex_Lower(dest, data, size);
676*f6dc9357SAndroid Build Coastguard Worker   else if (size == 0)
677*f6dc9357SAndroid Build Coastguard Worker   {
678*f6dc9357SAndroid Build Coastguard Worker     *dest = 0;
679*f6dc9357SAndroid Build Coastguard Worker     return;
680*f6dc9357SAndroid Build Coastguard Worker   }
681*f6dc9357SAndroid Build Coastguard Worker   else
682*f6dc9357SAndroid Build Coastguard Worker   {
683*f6dc9357SAndroid Build Coastguard Worker     const char *dest_start = dest;
684*f6dc9357SAndroid Build Coastguard Worker     dest += size * 2;
685*f6dc9357SAndroid Build Coastguard Worker     *dest = 0;
686*f6dc9357SAndroid Build Coastguard Worker     do
687*f6dc9357SAndroid Build Coastguard Worker     {
688*f6dc9357SAndroid Build Coastguard Worker       const size_t b = *data++;
689*f6dc9357SAndroid Build Coastguard Worker       dest -= 2;
690*f6dc9357SAndroid Build Coastguard Worker       dest[0] = GET_HEX_CHAR_UPPER(b >> 4);
691*f6dc9357SAndroid Build Coastguard Worker       dest[1] = GET_HEX_CHAR_UPPER(b & 15);
692*f6dc9357SAndroid Build Coastguard Worker     }
693*f6dc9357SAndroid Build Coastguard Worker     while (dest != dest_start);
694*f6dc9357SAndroid Build Coastguard Worker   }
695*f6dc9357SAndroid Build Coastguard Worker }
696*f6dc9357SAndroid Build Coastguard Worker 
WriteToString(unsigned digestIndex,char * s) const697*f6dc9357SAndroid Build Coastguard Worker void CHasherState::WriteToString(unsigned digestIndex, char *s) const
698*f6dc9357SAndroid Build Coastguard Worker {
699*f6dc9357SAndroid Build Coastguard Worker   HashHexToString(s, Digests[digestIndex], DigestSize);
700*f6dc9357SAndroid Build Coastguard Worker 
701*f6dc9357SAndroid Build Coastguard Worker   if (digestIndex != 0 && NumSums[digestIndex] != 1)
702*f6dc9357SAndroid Build Coastguard Worker   {
703*f6dc9357SAndroid Build Coastguard Worker     unsigned numExtraBytes = GetNumExtraBytes_for_Group(digestIndex);
704*f6dc9357SAndroid Build Coastguard Worker     if (numExtraBytes > 4)
705*f6dc9357SAndroid Build Coastguard Worker       numExtraBytes = 8;
706*f6dc9357SAndroid Build Coastguard Worker     else // if (numExtraBytes >= 0)
707*f6dc9357SAndroid Build Coastguard Worker       numExtraBytes = 4;
708*f6dc9357SAndroid Build Coastguard Worker     // if (numExtraBytes != 0)
709*f6dc9357SAndroid Build Coastguard Worker     {
710*f6dc9357SAndroid Build Coastguard Worker       s += strlen(s);
711*f6dc9357SAndroid Build Coastguard Worker       *s++ = '-';
712*f6dc9357SAndroid Build Coastguard Worker       // *s = 0;
713*f6dc9357SAndroid Build Coastguard Worker       HashHexToString(s, GetExtraData_for_Group(digestIndex), numExtraBytes);
714*f6dc9357SAndroid Build Coastguard Worker     }
715*f6dc9357SAndroid Build Coastguard Worker   }
716*f6dc9357SAndroid Build Coastguard Worker }
717*f6dc9357SAndroid Build Coastguard Worker 
718*f6dc9357SAndroid Build Coastguard Worker 
719*f6dc9357SAndroid Build Coastguard Worker 
720*f6dc9357SAndroid Build Coastguard Worker // ---------- Hash Handler ----------
721*f6dc9357SAndroid Build Coastguard Worker 
722*f6dc9357SAndroid Build Coastguard Worker namespace NHash {
723*f6dc9357SAndroid Build Coastguard Worker 
724*f6dc9357SAndroid Build Coastguard Worker #define IsWhite(c) ((c) == ' ' || (c) == '\t')
725*f6dc9357SAndroid Build Coastguard Worker 
IsDir() const726*f6dc9357SAndroid Build Coastguard Worker bool CHashPair::IsDir() const
727*f6dc9357SAndroid Build Coastguard Worker {
728*f6dc9357SAndroid Build Coastguard Worker   if (Name.IsEmpty() || Name.Back() != '/')
729*f6dc9357SAndroid Build Coastguard Worker     return false;
730*f6dc9357SAndroid Build Coastguard Worker   // here we expect that Dir items contain only zeros or no Hash
731*f6dc9357SAndroid Build Coastguard Worker   for (size_t i = 0; i < Hash.Size(); i++)
732*f6dc9357SAndroid Build Coastguard Worker     if (Hash.ConstData()[i] != 0)
733*f6dc9357SAndroid Build Coastguard Worker       return false;
734*f6dc9357SAndroid Build Coastguard Worker   return true;
735*f6dc9357SAndroid Build Coastguard Worker }
736*f6dc9357SAndroid Build Coastguard Worker 
737*f6dc9357SAndroid Build Coastguard Worker 
ParseCksum(const char * s)738*f6dc9357SAndroid Build Coastguard Worker bool CHashPair::ParseCksum(const char *s)
739*f6dc9357SAndroid Build Coastguard Worker {
740*f6dc9357SAndroid Build Coastguard Worker   const char *end;
741*f6dc9357SAndroid Build Coastguard Worker 
742*f6dc9357SAndroid Build Coastguard Worker   const UInt32 crc = ConvertStringToUInt32(s, &end);
743*f6dc9357SAndroid Build Coastguard Worker   if (*end != ' ')
744*f6dc9357SAndroid Build Coastguard Worker     return false;
745*f6dc9357SAndroid Build Coastguard Worker   end++;
746*f6dc9357SAndroid Build Coastguard Worker 
747*f6dc9357SAndroid Build Coastguard Worker   const UInt64 size = ConvertStringToUInt64(end, &end);
748*f6dc9357SAndroid Build Coastguard Worker   if (*end != ' ')
749*f6dc9357SAndroid Build Coastguard Worker     return false;
750*f6dc9357SAndroid Build Coastguard Worker   end++;
751*f6dc9357SAndroid Build Coastguard Worker 
752*f6dc9357SAndroid Build Coastguard Worker   Name = end;
753*f6dc9357SAndroid Build Coastguard Worker 
754*f6dc9357SAndroid Build Coastguard Worker   Hash.Alloc(4);
755*f6dc9357SAndroid Build Coastguard Worker   SetBe32(Hash, crc)
756*f6dc9357SAndroid Build Coastguard Worker 
757*f6dc9357SAndroid Build Coastguard Worker   Size_from_Arc = size;
758*f6dc9357SAndroid Build Coastguard Worker   Size_from_Arc_Defined = true;
759*f6dc9357SAndroid Build Coastguard Worker 
760*f6dc9357SAndroid Build Coastguard Worker   return true;
761*f6dc9357SAndroid Build Coastguard Worker }
762*f6dc9357SAndroid Build Coastguard Worker 
763*f6dc9357SAndroid Build Coastguard Worker 
764*f6dc9357SAndroid Build Coastguard Worker 
SkipWhite(const char * s)765*f6dc9357SAndroid Build Coastguard Worker static const char *SkipWhite(const char *s)
766*f6dc9357SAndroid Build Coastguard Worker {
767*f6dc9357SAndroid Build Coastguard Worker   while (IsWhite(*s))
768*f6dc9357SAndroid Build Coastguard Worker     s++;
769*f6dc9357SAndroid Build Coastguard Worker   return s;
770*f6dc9357SAndroid Build Coastguard Worker }
771*f6dc9357SAndroid Build Coastguard Worker 
772*f6dc9357SAndroid Build Coastguard Worker static const char * const k_CsumMethodNames[] =
773*f6dc9357SAndroid Build Coastguard Worker {
774*f6dc9357SAndroid Build Coastguard Worker     "sha256"
775*f6dc9357SAndroid Build Coastguard Worker   , "sha224"
776*f6dc9357SAndroid Build Coastguard Worker //  , "sha512-224"
777*f6dc9357SAndroid Build Coastguard Worker //  , "sha512-256"
778*f6dc9357SAndroid Build Coastguard Worker   , "sha384"
779*f6dc9357SAndroid Build Coastguard Worker   , "sha512"
780*f6dc9357SAndroid Build Coastguard Worker //  , "sha3-224"
781*f6dc9357SAndroid Build Coastguard Worker   , "sha3-256"
782*f6dc9357SAndroid Build Coastguard Worker //  , "sha3-384"
783*f6dc9357SAndroid Build Coastguard Worker //  , "sha3-512"
784*f6dc9357SAndroid Build Coastguard Worker //  , "shake128"
785*f6dc9357SAndroid Build Coastguard Worker //  , "shake256"
786*f6dc9357SAndroid Build Coastguard Worker   , "sha1"
787*f6dc9357SAndroid Build Coastguard Worker   , "md5"
788*f6dc9357SAndroid Build Coastguard Worker   , "blake2sp"
789*f6dc9357SAndroid Build Coastguard Worker   , "blake2b"
790*f6dc9357SAndroid Build Coastguard Worker   , "xxh64"
791*f6dc9357SAndroid Build Coastguard Worker   , "crc64"
792*f6dc9357SAndroid Build Coastguard Worker   , "crc32"
793*f6dc9357SAndroid Build Coastguard Worker   , "cksum"
794*f6dc9357SAndroid Build Coastguard Worker };
795*f6dc9357SAndroid Build Coastguard Worker 
GetMethod_from_FileName(const UString & name)796*f6dc9357SAndroid Build Coastguard Worker static UString GetMethod_from_FileName(const UString &name)
797*f6dc9357SAndroid Build Coastguard Worker {
798*f6dc9357SAndroid Build Coastguard Worker   AString s;
799*f6dc9357SAndroid Build Coastguard Worker   ConvertUnicodeToUTF8(name, s);
800*f6dc9357SAndroid Build Coastguard Worker   const int dotPos = s.ReverseFind_Dot();
801*f6dc9357SAndroid Build Coastguard Worker   const char *src = s.Ptr();
802*f6dc9357SAndroid Build Coastguard Worker   bool isExtension = false;
803*f6dc9357SAndroid Build Coastguard Worker   if (dotPos >= 0)
804*f6dc9357SAndroid Build Coastguard Worker   {
805*f6dc9357SAndroid Build Coastguard Worker     isExtension = true;
806*f6dc9357SAndroid Build Coastguard Worker     src = s.Ptr(dotPos + 1);
807*f6dc9357SAndroid Build Coastguard Worker   }
808*f6dc9357SAndroid Build Coastguard Worker   const char *m = "";
809*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
810*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < Z7_ARRAY_SIZE(k_CsumMethodNames); i++)
811*f6dc9357SAndroid Build Coastguard Worker   {
812*f6dc9357SAndroid Build Coastguard Worker     m = k_CsumMethodNames[i];
813*f6dc9357SAndroid Build Coastguard Worker     if (isExtension)
814*f6dc9357SAndroid Build Coastguard Worker     {
815*f6dc9357SAndroid Build Coastguard Worker       if (StringsAreEqual_Ascii(src, m))
816*f6dc9357SAndroid Build Coastguard Worker         break;
817*f6dc9357SAndroid Build Coastguard Worker     }
818*f6dc9357SAndroid Build Coastguard Worker     else if (IsString1PrefixedByString2_NoCase_Ascii(src, m))
819*f6dc9357SAndroid Build Coastguard Worker       if (StringsAreEqual_Ascii(src + strlen(m), "sums"))
820*f6dc9357SAndroid Build Coastguard Worker         break;
821*f6dc9357SAndroid Build Coastguard Worker   }
822*f6dc9357SAndroid Build Coastguard Worker   UString res;
823*f6dc9357SAndroid Build Coastguard Worker   if (i != Z7_ARRAY_SIZE(k_CsumMethodNames))
824*f6dc9357SAndroid Build Coastguard Worker     res = m;
825*f6dc9357SAndroid Build Coastguard Worker   return res;
826*f6dc9357SAndroid Build Coastguard Worker }
827*f6dc9357SAndroid Build Coastguard Worker 
828*f6dc9357SAndroid Build Coastguard Worker 
Parse(const char * s)829*f6dc9357SAndroid Build Coastguard Worker bool CHashPair::Parse(const char *s)
830*f6dc9357SAndroid Build Coastguard Worker {
831*f6dc9357SAndroid Build Coastguard Worker   // here we keep compatibility with original md5sum / shasum
832*f6dc9357SAndroid Build Coastguard Worker   bool escape = false;
833*f6dc9357SAndroid Build Coastguard Worker 
834*f6dc9357SAndroid Build Coastguard Worker   s = SkipWhite(s);
835*f6dc9357SAndroid Build Coastguard Worker 
836*f6dc9357SAndroid Build Coastguard Worker   if (*s == '\\')
837*f6dc9357SAndroid Build Coastguard Worker   {
838*f6dc9357SAndroid Build Coastguard Worker     s++;
839*f6dc9357SAndroid Build Coastguard Worker     escape = true;
840*f6dc9357SAndroid Build Coastguard Worker   }
841*f6dc9357SAndroid Build Coastguard Worker   Escape = escape;
842*f6dc9357SAndroid Build Coastguard Worker 
843*f6dc9357SAndroid Build Coastguard Worker   // const char *kMethod = GetMethod_from_FileName(s);
844*f6dc9357SAndroid Build Coastguard Worker   // if (kMethod)
845*f6dc9357SAndroid Build Coastguard Worker   if ((size_t)(FindNonHexChar(s) - s) < 4)
846*f6dc9357SAndroid Build Coastguard Worker   {
847*f6dc9357SAndroid Build Coastguard Worker     // BSD-style checksum line
848*f6dc9357SAndroid Build Coastguard Worker     {
849*f6dc9357SAndroid Build Coastguard Worker       const char *s2 = s;
850*f6dc9357SAndroid Build Coastguard Worker       for (; *s2 != 0; s2++)
851*f6dc9357SAndroid Build Coastguard Worker       {
852*f6dc9357SAndroid Build Coastguard Worker         const char c = *s2;
853*f6dc9357SAndroid Build Coastguard Worker         if (c == 0)
854*f6dc9357SAndroid Build Coastguard Worker           return false;
855*f6dc9357SAndroid Build Coastguard Worker         if (c == ' ' || c == '(')
856*f6dc9357SAndroid Build Coastguard Worker           break;
857*f6dc9357SAndroid Build Coastguard Worker       }
858*f6dc9357SAndroid Build Coastguard Worker       Method.SetFrom(s, (unsigned)(s2 - s));
859*f6dc9357SAndroid Build Coastguard Worker       s = s2;
860*f6dc9357SAndroid Build Coastguard Worker     }
861*f6dc9357SAndroid Build Coastguard Worker     IsBSD = true;
862*f6dc9357SAndroid Build Coastguard Worker     if (*s == ' ')
863*f6dc9357SAndroid Build Coastguard Worker       s++;
864*f6dc9357SAndroid Build Coastguard Worker     if (*s != '(')
865*f6dc9357SAndroid Build Coastguard Worker       return false;
866*f6dc9357SAndroid Build Coastguard Worker     s++;
867*f6dc9357SAndroid Build Coastguard Worker     {
868*f6dc9357SAndroid Build Coastguard Worker       const char *s2 = s;
869*f6dc9357SAndroid Build Coastguard Worker       for (; *s2 != 0; s2++)
870*f6dc9357SAndroid Build Coastguard Worker       {}
871*f6dc9357SAndroid Build Coastguard Worker       for (;;)
872*f6dc9357SAndroid Build Coastguard Worker       {
873*f6dc9357SAndroid Build Coastguard Worker         s2--;
874*f6dc9357SAndroid Build Coastguard Worker         if (s2 < s)
875*f6dc9357SAndroid Build Coastguard Worker           return false;
876*f6dc9357SAndroid Build Coastguard Worker         if (*s2 == ')')
877*f6dc9357SAndroid Build Coastguard Worker           break;
878*f6dc9357SAndroid Build Coastguard Worker       }
879*f6dc9357SAndroid Build Coastguard Worker       Name.SetFrom(s, (unsigned)(s2 - s));
880*f6dc9357SAndroid Build Coastguard Worker       s = s2 + 1;
881*f6dc9357SAndroid Build Coastguard Worker     }
882*f6dc9357SAndroid Build Coastguard Worker 
883*f6dc9357SAndroid Build Coastguard Worker     s = SkipWhite(s);
884*f6dc9357SAndroid Build Coastguard Worker     if (*s != '=')
885*f6dc9357SAndroid Build Coastguard Worker       return false;
886*f6dc9357SAndroid Build Coastguard Worker     s++;
887*f6dc9357SAndroid Build Coastguard Worker     s = SkipWhite(s);
888*f6dc9357SAndroid Build Coastguard Worker   }
889*f6dc9357SAndroid Build Coastguard Worker 
890*f6dc9357SAndroid Build Coastguard Worker   {
891*f6dc9357SAndroid Build Coastguard Worker     const size_t numChars = (size_t)(FindNonHexChar(s) - s) & ~(size_t)1;
892*f6dc9357SAndroid Build Coastguard Worker     Hash.Alloc(numChars / 2);
893*f6dc9357SAndroid Build Coastguard Worker     if ((size_t)(ParseHexString(s, Hash) - Hash) != numChars / 2)
894*f6dc9357SAndroid Build Coastguard Worker       throw 101;
895*f6dc9357SAndroid Build Coastguard Worker     HashString.SetFrom(s, (unsigned)numChars);
896*f6dc9357SAndroid Build Coastguard Worker     s += numChars;
897*f6dc9357SAndroid Build Coastguard Worker   }
898*f6dc9357SAndroid Build Coastguard Worker 
899*f6dc9357SAndroid Build Coastguard Worker   if (IsBSD)
900*f6dc9357SAndroid Build Coastguard Worker   {
901*f6dc9357SAndroid Build Coastguard Worker     if (*s != 0)
902*f6dc9357SAndroid Build Coastguard Worker       return false;
903*f6dc9357SAndroid Build Coastguard Worker     if (escape)
904*f6dc9357SAndroid Build Coastguard Worker     {
905*f6dc9357SAndroid Build Coastguard Worker       const AString temp (Name);
906*f6dc9357SAndroid Build Coastguard Worker       return CSum_Name_EscapeToOriginal(temp, Name);
907*f6dc9357SAndroid Build Coastguard Worker     }
908*f6dc9357SAndroid Build Coastguard Worker     return true;
909*f6dc9357SAndroid Build Coastguard Worker   }
910*f6dc9357SAndroid Build Coastguard Worker 
911*f6dc9357SAndroid Build Coastguard Worker   if (*s == 0)
912*f6dc9357SAndroid Build Coastguard Worker     return true;
913*f6dc9357SAndroid Build Coastguard Worker 
914*f6dc9357SAndroid Build Coastguard Worker   if (*s != ' ')
915*f6dc9357SAndroid Build Coastguard Worker     return false;
916*f6dc9357SAndroid Build Coastguard Worker   s++;
917*f6dc9357SAndroid Build Coastguard Worker   const char c = *s;
918*f6dc9357SAndroid Build Coastguard Worker   if (c != ' '
919*f6dc9357SAndroid Build Coastguard Worker       && c != '*'
920*f6dc9357SAndroid Build Coastguard Worker       && c != 'U' // shasum Universal
921*f6dc9357SAndroid Build Coastguard Worker       && c != '^' // shasum 0/1
922*f6dc9357SAndroid Build Coastguard Worker      )
923*f6dc9357SAndroid Build Coastguard Worker     return false;
924*f6dc9357SAndroid Build Coastguard Worker   Mode = c;
925*f6dc9357SAndroid Build Coastguard Worker   s++;
926*f6dc9357SAndroid Build Coastguard Worker   if (escape)
927*f6dc9357SAndroid Build Coastguard Worker     return CSum_Name_EscapeToOriginal(s, Name);
928*f6dc9357SAndroid Build Coastguard Worker   Name = s;
929*f6dc9357SAndroid Build Coastguard Worker   return true;
930*f6dc9357SAndroid Build Coastguard Worker }
931*f6dc9357SAndroid Build Coastguard Worker 
932*f6dc9357SAndroid Build Coastguard Worker 
GetLine(CByteBuffer & buf,bool zeroMode,bool cr_lf_Mode,size_t & posCur,AString & s)933*f6dc9357SAndroid Build Coastguard Worker static bool GetLine(CByteBuffer &buf, bool zeroMode, bool cr_lf_Mode, size_t &posCur, AString &s)
934*f6dc9357SAndroid Build Coastguard Worker {
935*f6dc9357SAndroid Build Coastguard Worker   s.Empty();
936*f6dc9357SAndroid Build Coastguard Worker   size_t pos = posCur;
937*f6dc9357SAndroid Build Coastguard Worker   const Byte *p = buf;
938*f6dc9357SAndroid Build Coastguard Worker   unsigned numDigits = 0;
939*f6dc9357SAndroid Build Coastguard Worker   for (; pos < buf.Size(); pos++)
940*f6dc9357SAndroid Build Coastguard Worker   {
941*f6dc9357SAndroid Build Coastguard Worker     const Byte b = p[pos];
942*f6dc9357SAndroid Build Coastguard Worker     if (b == 0)
943*f6dc9357SAndroid Build Coastguard Worker     {
944*f6dc9357SAndroid Build Coastguard Worker       numDigits = 1;
945*f6dc9357SAndroid Build Coastguard Worker       break;
946*f6dc9357SAndroid Build Coastguard Worker     }
947*f6dc9357SAndroid Build Coastguard Worker     if (zeroMode)
948*f6dc9357SAndroid Build Coastguard Worker       continue;
949*f6dc9357SAndroid Build Coastguard Worker     if (b == 0x0a)
950*f6dc9357SAndroid Build Coastguard Worker     {
951*f6dc9357SAndroid Build Coastguard Worker       numDigits = 1;
952*f6dc9357SAndroid Build Coastguard Worker       break;
953*f6dc9357SAndroid Build Coastguard Worker     }
954*f6dc9357SAndroid Build Coastguard Worker     if (!cr_lf_Mode)
955*f6dc9357SAndroid Build Coastguard Worker       continue;
956*f6dc9357SAndroid Build Coastguard Worker     if (b == 0x0d)
957*f6dc9357SAndroid Build Coastguard Worker     {
958*f6dc9357SAndroid Build Coastguard Worker       if (pos + 1 >= buf.Size())
959*f6dc9357SAndroid Build Coastguard Worker       {
960*f6dc9357SAndroid Build Coastguard Worker         numDigits = 1;
961*f6dc9357SAndroid Build Coastguard Worker         break;
962*f6dc9357SAndroid Build Coastguard Worker         // return false;
963*f6dc9357SAndroid Build Coastguard Worker       }
964*f6dc9357SAndroid Build Coastguard Worker       if (p[pos + 1] == 0x0a)
965*f6dc9357SAndroid Build Coastguard Worker       {
966*f6dc9357SAndroid Build Coastguard Worker         numDigits = 2;
967*f6dc9357SAndroid Build Coastguard Worker         break;
968*f6dc9357SAndroid Build Coastguard Worker       }
969*f6dc9357SAndroid Build Coastguard Worker     }
970*f6dc9357SAndroid Build Coastguard Worker   }
971*f6dc9357SAndroid Build Coastguard Worker   s.SetFrom((const char *)(p + posCur), (unsigned)(pos - posCur));
972*f6dc9357SAndroid Build Coastguard Worker   posCur = pos + numDigits;
973*f6dc9357SAndroid Build Coastguard Worker   return true;
974*f6dc9357SAndroid Build Coastguard Worker }
975*f6dc9357SAndroid Build Coastguard Worker 
976*f6dc9357SAndroid Build Coastguard Worker 
Is_CR_LF_Data(const Byte * buf,size_t size)977*f6dc9357SAndroid Build Coastguard Worker static bool Is_CR_LF_Data(const Byte *buf, size_t size)
978*f6dc9357SAndroid Build Coastguard Worker {
979*f6dc9357SAndroid Build Coastguard Worker   bool isCrLf = false;
980*f6dc9357SAndroid Build Coastguard Worker   for (size_t i = 0; i < size;)
981*f6dc9357SAndroid Build Coastguard Worker   {
982*f6dc9357SAndroid Build Coastguard Worker     const Byte b = buf[i];
983*f6dc9357SAndroid Build Coastguard Worker     if (b == 0x0a)
984*f6dc9357SAndroid Build Coastguard Worker       return false;
985*f6dc9357SAndroid Build Coastguard Worker     if (b == 0x0d)
986*f6dc9357SAndroid Build Coastguard Worker     {
987*f6dc9357SAndroid Build Coastguard Worker       if (i == size - 1)
988*f6dc9357SAndroid Build Coastguard Worker         return false;
989*f6dc9357SAndroid Build Coastguard Worker       if (buf[i + 1] != 0x0a)
990*f6dc9357SAndroid Build Coastguard Worker         return false;
991*f6dc9357SAndroid Build Coastguard Worker       isCrLf = true;
992*f6dc9357SAndroid Build Coastguard Worker       i += 2;
993*f6dc9357SAndroid Build Coastguard Worker     }
994*f6dc9357SAndroid Build Coastguard Worker     else
995*f6dc9357SAndroid Build Coastguard Worker       i++;
996*f6dc9357SAndroid Build Coastguard Worker   }
997*f6dc9357SAndroid Build Coastguard Worker   return isCrLf;
998*f6dc9357SAndroid Build Coastguard Worker }
999*f6dc9357SAndroid Build Coastguard Worker 
1000*f6dc9357SAndroid Build Coastguard Worker 
1001*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
1002*f6dc9357SAndroid Build Coastguard Worker {
1003*f6dc9357SAndroid Build Coastguard Worker   // kpidComment,
1004*f6dc9357SAndroid Build Coastguard Worker   kpidCharacts
1005*f6dc9357SAndroid Build Coastguard Worker };
1006*f6dc9357SAndroid Build Coastguard Worker 
1007*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
1008*f6dc9357SAndroid Build Coastguard Worker {
1009*f6dc9357SAndroid Build Coastguard Worker   kpidPath,
1010*f6dc9357SAndroid Build Coastguard Worker   kpidSize,
1011*f6dc9357SAndroid Build Coastguard Worker   kpidPackSize,
1012*f6dc9357SAndroid Build Coastguard Worker   kpidMethod
1013*f6dc9357SAndroid Build Coastguard Worker };
1014*f6dc9357SAndroid Build Coastguard Worker 
1015*f6dc9357SAndroid Build Coastguard Worker static const Byte kRawProps[] =
1016*f6dc9357SAndroid Build Coastguard Worker {
1017*f6dc9357SAndroid Build Coastguard Worker   kpidChecksum
1018*f6dc9357SAndroid Build Coastguard Worker };
1019*f6dc9357SAndroid Build Coastguard Worker 
1020*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetParent (UInt32,UInt32 * parent,UInt32 * parentType))1021*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetParent(UInt32 /* index */ , UInt32 *parent, UInt32 *parentType))
1022*f6dc9357SAndroid Build Coastguard Worker {
1023*f6dc9357SAndroid Build Coastguard Worker   *parentType = NParentType::kDir;
1024*f6dc9357SAndroid Build Coastguard Worker   *parent = (UInt32)(Int32)-1;
1025*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1026*f6dc9357SAndroid Build Coastguard Worker }
1027*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetNumRawProps (UInt32 * numProps))1028*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))
1029*f6dc9357SAndroid Build Coastguard Worker {
1030*f6dc9357SAndroid Build Coastguard Worker   *numProps = Z7_ARRAY_SIZE(kRawProps);
1031*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1032*f6dc9357SAndroid Build Coastguard Worker }
1033*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetRawPropInfo (UInt32 index,BSTR * name,PROPID * propID))1034*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID))
1035*f6dc9357SAndroid Build Coastguard Worker {
1036*f6dc9357SAndroid Build Coastguard Worker   *propID = kRawProps[index];
1037*f6dc9357SAndroid Build Coastguard Worker   *name = NULL;
1038*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1039*f6dc9357SAndroid Build Coastguard Worker }
1040*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetRawProp (UInt32 index,PROPID propID,const void ** data,UInt32 * dataSize,UInt32 * propType))1041*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))
1042*f6dc9357SAndroid Build Coastguard Worker {
1043*f6dc9357SAndroid Build Coastguard Worker   *data = NULL;
1044*f6dc9357SAndroid Build Coastguard Worker   *dataSize = 0;
1045*f6dc9357SAndroid Build Coastguard Worker   *propType = 0;
1046*f6dc9357SAndroid Build Coastguard Worker 
1047*f6dc9357SAndroid Build Coastguard Worker   if (propID == kpidChecksum)
1048*f6dc9357SAndroid Build Coastguard Worker   {
1049*f6dc9357SAndroid Build Coastguard Worker     const CHashPair &hp = HashPairs[index];
1050*f6dc9357SAndroid Build Coastguard Worker     if (hp.Hash.Size() > 0)
1051*f6dc9357SAndroid Build Coastguard Worker     {
1052*f6dc9357SAndroid Build Coastguard Worker       *data = hp.Hash;
1053*f6dc9357SAndroid Build Coastguard Worker       *dataSize = (UInt32)hp.Hash.Size();
1054*f6dc9357SAndroid Build Coastguard Worker       *propType = NPropDataType::kRaw;
1055*f6dc9357SAndroid Build Coastguard Worker     }
1056*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1057*f6dc9357SAndroid Build Coastguard Worker   }
1058*f6dc9357SAndroid Build Coastguard Worker 
1059*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1060*f6dc9357SAndroid Build Coastguard Worker }
1061*f6dc9357SAndroid Build Coastguard Worker 
1062*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
1063*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
1064*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetNumberOfItems (UInt32 * numItems))1065*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
1066*f6dc9357SAndroid Build Coastguard Worker {
1067*f6dc9357SAndroid Build Coastguard Worker   *numItems = HashPairs.Size();
1068*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1069*f6dc9357SAndroid Build Coastguard Worker }
1070*f6dc9357SAndroid Build Coastguard Worker 
Add_OptSpace_String(UString & dest,const char * src)1071*f6dc9357SAndroid Build Coastguard Worker static void Add_OptSpace_String(UString &dest, const char *src)
1072*f6dc9357SAndroid Build Coastguard Worker {
1073*f6dc9357SAndroid Build Coastguard Worker   dest.Add_Space_if_NotEmpty();
1074*f6dc9357SAndroid Build Coastguard Worker   dest += src;
1075*f6dc9357SAndroid Build Coastguard Worker }
1076*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetArchiveProperty (PROPID propID,PROPVARIANT * value))1077*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1078*f6dc9357SAndroid Build Coastguard Worker {
1079*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
1080*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
1081*f6dc9357SAndroid Build Coastguard Worker   {
1082*f6dc9357SAndroid Build Coastguard Worker     case kpidPhySize: if (_phySize != 0) prop = _phySize; break;
1083*f6dc9357SAndroid Build Coastguard Worker     /*
1084*f6dc9357SAndroid Build Coastguard Worker     case kpidErrorFlags:
1085*f6dc9357SAndroid Build Coastguard Worker     {
1086*f6dc9357SAndroid Build Coastguard Worker       UInt32 v = 0;
1087*f6dc9357SAndroid Build Coastguard Worker       if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
1088*f6dc9357SAndroid Build Coastguard Worker       // if (_sres == k_Base64_RES_NeedMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
1089*f6dc9357SAndroid Build Coastguard Worker       if (v != 0)
1090*f6dc9357SAndroid Build Coastguard Worker         prop = v;
1091*f6dc9357SAndroid Build Coastguard Worker       break;
1092*f6dc9357SAndroid Build Coastguard Worker     }
1093*f6dc9357SAndroid Build Coastguard Worker     */
1094*f6dc9357SAndroid Build Coastguard Worker     case kpidCharacts:
1095*f6dc9357SAndroid Build Coastguard Worker     {
1096*f6dc9357SAndroid Build Coastguard Worker       UString s;
1097*f6dc9357SAndroid Build Coastguard Worker       if (_hashSize_Defined)
1098*f6dc9357SAndroid Build Coastguard Worker       {
1099*f6dc9357SAndroid Build Coastguard Worker         s.Add_Space_if_NotEmpty();
1100*f6dc9357SAndroid Build Coastguard Worker         s.Add_UInt32(_hashSize * 8);
1101*f6dc9357SAndroid Build Coastguard Worker         s += "-bit";
1102*f6dc9357SAndroid Build Coastguard Worker       }
1103*f6dc9357SAndroid Build Coastguard Worker       if (!_nameExtenstion.IsEmpty())
1104*f6dc9357SAndroid Build Coastguard Worker       {
1105*f6dc9357SAndroid Build Coastguard Worker         s.Add_Space_if_NotEmpty();
1106*f6dc9357SAndroid Build Coastguard Worker         s += _nameExtenstion;
1107*f6dc9357SAndroid Build Coastguard Worker       }
1108*f6dc9357SAndroid Build Coastguard Worker       if (_is_PgpMethod)
1109*f6dc9357SAndroid Build Coastguard Worker       {
1110*f6dc9357SAndroid Build Coastguard Worker         Add_OptSpace_String(s, "PGP");
1111*f6dc9357SAndroid Build Coastguard Worker         if (!_pgpMethod.IsEmpty())
1112*f6dc9357SAndroid Build Coastguard Worker         {
1113*f6dc9357SAndroid Build Coastguard Worker           s.Add_Colon();
1114*f6dc9357SAndroid Build Coastguard Worker           s += _pgpMethod;
1115*f6dc9357SAndroid Build Coastguard Worker         }
1116*f6dc9357SAndroid Build Coastguard Worker       }
1117*f6dc9357SAndroid Build Coastguard Worker       if (_is_ZeroMode)
1118*f6dc9357SAndroid Build Coastguard Worker         Add_OptSpace_String(s, "ZERO");
1119*f6dc9357SAndroid Build Coastguard Worker       if (_are_there_Tags)
1120*f6dc9357SAndroid Build Coastguard Worker         Add_OptSpace_String(s, "TAG");
1121*f6dc9357SAndroid Build Coastguard Worker       if (_are_there_Dirs)
1122*f6dc9357SAndroid Build Coastguard Worker         Add_OptSpace_String(s, "DIRS");
1123*f6dc9357SAndroid Build Coastguard Worker       prop = s;
1124*f6dc9357SAndroid Build Coastguard Worker       break;
1125*f6dc9357SAndroid Build Coastguard Worker     }
1126*f6dc9357SAndroid Build Coastguard Worker 
1127*f6dc9357SAndroid Build Coastguard Worker     case kpidReadOnly:
1128*f6dc9357SAndroid Build Coastguard Worker     {
1129*f6dc9357SAndroid Build Coastguard Worker       if (_isArc)
1130*f6dc9357SAndroid Build Coastguard Worker         if (!CanUpdate())
1131*f6dc9357SAndroid Build Coastguard Worker           prop = true;
1132*f6dc9357SAndroid Build Coastguard Worker       break;
1133*f6dc9357SAndroid Build Coastguard Worker     }
1134*f6dc9357SAndroid Build Coastguard Worker     default: break;
1135*f6dc9357SAndroid Build Coastguard Worker   }
1136*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
1137*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1138*f6dc9357SAndroid Build Coastguard Worker }
1139*f6dc9357SAndroid Build Coastguard Worker 
1140*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetProperty (UInt32 index,PROPID propID,PROPVARIANT * value))1141*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
1142*f6dc9357SAndroid Build Coastguard Worker {
1143*f6dc9357SAndroid Build Coastguard Worker   // COM_TRY_BEGIN
1144*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
1145*f6dc9357SAndroid Build Coastguard Worker   const CHashPair &hp = HashPairs[index];
1146*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
1147*f6dc9357SAndroid Build Coastguard Worker   {
1148*f6dc9357SAndroid Build Coastguard Worker     case kpidIsDir:
1149*f6dc9357SAndroid Build Coastguard Worker     {
1150*f6dc9357SAndroid Build Coastguard Worker       prop = hp.IsDir();
1151*f6dc9357SAndroid Build Coastguard Worker       break;
1152*f6dc9357SAndroid Build Coastguard Worker     }
1153*f6dc9357SAndroid Build Coastguard Worker     case kpidPath:
1154*f6dc9357SAndroid Build Coastguard Worker     {
1155*f6dc9357SAndroid Build Coastguard Worker       UString path;
1156*f6dc9357SAndroid Build Coastguard Worker       hp.Get_UString_Path(path);
1157*f6dc9357SAndroid Build Coastguard Worker 
1158*f6dc9357SAndroid Build Coastguard Worker       bool useBackslashReplacement = true;
1159*f6dc9357SAndroid Build Coastguard Worker       if (_supportWindowsBackslash && !hp.Escape && path.Find(L"\\\\") < 0)
1160*f6dc9357SAndroid Build Coastguard Worker       {
1161*f6dc9357SAndroid Build Coastguard Worker #if WCHAR_PATH_SEPARATOR == L'/'
1162*f6dc9357SAndroid Build Coastguard Worker         path.Replace(L'\\', L'/');
1163*f6dc9357SAndroid Build Coastguard Worker #else
1164*f6dc9357SAndroid Build Coastguard Worker         useBackslashReplacement = false;
1165*f6dc9357SAndroid Build Coastguard Worker #endif
1166*f6dc9357SAndroid Build Coastguard Worker       }
1167*f6dc9357SAndroid Build Coastguard Worker       NArchive::NItemName::ReplaceToOsSlashes_Remove_TailSlash(
1168*f6dc9357SAndroid Build Coastguard Worker           path, useBackslashReplacement);
1169*f6dc9357SAndroid Build Coastguard Worker       prop = path;
1170*f6dc9357SAndroid Build Coastguard Worker       break;
1171*f6dc9357SAndroid Build Coastguard Worker     }
1172*f6dc9357SAndroid Build Coastguard Worker     case kpidSize:
1173*f6dc9357SAndroid Build Coastguard Worker     {
1174*f6dc9357SAndroid Build Coastguard Worker       // client needs processed size of last file
1175*f6dc9357SAndroid Build Coastguard Worker       if (hp.Size_from_Disk_Defined)
1176*f6dc9357SAndroid Build Coastguard Worker         prop = (UInt64)hp.Size_from_Disk;
1177*f6dc9357SAndroid Build Coastguard Worker       else if (hp.Size_from_Arc_Defined)
1178*f6dc9357SAndroid Build Coastguard Worker         prop = (UInt64)hp.Size_from_Arc;
1179*f6dc9357SAndroid Build Coastguard Worker       break;
1180*f6dc9357SAndroid Build Coastguard Worker     }
1181*f6dc9357SAndroid Build Coastguard Worker     case kpidPackSize:
1182*f6dc9357SAndroid Build Coastguard Worker     {
1183*f6dc9357SAndroid Build Coastguard Worker       prop = (UInt64)hp.Hash.Size();
1184*f6dc9357SAndroid Build Coastguard Worker       break;
1185*f6dc9357SAndroid Build Coastguard Worker     }
1186*f6dc9357SAndroid Build Coastguard Worker     case kpidMethod:
1187*f6dc9357SAndroid Build Coastguard Worker     {
1188*f6dc9357SAndroid Build Coastguard Worker       if (!hp.Method.IsEmpty())
1189*f6dc9357SAndroid Build Coastguard Worker         prop = hp.Method;
1190*f6dc9357SAndroid Build Coastguard Worker       break;
1191*f6dc9357SAndroid Build Coastguard Worker     }
1192*f6dc9357SAndroid Build Coastguard Worker     default: break;
1193*f6dc9357SAndroid Build Coastguard Worker   }
1194*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
1195*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1196*f6dc9357SAndroid Build Coastguard Worker   // COM_TRY_END
1197*f6dc9357SAndroid Build Coastguard Worker }
1198*f6dc9357SAndroid Build Coastguard Worker 
1199*f6dc9357SAndroid Build Coastguard Worker 
ReadStream_to_Buf(IInStream * stream,CByteBuffer & buf,IArchiveOpenCallback * openCallback)1200*f6dc9357SAndroid Build Coastguard Worker static HRESULT ReadStream_to_Buf(IInStream *stream, CByteBuffer &buf, IArchiveOpenCallback *openCallback)
1201*f6dc9357SAndroid Build Coastguard Worker {
1202*f6dc9357SAndroid Build Coastguard Worker   buf.Free();
1203*f6dc9357SAndroid Build Coastguard Worker   UInt64 len;
1204*f6dc9357SAndroid Build Coastguard Worker   RINOK(InStream_AtBegin_GetSize(stream, len))
1205*f6dc9357SAndroid Build Coastguard Worker   if (len == 0 || len >= ((UInt64)1 << 31))
1206*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
1207*f6dc9357SAndroid Build Coastguard Worker   buf.Alloc((size_t)len);
1208*f6dc9357SAndroid Build Coastguard Worker   UInt64 pos = 0;
1209*f6dc9357SAndroid Build Coastguard Worker   // return ReadStream_FALSE(stream, buf, (size_t)len);
1210*f6dc9357SAndroid Build Coastguard Worker   for (;;)
1211*f6dc9357SAndroid Build Coastguard Worker   {
1212*f6dc9357SAndroid Build Coastguard Worker     const UInt32 kBlockSize = ((UInt32)1 << 24);
1213*f6dc9357SAndroid Build Coastguard Worker     const UInt32 curSize = (len < kBlockSize) ? (UInt32)len : kBlockSize;
1214*f6dc9357SAndroid Build Coastguard Worker     UInt32 processedSizeLoc;
1215*f6dc9357SAndroid Build Coastguard Worker     RINOK(stream->Read((Byte *)buf + pos, curSize, &processedSizeLoc))
1216*f6dc9357SAndroid Build Coastguard Worker     if (processedSizeLoc == 0)
1217*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
1218*f6dc9357SAndroid Build Coastguard Worker     len -= processedSizeLoc;
1219*f6dc9357SAndroid Build Coastguard Worker     pos += processedSizeLoc;
1220*f6dc9357SAndroid Build Coastguard Worker     if (len == 0)
1221*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
1222*f6dc9357SAndroid Build Coastguard Worker     if (openCallback)
1223*f6dc9357SAndroid Build Coastguard Worker     {
1224*f6dc9357SAndroid Build Coastguard Worker       const UInt64 files = 0;
1225*f6dc9357SAndroid Build Coastguard Worker       RINOK(openCallback->SetCompleted(&files, &pos))
1226*f6dc9357SAndroid Build Coastguard Worker     }
1227*f6dc9357SAndroid Build Coastguard Worker   }
1228*f6dc9357SAndroid Build Coastguard Worker }
1229*f6dc9357SAndroid Build Coastguard Worker 
1230*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::Open (IInStream * stream,const UInt64 *,IArchiveOpenCallback * openCallback))1231*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback))
1232*f6dc9357SAndroid Build Coastguard Worker {
1233*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
1234*f6dc9357SAndroid Build Coastguard Worker   {
1235*f6dc9357SAndroid Build Coastguard Worker     Close();
1236*f6dc9357SAndroid Build Coastguard Worker 
1237*f6dc9357SAndroid Build Coastguard Worker     CByteBuffer buf;
1238*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadStream_to_Buf(stream, buf, openCallback))
1239*f6dc9357SAndroid Build Coastguard Worker 
1240*f6dc9357SAndroid Build Coastguard Worker     CObjectVector<CHashPair> &pairs = HashPairs;
1241*f6dc9357SAndroid Build Coastguard Worker 
1242*f6dc9357SAndroid Build Coastguard Worker     bool zeroMode = false;
1243*f6dc9357SAndroid Build Coastguard Worker     bool cr_lf_Mode = false;
1244*f6dc9357SAndroid Build Coastguard Worker     {
1245*f6dc9357SAndroid Build Coastguard Worker       for (size_t i = 0; i < buf.Size(); i++)
1246*f6dc9357SAndroid Build Coastguard Worker         if (buf.ConstData()[i] == 0)
1247*f6dc9357SAndroid Build Coastguard Worker         {
1248*f6dc9357SAndroid Build Coastguard Worker           zeroMode = true;
1249*f6dc9357SAndroid Build Coastguard Worker           break;
1250*f6dc9357SAndroid Build Coastguard Worker         }
1251*f6dc9357SAndroid Build Coastguard Worker     }
1252*f6dc9357SAndroid Build Coastguard Worker     _is_ZeroMode = zeroMode;
1253*f6dc9357SAndroid Build Coastguard Worker     if (!zeroMode)
1254*f6dc9357SAndroid Build Coastguard Worker       cr_lf_Mode = Is_CR_LF_Data(buf, buf.Size());
1255*f6dc9357SAndroid Build Coastguard Worker 
1256*f6dc9357SAndroid Build Coastguard Worker     if (openCallback)
1257*f6dc9357SAndroid Build Coastguard Worker     {
1258*f6dc9357SAndroid Build Coastguard Worker       Z7_DECL_CMyComPtr_QI_FROM(
1259*f6dc9357SAndroid Build Coastguard Worker           IArchiveOpenVolumeCallback,
1260*f6dc9357SAndroid Build Coastguard Worker           openVolumeCallback, openCallback)
1261*f6dc9357SAndroid Build Coastguard Worker       if (openVolumeCallback)
1262*f6dc9357SAndroid Build Coastguard Worker       {
1263*f6dc9357SAndroid Build Coastguard Worker         NCOM::CPropVariant prop;
1264*f6dc9357SAndroid Build Coastguard Worker         RINOK(openVolumeCallback->GetProperty(kpidName, &prop))
1265*f6dc9357SAndroid Build Coastguard Worker         if (prop.vt == VT_BSTR)
1266*f6dc9357SAndroid Build Coastguard Worker           _nameExtenstion = GetMethod_from_FileName(prop.bstrVal);
1267*f6dc9357SAndroid Build Coastguard Worker       }
1268*f6dc9357SAndroid Build Coastguard Worker     }
1269*f6dc9357SAndroid Build Coastguard Worker 
1270*f6dc9357SAndroid Build Coastguard Worker     bool cksumMode = false;
1271*f6dc9357SAndroid Build Coastguard Worker     if (_nameExtenstion.IsEqualTo_Ascii_NoCase("cksum"))
1272*f6dc9357SAndroid Build Coastguard Worker       cksumMode = true;
1273*f6dc9357SAndroid Build Coastguard Worker     _is_CksumMode = cksumMode;
1274*f6dc9357SAndroid Build Coastguard Worker 
1275*f6dc9357SAndroid Build Coastguard Worker     size_t pos = 0;
1276*f6dc9357SAndroid Build Coastguard Worker     AString s;
1277*f6dc9357SAndroid Build Coastguard Worker     bool minusMode = false;
1278*f6dc9357SAndroid Build Coastguard Worker     unsigned numLines = 0;
1279*f6dc9357SAndroid Build Coastguard Worker 
1280*f6dc9357SAndroid Build Coastguard Worker     while (pos < buf.Size())
1281*f6dc9357SAndroid Build Coastguard Worker     {
1282*f6dc9357SAndroid Build Coastguard Worker       if (!GetLine(buf, zeroMode, cr_lf_Mode, pos, s))
1283*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1284*f6dc9357SAndroid Build Coastguard Worker       numLines++;
1285*f6dc9357SAndroid Build Coastguard Worker       if (s.IsEmpty())
1286*f6dc9357SAndroid Build Coastguard Worker         continue;
1287*f6dc9357SAndroid Build Coastguard Worker 
1288*f6dc9357SAndroid Build Coastguard Worker       if (s.IsPrefixedBy_Ascii_NoCase("; "))
1289*f6dc9357SAndroid Build Coastguard Worker       {
1290*f6dc9357SAndroid Build Coastguard Worker         if (numLines != 1)
1291*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
1292*f6dc9357SAndroid Build Coastguard Worker         // comment line of FileVerifier++
1293*f6dc9357SAndroid Build Coastguard Worker         continue;
1294*f6dc9357SAndroid Build Coastguard Worker       }
1295*f6dc9357SAndroid Build Coastguard Worker 
1296*f6dc9357SAndroid Build Coastguard Worker       if (s.IsPrefixedBy_Ascii_NoCase("-----"))
1297*f6dc9357SAndroid Build Coastguard Worker       {
1298*f6dc9357SAndroid Build Coastguard Worker         if (minusMode)
1299*f6dc9357SAndroid Build Coastguard Worker           break; // end of pgp mode
1300*f6dc9357SAndroid Build Coastguard Worker         minusMode = true;
1301*f6dc9357SAndroid Build Coastguard Worker         if (s.IsPrefixedBy_Ascii_NoCase("-----BEGIN PGP SIGNED MESSAGE"))
1302*f6dc9357SAndroid Build Coastguard Worker         {
1303*f6dc9357SAndroid Build Coastguard Worker           if (_is_PgpMethod)
1304*f6dc9357SAndroid Build Coastguard Worker             return S_FALSE;
1305*f6dc9357SAndroid Build Coastguard Worker           if (!GetLine(buf, zeroMode, cr_lf_Mode, pos, s))
1306*f6dc9357SAndroid Build Coastguard Worker             return S_FALSE;
1307*f6dc9357SAndroid Build Coastguard Worker           const char *kStart = "Hash: ";
1308*f6dc9357SAndroid Build Coastguard Worker           if (!s.IsPrefixedBy_Ascii_NoCase(kStart))
1309*f6dc9357SAndroid Build Coastguard Worker             return S_FALSE;
1310*f6dc9357SAndroid Build Coastguard Worker           _pgpMethod = s.Ptr((unsigned)strlen(kStart));
1311*f6dc9357SAndroid Build Coastguard Worker           _is_PgpMethod = true;
1312*f6dc9357SAndroid Build Coastguard Worker         }
1313*f6dc9357SAndroid Build Coastguard Worker         continue;
1314*f6dc9357SAndroid Build Coastguard Worker       }
1315*f6dc9357SAndroid Build Coastguard Worker 
1316*f6dc9357SAndroid Build Coastguard Worker       CHashPair pair;
1317*f6dc9357SAndroid Build Coastguard Worker       pair.FullLine = s;
1318*f6dc9357SAndroid Build Coastguard Worker       if (cksumMode)
1319*f6dc9357SAndroid Build Coastguard Worker       {
1320*f6dc9357SAndroid Build Coastguard Worker         if (!pair.ParseCksum(s))
1321*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
1322*f6dc9357SAndroid Build Coastguard Worker       }
1323*f6dc9357SAndroid Build Coastguard Worker       else if (!pair.Parse(s))
1324*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1325*f6dc9357SAndroid Build Coastguard Worker       pairs.Add(pair);
1326*f6dc9357SAndroid Build Coastguard Worker     }
1327*f6dc9357SAndroid Build Coastguard Worker 
1328*f6dc9357SAndroid Build Coastguard Worker     {
1329*f6dc9357SAndroid Build Coastguard Worker       unsigned hashSize = 0;
1330*f6dc9357SAndroid Build Coastguard Worker       bool hashSize_Dismatch = false;
1331*f6dc9357SAndroid Build Coastguard Worker       for (unsigned i = 0; i < HashPairs.Size(); i++)
1332*f6dc9357SAndroid Build Coastguard Worker       {
1333*f6dc9357SAndroid Build Coastguard Worker         const CHashPair &hp = HashPairs[i];
1334*f6dc9357SAndroid Build Coastguard Worker         if (i == 0)
1335*f6dc9357SAndroid Build Coastguard Worker           hashSize = (unsigned)hp.Hash.Size();
1336*f6dc9357SAndroid Build Coastguard Worker         else
1337*f6dc9357SAndroid Build Coastguard Worker           if (hashSize != hp.Hash.Size())
1338*f6dc9357SAndroid Build Coastguard Worker             hashSize_Dismatch = true;
1339*f6dc9357SAndroid Build Coastguard Worker 
1340*f6dc9357SAndroid Build Coastguard Worker         if (hp.IsBSD)
1341*f6dc9357SAndroid Build Coastguard Worker           _are_there_Tags = true;
1342*f6dc9357SAndroid Build Coastguard Worker         if (!_are_there_Dirs && hp.IsDir())
1343*f6dc9357SAndroid Build Coastguard Worker           _are_there_Dirs = true;
1344*f6dc9357SAndroid Build Coastguard Worker       }
1345*f6dc9357SAndroid Build Coastguard Worker       if (!hashSize_Dismatch && hashSize != 0)
1346*f6dc9357SAndroid Build Coastguard Worker       {
1347*f6dc9357SAndroid Build Coastguard Worker         _hashSize = hashSize;
1348*f6dc9357SAndroid Build Coastguard Worker         _hashSize_Defined = true;
1349*f6dc9357SAndroid Build Coastguard Worker       }
1350*f6dc9357SAndroid Build Coastguard Worker     }
1351*f6dc9357SAndroid Build Coastguard Worker 
1352*f6dc9357SAndroid Build Coastguard Worker     _phySize = buf.Size();
1353*f6dc9357SAndroid Build Coastguard Worker     _isArc = true;
1354*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1355*f6dc9357SAndroid Build Coastguard Worker   }
1356*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
1357*f6dc9357SAndroid Build Coastguard Worker }
1358*f6dc9357SAndroid Build Coastguard Worker 
1359*f6dc9357SAndroid Build Coastguard Worker 
ClearVars()1360*f6dc9357SAndroid Build Coastguard Worker void CHandler::ClearVars()
1361*f6dc9357SAndroid Build Coastguard Worker {
1362*f6dc9357SAndroid Build Coastguard Worker   _phySize = 0;
1363*f6dc9357SAndroid Build Coastguard Worker   _isArc = false;
1364*f6dc9357SAndroid Build Coastguard Worker   _is_CksumMode = false;
1365*f6dc9357SAndroid Build Coastguard Worker   _is_PgpMethod = false;
1366*f6dc9357SAndroid Build Coastguard Worker   _is_ZeroMode = false;
1367*f6dc9357SAndroid Build Coastguard Worker   _are_there_Tags = false;
1368*f6dc9357SAndroid Build Coastguard Worker   _are_there_Dirs = false;
1369*f6dc9357SAndroid Build Coastguard Worker   _hashSize_Defined = false;
1370*f6dc9357SAndroid Build Coastguard Worker   _hashSize = 0;
1371*f6dc9357SAndroid Build Coastguard Worker }
1372*f6dc9357SAndroid Build Coastguard Worker 
1373*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::Close ())1374*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
1375*f6dc9357SAndroid Build Coastguard Worker {
1376*f6dc9357SAndroid Build Coastguard Worker   ClearVars();
1377*f6dc9357SAndroid Build Coastguard Worker   _nameExtenstion.Empty();
1378*f6dc9357SAndroid Build Coastguard Worker   _pgpMethod.Empty();
1379*f6dc9357SAndroid Build Coastguard Worker   HashPairs.Clear();
1380*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1381*f6dc9357SAndroid Build Coastguard Worker }
1382*f6dc9357SAndroid Build Coastguard Worker 
1383*f6dc9357SAndroid Build Coastguard Worker 
CheckDigests(const Byte * a,const Byte * b,size_t size)1384*f6dc9357SAndroid Build Coastguard Worker static bool CheckDigests(const Byte *a, const Byte *b, size_t size)
1385*f6dc9357SAndroid Build Coastguard Worker {
1386*f6dc9357SAndroid Build Coastguard Worker   if (size <= 8)
1387*f6dc9357SAndroid Build Coastguard Worker   {
1388*f6dc9357SAndroid Build Coastguard Worker     /* we use reversed order for one digest, when text representation
1389*f6dc9357SAndroid Build Coastguard Worker        uses big-order for crc-32 and crc-64 */
1390*f6dc9357SAndroid Build Coastguard Worker     for (size_t i = 0; i < size; i++)
1391*f6dc9357SAndroid Build Coastguard Worker       if (a[i] != b[size - 1 - i])
1392*f6dc9357SAndroid Build Coastguard Worker         return false;
1393*f6dc9357SAndroid Build Coastguard Worker     return true;
1394*f6dc9357SAndroid Build Coastguard Worker   }
1395*f6dc9357SAndroid Build Coastguard Worker   {
1396*f6dc9357SAndroid Build Coastguard Worker     for (size_t i = 0; i < size; i++)
1397*f6dc9357SAndroid Build Coastguard Worker       if (a[i] != b[i])
1398*f6dc9357SAndroid Build Coastguard Worker         return false;
1399*f6dc9357SAndroid Build Coastguard Worker     return true;
1400*f6dc9357SAndroid Build Coastguard Worker   }
1401*f6dc9357SAndroid Build Coastguard Worker }
1402*f6dc9357SAndroid Build Coastguard Worker 
1403*f6dc9357SAndroid Build Coastguard Worker 
AddDefaultMethod(UStringVector & methods,unsigned size)1404*f6dc9357SAndroid Build Coastguard Worker static void AddDefaultMethod(UStringVector &methods, unsigned size)
1405*f6dc9357SAndroid Build Coastguard Worker {
1406*f6dc9357SAndroid Build Coastguard Worker   const char *m = NULL;
1407*f6dc9357SAndroid Build Coastguard Worker        if (size == 32) m = "sha256";
1408*f6dc9357SAndroid Build Coastguard Worker   else if (size == 20) m = "sha1";
1409*f6dc9357SAndroid Build Coastguard Worker   else if (size == 16) m = "md5";
1410*f6dc9357SAndroid Build Coastguard Worker   else if (size ==  8) m = "crc64";
1411*f6dc9357SAndroid Build Coastguard Worker   else if (size ==  4) m = "crc32";
1412*f6dc9357SAndroid Build Coastguard Worker   else
1413*f6dc9357SAndroid Build Coastguard Worker     return;
1414*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_EXTERNAL_CODECS
1415*f6dc9357SAndroid Build Coastguard Worker   const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr;
1416*f6dc9357SAndroid Build Coastguard Worker   #endif
1417*f6dc9357SAndroid Build Coastguard Worker   CMethodId id;
1418*f6dc9357SAndroid Build Coastguard Worker   if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS
1419*f6dc9357SAndroid Build Coastguard Worker       AString(m), id))
1420*f6dc9357SAndroid Build Coastguard Worker     methods.Add(UString(m));
1421*f6dc9357SAndroid Build Coastguard Worker }
1422*f6dc9357SAndroid Build Coastguard Worker 
1423*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::Extract (const UInt32 * indices,UInt32 numItems,Int32 testMode,IArchiveExtractCallback * extractCallback))1424*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1425*f6dc9357SAndroid Build Coastguard Worker     Int32 testMode, IArchiveExtractCallback *extractCallback))
1426*f6dc9357SAndroid Build Coastguard Worker {
1427*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
1428*f6dc9357SAndroid Build Coastguard Worker 
1429*f6dc9357SAndroid Build Coastguard Worker   /*
1430*f6dc9357SAndroid Build Coastguard Worker   if (testMode == 0)
1431*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
1432*f6dc9357SAndroid Build Coastguard Worker   */
1433*f6dc9357SAndroid Build Coastguard Worker 
1434*f6dc9357SAndroid Build Coastguard Worker   const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
1435*f6dc9357SAndroid Build Coastguard Worker   if (allFilesMode)
1436*f6dc9357SAndroid Build Coastguard Worker     numItems = HashPairs.Size();
1437*f6dc9357SAndroid Build Coastguard Worker   if (numItems == 0)
1438*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
1439*f6dc9357SAndroid Build Coastguard Worker 
1440*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_EXTERNAL_CODECS
1441*f6dc9357SAndroid Build Coastguard Worker   const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr;
1442*f6dc9357SAndroid Build Coastguard Worker   #endif
1443*f6dc9357SAndroid Build Coastguard Worker 
1444*f6dc9357SAndroid Build Coastguard Worker   CHashBundle hb_Glob;
1445*f6dc9357SAndroid Build Coastguard Worker   // UStringVector methods = options.Methods;
1446*f6dc9357SAndroid Build Coastguard Worker   UStringVector methods;
1447*f6dc9357SAndroid Build Coastguard Worker 
1448*f6dc9357SAndroid Build Coastguard Worker   if (methods.IsEmpty() && !_nameExtenstion.IsEmpty())
1449*f6dc9357SAndroid Build Coastguard Worker   {
1450*f6dc9357SAndroid Build Coastguard Worker     AString utf;
1451*f6dc9357SAndroid Build Coastguard Worker     ConvertUnicodeToUTF8(_nameExtenstion, utf);
1452*f6dc9357SAndroid Build Coastguard Worker     CMethodId id;
1453*f6dc9357SAndroid Build Coastguard Worker     if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS utf, id))
1454*f6dc9357SAndroid Build Coastguard Worker       methods.Add(_nameExtenstion);
1455*f6dc9357SAndroid Build Coastguard Worker   }
1456*f6dc9357SAndroid Build Coastguard Worker 
1457*f6dc9357SAndroid Build Coastguard Worker   if (methods.IsEmpty() && !_pgpMethod.IsEmpty())
1458*f6dc9357SAndroid Build Coastguard Worker   {
1459*f6dc9357SAndroid Build Coastguard Worker     CMethodId id;
1460*f6dc9357SAndroid Build Coastguard Worker     if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS _pgpMethod, id))
1461*f6dc9357SAndroid Build Coastguard Worker       methods.Add(UString(_pgpMethod));
1462*f6dc9357SAndroid Build Coastguard Worker   }
1463*f6dc9357SAndroid Build Coastguard Worker 
1464*f6dc9357SAndroid Build Coastguard Worker   if (methods.IsEmpty() && _pgpMethod.IsEmpty() && _hashSize_Defined)
1465*f6dc9357SAndroid Build Coastguard Worker     AddDefaultMethod(methods, _hashSize);
1466*f6dc9357SAndroid Build Coastguard Worker 
1467*f6dc9357SAndroid Build Coastguard Worker   RINOK(hb_Glob.SetMethods(
1468*f6dc9357SAndroid Build Coastguard Worker       EXTERNAL_CODECS_LOC_VARS
1469*f6dc9357SAndroid Build Coastguard Worker       methods))
1470*f6dc9357SAndroid Build Coastguard Worker 
1471*f6dc9357SAndroid Build Coastguard Worker   Z7_DECL_CMyComPtr_QI_FROM(
1472*f6dc9357SAndroid Build Coastguard Worker       IArchiveUpdateCallbackFile,
1473*f6dc9357SAndroid Build Coastguard Worker       updateCallbackFile, extractCallback)
1474*f6dc9357SAndroid Build Coastguard Worker   if (!updateCallbackFile)
1475*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
1476*f6dc9357SAndroid Build Coastguard Worker   {
1477*f6dc9357SAndroid Build Coastguard Worker     Z7_DECL_CMyComPtr_QI_FROM(
1478*f6dc9357SAndroid Build Coastguard Worker         IArchiveGetDiskProperty,
1479*f6dc9357SAndroid Build Coastguard Worker         GetDiskProperty, extractCallback)
1480*f6dc9357SAndroid Build Coastguard Worker     if (GetDiskProperty)
1481*f6dc9357SAndroid Build Coastguard Worker     {
1482*f6dc9357SAndroid Build Coastguard Worker       UInt64 totalSize = 0;
1483*f6dc9357SAndroid Build Coastguard Worker       UInt32 i;
1484*f6dc9357SAndroid Build Coastguard Worker       for (i = 0; i < numItems; i++)
1485*f6dc9357SAndroid Build Coastguard Worker       {
1486*f6dc9357SAndroid Build Coastguard Worker         const UInt32 index = allFilesMode ? i : indices[i];
1487*f6dc9357SAndroid Build Coastguard Worker         const CHashPair &hp = HashPairs[index];
1488*f6dc9357SAndroid Build Coastguard Worker         if (hp.IsDir())
1489*f6dc9357SAndroid Build Coastguard Worker           continue;
1490*f6dc9357SAndroid Build Coastguard Worker         {
1491*f6dc9357SAndroid Build Coastguard Worker           NCOM::CPropVariant prop;
1492*f6dc9357SAndroid Build Coastguard Worker           RINOK(GetDiskProperty->GetDiskProperty(index, kpidSize, &prop))
1493*f6dc9357SAndroid Build Coastguard Worker           if (prop.vt != VT_UI8)
1494*f6dc9357SAndroid Build Coastguard Worker             continue;
1495*f6dc9357SAndroid Build Coastguard Worker           totalSize += prop.uhVal.QuadPart;
1496*f6dc9357SAndroid Build Coastguard Worker         }
1497*f6dc9357SAndroid Build Coastguard Worker       }
1498*f6dc9357SAndroid Build Coastguard Worker       RINOK(extractCallback->SetTotal(totalSize))
1499*f6dc9357SAndroid Build Coastguard Worker       // RINOK(Hash_SetTotalUnpacked->Hash_SetTotalUnpacked(indices, numItems));
1500*f6dc9357SAndroid Build Coastguard Worker     }
1501*f6dc9357SAndroid Build Coastguard Worker   }
1502*f6dc9357SAndroid Build Coastguard Worker 
1503*f6dc9357SAndroid Build Coastguard Worker   const UInt32 kBufSize = 1 << 15;
1504*f6dc9357SAndroid Build Coastguard Worker   CHashMidBuf buf;
1505*f6dc9357SAndroid Build Coastguard Worker   if (!buf.Alloc(kBufSize))
1506*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
1507*f6dc9357SAndroid Build Coastguard Worker 
1508*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1509*f6dc9357SAndroid Build Coastguard Worker   lps->Init(extractCallback, false);
1510*f6dc9357SAndroid Build Coastguard Worker 
1511*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0;; i++)
1512*f6dc9357SAndroid Build Coastguard Worker   {
1513*f6dc9357SAndroid Build Coastguard Worker     RINOK(lps->SetCur())
1514*f6dc9357SAndroid Build Coastguard Worker     if (i >= numItems)
1515*f6dc9357SAndroid Build Coastguard Worker       break;
1516*f6dc9357SAndroid Build Coastguard Worker     const UInt32 index = allFilesMode ? i : indices[i];
1517*f6dc9357SAndroid Build Coastguard Worker 
1518*f6dc9357SAndroid Build Coastguard Worker     CHashPair &hp = HashPairs[index];
1519*f6dc9357SAndroid Build Coastguard Worker 
1520*f6dc9357SAndroid Build Coastguard Worker     UString path;
1521*f6dc9357SAndroid Build Coastguard Worker     hp.Get_UString_Path(path);
1522*f6dc9357SAndroid Build Coastguard Worker 
1523*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ISequentialInStream> inStream;
1524*f6dc9357SAndroid Build Coastguard Worker     const bool isDir = hp.IsDir();
1525*f6dc9357SAndroid Build Coastguard Worker     if (!isDir)
1526*f6dc9357SAndroid Build Coastguard Worker     {
1527*f6dc9357SAndroid Build Coastguard Worker       RINOK(updateCallbackFile->GetStream2(index, &inStream, NUpdateNotifyOp::kHashRead))
1528*f6dc9357SAndroid Build Coastguard Worker       if (!inStream)
1529*f6dc9357SAndroid Build Coastguard Worker       {
1530*f6dc9357SAndroid Build Coastguard Worker         continue; // we have shown error in GetStream2()
1531*f6dc9357SAndroid Build Coastguard Worker       }
1532*f6dc9357SAndroid Build Coastguard Worker       // askMode = NArchive::NExtract::NAskMode::kSkip;
1533*f6dc9357SAndroid Build Coastguard Worker     }
1534*f6dc9357SAndroid Build Coastguard Worker 
1535*f6dc9357SAndroid Build Coastguard Worker     Int32 askMode = testMode ?
1536*f6dc9357SAndroid Build Coastguard Worker         NArchive::NExtract::NAskMode::kTest :
1537*f6dc9357SAndroid Build Coastguard Worker         NArchive::NExtract::NAskMode::kExtract;
1538*f6dc9357SAndroid Build Coastguard Worker 
1539*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ISequentialOutStream> realOutStream;
1540*f6dc9357SAndroid Build Coastguard Worker     RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
1541*f6dc9357SAndroid Build Coastguard Worker 
1542*f6dc9357SAndroid Build Coastguard Worker     /* PrepareOperation() can expect kExtract to set
1543*f6dc9357SAndroid Build Coastguard Worker        Attrib and security of output file */
1544*f6dc9357SAndroid Build Coastguard Worker     askMode = NArchive::NExtract::NAskMode::kReadExternal;
1545*f6dc9357SAndroid Build Coastguard Worker 
1546*f6dc9357SAndroid Build Coastguard Worker     RINOK(extractCallback->PrepareOperation(askMode))
1547*f6dc9357SAndroid Build Coastguard Worker 
1548*f6dc9357SAndroid Build Coastguard Worker     const bool isAltStream = false;
1549*f6dc9357SAndroid Build Coastguard Worker 
1550*f6dc9357SAndroid Build Coastguard Worker     UInt64 fileSize = 0;
1551*f6dc9357SAndroid Build Coastguard Worker 
1552*f6dc9357SAndroid Build Coastguard Worker     CHashBundle hb_Loc;
1553*f6dc9357SAndroid Build Coastguard Worker 
1554*f6dc9357SAndroid Build Coastguard Worker     CHashBundle *hb_Use = &hb_Glob;
1555*f6dc9357SAndroid Build Coastguard Worker 
1556*f6dc9357SAndroid Build Coastguard Worker     HRESULT res_SetMethods = S_OK;
1557*f6dc9357SAndroid Build Coastguard Worker 
1558*f6dc9357SAndroid Build Coastguard Worker     UStringVector methods_loc;
1559*f6dc9357SAndroid Build Coastguard Worker 
1560*f6dc9357SAndroid Build Coastguard Worker     if (!hp.Method.IsEmpty())
1561*f6dc9357SAndroid Build Coastguard Worker     {
1562*f6dc9357SAndroid Build Coastguard Worker       hb_Use = &hb_Loc;
1563*f6dc9357SAndroid Build Coastguard Worker       CMethodId id;
1564*f6dc9357SAndroid Build Coastguard Worker       if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS hp.Method, id))
1565*f6dc9357SAndroid Build Coastguard Worker       {
1566*f6dc9357SAndroid Build Coastguard Worker         methods_loc.Add(UString(hp.Method));
1567*f6dc9357SAndroid Build Coastguard Worker         RINOK(hb_Loc.SetMethods(
1568*f6dc9357SAndroid Build Coastguard Worker             EXTERNAL_CODECS_LOC_VARS
1569*f6dc9357SAndroid Build Coastguard Worker             methods_loc))
1570*f6dc9357SAndroid Build Coastguard Worker       }
1571*f6dc9357SAndroid Build Coastguard Worker       else
1572*f6dc9357SAndroid Build Coastguard Worker         res_SetMethods = E_NOTIMPL;
1573*f6dc9357SAndroid Build Coastguard Worker     }
1574*f6dc9357SAndroid Build Coastguard Worker     else if (methods.IsEmpty())
1575*f6dc9357SAndroid Build Coastguard Worker     {
1576*f6dc9357SAndroid Build Coastguard Worker       AddDefaultMethod(methods_loc, (unsigned)hp.Hash.Size());
1577*f6dc9357SAndroid Build Coastguard Worker       if (!methods_loc.IsEmpty())
1578*f6dc9357SAndroid Build Coastguard Worker       {
1579*f6dc9357SAndroid Build Coastguard Worker         hb_Use = &hb_Loc;
1580*f6dc9357SAndroid Build Coastguard Worker         RINOK(hb_Loc.SetMethods(
1581*f6dc9357SAndroid Build Coastguard Worker             EXTERNAL_CODECS_LOC_VARS
1582*f6dc9357SAndroid Build Coastguard Worker             methods_loc))
1583*f6dc9357SAndroid Build Coastguard Worker       }
1584*f6dc9357SAndroid Build Coastguard Worker     }
1585*f6dc9357SAndroid Build Coastguard Worker 
1586*f6dc9357SAndroid Build Coastguard Worker     const bool isSupportedMode = hp.IsSupportedMode();
1587*f6dc9357SAndroid Build Coastguard Worker     hb_Use->InitForNewFile();
1588*f6dc9357SAndroid Build Coastguard Worker 
1589*f6dc9357SAndroid Build Coastguard Worker     if (inStream)
1590*f6dc9357SAndroid Build Coastguard Worker     {
1591*f6dc9357SAndroid Build Coastguard Worker       for (UInt32 step = 0;; step++)
1592*f6dc9357SAndroid Build Coastguard Worker       {
1593*f6dc9357SAndroid Build Coastguard Worker         if ((step & 0xFF) == 0)
1594*f6dc9357SAndroid Build Coastguard Worker         {
1595*f6dc9357SAndroid Build Coastguard Worker           RINOK(lps.Interface()->SetRatioInfo(NULL, &fileSize))
1596*f6dc9357SAndroid Build Coastguard Worker         }
1597*f6dc9357SAndroid Build Coastguard Worker         UInt32 size;
1598*f6dc9357SAndroid Build Coastguard Worker         RINOK(inStream->Read(buf, kBufSize, &size))
1599*f6dc9357SAndroid Build Coastguard Worker         if (size == 0)
1600*f6dc9357SAndroid Build Coastguard Worker           break;
1601*f6dc9357SAndroid Build Coastguard Worker         hb_Use->Update(buf, size);
1602*f6dc9357SAndroid Build Coastguard Worker         if (realOutStream)
1603*f6dc9357SAndroid Build Coastguard Worker         {
1604*f6dc9357SAndroid Build Coastguard Worker           RINOK(WriteStream(realOutStream, buf, size))
1605*f6dc9357SAndroid Build Coastguard Worker         }
1606*f6dc9357SAndroid Build Coastguard Worker         fileSize += size;
1607*f6dc9357SAndroid Build Coastguard Worker       }
1608*f6dc9357SAndroid Build Coastguard Worker 
1609*f6dc9357SAndroid Build Coastguard Worker       hp.Size_from_Disk = fileSize;
1610*f6dc9357SAndroid Build Coastguard Worker       hp.Size_from_Disk_Defined = true;
1611*f6dc9357SAndroid Build Coastguard Worker     }
1612*f6dc9357SAndroid Build Coastguard Worker 
1613*f6dc9357SAndroid Build Coastguard Worker     realOutStream.Release();
1614*f6dc9357SAndroid Build Coastguard Worker     inStream.Release();
1615*f6dc9357SAndroid Build Coastguard Worker 
1616*f6dc9357SAndroid Build Coastguard Worker     lps->InSize += hp.Hash.Size();
1617*f6dc9357SAndroid Build Coastguard Worker     lps->OutSize += fileSize;
1618*f6dc9357SAndroid Build Coastguard Worker 
1619*f6dc9357SAndroid Build Coastguard Worker     hb_Use->Final(isDir, isAltStream, path);
1620*f6dc9357SAndroid Build Coastguard Worker 
1621*f6dc9357SAndroid Build Coastguard Worker     Int32 opRes = NArchive::NExtract::NOperationResult::kUnsupportedMethod;
1622*f6dc9357SAndroid Build Coastguard Worker     if (isSupportedMode
1623*f6dc9357SAndroid Build Coastguard Worker         && res_SetMethods != E_NOTIMPL
1624*f6dc9357SAndroid Build Coastguard Worker         && hb_Use->Hashers.Size() > 0
1625*f6dc9357SAndroid Build Coastguard Worker         )
1626*f6dc9357SAndroid Build Coastguard Worker     {
1627*f6dc9357SAndroid Build Coastguard Worker       const CHasherState &hs = hb_Use->Hashers[0];
1628*f6dc9357SAndroid Build Coastguard Worker       if (hs.DigestSize == hp.Hash.Size())
1629*f6dc9357SAndroid Build Coastguard Worker       {
1630*f6dc9357SAndroid Build Coastguard Worker         opRes = NArchive::NExtract::NOperationResult::kCRCError;
1631*f6dc9357SAndroid Build Coastguard Worker         if (CheckDigests(hp.Hash, hs.Digests[0], hs.DigestSize))
1632*f6dc9357SAndroid Build Coastguard Worker           if (!hp.Size_from_Arc_Defined || hp.Size_from_Arc == fileSize)
1633*f6dc9357SAndroid Build Coastguard Worker             opRes = NArchive::NExtract::NOperationResult::kOK;
1634*f6dc9357SAndroid Build Coastguard Worker       }
1635*f6dc9357SAndroid Build Coastguard Worker     }
1636*f6dc9357SAndroid Build Coastguard Worker 
1637*f6dc9357SAndroid Build Coastguard Worker     RINOK(extractCallback->SetOperationResult(opRes))
1638*f6dc9357SAndroid Build Coastguard Worker   }
1639*f6dc9357SAndroid Build Coastguard Worker 
1640*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1641*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
1642*f6dc9357SAndroid Build Coastguard Worker }
1643*f6dc9357SAndroid Build Coastguard Worker 
1644*f6dc9357SAndroid Build Coastguard Worker 
1645*f6dc9357SAndroid Build Coastguard Worker // ---------- UPDATE ----------
1646*f6dc9357SAndroid Build Coastguard Worker 
1647*f6dc9357SAndroid Build Coastguard Worker struct CUpdateItem
1648*f6dc9357SAndroid Build Coastguard Worker {
1649*f6dc9357SAndroid Build Coastguard Worker   int IndexInArc;
1650*f6dc9357SAndroid Build Coastguard Worker   unsigned IndexInClient;
1651*f6dc9357SAndroid Build Coastguard Worker   UInt64 Size;
1652*f6dc9357SAndroid Build Coastguard Worker   bool NewData;
1653*f6dc9357SAndroid Build Coastguard Worker   bool NewProps;
1654*f6dc9357SAndroid Build Coastguard Worker   bool IsDir;
1655*f6dc9357SAndroid Build Coastguard Worker   UString Path;
1656*f6dc9357SAndroid Build Coastguard Worker 
CUpdateItemNHash::CUpdateItem1657*f6dc9357SAndroid Build Coastguard Worker   CUpdateItem(): Size(0), IsDir(false) {}
1658*f6dc9357SAndroid Build Coastguard Worker };
1659*f6dc9357SAndroid Build Coastguard Worker 
1660*f6dc9357SAndroid Build Coastguard Worker 
GetPropString(IArchiveUpdateCallback * callback,UInt32 index,PROPID propId,UString & res,bool convertSlash)1661*f6dc9357SAndroid Build Coastguard Worker static HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId,
1662*f6dc9357SAndroid Build Coastguard Worker     UString &res,
1663*f6dc9357SAndroid Build Coastguard Worker     bool convertSlash)
1664*f6dc9357SAndroid Build Coastguard Worker {
1665*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
1666*f6dc9357SAndroid Build Coastguard Worker   RINOK(callback->GetProperty(index, propId, &prop))
1667*f6dc9357SAndroid Build Coastguard Worker   if (prop.vt == VT_BSTR)
1668*f6dc9357SAndroid Build Coastguard Worker   {
1669*f6dc9357SAndroid Build Coastguard Worker     res = prop.bstrVal;
1670*f6dc9357SAndroid Build Coastguard Worker     if (convertSlash)
1671*f6dc9357SAndroid Build Coastguard Worker       NArchive::NItemName::ReplaceSlashes_OsToUnix(res);
1672*f6dc9357SAndroid Build Coastguard Worker   }
1673*f6dc9357SAndroid Build Coastguard Worker   else if (prop.vt != VT_EMPTY)
1674*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
1675*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1676*f6dc9357SAndroid Build Coastguard Worker }
1677*f6dc9357SAndroid Build Coastguard Worker 
1678*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::GetFileTimeType (UInt32 * type))1679*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type))
1680*f6dc9357SAndroid Build Coastguard Worker {
1681*f6dc9357SAndroid Build Coastguard Worker   *type = NFileTimeType::kUnix;
1682*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1683*f6dc9357SAndroid Build Coastguard Worker }
1684*f6dc9357SAndroid Build Coastguard Worker 
1685*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::UpdateItems (ISequentialOutStream * outStream,UInt32 numItems,IArchiveUpdateCallback * callback))1686*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
1687*f6dc9357SAndroid Build Coastguard Worker     IArchiveUpdateCallback *callback))
1688*f6dc9357SAndroid Build Coastguard Worker {
1689*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
1690*f6dc9357SAndroid Build Coastguard Worker 
1691*f6dc9357SAndroid Build Coastguard Worker   if (_isArc && !CanUpdate())
1692*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
1693*f6dc9357SAndroid Build Coastguard Worker 
1694*f6dc9357SAndroid Build Coastguard Worker   /*
1695*f6dc9357SAndroid Build Coastguard Worker   Z7_DECL_CMyComPtr_QI_FROM(IArchiveUpdateCallbackArcProp,
1696*f6dc9357SAndroid Build Coastguard Worker       reportArcProp, callback)
1697*f6dc9357SAndroid Build Coastguard Worker   */
1698*f6dc9357SAndroid Build Coastguard Worker 
1699*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CUpdateItem> updateItems;
1700*f6dc9357SAndroid Build Coastguard Worker 
1701*f6dc9357SAndroid Build Coastguard Worker   UInt64 complexity = 0;
1702*f6dc9357SAndroid Build Coastguard Worker 
1703*f6dc9357SAndroid Build Coastguard Worker   UInt32 i;
1704*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < numItems; i++)
1705*f6dc9357SAndroid Build Coastguard Worker   {
1706*f6dc9357SAndroid Build Coastguard Worker     CUpdateItem ui;
1707*f6dc9357SAndroid Build Coastguard Worker     Int32 newData;
1708*f6dc9357SAndroid Build Coastguard Worker     Int32 newProps;
1709*f6dc9357SAndroid Build Coastguard Worker     UInt32 indexInArc;
1710*f6dc9357SAndroid Build Coastguard Worker 
1711*f6dc9357SAndroid Build Coastguard Worker     if (!callback)
1712*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
1713*f6dc9357SAndroid Build Coastguard Worker 
1714*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc))
1715*f6dc9357SAndroid Build Coastguard Worker 
1716*f6dc9357SAndroid Build Coastguard Worker     ui.NewProps = IntToBool(newProps);
1717*f6dc9357SAndroid Build Coastguard Worker     ui.NewData = IntToBool(newData);
1718*f6dc9357SAndroid Build Coastguard Worker     ui.IndexInArc = (int)indexInArc;
1719*f6dc9357SAndroid Build Coastguard Worker     ui.IndexInClient = i;
1720*f6dc9357SAndroid Build Coastguard Worker     if (IntToBool(newProps))
1721*f6dc9357SAndroid Build Coastguard Worker     {
1722*f6dc9357SAndroid Build Coastguard Worker       {
1723*f6dc9357SAndroid Build Coastguard Worker         NCOM::CPropVariant prop;
1724*f6dc9357SAndroid Build Coastguard Worker         RINOK(callback->GetProperty(i, kpidIsDir, &prop))
1725*f6dc9357SAndroid Build Coastguard Worker         if (prop.vt == VT_EMPTY)
1726*f6dc9357SAndroid Build Coastguard Worker           ui.IsDir = false;
1727*f6dc9357SAndroid Build Coastguard Worker         else if (prop.vt != VT_BOOL)
1728*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
1729*f6dc9357SAndroid Build Coastguard Worker         else
1730*f6dc9357SAndroid Build Coastguard Worker           ui.IsDir = (prop.boolVal != VARIANT_FALSE);
1731*f6dc9357SAndroid Build Coastguard Worker       }
1732*f6dc9357SAndroid Build Coastguard Worker 
1733*f6dc9357SAndroid Build Coastguard Worker       RINOK(GetPropString(callback, i, kpidPath, ui.Path,
1734*f6dc9357SAndroid Build Coastguard Worker           true)) // convertSlash
1735*f6dc9357SAndroid Build Coastguard Worker       /*
1736*f6dc9357SAndroid Build Coastguard Worker       if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/')
1737*f6dc9357SAndroid Build Coastguard Worker         ui.Name += '/';
1738*f6dc9357SAndroid Build Coastguard Worker       */
1739*f6dc9357SAndroid Build Coastguard Worker     }
1740*f6dc9357SAndroid Build Coastguard Worker 
1741*f6dc9357SAndroid Build Coastguard Worker     if (IntToBool(newData))
1742*f6dc9357SAndroid Build Coastguard Worker     {
1743*f6dc9357SAndroid Build Coastguard Worker       NCOM::CPropVariant prop;
1744*f6dc9357SAndroid Build Coastguard Worker       RINOK(callback->GetProperty(i, kpidSize, &prop))
1745*f6dc9357SAndroid Build Coastguard Worker       if (prop.vt == VT_UI8)
1746*f6dc9357SAndroid Build Coastguard Worker       {
1747*f6dc9357SAndroid Build Coastguard Worker         ui.Size = prop.uhVal.QuadPart;
1748*f6dc9357SAndroid Build Coastguard Worker         complexity += ui.Size;
1749*f6dc9357SAndroid Build Coastguard Worker       }
1750*f6dc9357SAndroid Build Coastguard Worker       else if (prop.vt == VT_EMPTY)
1751*f6dc9357SAndroid Build Coastguard Worker         ui.Size = (UInt64)(Int64)-1;
1752*f6dc9357SAndroid Build Coastguard Worker       else
1753*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
1754*f6dc9357SAndroid Build Coastguard Worker     }
1755*f6dc9357SAndroid Build Coastguard Worker 
1756*f6dc9357SAndroid Build Coastguard Worker     updateItems.Add(ui);
1757*f6dc9357SAndroid Build Coastguard Worker   }
1758*f6dc9357SAndroid Build Coastguard Worker 
1759*f6dc9357SAndroid Build Coastguard Worker   if (complexity != 0)
1760*f6dc9357SAndroid Build Coastguard Worker   {
1761*f6dc9357SAndroid Build Coastguard Worker     RINOK(callback->SetTotal(complexity))
1762*f6dc9357SAndroid Build Coastguard Worker   }
1763*f6dc9357SAndroid Build Coastguard Worker 
1764*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_EXTERNAL_CODECS
1765*f6dc9357SAndroid Build Coastguard Worker   const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr;
1766*f6dc9357SAndroid Build Coastguard Worker   #endif
1767*f6dc9357SAndroid Build Coastguard Worker 
1768*f6dc9357SAndroid Build Coastguard Worker   CHashBundle hb;
1769*f6dc9357SAndroid Build Coastguard Worker   UStringVector methods;
1770*f6dc9357SAndroid Build Coastguard Worker   if (!_methods.IsEmpty())
1771*f6dc9357SAndroid Build Coastguard Worker   {
1772*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR(k, _methods)
1773*f6dc9357SAndroid Build Coastguard Worker     {
1774*f6dc9357SAndroid Build Coastguard Worker       methods.Add(_methods[k]);
1775*f6dc9357SAndroid Build Coastguard Worker     }
1776*f6dc9357SAndroid Build Coastguard Worker   }
1777*f6dc9357SAndroid Build Coastguard Worker   else if (_crcSize_WasSet)
1778*f6dc9357SAndroid Build Coastguard Worker   {
1779*f6dc9357SAndroid Build Coastguard Worker     AddDefaultMethod(methods, _crcSize);
1780*f6dc9357SAndroid Build Coastguard Worker   }
1781*f6dc9357SAndroid Build Coastguard Worker   else
1782*f6dc9357SAndroid Build Coastguard Worker   {
1783*f6dc9357SAndroid Build Coastguard Worker     Z7_DECL_CMyComPtr_QI_FROM(
1784*f6dc9357SAndroid Build Coastguard Worker         IArchiveGetRootProps,
1785*f6dc9357SAndroid Build Coastguard Worker         getRootProps, callback)
1786*f6dc9357SAndroid Build Coastguard Worker     if (getRootProps)
1787*f6dc9357SAndroid Build Coastguard Worker     {
1788*f6dc9357SAndroid Build Coastguard Worker       NCOM::CPropVariant prop;
1789*f6dc9357SAndroid Build Coastguard Worker       RINOK(getRootProps->GetRootProp(kpidArcFileName, &prop))
1790*f6dc9357SAndroid Build Coastguard Worker       if (prop.vt == VT_BSTR)
1791*f6dc9357SAndroid Build Coastguard Worker       {
1792*f6dc9357SAndroid Build Coastguard Worker         const UString method = GetMethod_from_FileName(prop.bstrVal);
1793*f6dc9357SAndroid Build Coastguard Worker         if (!method.IsEmpty())
1794*f6dc9357SAndroid Build Coastguard Worker           methods.Add(method);
1795*f6dc9357SAndroid Build Coastguard Worker       }
1796*f6dc9357SAndroid Build Coastguard Worker     }
1797*f6dc9357SAndroid Build Coastguard Worker   }
1798*f6dc9357SAndroid Build Coastguard Worker 
1799*f6dc9357SAndroid Build Coastguard Worker   RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS methods))
1800*f6dc9357SAndroid Build Coastguard Worker 
1801*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1802*f6dc9357SAndroid Build Coastguard Worker   lps->Init(callback, true);
1803*f6dc9357SAndroid Build Coastguard Worker 
1804*f6dc9357SAndroid Build Coastguard Worker   const UInt32 kBufSize = 1 << 15;
1805*f6dc9357SAndroid Build Coastguard Worker   CHashMidBuf buf;
1806*f6dc9357SAndroid Build Coastguard Worker   if (!buf.Alloc(kBufSize))
1807*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
1808*f6dc9357SAndroid Build Coastguard Worker 
1809*f6dc9357SAndroid Build Coastguard Worker   CDynLimBuf hashFileString((size_t)1 << 31);
1810*f6dc9357SAndroid Build Coastguard Worker 
1811*f6dc9357SAndroid Build Coastguard Worker   CHashOptionsLocal options = _options;
1812*f6dc9357SAndroid Build Coastguard Worker 
1813*f6dc9357SAndroid Build Coastguard Worker   if (_isArc)
1814*f6dc9357SAndroid Build Coastguard Worker   {
1815*f6dc9357SAndroid Build Coastguard Worker     if (!options.HashMode_Zero.Def && _is_ZeroMode)
1816*f6dc9357SAndroid Build Coastguard Worker       options.HashMode_Zero.Val = true;
1817*f6dc9357SAndroid Build Coastguard Worker     if (!options.HashMode_Tag.Def && _are_there_Tags)
1818*f6dc9357SAndroid Build Coastguard Worker       options.HashMode_Tag.Val = true;
1819*f6dc9357SAndroid Build Coastguard Worker     if (!options.HashMode_Dirs.Def && _are_there_Dirs)
1820*f6dc9357SAndroid Build Coastguard Worker       options.HashMode_Dirs.Val = true;
1821*f6dc9357SAndroid Build Coastguard Worker   }
1822*f6dc9357SAndroid Build Coastguard Worker   if (options.HashMode_OnlyHash.Val && updateItems.Size() != 1)
1823*f6dc9357SAndroid Build Coastguard Worker     options.HashMode_OnlyHash.Val = false;
1824*f6dc9357SAndroid Build Coastguard Worker 
1825*f6dc9357SAndroid Build Coastguard Worker   complexity = 0;
1826*f6dc9357SAndroid Build Coastguard Worker 
1827*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < updateItems.Size(); i++)
1828*f6dc9357SAndroid Build Coastguard Worker   {
1829*f6dc9357SAndroid Build Coastguard Worker     lps->InSize = complexity;
1830*f6dc9357SAndroid Build Coastguard Worker     RINOK(lps->SetCur())
1831*f6dc9357SAndroid Build Coastguard Worker 
1832*f6dc9357SAndroid Build Coastguard Worker     const CUpdateItem &ui = updateItems[i];
1833*f6dc9357SAndroid Build Coastguard Worker 
1834*f6dc9357SAndroid Build Coastguard Worker     /*
1835*f6dc9357SAndroid Build Coastguard Worker     CHashPair item;
1836*f6dc9357SAndroid Build Coastguard Worker     if (!ui.NewProps)
1837*f6dc9357SAndroid Build Coastguard Worker       item = HashPairs[(unsigned)ui.IndexInArc];
1838*f6dc9357SAndroid Build Coastguard Worker     */
1839*f6dc9357SAndroid Build Coastguard Worker 
1840*f6dc9357SAndroid Build Coastguard Worker     if (ui.NewData)
1841*f6dc9357SAndroid Build Coastguard Worker     {
1842*f6dc9357SAndroid Build Coastguard Worker       UInt64 currentComplexity = ui.Size;
1843*f6dc9357SAndroid Build Coastguard Worker       UInt64 fileSize = 0;
1844*f6dc9357SAndroid Build Coastguard Worker 
1845*f6dc9357SAndroid Build Coastguard Worker       CMyComPtr<ISequentialInStream> fileInStream;
1846*f6dc9357SAndroid Build Coastguard Worker       bool needWrite = true;
1847*f6dc9357SAndroid Build Coastguard Worker       {
1848*f6dc9357SAndroid Build Coastguard Worker         HRESULT res = callback->GetStream(ui.IndexInClient, &fileInStream);
1849*f6dc9357SAndroid Build Coastguard Worker 
1850*f6dc9357SAndroid Build Coastguard Worker         if (res == S_FALSE)
1851*f6dc9357SAndroid Build Coastguard Worker           needWrite = false;
1852*f6dc9357SAndroid Build Coastguard Worker         else
1853*f6dc9357SAndroid Build Coastguard Worker         {
1854*f6dc9357SAndroid Build Coastguard Worker           RINOK(res)
1855*f6dc9357SAndroid Build Coastguard Worker 
1856*f6dc9357SAndroid Build Coastguard Worker           if (fileInStream)
1857*f6dc9357SAndroid Build Coastguard Worker           {
1858*f6dc9357SAndroid Build Coastguard Worker             Z7_DECL_CMyComPtr_QI_FROM(
1859*f6dc9357SAndroid Build Coastguard Worker                 IStreamGetSize,
1860*f6dc9357SAndroid Build Coastguard Worker                 streamGetSize, fileInStream)
1861*f6dc9357SAndroid Build Coastguard Worker             if (streamGetSize)
1862*f6dc9357SAndroid Build Coastguard Worker             {
1863*f6dc9357SAndroid Build Coastguard Worker               UInt64 size;
1864*f6dc9357SAndroid Build Coastguard Worker               if (streamGetSize->GetSize(&size) == S_OK)
1865*f6dc9357SAndroid Build Coastguard Worker                 currentComplexity = size;
1866*f6dc9357SAndroid Build Coastguard Worker             }
1867*f6dc9357SAndroid Build Coastguard Worker             /*
1868*f6dc9357SAndroid Build Coastguard Worker             Z7_DECL_CMyComPtr_QI_FROM(
1869*f6dc9357SAndroid Build Coastguard Worker                 IStreamGetProps,
1870*f6dc9357SAndroid Build Coastguard Worker                 getProps, fileInStream)
1871*f6dc9357SAndroid Build Coastguard Worker             if (getProps)
1872*f6dc9357SAndroid Build Coastguard Worker             {
1873*f6dc9357SAndroid Build Coastguard Worker               FILETIME mTime;
1874*f6dc9357SAndroid Build Coastguard Worker               UInt64 size2;
1875*f6dc9357SAndroid Build Coastguard Worker               if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK)
1876*f6dc9357SAndroid Build Coastguard Worker               {
1877*f6dc9357SAndroid Build Coastguard Worker                 currentComplexity = size2;
1878*f6dc9357SAndroid Build Coastguard Worker                 // item.MTime = NTime::FileTimeToUnixTime64(mTime);;
1879*f6dc9357SAndroid Build Coastguard Worker               }
1880*f6dc9357SAndroid Build Coastguard Worker             }
1881*f6dc9357SAndroid Build Coastguard Worker             */
1882*f6dc9357SAndroid Build Coastguard Worker           }
1883*f6dc9357SAndroid Build Coastguard Worker           else
1884*f6dc9357SAndroid Build Coastguard Worker           {
1885*f6dc9357SAndroid Build Coastguard Worker             currentComplexity = 0;
1886*f6dc9357SAndroid Build Coastguard Worker           }
1887*f6dc9357SAndroid Build Coastguard Worker         }
1888*f6dc9357SAndroid Build Coastguard Worker       }
1889*f6dc9357SAndroid Build Coastguard Worker 
1890*f6dc9357SAndroid Build Coastguard Worker       hb.InitForNewFile();
1891*f6dc9357SAndroid Build Coastguard Worker       const bool isDir = ui.IsDir;
1892*f6dc9357SAndroid Build Coastguard Worker 
1893*f6dc9357SAndroid Build Coastguard Worker       if (needWrite && fileInStream && !isDir)
1894*f6dc9357SAndroid Build Coastguard Worker       {
1895*f6dc9357SAndroid Build Coastguard Worker         for (UInt32 step = 0;; step++)
1896*f6dc9357SAndroid Build Coastguard Worker         {
1897*f6dc9357SAndroid Build Coastguard Worker           if ((step & 0xFF) == 0)
1898*f6dc9357SAndroid Build Coastguard Worker           {
1899*f6dc9357SAndroid Build Coastguard Worker             RINOK(lps.Interface()->SetRatioInfo(&fileSize, NULL))
1900*f6dc9357SAndroid Build Coastguard Worker             // RINOK(callback->SetCompleted(&completeValue));
1901*f6dc9357SAndroid Build Coastguard Worker           }
1902*f6dc9357SAndroid Build Coastguard Worker           UInt32 size;
1903*f6dc9357SAndroid Build Coastguard Worker           RINOK(fileInStream->Read(buf, kBufSize, &size))
1904*f6dc9357SAndroid Build Coastguard Worker           if (size == 0)
1905*f6dc9357SAndroid Build Coastguard Worker             break;
1906*f6dc9357SAndroid Build Coastguard Worker           hb.Update(buf, size);
1907*f6dc9357SAndroid Build Coastguard Worker           fileSize += size;
1908*f6dc9357SAndroid Build Coastguard Worker         }
1909*f6dc9357SAndroid Build Coastguard Worker         currentComplexity = fileSize;
1910*f6dc9357SAndroid Build Coastguard Worker       }
1911*f6dc9357SAndroid Build Coastguard Worker 
1912*f6dc9357SAndroid Build Coastguard Worker       fileInStream.Release();
1913*f6dc9357SAndroid Build Coastguard Worker       const bool isAltStream = false;
1914*f6dc9357SAndroid Build Coastguard Worker       hb.Final(isDir, isAltStream, ui.Path);
1915*f6dc9357SAndroid Build Coastguard Worker 
1916*f6dc9357SAndroid Build Coastguard Worker       if (options.HashMode_Dirs.Val || !isDir)
1917*f6dc9357SAndroid Build Coastguard Worker       {
1918*f6dc9357SAndroid Build Coastguard Worker         if (!hb.Hashers.IsEmpty())
1919*f6dc9357SAndroid Build Coastguard Worker           lps->OutSize += hb.Hashers[0].DigestSize;
1920*f6dc9357SAndroid Build Coastguard Worker         WriteLine(hashFileString,
1921*f6dc9357SAndroid Build Coastguard Worker             options,
1922*f6dc9357SAndroid Build Coastguard Worker             ui.Path,
1923*f6dc9357SAndroid Build Coastguard Worker             isDir,
1924*f6dc9357SAndroid Build Coastguard Worker             hb);
1925*f6dc9357SAndroid Build Coastguard Worker         if (hashFileString.IsError())
1926*f6dc9357SAndroid Build Coastguard Worker           return E_OUTOFMEMORY;
1927*f6dc9357SAndroid Build Coastguard Worker       }
1928*f6dc9357SAndroid Build Coastguard Worker 
1929*f6dc9357SAndroid Build Coastguard Worker       complexity += currentComplexity;
1930*f6dc9357SAndroid Build Coastguard Worker 
1931*f6dc9357SAndroid Build Coastguard Worker       /*
1932*f6dc9357SAndroid Build Coastguard Worker       if (reportArcProp)
1933*f6dc9357SAndroid Build Coastguard Worker       {
1934*f6dc9357SAndroid Build Coastguard Worker         PROPVARIANT prop;
1935*f6dc9357SAndroid Build Coastguard Worker         prop.vt = VT_EMPTY;
1936*f6dc9357SAndroid Build Coastguard Worker         prop.wReserved1 = 0;
1937*f6dc9357SAndroid Build Coastguard Worker 
1938*f6dc9357SAndroid Build Coastguard Worker         NCOM::PropVarEm_Set_UInt64(&prop, fileSize);
1939*f6dc9357SAndroid Build Coastguard Worker         RINOK(reportArcProp->ReportProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, kpidSize, &prop));
1940*f6dc9357SAndroid Build Coastguard Worker 
1941*f6dc9357SAndroid Build Coastguard Worker         for (unsigned k = 0; k < hb.Hashers.Size(); k++)
1942*f6dc9357SAndroid Build Coastguard Worker         {
1943*f6dc9357SAndroid Build Coastguard Worker           const CHasherState &hs = hb.Hashers[k];
1944*f6dc9357SAndroid Build Coastguard Worker 
1945*f6dc9357SAndroid Build Coastguard Worker           if (hs.DigestSize == 4 && hs.Name.IsEqualTo_Ascii_NoCase("crc32"))
1946*f6dc9357SAndroid Build Coastguard Worker           {
1947*f6dc9357SAndroid Build Coastguard Worker             NCOM::PropVarEm_Set_UInt32(&prop, GetUi32(hs.Digests[k_HashCalc_Index_Current]));
1948*f6dc9357SAndroid Build Coastguard Worker             RINOK(reportArcProp->ReportProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, kpidCRC, &prop));
1949*f6dc9357SAndroid Build Coastguard Worker           }
1950*f6dc9357SAndroid Build Coastguard Worker           else
1951*f6dc9357SAndroid Build Coastguard Worker           {
1952*f6dc9357SAndroid Build Coastguard Worker             RINOK(reportArcProp->ReportRawProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient,
1953*f6dc9357SAndroid Build Coastguard Worker               kpidChecksum, hs.Digests[k_HashCalc_Index_Current],
1954*f6dc9357SAndroid Build Coastguard Worker               hs.DigestSize, NPropDataType::kRaw));
1955*f6dc9357SAndroid Build Coastguard Worker           }
1956*f6dc9357SAndroid Build Coastguard Worker           RINOK(reportArcProp->ReportFinished(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, NArchive::NUpdate::NOperationResult::kOK));
1957*f6dc9357SAndroid Build Coastguard Worker         }
1958*f6dc9357SAndroid Build Coastguard Worker       }
1959*f6dc9357SAndroid Build Coastguard Worker       */
1960*f6dc9357SAndroid Build Coastguard Worker       RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK))
1961*f6dc9357SAndroid Build Coastguard Worker     }
1962*f6dc9357SAndroid Build Coastguard Worker     else
1963*f6dc9357SAndroid Build Coastguard Worker     {
1964*f6dc9357SAndroid Build Coastguard Worker       // old data
1965*f6dc9357SAndroid Build Coastguard Worker       const CHashPair &existItem = HashPairs[(unsigned)ui.IndexInArc];
1966*f6dc9357SAndroid Build Coastguard Worker       if (ui.NewProps)
1967*f6dc9357SAndroid Build Coastguard Worker       {
1968*f6dc9357SAndroid Build Coastguard Worker         WriteLine(hashFileString,
1969*f6dc9357SAndroid Build Coastguard Worker             options,
1970*f6dc9357SAndroid Build Coastguard Worker             ui.Path,
1971*f6dc9357SAndroid Build Coastguard Worker             ui.IsDir,
1972*f6dc9357SAndroid Build Coastguard Worker             existItem.Method, existItem.HashString
1973*f6dc9357SAndroid Build Coastguard Worker             );
1974*f6dc9357SAndroid Build Coastguard Worker       }
1975*f6dc9357SAndroid Build Coastguard Worker       else
1976*f6dc9357SAndroid Build Coastguard Worker       {
1977*f6dc9357SAndroid Build Coastguard Worker         hashFileString += existItem.FullLine;
1978*f6dc9357SAndroid Build Coastguard Worker         Add_LF(hashFileString, options);
1979*f6dc9357SAndroid Build Coastguard Worker       }
1980*f6dc9357SAndroid Build Coastguard Worker     }
1981*f6dc9357SAndroid Build Coastguard Worker     if (hashFileString.IsError())
1982*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
1983*f6dc9357SAndroid Build Coastguard Worker   }
1984*f6dc9357SAndroid Build Coastguard Worker 
1985*f6dc9357SAndroid Build Coastguard Worker   RINOK(WriteStream(outStream, hashFileString, hashFileString.Len()))
1986*f6dc9357SAndroid Build Coastguard Worker 
1987*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1988*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
1989*f6dc9357SAndroid Build Coastguard Worker }
1990*f6dc9357SAndroid Build Coastguard Worker 
1991*f6dc9357SAndroid Build Coastguard Worker 
1992*f6dc9357SAndroid Build Coastguard Worker 
SetProperty(const wchar_t * nameSpec,const PROPVARIANT & value)1993*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
1994*f6dc9357SAndroid Build Coastguard Worker {
1995*f6dc9357SAndroid Build Coastguard Worker   UString name = nameSpec;
1996*f6dc9357SAndroid Build Coastguard Worker   name.MakeLower_Ascii();
1997*f6dc9357SAndroid Build Coastguard Worker   if (name.IsEmpty())
1998*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
1999*f6dc9357SAndroid Build Coastguard Worker 
2000*f6dc9357SAndroid Build Coastguard Worker   if (name.IsEqualTo("m")) // "hm" hash method
2001*f6dc9357SAndroid Build Coastguard Worker   {
2002*f6dc9357SAndroid Build Coastguard Worker     // COneMethodInfo omi;
2003*f6dc9357SAndroid Build Coastguard Worker     // RINOK(omi.ParseMethodFromPROPVARIANT(L"", value));
2004*f6dc9357SAndroid Build Coastguard Worker     // _methods.Add(omi.MethodName); // change it. use omi.PropsString
2005*f6dc9357SAndroid Build Coastguard Worker     if (value.vt != VT_BSTR)
2006*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
2007*f6dc9357SAndroid Build Coastguard Worker     UString s (value.bstrVal);
2008*f6dc9357SAndroid Build Coastguard Worker     _methods.Add(s);
2009*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
2010*f6dc9357SAndroid Build Coastguard Worker   }
2011*f6dc9357SAndroid Build Coastguard Worker 
2012*f6dc9357SAndroid Build Coastguard Worker   if (name.IsEqualTo("flags"))
2013*f6dc9357SAndroid Build Coastguard Worker   {
2014*f6dc9357SAndroid Build Coastguard Worker     if (value.vt != VT_BSTR)
2015*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
2016*f6dc9357SAndroid Build Coastguard Worker     if (!_options.ParseString(value.bstrVal))
2017*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
2018*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
2019*f6dc9357SAndroid Build Coastguard Worker   }
2020*f6dc9357SAndroid Build Coastguard Worker 
2021*f6dc9357SAndroid Build Coastguard Worker   if (name.IsEqualTo("backslash"))
2022*f6dc9357SAndroid Build Coastguard Worker     return PROPVARIANT_to_bool(value, _supportWindowsBackslash);
2023*f6dc9357SAndroid Build Coastguard Worker 
2024*f6dc9357SAndroid Build Coastguard Worker   if (name.IsPrefixedBy_Ascii_NoCase("crc"))
2025*f6dc9357SAndroid Build Coastguard Worker   {
2026*f6dc9357SAndroid Build Coastguard Worker     name.Delete(0, 3);
2027*f6dc9357SAndroid Build Coastguard Worker     _crcSize = 4;
2028*f6dc9357SAndroid Build Coastguard Worker     _crcSize_WasSet = true;
2029*f6dc9357SAndroid Build Coastguard Worker     return ParsePropToUInt32(name, value, _crcSize);
2030*f6dc9357SAndroid Build Coastguard Worker   }
2031*f6dc9357SAndroid Build Coastguard Worker 
2032*f6dc9357SAndroid Build Coastguard Worker   // common properties
2033*f6dc9357SAndroid Build Coastguard Worker   if (name.IsPrefixedBy_Ascii_NoCase("mt")
2034*f6dc9357SAndroid Build Coastguard Worker       || name.IsPrefixedBy_Ascii_NoCase("memuse"))
2035*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
2036*f6dc9357SAndroid Build Coastguard Worker 
2037*f6dc9357SAndroid Build Coastguard Worker   return E_INVALIDARG;
2038*f6dc9357SAndroid Build Coastguard Worker }
2039*f6dc9357SAndroid Build Coastguard Worker 
2040*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CHandler::SetProperties (const wchar_t * const * names,const PROPVARIANT * values,UInt32 numProps))2041*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
2042*f6dc9357SAndroid Build Coastguard Worker {
2043*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
2044*f6dc9357SAndroid Build Coastguard Worker 
2045*f6dc9357SAndroid Build Coastguard Worker   InitProps();
2046*f6dc9357SAndroid Build Coastguard Worker 
2047*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < numProps; i++)
2048*f6dc9357SAndroid Build Coastguard Worker   {
2049*f6dc9357SAndroid Build Coastguard Worker     RINOK(SetProperty(names[i], values[i]))
2050*f6dc9357SAndroid Build Coastguard Worker   }
2051*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
2052*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
2053*f6dc9357SAndroid Build Coastguard Worker }
2054*f6dc9357SAndroid Build Coastguard Worker 
CHandler()2055*f6dc9357SAndroid Build Coastguard Worker CHandler::CHandler()
2056*f6dc9357SAndroid Build Coastguard Worker {
2057*f6dc9357SAndroid Build Coastguard Worker   ClearVars();
2058*f6dc9357SAndroid Build Coastguard Worker   InitProps();
2059*f6dc9357SAndroid Build Coastguard Worker }
2060*f6dc9357SAndroid Build Coastguard Worker 
2061*f6dc9357SAndroid Build Coastguard Worker }
2062*f6dc9357SAndroid Build Coastguard Worker 
2063*f6dc9357SAndroid Build Coastguard Worker 
2064*f6dc9357SAndroid Build Coastguard Worker 
CreateHashHandler_In()2065*f6dc9357SAndroid Build Coastguard Worker static IInArchive  *CreateHashHandler_In()  { return new NHash::CHandler; }
CreateHashHandler_Out()2066*f6dc9357SAndroid Build Coastguard Worker static IOutArchive *CreateHashHandler_Out() { return new NHash::CHandler; }
2067*f6dc9357SAndroid Build Coastguard Worker 
Codecs_AddHashArcHandler(CCodecs * codecs)2068*f6dc9357SAndroid Build Coastguard Worker void Codecs_AddHashArcHandler(CCodecs *codecs)
2069*f6dc9357SAndroid Build Coastguard Worker {
2070*f6dc9357SAndroid Build Coastguard Worker   {
2071*f6dc9357SAndroid Build Coastguard Worker     CArcInfoEx item;
2072*f6dc9357SAndroid Build Coastguard Worker 
2073*f6dc9357SAndroid Build Coastguard Worker     item.Name = "Hash";
2074*f6dc9357SAndroid Build Coastguard Worker     item.CreateInArchive = CreateHashHandler_In;
2075*f6dc9357SAndroid Build Coastguard Worker     item.CreateOutArchive = CreateHashHandler_Out;
2076*f6dc9357SAndroid Build Coastguard Worker     item.IsArcFunc = NULL;
2077*f6dc9357SAndroid Build Coastguard Worker     item.Flags =
2078*f6dc9357SAndroid Build Coastguard Worker         NArcInfoFlags::kKeepName
2079*f6dc9357SAndroid Build Coastguard Worker       | NArcInfoFlags::kStartOpen
2080*f6dc9357SAndroid Build Coastguard Worker       | NArcInfoFlags::kByExtOnlyOpen
2081*f6dc9357SAndroid Build Coastguard Worker       // | NArcInfoFlags::kPureStartOpen
2082*f6dc9357SAndroid Build Coastguard Worker       | NArcInfoFlags::kHashHandler
2083*f6dc9357SAndroid Build Coastguard Worker       ;
2084*f6dc9357SAndroid Build Coastguard Worker 
2085*f6dc9357SAndroid Build Coastguard Worker     // ubuntu uses "SHA256SUMS" file
2086*f6dc9357SAndroid Build Coastguard Worker     item.AddExts(UString (
2087*f6dc9357SAndroid Build Coastguard Worker         "sha256"
2088*f6dc9357SAndroid Build Coastguard Worker         " sha512"
2089*f6dc9357SAndroid Build Coastguard Worker         " sha384"
2090*f6dc9357SAndroid Build Coastguard Worker         " sha224"
2091*f6dc9357SAndroid Build Coastguard Worker         // " sha512-224"
2092*f6dc9357SAndroid Build Coastguard Worker         // " sha512-256"
2093*f6dc9357SAndroid Build Coastguard Worker         // " sha3-224"
2094*f6dc9357SAndroid Build Coastguard Worker         " sha3-256"
2095*f6dc9357SAndroid Build Coastguard Worker         // " sha3-384"
2096*f6dc9357SAndroid Build Coastguard Worker         // " sha3-512"
2097*f6dc9357SAndroid Build Coastguard Worker         // " shake128"
2098*f6dc9357SAndroid Build Coastguard Worker         // " shake256"
2099*f6dc9357SAndroid Build Coastguard Worker         " sha1"
2100*f6dc9357SAndroid Build Coastguard Worker         " sha"
2101*f6dc9357SAndroid Build Coastguard Worker         " md5"
2102*f6dc9357SAndroid Build Coastguard Worker         " blake2sp"
2103*f6dc9357SAndroid Build Coastguard Worker         " xxh64"
2104*f6dc9357SAndroid Build Coastguard Worker         " crc32 crc64"
2105*f6dc9357SAndroid Build Coastguard Worker         " asc"
2106*f6dc9357SAndroid Build Coastguard Worker         " cksum"
2107*f6dc9357SAndroid Build Coastguard Worker         // " b2sum"
2108*f6dc9357SAndroid Build Coastguard Worker         ),
2109*f6dc9357SAndroid Build Coastguard Worker         UString());
2110*f6dc9357SAndroid Build Coastguard Worker 
2111*f6dc9357SAndroid Build Coastguard Worker     item.UpdateEnabled = (item.CreateOutArchive != NULL);
2112*f6dc9357SAndroid Build Coastguard Worker     item.SignatureOffset = 0;
2113*f6dc9357SAndroid Build Coastguard Worker     // item.Version = MY_VER_MIX;
2114*f6dc9357SAndroid Build Coastguard Worker     item.NewInterface = true;
2115*f6dc9357SAndroid Build Coastguard Worker 
2116*f6dc9357SAndroid Build Coastguard Worker     item.Signatures.AddNew().CopyFrom(NULL, 0);
2117*f6dc9357SAndroid Build Coastguard Worker 
2118*f6dc9357SAndroid Build Coastguard Worker     codecs->Formats.Add(item);
2119*f6dc9357SAndroid Build Coastguard Worker   }
2120*f6dc9357SAndroid Build Coastguard Worker }
2121