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