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
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, size_t 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 Z7_PURE_INTERFACES_BEGIN
69
70
DECLARE_INTERFACE(IHashCalc)71 DECLARE_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
79 Z7_PURE_INTERFACES_END
80
81 struct 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() {}
CHashBundleZ7_final100 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
111 Z7_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
128 Z7_IFACE_DECL_PURE_(IHashCallbackUI, IDirItemsCallback)
129
130 Z7_PURE_INTERFACES_END
131
132
133 struct CHashOptionsLocal
134 {
135 CBoolPair HashMode_Zero;
136 CBoolPair HashMode_Tag;
137 CBoolPair HashMode_Dirs;
138 CBoolPair HashMode_OnlyHash;
139
Init_HashOptionsLocalCHashOptionsLocal140 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
CHashOptionsLocalCHashOptionsLocal149 CHashOptionsLocal()
150 {
151 Init_HashOptionsLocal();
152 }
153
ParseFlagCharOptionCHashOptionsLocal154 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
ParseStringCHashOptionsLocal165 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
188 struct 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
CHashOptionsCHashOptions202 CHashOptions():
203 PreserveATime(false),
204 OpenShareForWrite(false),
205 StdInMode(false),
206 AltStreamsMode(false),
207 PathMode(NWildcard::k_RelatPath) {}
208 };
209
210
211 HRESULT 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
222 namespace NHash {
223
224 struct CHashPair
225 {
226 CByteBuffer Hash;
227 char Mode;
228 bool IsBSD;
229 bool Escape;
230 bool Size_from_Arc_Defined;
231 bool Size_from_Disk_Defined;
232 AString Method;
233 AString Name;
234
235 AString FullLine;
236 AString HashString;
237 // unsigned HashLengthInBits;
238
239 // AString MethodName;
240 UInt64 Size_from_Arc;
241 UInt64 Size_from_Disk;
242
243 bool IsDir() const;
244
Get_UString_PathCHashPair245 void Get_UString_Path(UString &path) const
246 {
247 path.Empty();
248 if (!ConvertUTF8ToUnicode(Name, path))
249 return;
250 }
251
252 bool ParseCksum(const char *s);
253 bool Parse(const char *s);
254
IsSupportedModeCHashPair255 bool IsSupportedMode() const
256 {
257 return Mode != 'U' && Mode != '^';
258 }
259
CHashPairCHashPair260 CHashPair():
261 Mode(0)
262 , IsBSD(false)
263 , Escape(false)
264 , Size_from_Arc_Defined(false)
265 , Size_from_Disk_Defined(false)
266 // , HashLengthInBits(0)
267 , Size_from_Arc(0)
268 , Size_from_Disk(0)
269 {}
270 };
271
272
273 Z7_CLASS_IMP_CHandler_IInArchive_3(
274 IArchiveGetRawProps,
275 /* public IGetArchiveHashHandler, */
276 IOutArchive,
277 ISetProperties
278 )
279 bool _isArc;
280 bool _supportWindowsBackslash;
281 bool _crcSize_WasSet;
282 UInt64 _phySize;
283 CObjectVector<CHashPair> HashPairs;
284 UString _nameExtenstion;
285 // UString _method_fromName;
286 AString _pgpMethod;
287 bool _is_CksumMode;
288 bool _is_PgpMethod;
289 bool _is_ZeroMode;
290 bool _are_there_Tags;
291 bool _are_there_Dirs;
292 bool _hashSize_Defined;
293 unsigned _hashSize;
294 UInt32 _crcSize;
295 UStringVector _methods;
296 CHashOptionsLocal _options;
297
298 void ClearVars();
299
InitProps()300 void InitProps()
301 {
302 _supportWindowsBackslash = true;
303 _crcSize_WasSet = false;
304 _crcSize = 4;
305 _methods.Clear();
306 _options.Init_HashOptionsLocal();
307 }
308
CanUpdate()309 bool CanUpdate() const
310 {
311 if (!_isArc || _is_PgpMethod || _is_CksumMode)
312 return false;
313 return true;
314 }
315
316 HRESULT SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value);
317
318 public:
319 CHandler();
320 };
321
322 }
323
324 void Codecs_AddHashArcHandler(CCodecs *codecs);
325
326 #endif
327
328
329 #endif
330