1370b324cSopenharmony_ci// HashCalc.h
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#ifndef ZIP7_INC_HASH_CALC_H
4370b324cSopenharmony_ci#define ZIP7_INC_HASH_CALC_H
5370b324cSopenharmony_ci
6370b324cSopenharmony_ci#include "../../../Common/UTFConvert.h"
7370b324cSopenharmony_ci#include "../../../Common/Wildcard.h"
8370b324cSopenharmony_ci
9370b324cSopenharmony_ci#include "../../Common/CreateCoder.h"
10370b324cSopenharmony_ci#include "../../Common/MethodProps.h"
11370b324cSopenharmony_ci
12370b324cSopenharmony_ci#include "DirItem.h"
13370b324cSopenharmony_ci#include "IFileExtractCallback.h"
14370b324cSopenharmony_ci
15370b324cSopenharmony_ciconst unsigned k_HashCalc_DigestSize_Max = 64;
16370b324cSopenharmony_ciconst unsigned k_HashCalc_ExtraSize = 8;
17370b324cSopenharmony_ciconst unsigned k_HashCalc_NumGroups = 4;
18370b324cSopenharmony_ci
19370b324cSopenharmony_ci/*
20370b324cSopenharmony_ci  if (size <= 8) : upper case : reversed byte order : it shows 32-bit/64-bit number, if data contains little-endian number
21370b324cSopenharmony_ci  if (size >  8) : lower case : original byte order (as big-endian byte sequence)
22370b324cSopenharmony_ci*/
23370b324cSopenharmony_civoid HashHexToString(char *dest, const Byte *data, UInt32 size);
24370b324cSopenharmony_ci
25370b324cSopenharmony_cienum
26370b324cSopenharmony_ci{
27370b324cSopenharmony_ci  k_HashCalc_Index_Current,
28370b324cSopenharmony_ci  k_HashCalc_Index_DataSum,
29370b324cSopenharmony_ci  k_HashCalc_Index_NamesSum,
30370b324cSopenharmony_ci  k_HashCalc_Index_StreamsSum
31370b324cSopenharmony_ci};
32370b324cSopenharmony_ci
33370b324cSopenharmony_cistruct CHasherState
34370b324cSopenharmony_ci{
35370b324cSopenharmony_ci  CMyComPtr<IHasher> Hasher;
36370b324cSopenharmony_ci  AString Name;
37370b324cSopenharmony_ci  UInt32 DigestSize;
38370b324cSopenharmony_ci  UInt64 NumSums[k_HashCalc_NumGroups];
39370b324cSopenharmony_ci  Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max + k_HashCalc_ExtraSize];
40370b324cSopenharmony_ci
41370b324cSopenharmony_ci  void InitDigestGroup(unsigned groupIndex)
42370b324cSopenharmony_ci  {
43370b324cSopenharmony_ci    NumSums[groupIndex] = 0;
44370b324cSopenharmony_ci    memset(Digests[groupIndex], 0, sizeof(Digests[groupIndex]));
45370b324cSopenharmony_ci  }
46370b324cSopenharmony_ci
47370b324cSopenharmony_ci  const Byte *GetExtraData_for_Group(unsigned groupIndex) const
48370b324cSopenharmony_ci  {
49370b324cSopenharmony_ci    return Digests[groupIndex] + k_HashCalc_DigestSize_Max;
50370b324cSopenharmony_ci  }
51370b324cSopenharmony_ci
52370b324cSopenharmony_ci  unsigned GetNumExtraBytes_for_Group(unsigned groupIndex) const
53370b324cSopenharmony_ci  {
54370b324cSopenharmony_ci    const Byte *p = GetExtraData_for_Group(groupIndex);
55370b324cSopenharmony_ci    // we use little-endian to read extra bytes
56370b324cSopenharmony_ci    for (unsigned i = k_HashCalc_ExtraSize; i != 0; i--)
57370b324cSopenharmony_ci      if (p[i - 1] != 0)
58370b324cSopenharmony_ci        return i;
59370b324cSopenharmony_ci    return 0;
60370b324cSopenharmony_ci  }
61370b324cSopenharmony_ci
62370b324cSopenharmony_ci  void AddDigest(unsigned groupIndex, const Byte *data);
63370b324cSopenharmony_ci
64370b324cSopenharmony_ci  void WriteToString(unsigned digestIndex, char *s) const;
65370b324cSopenharmony_ci};
66370b324cSopenharmony_ci
67370b324cSopenharmony_ci
68370b324cSopenharmony_ciZ7_PURE_INTERFACES_BEGIN
69370b324cSopenharmony_ci
70370b324cSopenharmony_ci
71370b324cSopenharmony_ciDECLARE_INTERFACE(IHashCalc)
72370b324cSopenharmony_ci{
73370b324cSopenharmony_ci  virtual void InitForNewFile() = 0;
74370b324cSopenharmony_ci  virtual void Update(const void *data, UInt32 size) = 0;
75370b324cSopenharmony_ci  virtual void SetSize(UInt64 size) = 0;
76370b324cSopenharmony_ci  virtual void Final(bool isDir, bool isAltStream, const UString &path) = 0;
77370b324cSopenharmony_ci};
78370b324cSopenharmony_ci
79370b324cSopenharmony_ciZ7_PURE_INTERFACES_END
80370b324cSopenharmony_ci
81370b324cSopenharmony_cistruct CHashBundle Z7_final: public IHashCalc
82370b324cSopenharmony_ci{
83370b324cSopenharmony_ci  CObjectVector<CHasherState> Hashers;
84370b324cSopenharmony_ci
85370b324cSopenharmony_ci  UInt64 NumDirs;
86370b324cSopenharmony_ci  UInt64 NumFiles;
87370b324cSopenharmony_ci  UInt64 NumAltStreams;
88370b324cSopenharmony_ci  UInt64 FilesSize;
89370b324cSopenharmony_ci  UInt64 AltStreamsSize;
90370b324cSopenharmony_ci  UInt64 NumErrors;
91370b324cSopenharmony_ci
92370b324cSopenharmony_ci  UInt64 CurSize;
93370b324cSopenharmony_ci
94370b324cSopenharmony_ci  UString MainName;
95370b324cSopenharmony_ci  UString FirstFileName;
96370b324cSopenharmony_ci
97370b324cSopenharmony_ci  HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods);
98370b324cSopenharmony_ci
99370b324cSopenharmony_ci  // void Init() {}
100370b324cSopenharmony_ci  CHashBundle()
101370b324cSopenharmony_ci  {
102370b324cSopenharmony_ci    NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;
103370b324cSopenharmony_ci  }
104370b324cSopenharmony_ci
105370b324cSopenharmony_ci  void InitForNewFile() Z7_override;
106370b324cSopenharmony_ci  void Update(const void *data, UInt32 size) Z7_override;
107370b324cSopenharmony_ci  void SetSize(UInt64 size) Z7_override;
108370b324cSopenharmony_ci  void Final(bool isDir, bool isAltStream, const UString &path) Z7_override;
109370b324cSopenharmony_ci};
110370b324cSopenharmony_ci
111370b324cSopenharmony_ciZ7_PURE_INTERFACES_BEGIN
112370b324cSopenharmony_ci
113370b324cSopenharmony_ci// INTERFACE_IDirItemsCallback(x)
114370b324cSopenharmony_ci
115370b324cSopenharmony_ci#define Z7_IFACEN_IHashCallbackUI(x) \
116370b324cSopenharmony_ci  virtual HRESULT StartScanning() x \
117370b324cSopenharmony_ci  virtual HRESULT FinishScanning(const CDirItemsStat &st) x \
118370b324cSopenharmony_ci  virtual HRESULT SetNumFiles(UInt64 numFiles) x \
119370b324cSopenharmony_ci  virtual HRESULT SetTotal(UInt64 size) x \
120370b324cSopenharmony_ci  virtual HRESULT SetCompleted(const UInt64 *completeValue) x \
121370b324cSopenharmony_ci  virtual HRESULT CheckBreak() x \
122370b324cSopenharmony_ci  virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x \
123370b324cSopenharmony_ci  virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x \
124370b324cSopenharmony_ci  virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x \
125370b324cSopenharmony_ci  virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x \
126370b324cSopenharmony_ci  virtual HRESULT AfterLastFile(CHashBundle &hb) x \
127370b324cSopenharmony_ci
128370b324cSopenharmony_ciZ7_IFACE_DECL_PURE_(IHashCallbackUI, IDirItemsCallback)
129370b324cSopenharmony_ci
130370b324cSopenharmony_ciZ7_PURE_INTERFACES_END
131370b324cSopenharmony_ci
132370b324cSopenharmony_ci
133370b324cSopenharmony_cistruct CHashOptionsLocal
134370b324cSopenharmony_ci{
135370b324cSopenharmony_ci  CBoolPair HashMode_Zero;
136370b324cSopenharmony_ci  CBoolPair HashMode_Tag;
137370b324cSopenharmony_ci  CBoolPair HashMode_Dirs;
138370b324cSopenharmony_ci  CBoolPair HashMode_OnlyHash;
139370b324cSopenharmony_ci
140370b324cSopenharmony_ci  void Init_HashOptionsLocal()
141370b324cSopenharmony_ci  {
142370b324cSopenharmony_ci    HashMode_Zero.Init();
143370b324cSopenharmony_ci    HashMode_Tag.Init();
144370b324cSopenharmony_ci    HashMode_Dirs.Init();
145370b324cSopenharmony_ci    HashMode_OnlyHash.Init();
146370b324cSopenharmony_ci    // HashMode_Dirs = true; // for debug
147370b324cSopenharmony_ci  }
148370b324cSopenharmony_ci
149370b324cSopenharmony_ci  CHashOptionsLocal()
150370b324cSopenharmony_ci  {
151370b324cSopenharmony_ci    Init_HashOptionsLocal();
152370b324cSopenharmony_ci  }
153370b324cSopenharmony_ci
154370b324cSopenharmony_ci  bool ParseFlagCharOption(wchar_t c, bool val)
155370b324cSopenharmony_ci  {
156370b324cSopenharmony_ci    c = MyCharLower_Ascii(c);
157370b324cSopenharmony_ci         if (c == 'z') HashMode_Zero.SetVal_as_Defined(val);
158370b324cSopenharmony_ci    else if (c == 't') HashMode_Tag.SetVal_as_Defined(val);
159370b324cSopenharmony_ci    else if (c == 'd') HashMode_Dirs.SetVal_as_Defined(val);
160370b324cSopenharmony_ci    else if (c == 'h') HashMode_OnlyHash.SetVal_as_Defined(val);
161370b324cSopenharmony_ci    else return false;
162370b324cSopenharmony_ci    return true;
163370b324cSopenharmony_ci  }
164370b324cSopenharmony_ci
165370b324cSopenharmony_ci  bool ParseString(const UString &s)
166370b324cSopenharmony_ci  {
167370b324cSopenharmony_ci    for (unsigned i = 0; i < s.Len();)
168370b324cSopenharmony_ci    {
169370b324cSopenharmony_ci      const wchar_t c = s[i++];
170370b324cSopenharmony_ci      bool val = true;
171370b324cSopenharmony_ci      if (i < s.Len())
172370b324cSopenharmony_ci      {
173370b324cSopenharmony_ci        const wchar_t next  = s[i];
174370b324cSopenharmony_ci        if (next == '-')
175370b324cSopenharmony_ci        {
176370b324cSopenharmony_ci          val = false;
177370b324cSopenharmony_ci          i++;
178370b324cSopenharmony_ci        }
179370b324cSopenharmony_ci      }
180370b324cSopenharmony_ci      if (!ParseFlagCharOption(c, val))
181370b324cSopenharmony_ci        return false;
182370b324cSopenharmony_ci    }
183370b324cSopenharmony_ci    return true;
184370b324cSopenharmony_ci  }
185370b324cSopenharmony_ci};
186370b324cSopenharmony_ci
187370b324cSopenharmony_ci
188370b324cSopenharmony_cistruct CHashOptions
189370b324cSopenharmony_ci  // : public CHashOptionsLocal
190370b324cSopenharmony_ci{
191370b324cSopenharmony_ci  UStringVector Methods;
192370b324cSopenharmony_ci  // UString HashFilePath;
193370b324cSopenharmony_ci
194370b324cSopenharmony_ci  bool PreserveATime;
195370b324cSopenharmony_ci  bool OpenShareForWrite;
196370b324cSopenharmony_ci  bool StdInMode;
197370b324cSopenharmony_ci  bool AltStreamsMode;
198370b324cSopenharmony_ci  CBoolPair SymLinks;
199370b324cSopenharmony_ci
200370b324cSopenharmony_ci  NWildcard::ECensorPathMode PathMode;
201370b324cSopenharmony_ci
202370b324cSopenharmony_ci  CHashOptions():
203370b324cSopenharmony_ci      PreserveATime(false),
204370b324cSopenharmony_ci      OpenShareForWrite(false),
205370b324cSopenharmony_ci      StdInMode(false),
206370b324cSopenharmony_ci      AltStreamsMode(false),
207370b324cSopenharmony_ci      PathMode(NWildcard::k_RelatPath) {}
208370b324cSopenharmony_ci};
209370b324cSopenharmony_ci
210370b324cSopenharmony_ci
211370b324cSopenharmony_ciHRESULT HashCalc(
212370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
213370b324cSopenharmony_ci    const NWildcard::CCensor &censor,
214370b324cSopenharmony_ci    const CHashOptions &options,
215370b324cSopenharmony_ci    AString &errorInfo,
216370b324cSopenharmony_ci    IHashCallbackUI *callback);
217370b324cSopenharmony_ci
218370b324cSopenharmony_ci
219370b324cSopenharmony_ci
220370b324cSopenharmony_ci#ifndef Z7_SFX
221370b324cSopenharmony_ci
222370b324cSopenharmony_cinamespace NHash {
223370b324cSopenharmony_ci
224370b324cSopenharmony_cistruct CHashPair
225370b324cSopenharmony_ci{
226370b324cSopenharmony_ci  CByteBuffer Hash;
227370b324cSopenharmony_ci  char Mode;
228370b324cSopenharmony_ci  bool IsBSD;
229370b324cSopenharmony_ci  bool Size_from_Arc_Defined;
230370b324cSopenharmony_ci  bool Size_from_Disk_Defined;
231370b324cSopenharmony_ci  AString Method;
232370b324cSopenharmony_ci  AString Name;
233370b324cSopenharmony_ci
234370b324cSopenharmony_ci  AString FullLine;
235370b324cSopenharmony_ci  AString HashString;
236370b324cSopenharmony_ci  // unsigned HashLengthInBits;
237370b324cSopenharmony_ci
238370b324cSopenharmony_ci  // AString MethodName;
239370b324cSopenharmony_ci  UInt64 Size_from_Arc;
240370b324cSopenharmony_ci  UInt64 Size_from_Disk;
241370b324cSopenharmony_ci
242370b324cSopenharmony_ci  bool IsDir() const;
243370b324cSopenharmony_ci
244370b324cSopenharmony_ci  void Get_UString_Path(UString &path) const
245370b324cSopenharmony_ci  {
246370b324cSopenharmony_ci    path.Empty();
247370b324cSopenharmony_ci    if (!ConvertUTF8ToUnicode(Name, path))
248370b324cSopenharmony_ci      return;
249370b324cSopenharmony_ci  }
250370b324cSopenharmony_ci
251370b324cSopenharmony_ci  bool ParseCksum(const char *s);
252370b324cSopenharmony_ci  bool Parse(const char *s);
253370b324cSopenharmony_ci
254370b324cSopenharmony_ci  bool IsSupportedMode() const
255370b324cSopenharmony_ci  {
256370b324cSopenharmony_ci    return Mode != 'U' && Mode != '^';
257370b324cSopenharmony_ci  }
258370b324cSopenharmony_ci
259370b324cSopenharmony_ci  CHashPair():
260370b324cSopenharmony_ci      Mode(0)
261370b324cSopenharmony_ci      , IsBSD(false)
262370b324cSopenharmony_ci      , Size_from_Arc_Defined(false)
263370b324cSopenharmony_ci      , Size_from_Disk_Defined(false)
264370b324cSopenharmony_ci      // , HashLengthInBits(0)
265370b324cSopenharmony_ci      , Size_from_Arc(0)
266370b324cSopenharmony_ci      , Size_from_Disk(0)
267370b324cSopenharmony_ci    {}
268370b324cSopenharmony_ci};
269370b324cSopenharmony_ci
270370b324cSopenharmony_ci
271370b324cSopenharmony_ciZ7_CLASS_IMP_CHandler_IInArchive_3(
272370b324cSopenharmony_ci    IArchiveGetRawProps,
273370b324cSopenharmony_ci    /* public IGetArchiveHashHandler, */
274370b324cSopenharmony_ci    IOutArchive,
275370b324cSopenharmony_ci    ISetProperties
276370b324cSopenharmony_ci)
277370b324cSopenharmony_ci  bool _isArc;
278370b324cSopenharmony_ci  UInt64 _phySize;
279370b324cSopenharmony_ci  CObjectVector<CHashPair> HashPairs;
280370b324cSopenharmony_ci  UString _nameExtenstion;
281370b324cSopenharmony_ci  // UString _method_fromName;
282370b324cSopenharmony_ci  AString _pgpMethod;
283370b324cSopenharmony_ci  bool _is_CksumMode;
284370b324cSopenharmony_ci  bool _is_PgpMethod;
285370b324cSopenharmony_ci  bool _is_ZeroMode;
286370b324cSopenharmony_ci  bool _are_there_Tags;
287370b324cSopenharmony_ci  bool _are_there_Dirs;
288370b324cSopenharmony_ci  bool _hashSize_Defined;
289370b324cSopenharmony_ci  unsigned _hashSize;
290370b324cSopenharmony_ci
291370b324cSopenharmony_ci  bool _crcSize_WasSet;
292370b324cSopenharmony_ci  UInt32 _crcSize;
293370b324cSopenharmony_ci  UStringVector _methods;
294370b324cSopenharmony_ci
295370b324cSopenharmony_ci  void ClearVars();
296370b324cSopenharmony_ci
297370b324cSopenharmony_ci  void InitProps()
298370b324cSopenharmony_ci  {
299370b324cSopenharmony_ci    _crcSize_WasSet = false;
300370b324cSopenharmony_ci    _crcSize = 4;
301370b324cSopenharmony_ci    _methods.Clear();
302370b324cSopenharmony_ci    _options.Init_HashOptionsLocal();
303370b324cSopenharmony_ci  }
304370b324cSopenharmony_ci
305370b324cSopenharmony_ci  CHashOptionsLocal _options;
306370b324cSopenharmony_ci
307370b324cSopenharmony_ci  bool CanUpdate() const
308370b324cSopenharmony_ci  {
309370b324cSopenharmony_ci    if (!_isArc || _is_PgpMethod || _is_CksumMode)
310370b324cSopenharmony_ci      return false;
311370b324cSopenharmony_ci    return true;
312370b324cSopenharmony_ci
313370b324cSopenharmony_ci  }
314370b324cSopenharmony_ci
315370b324cSopenharmony_ci  HRESULT SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value);
316370b324cSopenharmony_ci
317370b324cSopenharmony_cipublic:
318370b324cSopenharmony_ci  CHandler();
319370b324cSopenharmony_ci};
320370b324cSopenharmony_ci
321370b324cSopenharmony_ci}
322370b324cSopenharmony_ci
323370b324cSopenharmony_civoid Codecs_AddHashArcHandler(CCodecs *codecs);
324370b324cSopenharmony_ci
325370b324cSopenharmony_ci#endif
326370b324cSopenharmony_ci
327370b324cSopenharmony_ci
328370b324cSopenharmony_ci#endif
329