xref: /third_party/lzma/CPP/7zip/UI/Common/HashCalc.h (revision 370b324c)
1// HashCalc.h
2
3#ifndef ZIP7_INC_HASH_CALC_H
4#define ZIP7_INC_HASH_CALC_H
5
6#include "../../../Common/UTFConvert.h"
7#include "../../../Common/Wildcard.h"
8
9#include "../../Common/CreateCoder.h"
10#include "../../Common/MethodProps.h"
11
12#include "DirItem.h"
13#include "IFileExtractCallback.h"
14
15const unsigned k_HashCalc_DigestSize_Max = 64;
16const unsigned k_HashCalc_ExtraSize = 8;
17const unsigned k_HashCalc_NumGroups = 4;
18
19/*
20  if (size <= 8) : upper case : reversed byte order : it shows 32-bit/64-bit number, if data contains little-endian number
21  if (size >  8) : lower case : original byte order (as big-endian byte sequence)
22*/
23void HashHexToString(char *dest, const Byte *data, UInt32 size);
24
25enum
26{
27  k_HashCalc_Index_Current,
28  k_HashCalc_Index_DataSum,
29  k_HashCalc_Index_NamesSum,
30  k_HashCalc_Index_StreamsSum
31};
32
33struct CHasherState
34{
35  CMyComPtr<IHasher> Hasher;
36  AString Name;
37  UInt32 DigestSize;
38  UInt64 NumSums[k_HashCalc_NumGroups];
39  Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max + k_HashCalc_ExtraSize];
40
41  void InitDigestGroup(unsigned groupIndex)
42  {
43    NumSums[groupIndex] = 0;
44    memset(Digests[groupIndex], 0, sizeof(Digests[groupIndex]));
45  }
46
47  const Byte *GetExtraData_for_Group(unsigned groupIndex) const
48  {
49    return Digests[groupIndex] + k_HashCalc_DigestSize_Max;
50  }
51
52  unsigned GetNumExtraBytes_for_Group(unsigned groupIndex) const
53  {
54    const Byte *p = GetExtraData_for_Group(groupIndex);
55    // we use little-endian to read extra bytes
56    for (unsigned i = k_HashCalc_ExtraSize; i != 0; i--)
57      if (p[i - 1] != 0)
58        return i;
59    return 0;
60  }
61
62  void AddDigest(unsigned groupIndex, const Byte *data);
63
64  void WriteToString(unsigned digestIndex, char *s) const;
65};
66
67
68Z7_PURE_INTERFACES_BEGIN
69
70
71DECLARE_INTERFACE(IHashCalc)
72{
73  virtual void InitForNewFile() = 0;
74  virtual void Update(const void *data, UInt32 size) = 0;
75  virtual void SetSize(UInt64 size) = 0;
76  virtual void Final(bool isDir, bool isAltStream, const UString &path) = 0;
77};
78
79Z7_PURE_INTERFACES_END
80
81struct CHashBundle Z7_final: public IHashCalc
82{
83  CObjectVector<CHasherState> Hashers;
84
85  UInt64 NumDirs;
86  UInt64 NumFiles;
87  UInt64 NumAltStreams;
88  UInt64 FilesSize;
89  UInt64 AltStreamsSize;
90  UInt64 NumErrors;
91
92  UInt64 CurSize;
93
94  UString MainName;
95  UString FirstFileName;
96
97  HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods);
98
99  // void Init() {}
100  CHashBundle()
101  {
102    NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;
103  }
104
105  void InitForNewFile() Z7_override;
106  void Update(const void *data, UInt32 size) Z7_override;
107  void SetSize(UInt64 size) Z7_override;
108  void Final(bool isDir, bool isAltStream, const UString &path) Z7_override;
109};
110
111Z7_PURE_INTERFACES_BEGIN
112
113// INTERFACE_IDirItemsCallback(x)
114
115#define Z7_IFACEN_IHashCallbackUI(x) \
116  virtual HRESULT StartScanning() x \
117  virtual HRESULT FinishScanning(const CDirItemsStat &st) x \
118  virtual HRESULT SetNumFiles(UInt64 numFiles) x \
119  virtual HRESULT SetTotal(UInt64 size) x \
120  virtual HRESULT SetCompleted(const UInt64 *completeValue) x \
121  virtual HRESULT CheckBreak() x \
122  virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x \
123  virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x \
124  virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x \
125  virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x \
126  virtual HRESULT AfterLastFile(CHashBundle &hb) x \
127
128Z7_IFACE_DECL_PURE_(IHashCallbackUI, IDirItemsCallback)
129
130Z7_PURE_INTERFACES_END
131
132
133struct CHashOptionsLocal
134{
135  CBoolPair HashMode_Zero;
136  CBoolPair HashMode_Tag;
137  CBoolPair HashMode_Dirs;
138  CBoolPair HashMode_OnlyHash;
139
140  void Init_HashOptionsLocal()
141  {
142    HashMode_Zero.Init();
143    HashMode_Tag.Init();
144    HashMode_Dirs.Init();
145    HashMode_OnlyHash.Init();
146    // HashMode_Dirs = true; // for debug
147  }
148
149  CHashOptionsLocal()
150  {
151    Init_HashOptionsLocal();
152  }
153
154  bool ParseFlagCharOption(wchar_t c, bool val)
155  {
156    c = MyCharLower_Ascii(c);
157         if (c == 'z') HashMode_Zero.SetVal_as_Defined(val);
158    else if (c == 't') HashMode_Tag.SetVal_as_Defined(val);
159    else if (c == 'd') HashMode_Dirs.SetVal_as_Defined(val);
160    else if (c == 'h') HashMode_OnlyHash.SetVal_as_Defined(val);
161    else return false;
162    return true;
163  }
164
165  bool ParseString(const UString &s)
166  {
167    for (unsigned i = 0; i < s.Len();)
168    {
169      const wchar_t c = s[i++];
170      bool val = true;
171      if (i < s.Len())
172      {
173        const wchar_t next  = s[i];
174        if (next == '-')
175        {
176          val = false;
177          i++;
178        }
179      }
180      if (!ParseFlagCharOption(c, val))
181        return false;
182    }
183    return true;
184  }
185};
186
187
188struct CHashOptions
189  // : public CHashOptionsLocal
190{
191  UStringVector Methods;
192  // UString HashFilePath;
193
194  bool PreserveATime;
195  bool OpenShareForWrite;
196  bool StdInMode;
197  bool AltStreamsMode;
198  CBoolPair SymLinks;
199
200  NWildcard::ECensorPathMode PathMode;
201
202  CHashOptions():
203      PreserveATime(false),
204      OpenShareForWrite(false),
205      StdInMode(false),
206      AltStreamsMode(false),
207      PathMode(NWildcard::k_RelatPath) {}
208};
209
210
211HRESULT HashCalc(
212    DECL_EXTERNAL_CODECS_LOC_VARS
213    const NWildcard::CCensor &censor,
214    const CHashOptions &options,
215    AString &errorInfo,
216    IHashCallbackUI *callback);
217
218
219
220#ifndef Z7_SFX
221
222namespace NHash {
223
224struct CHashPair
225{
226  CByteBuffer Hash;
227  char Mode;
228  bool IsBSD;
229  bool Size_from_Arc_Defined;
230  bool Size_from_Disk_Defined;
231  AString Method;
232  AString Name;
233
234  AString FullLine;
235  AString HashString;
236  // unsigned HashLengthInBits;
237
238  // AString MethodName;
239  UInt64 Size_from_Arc;
240  UInt64 Size_from_Disk;
241
242  bool IsDir() const;
243
244  void Get_UString_Path(UString &path) const
245  {
246    path.Empty();
247    if (!ConvertUTF8ToUnicode(Name, path))
248      return;
249  }
250
251  bool ParseCksum(const char *s);
252  bool Parse(const char *s);
253
254  bool IsSupportedMode() const
255  {
256    return Mode != 'U' && Mode != '^';
257  }
258
259  CHashPair():
260      Mode(0)
261      , IsBSD(false)
262      , Size_from_Arc_Defined(false)
263      , Size_from_Disk_Defined(false)
264      // , HashLengthInBits(0)
265      , Size_from_Arc(0)
266      , Size_from_Disk(0)
267    {}
268};
269
270
271Z7_CLASS_IMP_CHandler_IInArchive_3(
272    IArchiveGetRawProps,
273    /* public IGetArchiveHashHandler, */
274    IOutArchive,
275    ISetProperties
276)
277  bool _isArc;
278  UInt64 _phySize;
279  CObjectVector<CHashPair> HashPairs;
280  UString _nameExtenstion;
281  // UString _method_fromName;
282  AString _pgpMethod;
283  bool _is_CksumMode;
284  bool _is_PgpMethod;
285  bool _is_ZeroMode;
286  bool _are_there_Tags;
287  bool _are_there_Dirs;
288  bool _hashSize_Defined;
289  unsigned _hashSize;
290
291  bool _crcSize_WasSet;
292  UInt32 _crcSize;
293  UStringVector _methods;
294
295  void ClearVars();
296
297  void InitProps()
298  {
299    _crcSize_WasSet = false;
300    _crcSize = 4;
301    _methods.Clear();
302    _options.Init_HashOptionsLocal();
303  }
304
305  CHashOptionsLocal _options;
306
307  bool CanUpdate() const
308  {
309    if (!_isArc || _is_PgpMethod || _is_CksumMode)
310      return false;
311    return true;
312
313  }
314
315  HRESULT SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value);
316
317public:
318  CHandler();
319};
320
321}
322
323void Codecs_AddHashArcHandler(CCodecs *codecs);
324
325#endif
326
327
328#endif
329