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