• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // HashCalc.h
2 
3 #ifndef __HASH_CALC_H
4 #define __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 
15 const unsigned k_HashCalc_DigestSize_Max = 64;
16 const unsigned k_HashCalc_ExtraSize = 8;
17 const 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 */
23 void HashHexToString(char *dest, const Byte *data, UInt32 size);
24 
25 enum
26 {
27   k_HashCalc_Index_Current,
28   k_HashCalc_Index_DataSum,
29   k_HashCalc_Index_NamesSum,
30   k_HashCalc_Index_StreamsSum
31 };
32 
33 struct 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 
InitDigestGroupCHasherState41   void InitDigestGroup(unsigned groupIndex)
42   {
43     NumSums[groupIndex] = 0;
44     memset(Digests[groupIndex], 0, sizeof(Digests[groupIndex]));
45   }
46 
GetExtraData_for_GroupCHasherState47   const Byte *GetExtraData_for_Group(unsigned groupIndex) const
48   {
49     return Digests[groupIndex] + k_HashCalc_DigestSize_Max;
50   }
51 
GetNumExtraBytes_for_GroupCHasherState52   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 
68 
69 struct IHashCalc
70 {
71   virtual void InitForNewFile() = 0;
72   virtual void Update(const void *data, UInt32 size) = 0;
73   virtual void SetSize(UInt64 size) = 0;
74   virtual void Final(bool isDir, bool isAltStream, const UString &path) = 0;
75 };
76 
77 struct CHashBundle: public IHashCalc
78 {
79   CObjectVector<CHasherState> Hashers;
80 
81   UInt64 NumDirs;
82   UInt64 NumFiles;
83   UInt64 NumAltStreams;
84   UInt64 FilesSize;
85   UInt64 AltStreamsSize;
86   UInt64 NumErrors;
87 
88   UInt64 CurSize;
89 
90   UString MainName;
91   UString FirstFileName;
92 
93   HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods);
94 
95   // void Init() {}
CHashBundleCHashBundle96   CHashBundle()
97   {
98     NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;
99   }
100 
~CHashBundleCHashBundle101   virtual ~CHashBundle() {};
102 
103   void InitForNewFile();
104   void Update(const void *data, UInt32 size);
105   void SetSize(UInt64 size);
106   void Final(bool isDir, bool isAltStream, const UString &path);
107 };
108 
109 #define INTERFACE_IHashCallbackUI(x) \
110   INTERFACE_IDirItemsCallback(x) \
111   virtual HRESULT StartScanning() x; \
112   virtual HRESULT FinishScanning(const CDirItemsStat &st) x; \
113   virtual HRESULT SetNumFiles(UInt64 numFiles) x; \
114   virtual HRESULT SetTotal(UInt64 size) x; \
115   virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \
116   virtual HRESULT CheckBreak() x; \
117   virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x; \
118   virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x; \
119   virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \
120   virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x; \
121   virtual HRESULT AfterLastFile(CHashBundle &hb) x; \
122 
123 struct IHashCallbackUI: public IDirItemsCallback
124 {
125   INTERFACE_IHashCallbackUI(=0)
126 };
127 
128 
129 struct CHashOptionsLocal
130 {
131   CBoolPair HashMode_Zero;
132   CBoolPair HashMode_Tag;
133   CBoolPair HashMode_Dirs;
134   CBoolPair HashMode_OnlyHash;
135 
Init_HashOptionsLocalCHashOptionsLocal136   void Init_HashOptionsLocal()
137   {
138     HashMode_Zero.Init();
139     HashMode_Tag.Init();
140     HashMode_Dirs.Init();
141     HashMode_OnlyHash.Init();
142     // HashMode_Dirs = true; // for debug
143   }
144 
CHashOptionsLocalCHashOptionsLocal145   CHashOptionsLocal()
146   {
147     Init_HashOptionsLocal();
148   }
149 
ParseFlagCharOptionCHashOptionsLocal150   bool ParseFlagCharOption(wchar_t c, bool val)
151   {
152     c = MyCharLower_Ascii(c);
153          if (c == 'z') HashMode_Zero.SetVal_as_Defined(val);
154     else if (c == 't') HashMode_Tag.SetVal_as_Defined(val);
155     else if (c == 'd') HashMode_Dirs.SetVal_as_Defined(val);
156     else if (c == 'h') HashMode_OnlyHash.SetVal_as_Defined(val);
157     else return false;
158     return true;
159   }
160 
ParseStringCHashOptionsLocal161   bool ParseString(const UString &s)
162   {
163     for (unsigned i = 0; i < s.Len();)
164     {
165       const wchar_t c = s[i++];
166       bool val = true;
167       if (i < s.Len())
168       {
169         const wchar_t next  = s[i];
170         if (next == '-')
171         {
172           val = false;
173           i++;
174         }
175       }
176       if (!ParseFlagCharOption(c, val))
177         return false;
178     }
179     return true;
180   }
181 };
182 
183 
184 struct CHashOptions
185   // : public CHashOptionsLocal
186 {
187   UStringVector Methods;
188   // UString HashFilePath;
189 
190   bool PreserveATime;
191   bool OpenShareForWrite;
192   bool StdInMode;
193   bool AltStreamsMode;
194   CBoolPair SymLinks;
195 
196   NWildcard::ECensorPathMode PathMode;
197 
CHashOptionsCHashOptions198   CHashOptions():
199       PreserveATime(false),
200       OpenShareForWrite(false),
201       StdInMode(false),
202       AltStreamsMode(false),
203       PathMode(NWildcard::k_RelatPath) {};
204 };
205 
206 
207 HRESULT HashCalc(
208     DECL_EXTERNAL_CODECS_LOC_VARS
209     const NWildcard::CCensor &censor,
210     const CHashOptions &options,
211     AString &errorInfo,
212     IHashCallbackUI *callback);
213 
214 
215 
216 #ifndef _SFX
217 
218 namespace NHash {
219 
220 struct CHashPair
221 {
222   CByteBuffer Hash;
223   char Mode;
224   bool IsBSD;
225   bool Size_from_Arc_Defined;
226   bool Size_from_Disk_Defined;
227   AString Method;
228   AString Name;
229 
230   AString FullLine;
231   AString HashString;
232   // unsigned HashLengthInBits;
233 
234   // AString MethodName;
235   UInt64 Size_from_Arc;
236   UInt64 Size_from_Disk;
237 
238   bool IsDir() const;
239 
Get_UString_PathCHashPair240   void Get_UString_Path(UString &path) const
241   {
242     path.Empty();
243     if (!ConvertUTF8ToUnicode(Name, path))
244       return;
245   }
246 
247   bool ParseCksum(const char *s);
248   bool Parse(const char *s);
249 
IsSupportedModeCHashPair250   bool IsSupportedMode() const
251   {
252     return Mode != 'U' && Mode != '^';
253   }
254 
CHashPairCHashPair255   CHashPair():
256       Mode(0)
257       , IsBSD(false)
258       , Size_from_Arc_Defined(false)
259       , Size_from_Disk_Defined(false)
260       // , HashLengthInBits(0)
261       , Size_from_Arc(0)
262       , Size_from_Disk(0)
263     {}
264 };
265 
266 
267 class CHandler:
268   public IInArchive,
269   public IArchiveGetRawProps,
270   // public IGetArchiveHashHandler,
271   public IOutArchive,
272   public ISetProperties,
273   public CMyUnknownImp
274 {
275   bool _isArc;
276   UInt64 _phySize;
277   CObjectVector<CHashPair> HashPairs;
278   UString _nameExtenstion;
279   // UString _method_fromName;
280   AString _pgpMethod;
281   bool _is_CksumMode;
282   bool _is_PgpMethod;
283   bool _is_ZeroMode;
284   bool _are_there_Tags;
285   bool _are_there_Dirs;
286   bool _hashSize_Defined;
287   unsigned _hashSize;
288 
289   bool _crcSize_WasSet;
290   UInt32 _crcSize;
291   UStringVector _methods;
292 
293   void ClearVars();
294 
InitProps()295   void InitProps()
296   {
297     _crcSize_WasSet = false;
298     _crcSize = 4;
299     _methods.Clear();
300     _options.Init_HashOptionsLocal();
301   }
302 
303   CHashOptionsLocal _options;
304 
CanUpdate()305   bool CanUpdate() const
306   {
307     if (!_isArc || _is_PgpMethod || _is_CksumMode)
308       return false;
309     return true;
310 
311   }
312 
313   HRESULT SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value);
314 
315 public:
316 
317   CHandler();
318 
319   MY_UNKNOWN_IMP4(
320       IInArchive,
321       IArchiveGetRawProps,
322       IOutArchive,
323       ISetProperties
324       /*, IGetArchiveHashHandler */
325       )
326   INTERFACE_IInArchive(;)
327   INTERFACE_IOutArchive(;)
328   INTERFACE_IArchiveGetRawProps(;)
329   // STDMETHOD(GetArchiveHashHandler)(CHandler **handler);
330   STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
331 };
332 
333 }
334 
335 void Codecs_AddHashArcHandler(CCodecs *codecs);
336 
337 #endif
338 
339 
340 #endif
341