1370b324cSopenharmony_ci// HashCalc.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#include "../../../../C/Alloc.h" 6370b324cSopenharmony_ci#include "../../../../C/CpuArch.h" 7370b324cSopenharmony_ci 8370b324cSopenharmony_ci#include "../../../Common/DynLimBuf.h" 9370b324cSopenharmony_ci#include "../../../Common/IntToString.h" 10370b324cSopenharmony_ci#include "../../../Common/StringToInt.h" 11370b324cSopenharmony_ci 12370b324cSopenharmony_ci#include "../../Common/FileStreams.h" 13370b324cSopenharmony_ci#include "../../Common/ProgressUtils.h" 14370b324cSopenharmony_ci#include "../../Common/StreamObjects.h" 15370b324cSopenharmony_ci#include "../../Common/StreamUtils.h" 16370b324cSopenharmony_ci 17370b324cSopenharmony_ci#include "../../Archive/Common/ItemNameUtils.h" 18370b324cSopenharmony_ci#include "../../Archive/IArchive.h" 19370b324cSopenharmony_ci 20370b324cSopenharmony_ci#include "EnumDirItems.h" 21370b324cSopenharmony_ci#include "HashCalc.h" 22370b324cSopenharmony_ci 23370b324cSopenharmony_ciusing namespace NWindows; 24370b324cSopenharmony_ci 25370b324cSopenharmony_ci#ifdef Z7_EXTERNAL_CODECS 26370b324cSopenharmony_ciextern const CExternalCodecs *g_ExternalCodecs_Ptr; 27370b324cSopenharmony_ci#endif 28370b324cSopenharmony_ci 29370b324cSopenharmony_ciclass CHashMidBuf 30370b324cSopenharmony_ci{ 31370b324cSopenharmony_ci void *_data; 32370b324cSopenharmony_cipublic: 33370b324cSopenharmony_ci CHashMidBuf(): _data(NULL) {} 34370b324cSopenharmony_ci operator void *() { return _data; } 35370b324cSopenharmony_ci bool Alloc(size_t size) 36370b324cSopenharmony_ci { 37370b324cSopenharmony_ci if (_data) 38370b324cSopenharmony_ci return false; 39370b324cSopenharmony_ci _data = ::MidAlloc(size); 40370b324cSopenharmony_ci return _data != NULL; 41370b324cSopenharmony_ci } 42370b324cSopenharmony_ci ~CHashMidBuf() { ::MidFree(_data); } 43370b324cSopenharmony_ci}; 44370b324cSopenharmony_ci 45370b324cSopenharmony_cistatic const char * const k_DefaultHashMethod = "CRC32"; 46370b324cSopenharmony_ci 47370b324cSopenharmony_ciHRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods) 48370b324cSopenharmony_ci{ 49370b324cSopenharmony_ci UStringVector names = hashMethods; 50370b324cSopenharmony_ci if (names.IsEmpty()) 51370b324cSopenharmony_ci names.Add(UString(k_DefaultHashMethod)); 52370b324cSopenharmony_ci 53370b324cSopenharmony_ci CRecordVector<CMethodId> ids; 54370b324cSopenharmony_ci CObjectVector<COneMethodInfo> methods; 55370b324cSopenharmony_ci 56370b324cSopenharmony_ci unsigned i; 57370b324cSopenharmony_ci for (i = 0; i < names.Size(); i++) 58370b324cSopenharmony_ci { 59370b324cSopenharmony_ci COneMethodInfo m; 60370b324cSopenharmony_ci RINOK(m.ParseMethodFromString(names[i])) 61370b324cSopenharmony_ci 62370b324cSopenharmony_ci if (m.MethodName.IsEmpty()) 63370b324cSopenharmony_ci m.MethodName = k_DefaultHashMethod; 64370b324cSopenharmony_ci 65370b324cSopenharmony_ci if (m.MethodName == "*") 66370b324cSopenharmony_ci { 67370b324cSopenharmony_ci CRecordVector<CMethodId> tempMethods; 68370b324cSopenharmony_ci GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods); 69370b324cSopenharmony_ci methods.Clear(); 70370b324cSopenharmony_ci ids.Clear(); 71370b324cSopenharmony_ci FOR_VECTOR (t, tempMethods) 72370b324cSopenharmony_ci { 73370b324cSopenharmony_ci unsigned index = ids.AddToUniqueSorted(tempMethods[t]); 74370b324cSopenharmony_ci if (ids.Size() != methods.Size()) 75370b324cSopenharmony_ci methods.Insert(index, m); 76370b324cSopenharmony_ci } 77370b324cSopenharmony_ci break; 78370b324cSopenharmony_ci } 79370b324cSopenharmony_ci else 80370b324cSopenharmony_ci { 81370b324cSopenharmony_ci // m.MethodName.RemoveChar(L'-'); 82370b324cSopenharmony_ci CMethodId id; 83370b324cSopenharmony_ci if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id)) 84370b324cSopenharmony_ci return E_NOTIMPL; 85370b324cSopenharmony_ci unsigned index = ids.AddToUniqueSorted(id); 86370b324cSopenharmony_ci if (ids.Size() != methods.Size()) 87370b324cSopenharmony_ci methods.Insert(index, m); 88370b324cSopenharmony_ci } 89370b324cSopenharmony_ci } 90370b324cSopenharmony_ci 91370b324cSopenharmony_ci for (i = 0; i < ids.Size(); i++) 92370b324cSopenharmony_ci { 93370b324cSopenharmony_ci CMyComPtr<IHasher> hasher; 94370b324cSopenharmony_ci AString name; 95370b324cSopenharmony_ci RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher)) 96370b324cSopenharmony_ci if (!hasher) 97370b324cSopenharmony_ci throw "Can't create hasher"; 98370b324cSopenharmony_ci const COneMethodInfo &m = methods[i]; 99370b324cSopenharmony_ci { 100370b324cSopenharmony_ci CMyComPtr<ICompressSetCoderProperties> scp; 101370b324cSopenharmony_ci hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); 102370b324cSopenharmony_ci if (scp) 103370b324cSopenharmony_ci RINOK(m.SetCoderProps(scp, NULL)) 104370b324cSopenharmony_ci } 105370b324cSopenharmony_ci const UInt32 digestSize = hasher->GetDigestSize(); 106370b324cSopenharmony_ci if (digestSize > k_HashCalc_DigestSize_Max) 107370b324cSopenharmony_ci return E_NOTIMPL; 108370b324cSopenharmony_ci CHasherState &h = Hashers.AddNew(); 109370b324cSopenharmony_ci h.DigestSize = digestSize; 110370b324cSopenharmony_ci h.Hasher = hasher; 111370b324cSopenharmony_ci h.Name = name; 112370b324cSopenharmony_ci for (unsigned k = 0; k < k_HashCalc_NumGroups; k++) 113370b324cSopenharmony_ci h.InitDigestGroup(k); 114370b324cSopenharmony_ci } 115370b324cSopenharmony_ci 116370b324cSopenharmony_ci return S_OK; 117370b324cSopenharmony_ci} 118370b324cSopenharmony_ci 119370b324cSopenharmony_civoid CHashBundle::InitForNewFile() 120370b324cSopenharmony_ci{ 121370b324cSopenharmony_ci CurSize = 0; 122370b324cSopenharmony_ci FOR_VECTOR (i, Hashers) 123370b324cSopenharmony_ci { 124370b324cSopenharmony_ci CHasherState &h = Hashers[i]; 125370b324cSopenharmony_ci h.Hasher->Init(); 126370b324cSopenharmony_ci h.InitDigestGroup(k_HashCalc_Index_Current); 127370b324cSopenharmony_ci } 128370b324cSopenharmony_ci} 129370b324cSopenharmony_ci 130370b324cSopenharmony_civoid CHashBundle::Update(const void *data, UInt32 size) 131370b324cSopenharmony_ci{ 132370b324cSopenharmony_ci CurSize += size; 133370b324cSopenharmony_ci FOR_VECTOR (i, Hashers) 134370b324cSopenharmony_ci Hashers[i].Hasher->Update(data, size); 135370b324cSopenharmony_ci} 136370b324cSopenharmony_ci 137370b324cSopenharmony_civoid CHashBundle::SetSize(UInt64 size) 138370b324cSopenharmony_ci{ 139370b324cSopenharmony_ci CurSize = size; 140370b324cSopenharmony_ci} 141370b324cSopenharmony_ci 142370b324cSopenharmony_cistatic void AddDigests(Byte *dest, const Byte *src, UInt32 size) 143370b324cSopenharmony_ci{ 144370b324cSopenharmony_ci unsigned next = 0; 145370b324cSopenharmony_ci /* 146370b324cSopenharmony_ci // we could use big-endian addition for sha-1 and sha-256 147370b324cSopenharmony_ci // but another hashers are little-endian 148370b324cSopenharmony_ci if (size > 8) 149370b324cSopenharmony_ci { 150370b324cSopenharmony_ci for (unsigned i = size; i != 0;) 151370b324cSopenharmony_ci { 152370b324cSopenharmony_ci i--; 153370b324cSopenharmony_ci next += (unsigned)dest[i] + (unsigned)src[i]; 154370b324cSopenharmony_ci dest[i] = (Byte)next; 155370b324cSopenharmony_ci next >>= 8; 156370b324cSopenharmony_ci } 157370b324cSopenharmony_ci } 158370b324cSopenharmony_ci else 159370b324cSopenharmony_ci */ 160370b324cSopenharmony_ci { 161370b324cSopenharmony_ci for (unsigned i = 0; i < size; i++) 162370b324cSopenharmony_ci { 163370b324cSopenharmony_ci next += (unsigned)dest[i] + (unsigned)src[i]; 164370b324cSopenharmony_ci dest[i] = (Byte)next; 165370b324cSopenharmony_ci next >>= 8; 166370b324cSopenharmony_ci } 167370b324cSopenharmony_ci } 168370b324cSopenharmony_ci 169370b324cSopenharmony_ci // we use little-endian to store extra bytes 170370b324cSopenharmony_ci dest += k_HashCalc_DigestSize_Max; 171370b324cSopenharmony_ci for (unsigned i = 0; i < k_HashCalc_ExtraSize; i++) 172370b324cSopenharmony_ci { 173370b324cSopenharmony_ci next += (unsigned)dest[i]; 174370b324cSopenharmony_ci dest[i] = (Byte)next; 175370b324cSopenharmony_ci next >>= 8; 176370b324cSopenharmony_ci } 177370b324cSopenharmony_ci} 178370b324cSopenharmony_ci 179370b324cSopenharmony_civoid CHasherState::AddDigest(unsigned groupIndex, const Byte *data) 180370b324cSopenharmony_ci{ 181370b324cSopenharmony_ci NumSums[groupIndex]++; 182370b324cSopenharmony_ci AddDigests(Digests[groupIndex], data, DigestSize); 183370b324cSopenharmony_ci} 184370b324cSopenharmony_ci 185370b324cSopenharmony_civoid CHashBundle::Final(bool isDir, bool isAltStream, const UString &path) 186370b324cSopenharmony_ci{ 187370b324cSopenharmony_ci if (isDir) 188370b324cSopenharmony_ci NumDirs++; 189370b324cSopenharmony_ci else if (isAltStream) 190370b324cSopenharmony_ci { 191370b324cSopenharmony_ci NumAltStreams++; 192370b324cSopenharmony_ci AltStreamsSize += CurSize; 193370b324cSopenharmony_ci } 194370b324cSopenharmony_ci else 195370b324cSopenharmony_ci { 196370b324cSopenharmony_ci NumFiles++; 197370b324cSopenharmony_ci FilesSize += CurSize; 198370b324cSopenharmony_ci } 199370b324cSopenharmony_ci 200370b324cSopenharmony_ci Byte pre[16]; 201370b324cSopenharmony_ci memset(pre, 0, sizeof(pre)); 202370b324cSopenharmony_ci if (isDir) 203370b324cSopenharmony_ci pre[0] = 1; 204370b324cSopenharmony_ci 205370b324cSopenharmony_ci FOR_VECTOR (i, Hashers) 206370b324cSopenharmony_ci { 207370b324cSopenharmony_ci CHasherState &h = Hashers[i]; 208370b324cSopenharmony_ci if (!isDir) 209370b324cSopenharmony_ci { 210370b324cSopenharmony_ci h.Hasher->Final(h.Digests[0]); // k_HashCalc_Index_Current 211370b324cSopenharmony_ci if (!isAltStream) 212370b324cSopenharmony_ci h.AddDigest(k_HashCalc_Index_DataSum, h.Digests[0]); 213370b324cSopenharmony_ci } 214370b324cSopenharmony_ci 215370b324cSopenharmony_ci h.Hasher->Init(); 216370b324cSopenharmony_ci h.Hasher->Update(pre, sizeof(pre)); 217370b324cSopenharmony_ci h.Hasher->Update(h.Digests[0], h.DigestSize); 218370b324cSopenharmony_ci 219370b324cSopenharmony_ci for (unsigned k = 0; k < path.Len(); k++) 220370b324cSopenharmony_ci { 221370b324cSopenharmony_ci wchar_t c = path[k]; 222370b324cSopenharmony_ci 223370b324cSopenharmony_ci // 21.04: we want same hash for linux and windows paths 224370b324cSopenharmony_ci #if CHAR_PATH_SEPARATOR != '/' 225370b324cSopenharmony_ci if (c == CHAR_PATH_SEPARATOR) 226370b324cSopenharmony_ci c = '/'; 227370b324cSopenharmony_ci // if (c == (wchar_t)('\\' + 0xf000)) c = '\\'; // to debug WSL 228370b324cSopenharmony_ci // if (c > 0xf000 && c < 0xf080) c -= 0xf000; // to debug WSL 229370b324cSopenharmony_ci #endif 230370b324cSopenharmony_ci 231370b324cSopenharmony_ci Byte temp[2] = { (Byte)(c & 0xFF), (Byte)((c >> 8) & 0xFF) }; 232370b324cSopenharmony_ci h.Hasher->Update(temp, 2); 233370b324cSopenharmony_ci } 234370b324cSopenharmony_ci 235370b324cSopenharmony_ci Byte tempDigest[k_HashCalc_DigestSize_Max]; 236370b324cSopenharmony_ci h.Hasher->Final(tempDigest); 237370b324cSopenharmony_ci if (!isAltStream) 238370b324cSopenharmony_ci h.AddDigest(k_HashCalc_Index_NamesSum, tempDigest); 239370b324cSopenharmony_ci h.AddDigest(k_HashCalc_Index_StreamsSum, tempDigest); 240370b324cSopenharmony_ci } 241370b324cSopenharmony_ci} 242370b324cSopenharmony_ci 243370b324cSopenharmony_ci 244370b324cSopenharmony_cistatic void CSum_Name_OriginalToEscape(const AString &src, AString &dest) 245370b324cSopenharmony_ci{ 246370b324cSopenharmony_ci dest.Empty(); 247370b324cSopenharmony_ci for (unsigned i = 0; i < src.Len();) 248370b324cSopenharmony_ci { 249370b324cSopenharmony_ci char c = src[i++]; 250370b324cSopenharmony_ci if (c == '\n') 251370b324cSopenharmony_ci { 252370b324cSopenharmony_ci dest += '\\'; 253370b324cSopenharmony_ci c = 'n'; 254370b324cSopenharmony_ci } 255370b324cSopenharmony_ci else if (c == '\\') 256370b324cSopenharmony_ci dest += '\\'; 257370b324cSopenharmony_ci dest += c; 258370b324cSopenharmony_ci } 259370b324cSopenharmony_ci} 260370b324cSopenharmony_ci 261370b324cSopenharmony_ci 262370b324cSopenharmony_cistatic bool CSum_Name_EscapeToOriginal(const char *s, AString &dest) 263370b324cSopenharmony_ci{ 264370b324cSopenharmony_ci bool isOK = true; 265370b324cSopenharmony_ci dest.Empty(); 266370b324cSopenharmony_ci for (;;) 267370b324cSopenharmony_ci { 268370b324cSopenharmony_ci char c = *s++; 269370b324cSopenharmony_ci if (c == 0) 270370b324cSopenharmony_ci break; 271370b324cSopenharmony_ci if (c == '\\') 272370b324cSopenharmony_ci { 273370b324cSopenharmony_ci const char c1 = *s; 274370b324cSopenharmony_ci if (c1 == 'n') 275370b324cSopenharmony_ci { 276370b324cSopenharmony_ci c = '\n'; 277370b324cSopenharmony_ci s++; 278370b324cSopenharmony_ci } 279370b324cSopenharmony_ci else if (c1 == '\\') 280370b324cSopenharmony_ci { 281370b324cSopenharmony_ci c = c1; 282370b324cSopenharmony_ci s++; 283370b324cSopenharmony_ci } 284370b324cSopenharmony_ci else 285370b324cSopenharmony_ci { 286370b324cSopenharmony_ci // original md5sum returns NULL for such bad strings 287370b324cSopenharmony_ci isOK = false; 288370b324cSopenharmony_ci } 289370b324cSopenharmony_ci } 290370b324cSopenharmony_ci dest += c; 291370b324cSopenharmony_ci } 292370b324cSopenharmony_ci return isOK; 293370b324cSopenharmony_ci} 294370b324cSopenharmony_ci 295370b324cSopenharmony_ci 296370b324cSopenharmony_ci 297370b324cSopenharmony_cistatic void SetSpacesAndNul(char *s, unsigned num) 298370b324cSopenharmony_ci{ 299370b324cSopenharmony_ci for (unsigned i = 0; i < num; i++) 300370b324cSopenharmony_ci s[i] = ' '; 301370b324cSopenharmony_ci s[num] = 0; 302370b324cSopenharmony_ci} 303370b324cSopenharmony_ci 304370b324cSopenharmony_cistatic const unsigned kHashColumnWidth_Min = 4 * 2; 305370b324cSopenharmony_ci 306370b324cSopenharmony_cistatic unsigned GetColumnWidth(unsigned digestSize) 307370b324cSopenharmony_ci{ 308370b324cSopenharmony_ci const unsigned width = digestSize * 2; 309370b324cSopenharmony_ci return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width; 310370b324cSopenharmony_ci} 311370b324cSopenharmony_ci 312370b324cSopenharmony_ci 313370b324cSopenharmony_cistatic void AddHashResultLine( 314370b324cSopenharmony_ci AString &_s, 315370b324cSopenharmony_ci // bool showHash, 316370b324cSopenharmony_ci // UInt64 fileSize, bool showSize, 317370b324cSopenharmony_ci const CObjectVector<CHasherState> &hashers 318370b324cSopenharmony_ci // unsigned digestIndex, = k_HashCalc_Index_Current 319370b324cSopenharmony_ci ) 320370b324cSopenharmony_ci{ 321370b324cSopenharmony_ci FOR_VECTOR (i, hashers) 322370b324cSopenharmony_ci { 323370b324cSopenharmony_ci const CHasherState &h = hashers[i]; 324370b324cSopenharmony_ci char s[k_HashCalc_DigestSize_Max * 2 + 64]; 325370b324cSopenharmony_ci s[0] = 0; 326370b324cSopenharmony_ci // if (showHash) 327370b324cSopenharmony_ci HashHexToString(s, h.Digests[k_HashCalc_Index_Current], h.DigestSize); 328370b324cSopenharmony_ci const unsigned pos = (unsigned)strlen(s); 329370b324cSopenharmony_ci const int numSpaces = (int)GetColumnWidth(h.DigestSize) - (int)pos; 330370b324cSopenharmony_ci if (numSpaces > 0) 331370b324cSopenharmony_ci SetSpacesAndNul(s + pos, (unsigned)numSpaces); 332370b324cSopenharmony_ci if (i != 0) 333370b324cSopenharmony_ci _s.Add_Space(); 334370b324cSopenharmony_ci _s += s; 335370b324cSopenharmony_ci } 336370b324cSopenharmony_ci 337370b324cSopenharmony_ci /* 338370b324cSopenharmony_ci if (showSize) 339370b324cSopenharmony_ci { 340370b324cSopenharmony_ci _s.Add_Space(); 341370b324cSopenharmony_ci static const unsigned kSizeField_Len = 13; // same as in HashCon.cpp 342370b324cSopenharmony_ci char s[kSizeField_Len + 32]; 343370b324cSopenharmony_ci char *p = s; 344370b324cSopenharmony_ci SetSpacesAndNul(s, kSizeField_Len); 345370b324cSopenharmony_ci p = s + kSizeField_Len; 346370b324cSopenharmony_ci ConvertUInt64ToString(fileSize, p); 347370b324cSopenharmony_ci int numSpaces = (int)kSizeField_Len - (int)strlen(p); 348370b324cSopenharmony_ci if (numSpaces > 0) 349370b324cSopenharmony_ci p -= (unsigned)numSpaces; 350370b324cSopenharmony_ci _s += p; 351370b324cSopenharmony_ci } 352370b324cSopenharmony_ci */ 353370b324cSopenharmony_ci} 354370b324cSopenharmony_ci 355370b324cSopenharmony_ci 356370b324cSopenharmony_cistatic void Add_LF(CDynLimBuf &hashFileString, const CHashOptionsLocal &options) 357370b324cSopenharmony_ci{ 358370b324cSopenharmony_ci hashFileString += (char)(options.HashMode_Zero.Val ? 0 : '\n'); 359370b324cSopenharmony_ci} 360370b324cSopenharmony_ci 361370b324cSopenharmony_ci 362370b324cSopenharmony_ci 363370b324cSopenharmony_ci 364370b324cSopenharmony_cistatic void WriteLine(CDynLimBuf &hashFileString, 365370b324cSopenharmony_ci const CHashOptionsLocal &options, 366370b324cSopenharmony_ci const UString &path2, 367370b324cSopenharmony_ci bool isDir, 368370b324cSopenharmony_ci const AString &methodName, 369370b324cSopenharmony_ci const AString &hashesString) 370370b324cSopenharmony_ci{ 371370b324cSopenharmony_ci if (options.HashMode_OnlyHash.Val) 372370b324cSopenharmony_ci { 373370b324cSopenharmony_ci hashFileString += hashesString; 374370b324cSopenharmony_ci Add_LF(hashFileString, options); 375370b324cSopenharmony_ci return; 376370b324cSopenharmony_ci } 377370b324cSopenharmony_ci 378370b324cSopenharmony_ci UString path = path2; 379370b324cSopenharmony_ci 380370b324cSopenharmony_ci bool isBin = false; 381370b324cSopenharmony_ci const bool zeroMode = options.HashMode_Zero.Val; 382370b324cSopenharmony_ci const bool tagMode = options.HashMode_Tag.Val; 383370b324cSopenharmony_ci 384370b324cSopenharmony_ci#if CHAR_PATH_SEPARATOR != '/' 385370b324cSopenharmony_ci path.Replace(WCHAR_PATH_SEPARATOR, L'/'); 386370b324cSopenharmony_ci // path.Replace((wchar_t)('\\' + 0xf000), L'\\'); // to debug WSL 387370b324cSopenharmony_ci#endif 388370b324cSopenharmony_ci 389370b324cSopenharmony_ci AString utf8; 390370b324cSopenharmony_ci ConvertUnicodeToUTF8(path, utf8); 391370b324cSopenharmony_ci 392370b324cSopenharmony_ci AString esc; 393370b324cSopenharmony_ci CSum_Name_OriginalToEscape(utf8, esc); 394370b324cSopenharmony_ci 395370b324cSopenharmony_ci if (!zeroMode) 396370b324cSopenharmony_ci { 397370b324cSopenharmony_ci if (esc != utf8) 398370b324cSopenharmony_ci { 399370b324cSopenharmony_ci /* Original md5sum writes escape in that case. 400370b324cSopenharmony_ci We do same for compatibility with original md5sum. */ 401370b324cSopenharmony_ci hashFileString += '\\'; 402370b324cSopenharmony_ci } 403370b324cSopenharmony_ci } 404370b324cSopenharmony_ci 405370b324cSopenharmony_ci if (isDir && !esc.IsEmpty() && esc.Back() != '/') 406370b324cSopenharmony_ci esc += '/'; 407370b324cSopenharmony_ci 408370b324cSopenharmony_ci if (tagMode) 409370b324cSopenharmony_ci { 410370b324cSopenharmony_ci if (!methodName.IsEmpty()) 411370b324cSopenharmony_ci { 412370b324cSopenharmony_ci hashFileString += methodName; 413370b324cSopenharmony_ci hashFileString += ' '; 414370b324cSopenharmony_ci } 415370b324cSopenharmony_ci hashFileString += '('; 416370b324cSopenharmony_ci hashFileString += esc; 417370b324cSopenharmony_ci hashFileString += ')'; 418370b324cSopenharmony_ci hashFileString += " = "; 419370b324cSopenharmony_ci } 420370b324cSopenharmony_ci 421370b324cSopenharmony_ci hashFileString += hashesString; 422370b324cSopenharmony_ci 423370b324cSopenharmony_ci if (!tagMode) 424370b324cSopenharmony_ci { 425370b324cSopenharmony_ci hashFileString += ' '; 426370b324cSopenharmony_ci hashFileString += (char)(isBin ? '*' : ' '); 427370b324cSopenharmony_ci hashFileString += esc; 428370b324cSopenharmony_ci } 429370b324cSopenharmony_ci 430370b324cSopenharmony_ci Add_LF(hashFileString, options); 431370b324cSopenharmony_ci} 432370b324cSopenharmony_ci 433370b324cSopenharmony_ci 434370b324cSopenharmony_ci 435370b324cSopenharmony_cistatic void WriteLine(CDynLimBuf &hashFileString, 436370b324cSopenharmony_ci const CHashOptionsLocal &options, 437370b324cSopenharmony_ci const UString &path, 438370b324cSopenharmony_ci bool isDir, 439370b324cSopenharmony_ci const CHashBundle &hb) 440370b324cSopenharmony_ci{ 441370b324cSopenharmony_ci AString methodName; 442370b324cSopenharmony_ci if (!hb.Hashers.IsEmpty()) 443370b324cSopenharmony_ci methodName = hb.Hashers[0].Name; 444370b324cSopenharmony_ci 445370b324cSopenharmony_ci AString hashesString; 446370b324cSopenharmony_ci AddHashResultLine(hashesString, hb.Hashers); 447370b324cSopenharmony_ci WriteLine(hashFileString, options, path, isDir, methodName, hashesString); 448370b324cSopenharmony_ci} 449370b324cSopenharmony_ci 450370b324cSopenharmony_ci 451370b324cSopenharmony_ciHRESULT HashCalc( 452370b324cSopenharmony_ci DECL_EXTERNAL_CODECS_LOC_VARS 453370b324cSopenharmony_ci const NWildcard::CCensor &censor, 454370b324cSopenharmony_ci const CHashOptions &options, 455370b324cSopenharmony_ci AString &errorInfo, 456370b324cSopenharmony_ci IHashCallbackUI *callback) 457370b324cSopenharmony_ci{ 458370b324cSopenharmony_ci CDirItems dirItems; 459370b324cSopenharmony_ci dirItems.Callback = callback; 460370b324cSopenharmony_ci 461370b324cSopenharmony_ci if (options.StdInMode) 462370b324cSopenharmony_ci { 463370b324cSopenharmony_ci CDirItem di; 464370b324cSopenharmony_ci di.Size = (UInt64)(Int64)-1; 465370b324cSopenharmony_ci di.SetAsFile(); 466370b324cSopenharmony_ci dirItems.Items.Add(di); 467370b324cSopenharmony_ci } 468370b324cSopenharmony_ci else 469370b324cSopenharmony_ci { 470370b324cSopenharmony_ci RINOK(callback->StartScanning()) 471370b324cSopenharmony_ci 472370b324cSopenharmony_ci dirItems.SymLinks = options.SymLinks.Val; 473370b324cSopenharmony_ci dirItems.ScanAltStreams = options.AltStreamsMode; 474370b324cSopenharmony_ci dirItems.ExcludeDirItems = censor.ExcludeDirItems; 475370b324cSopenharmony_ci dirItems.ExcludeFileItems = censor.ExcludeFileItems; 476370b324cSopenharmony_ci 477370b324cSopenharmony_ci dirItems.ShareForWrite = options.OpenShareForWrite; 478370b324cSopenharmony_ci 479370b324cSopenharmony_ci HRESULT res = EnumerateItems(censor, 480370b324cSopenharmony_ci options.PathMode, 481370b324cSopenharmony_ci UString(), 482370b324cSopenharmony_ci dirItems); 483370b324cSopenharmony_ci 484370b324cSopenharmony_ci if (res != S_OK) 485370b324cSopenharmony_ci { 486370b324cSopenharmony_ci if (res != E_ABORT) 487370b324cSopenharmony_ci errorInfo = "Scanning error"; 488370b324cSopenharmony_ci return res; 489370b324cSopenharmony_ci } 490370b324cSopenharmony_ci RINOK(callback->FinishScanning(dirItems.Stat)) 491370b324cSopenharmony_ci } 492370b324cSopenharmony_ci 493370b324cSopenharmony_ci unsigned i; 494370b324cSopenharmony_ci CHashBundle hb; 495370b324cSopenharmony_ci RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods)) 496370b324cSopenharmony_ci // hb.Init(); 497370b324cSopenharmony_ci 498370b324cSopenharmony_ci hb.NumErrors = dirItems.Stat.NumErrors; 499370b324cSopenharmony_ci 500370b324cSopenharmony_ci UInt64 totalSize = 0; 501370b324cSopenharmony_ci if (options.StdInMode) 502370b324cSopenharmony_ci { 503370b324cSopenharmony_ci RINOK(callback->SetNumFiles(1)) 504370b324cSopenharmony_ci } 505370b324cSopenharmony_ci else 506370b324cSopenharmony_ci { 507370b324cSopenharmony_ci totalSize = dirItems.Stat.GetTotalBytes(); 508370b324cSopenharmony_ci RINOK(callback->SetTotal(totalSize)) 509370b324cSopenharmony_ci } 510370b324cSopenharmony_ci 511370b324cSopenharmony_ci const UInt32 kBufSize = 1 << 15; 512370b324cSopenharmony_ci CHashMidBuf buf; 513370b324cSopenharmony_ci if (!buf.Alloc(kBufSize)) 514370b324cSopenharmony_ci return E_OUTOFMEMORY; 515370b324cSopenharmony_ci 516370b324cSopenharmony_ci UInt64 completeValue = 0; 517370b324cSopenharmony_ci 518370b324cSopenharmony_ci RINOK(callback->BeforeFirstFile(hb)) 519370b324cSopenharmony_ci 520370b324cSopenharmony_ci /* 521370b324cSopenharmony_ci CDynLimBuf hashFileString((size_t)1 << 31); 522370b324cSopenharmony_ci const bool needGenerate = !options.HashFilePath.IsEmpty(); 523370b324cSopenharmony_ci */ 524370b324cSopenharmony_ci 525370b324cSopenharmony_ci for (i = 0; i < dirItems.Items.Size(); i++) 526370b324cSopenharmony_ci { 527370b324cSopenharmony_ci CMyComPtr<ISequentialInStream> inStream; 528370b324cSopenharmony_ci UString path; 529370b324cSopenharmony_ci bool isDir = false; 530370b324cSopenharmony_ci bool isAltStream = false; 531370b324cSopenharmony_ci 532370b324cSopenharmony_ci if (options.StdInMode) 533370b324cSopenharmony_ci { 534370b324cSopenharmony_ci inStream = new CStdInFileStream; 535370b324cSopenharmony_ci } 536370b324cSopenharmony_ci else 537370b324cSopenharmony_ci { 538370b324cSopenharmony_ci path = dirItems.GetLogPath(i); 539370b324cSopenharmony_ci const CDirItem &di = dirItems.Items[i]; 540370b324cSopenharmony_ci #ifdef _WIN32 541370b324cSopenharmony_ci isAltStream = di.IsAltStream; 542370b324cSopenharmony_ci #endif 543370b324cSopenharmony_ci 544370b324cSopenharmony_ci #ifndef UNDER_CE 545370b324cSopenharmony_ci // if (di.AreReparseData()) 546370b324cSopenharmony_ci if (di.ReparseData.Size() != 0) 547370b324cSopenharmony_ci { 548370b324cSopenharmony_ci CBufInStream *inStreamSpec = new CBufInStream(); 549370b324cSopenharmony_ci inStream = inStreamSpec; 550370b324cSopenharmony_ci inStreamSpec->Init(di.ReparseData, di.ReparseData.Size()); 551370b324cSopenharmony_ci } 552370b324cSopenharmony_ci else 553370b324cSopenharmony_ci #endif 554370b324cSopenharmony_ci { 555370b324cSopenharmony_ci CInFileStream *inStreamSpec = new CInFileStream; 556370b324cSopenharmony_ci inStreamSpec->Set_PreserveATime(options.PreserveATime); 557370b324cSopenharmony_ci inStream = inStreamSpec; 558370b324cSopenharmony_ci isDir = di.IsDir(); 559370b324cSopenharmony_ci if (!isDir) 560370b324cSopenharmony_ci { 561370b324cSopenharmony_ci const FString phyPath = dirItems.GetPhyPath(i); 562370b324cSopenharmony_ci if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite)) 563370b324cSopenharmony_ci { 564370b324cSopenharmony_ci HRESULT res = callback->OpenFileError(phyPath, ::GetLastError()); 565370b324cSopenharmony_ci hb.NumErrors++; 566370b324cSopenharmony_ci if (res != S_FALSE) 567370b324cSopenharmony_ci return res; 568370b324cSopenharmony_ci continue; 569370b324cSopenharmony_ci } 570370b324cSopenharmony_ci if (!options.StdInMode) 571370b324cSopenharmony_ci { 572370b324cSopenharmony_ci UInt64 curSize = 0; 573370b324cSopenharmony_ci if (inStreamSpec->GetSize(&curSize) == S_OK) 574370b324cSopenharmony_ci { 575370b324cSopenharmony_ci if (curSize > di.Size) 576370b324cSopenharmony_ci { 577370b324cSopenharmony_ci totalSize += curSize - di.Size; 578370b324cSopenharmony_ci RINOK(callback->SetTotal(totalSize)) 579370b324cSopenharmony_ci // printf("\ntotal = %d MiB\n", (unsigned)(totalSize >> 20)); 580370b324cSopenharmony_ci } 581370b324cSopenharmony_ci } 582370b324cSopenharmony_ci } 583370b324cSopenharmony_ci // inStreamSpec->ReloadProps(); 584370b324cSopenharmony_ci } 585370b324cSopenharmony_ci } 586370b324cSopenharmony_ci } 587370b324cSopenharmony_ci 588370b324cSopenharmony_ci RINOK(callback->GetStream(path, isDir)) 589370b324cSopenharmony_ci UInt64 fileSize = 0; 590370b324cSopenharmony_ci 591370b324cSopenharmony_ci hb.InitForNewFile(); 592370b324cSopenharmony_ci 593370b324cSopenharmony_ci if (!isDir) 594370b324cSopenharmony_ci { 595370b324cSopenharmony_ci for (UInt32 step = 0;; step++) 596370b324cSopenharmony_ci { 597370b324cSopenharmony_ci if ((step & 0xFF) == 0) 598370b324cSopenharmony_ci { 599370b324cSopenharmony_ci // printf("\ncompl = %d\n", (unsigned)(completeValue >> 20)); 600370b324cSopenharmony_ci RINOK(callback->SetCompleted(&completeValue)) 601370b324cSopenharmony_ci } 602370b324cSopenharmony_ci UInt32 size; 603370b324cSopenharmony_ci RINOK(inStream->Read(buf, kBufSize, &size)) 604370b324cSopenharmony_ci if (size == 0) 605370b324cSopenharmony_ci break; 606370b324cSopenharmony_ci hb.Update(buf, size); 607370b324cSopenharmony_ci fileSize += size; 608370b324cSopenharmony_ci completeValue += size; 609370b324cSopenharmony_ci } 610370b324cSopenharmony_ci } 611370b324cSopenharmony_ci 612370b324cSopenharmony_ci hb.Final(isDir, isAltStream, path); 613370b324cSopenharmony_ci 614370b324cSopenharmony_ci /* 615370b324cSopenharmony_ci if (needGenerate 616370b324cSopenharmony_ci && (options.HashMode_Dirs.Val || !isDir)) 617370b324cSopenharmony_ci { 618370b324cSopenharmony_ci WriteLine(hashFileString, 619370b324cSopenharmony_ci options, 620370b324cSopenharmony_ci path, // change it 621370b324cSopenharmony_ci isDir, 622370b324cSopenharmony_ci hb); 623370b324cSopenharmony_ci 624370b324cSopenharmony_ci if (hashFileString.IsError()) 625370b324cSopenharmony_ci return E_OUTOFMEMORY; 626370b324cSopenharmony_ci } 627370b324cSopenharmony_ci */ 628370b324cSopenharmony_ci 629370b324cSopenharmony_ci RINOK(callback->SetOperationResult(fileSize, hb, !isDir)) 630370b324cSopenharmony_ci RINOK(callback->SetCompleted(&completeValue)) 631370b324cSopenharmony_ci } 632370b324cSopenharmony_ci 633370b324cSopenharmony_ci /* 634370b324cSopenharmony_ci if (needGenerate) 635370b324cSopenharmony_ci { 636370b324cSopenharmony_ci NFile::NIO::COutFile file; 637370b324cSopenharmony_ci if (!file.Create(us2fs(options.HashFilePath), true)) // createAlways 638370b324cSopenharmony_ci return GetLastError_noZero_HRESULT(); 639370b324cSopenharmony_ci if (!file.WriteFull(hashFileString, hashFileString.Len())) 640370b324cSopenharmony_ci return GetLastError_noZero_HRESULT(); 641370b324cSopenharmony_ci } 642370b324cSopenharmony_ci */ 643370b324cSopenharmony_ci 644370b324cSopenharmony_ci return callback->AfterLastFile(hb); 645370b324cSopenharmony_ci} 646370b324cSopenharmony_ci 647370b324cSopenharmony_ci 648370b324cSopenharmony_cistatic inline char GetHex_Upper(unsigned v) 649370b324cSopenharmony_ci{ 650370b324cSopenharmony_ci return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10))); 651370b324cSopenharmony_ci} 652370b324cSopenharmony_ci 653370b324cSopenharmony_cistatic inline char GetHex_Lower(unsigned v) 654370b324cSopenharmony_ci{ 655370b324cSopenharmony_ci return (char)((v < 10) ? ('0' + v) : ('a' + (v - 10))); 656370b324cSopenharmony_ci} 657370b324cSopenharmony_ci 658370b324cSopenharmony_civoid HashHexToString(char *dest, const Byte *data, UInt32 size) 659370b324cSopenharmony_ci{ 660370b324cSopenharmony_ci dest[size * 2] = 0; 661370b324cSopenharmony_ci 662370b324cSopenharmony_ci if (!data) 663370b324cSopenharmony_ci { 664370b324cSopenharmony_ci for (UInt32 i = 0; i < size; i++) 665370b324cSopenharmony_ci { 666370b324cSopenharmony_ci dest[0] = ' '; 667370b324cSopenharmony_ci dest[1] = ' '; 668370b324cSopenharmony_ci dest += 2; 669370b324cSopenharmony_ci } 670370b324cSopenharmony_ci return; 671370b324cSopenharmony_ci } 672370b324cSopenharmony_ci 673370b324cSopenharmony_ci if (size <= 8) 674370b324cSopenharmony_ci { 675370b324cSopenharmony_ci dest += size * 2; 676370b324cSopenharmony_ci for (UInt32 i = 0; i < size; i++) 677370b324cSopenharmony_ci { 678370b324cSopenharmony_ci const unsigned b = data[i]; 679370b324cSopenharmony_ci dest -= 2; 680370b324cSopenharmony_ci dest[0] = GetHex_Upper((b >> 4) & 0xF); 681370b324cSopenharmony_ci dest[1] = GetHex_Upper(b & 0xF); 682370b324cSopenharmony_ci } 683370b324cSopenharmony_ci } 684370b324cSopenharmony_ci else 685370b324cSopenharmony_ci { 686370b324cSopenharmony_ci for (UInt32 i = 0; i < size; i++) 687370b324cSopenharmony_ci { 688370b324cSopenharmony_ci const unsigned b = data[i]; 689370b324cSopenharmony_ci dest[0] = GetHex_Lower((b >> 4) & 0xF); 690370b324cSopenharmony_ci dest[1] = GetHex_Lower(b & 0xF); 691370b324cSopenharmony_ci dest += 2; 692370b324cSopenharmony_ci } 693370b324cSopenharmony_ci } 694370b324cSopenharmony_ci} 695370b324cSopenharmony_ci 696370b324cSopenharmony_civoid CHasherState::WriteToString(unsigned digestIndex, char *s) const 697370b324cSopenharmony_ci{ 698370b324cSopenharmony_ci HashHexToString(s, Digests[digestIndex], DigestSize); 699370b324cSopenharmony_ci 700370b324cSopenharmony_ci if (digestIndex != 0 && NumSums[digestIndex] != 1) 701370b324cSopenharmony_ci { 702370b324cSopenharmony_ci unsigned numExtraBytes = GetNumExtraBytes_for_Group(digestIndex); 703370b324cSopenharmony_ci if (numExtraBytes > 4) 704370b324cSopenharmony_ci numExtraBytes = 8; 705370b324cSopenharmony_ci else // if (numExtraBytes >= 0) 706370b324cSopenharmony_ci numExtraBytes = 4; 707370b324cSopenharmony_ci // if (numExtraBytes != 0) 708370b324cSopenharmony_ci { 709370b324cSopenharmony_ci s += strlen(s); 710370b324cSopenharmony_ci *s++ = '-'; 711370b324cSopenharmony_ci // *s = 0; 712370b324cSopenharmony_ci HashHexToString(s, GetExtraData_for_Group(digestIndex), numExtraBytes); 713370b324cSopenharmony_ci } 714370b324cSopenharmony_ci } 715370b324cSopenharmony_ci} 716370b324cSopenharmony_ci 717370b324cSopenharmony_ci 718370b324cSopenharmony_ci 719370b324cSopenharmony_ci// ---------- Hash Handler ---------- 720370b324cSopenharmony_ci 721370b324cSopenharmony_cinamespace NHash { 722370b324cSopenharmony_ci 723370b324cSopenharmony_cistatic size_t ParseHexString(const char *s, Byte *dest) throw() 724370b324cSopenharmony_ci{ 725370b324cSopenharmony_ci size_t num; 726370b324cSopenharmony_ci for (num = 0;; num++, s += 2) 727370b324cSopenharmony_ci { 728370b324cSopenharmony_ci unsigned c = (Byte)s[0]; 729370b324cSopenharmony_ci unsigned v0; 730370b324cSopenharmony_ci if (c >= '0' && c <= '9') v0 = (c - '0'); 731370b324cSopenharmony_ci else if (c >= 'A' && c <= 'F') v0 = 10 + (c - 'A'); 732370b324cSopenharmony_ci else if (c >= 'a' && c <= 'f') v0 = 10 + (c - 'a'); 733370b324cSopenharmony_ci else 734370b324cSopenharmony_ci return num; 735370b324cSopenharmony_ci c = (Byte)s[1]; 736370b324cSopenharmony_ci unsigned v1; 737370b324cSopenharmony_ci if (c >= '0' && c <= '9') v1 = (c - '0'); 738370b324cSopenharmony_ci else if (c >= 'A' && c <= 'F') v1 = 10 + (c - 'A'); 739370b324cSopenharmony_ci else if (c >= 'a' && c <= 'f') v1 = 10 + (c - 'a'); 740370b324cSopenharmony_ci else 741370b324cSopenharmony_ci return num; 742370b324cSopenharmony_ci if (dest) 743370b324cSopenharmony_ci dest[num] = (Byte)(v1 | (v0 << 4)); 744370b324cSopenharmony_ci } 745370b324cSopenharmony_ci} 746370b324cSopenharmony_ci 747370b324cSopenharmony_ci 748370b324cSopenharmony_ci#define IsWhite(c) ((c) == ' ' || (c) == '\t') 749370b324cSopenharmony_ci 750370b324cSopenharmony_cibool CHashPair::IsDir() const 751370b324cSopenharmony_ci{ 752370b324cSopenharmony_ci if (Name.IsEmpty() || Name.Back() != '/') 753370b324cSopenharmony_ci return false; 754370b324cSopenharmony_ci // here we expect that Dir items contain only zeros or no Hash 755370b324cSopenharmony_ci for (size_t i = 0; i < Hash.Size(); i++) 756370b324cSopenharmony_ci if (Hash[i] != 0) 757370b324cSopenharmony_ci return false; 758370b324cSopenharmony_ci return true; 759370b324cSopenharmony_ci} 760370b324cSopenharmony_ci 761370b324cSopenharmony_ci 762370b324cSopenharmony_cibool CHashPair::ParseCksum(const char *s) 763370b324cSopenharmony_ci{ 764370b324cSopenharmony_ci const char *end; 765370b324cSopenharmony_ci 766370b324cSopenharmony_ci const UInt32 crc = ConvertStringToUInt32(s, &end); 767370b324cSopenharmony_ci if (*end != ' ') 768370b324cSopenharmony_ci return false; 769370b324cSopenharmony_ci end++; 770370b324cSopenharmony_ci 771370b324cSopenharmony_ci const UInt64 size = ConvertStringToUInt64(end, &end); 772370b324cSopenharmony_ci if (*end != ' ') 773370b324cSopenharmony_ci return false; 774370b324cSopenharmony_ci end++; 775370b324cSopenharmony_ci 776370b324cSopenharmony_ci Name = end; 777370b324cSopenharmony_ci 778370b324cSopenharmony_ci Hash.Alloc(4); 779370b324cSopenharmony_ci SetBe32(Hash, crc) 780370b324cSopenharmony_ci 781370b324cSopenharmony_ci Size_from_Arc = size; 782370b324cSopenharmony_ci Size_from_Arc_Defined = true; 783370b324cSopenharmony_ci 784370b324cSopenharmony_ci return true; 785370b324cSopenharmony_ci} 786370b324cSopenharmony_ci 787370b324cSopenharmony_ci 788370b324cSopenharmony_ci 789370b324cSopenharmony_cistatic const char *SkipWhite(const char *s) 790370b324cSopenharmony_ci{ 791370b324cSopenharmony_ci while (IsWhite(*s)) 792370b324cSopenharmony_ci s++; 793370b324cSopenharmony_ci return s; 794370b324cSopenharmony_ci} 795370b324cSopenharmony_ci 796370b324cSopenharmony_cistatic const char * const k_CsumMethodNames[] = 797370b324cSopenharmony_ci{ 798370b324cSopenharmony_ci "sha256" 799370b324cSopenharmony_ci , "sha224" 800370b324cSopenharmony_ci// , "sha512/224" 801370b324cSopenharmony_ci// , "sha512/256" 802370b324cSopenharmony_ci , "sha512" 803370b324cSopenharmony_ci , "sha384" 804370b324cSopenharmony_ci , "sha1" 805370b324cSopenharmony_ci , "md5" 806370b324cSopenharmony_ci , "blake2b" 807370b324cSopenharmony_ci , "crc64" 808370b324cSopenharmony_ci , "crc32" 809370b324cSopenharmony_ci , "cksum" 810370b324cSopenharmony_ci}; 811370b324cSopenharmony_ci 812370b324cSopenharmony_cistatic UString GetMethod_from_FileName(const UString &name) 813370b324cSopenharmony_ci{ 814370b324cSopenharmony_ci AString s; 815370b324cSopenharmony_ci ConvertUnicodeToUTF8(name, s); 816370b324cSopenharmony_ci const int dotPos = s.ReverseFind_Dot(); 817370b324cSopenharmony_ci const char *src = s.Ptr(); 818370b324cSopenharmony_ci bool isExtension = false; 819370b324cSopenharmony_ci if (dotPos >= 0) 820370b324cSopenharmony_ci { 821370b324cSopenharmony_ci isExtension = true; 822370b324cSopenharmony_ci src = s.Ptr(dotPos + 1); 823370b324cSopenharmony_ci } 824370b324cSopenharmony_ci const char *m = ""; 825370b324cSopenharmony_ci unsigned i; 826370b324cSopenharmony_ci for (i = 0; i < Z7_ARRAY_SIZE(k_CsumMethodNames); i++) 827370b324cSopenharmony_ci { 828370b324cSopenharmony_ci m = k_CsumMethodNames[i]; 829370b324cSopenharmony_ci if (isExtension) 830370b324cSopenharmony_ci { 831370b324cSopenharmony_ci if (StringsAreEqual_Ascii(src, m)) 832370b324cSopenharmony_ci break; 833370b324cSopenharmony_ci } 834370b324cSopenharmony_ci else if (IsString1PrefixedByString2_NoCase_Ascii(src, m)) 835370b324cSopenharmony_ci if (StringsAreEqual_Ascii(src + strlen(m), "sums")) 836370b324cSopenharmony_ci break; 837370b324cSopenharmony_ci } 838370b324cSopenharmony_ci UString res; 839370b324cSopenharmony_ci if (i != Z7_ARRAY_SIZE(k_CsumMethodNames)) 840370b324cSopenharmony_ci res = m; 841370b324cSopenharmony_ci return res; 842370b324cSopenharmony_ci} 843370b324cSopenharmony_ci 844370b324cSopenharmony_ci 845370b324cSopenharmony_cibool CHashPair::Parse(const char *s) 846370b324cSopenharmony_ci{ 847370b324cSopenharmony_ci // here we keep compatibility with original md5sum / shasum 848370b324cSopenharmony_ci bool escape = false; 849370b324cSopenharmony_ci 850370b324cSopenharmony_ci s = SkipWhite(s); 851370b324cSopenharmony_ci 852370b324cSopenharmony_ci if (*s == '\\') 853370b324cSopenharmony_ci { 854370b324cSopenharmony_ci s++; 855370b324cSopenharmony_ci escape = true; 856370b324cSopenharmony_ci } 857370b324cSopenharmony_ci 858370b324cSopenharmony_ci // const char *kMethod = GetMethod_from_FileName(s); 859370b324cSopenharmony_ci // if (kMethod) 860370b324cSopenharmony_ci if (ParseHexString(s, NULL) < 4) 861370b324cSopenharmony_ci { 862370b324cSopenharmony_ci // BSD-style checksum line 863370b324cSopenharmony_ci { 864370b324cSopenharmony_ci const char *s2 = s; 865370b324cSopenharmony_ci for (; *s2 != 0; s2++) 866370b324cSopenharmony_ci { 867370b324cSopenharmony_ci const char c = *s2; 868370b324cSopenharmony_ci if (c == 0) 869370b324cSopenharmony_ci return false; 870370b324cSopenharmony_ci if (c == ' ' || c == '(') 871370b324cSopenharmony_ci break; 872370b324cSopenharmony_ci } 873370b324cSopenharmony_ci Method.SetFrom(s, (unsigned)(s2 - s)); 874370b324cSopenharmony_ci s = s2; 875370b324cSopenharmony_ci } 876370b324cSopenharmony_ci IsBSD = true; 877370b324cSopenharmony_ci if (*s == ' ') 878370b324cSopenharmony_ci s++; 879370b324cSopenharmony_ci if (*s != '(') 880370b324cSopenharmony_ci return false; 881370b324cSopenharmony_ci s++; 882370b324cSopenharmony_ci { 883370b324cSopenharmony_ci const char *s2 = s; 884370b324cSopenharmony_ci for (; *s2 != 0; s2++) 885370b324cSopenharmony_ci {} 886370b324cSopenharmony_ci for (;;) 887370b324cSopenharmony_ci { 888370b324cSopenharmony_ci s2--; 889370b324cSopenharmony_ci if (s2 < s) 890370b324cSopenharmony_ci return false; 891370b324cSopenharmony_ci if (*s2 == ')') 892370b324cSopenharmony_ci break; 893370b324cSopenharmony_ci } 894370b324cSopenharmony_ci Name.SetFrom(s, (unsigned)(s2 - s)); 895370b324cSopenharmony_ci s = s2 + 1; 896370b324cSopenharmony_ci } 897370b324cSopenharmony_ci 898370b324cSopenharmony_ci s = SkipWhite(s); 899370b324cSopenharmony_ci if (*s != '=') 900370b324cSopenharmony_ci return false; 901370b324cSopenharmony_ci s++; 902370b324cSopenharmony_ci s = SkipWhite(s); 903370b324cSopenharmony_ci } 904370b324cSopenharmony_ci 905370b324cSopenharmony_ci { 906370b324cSopenharmony_ci const size_t num = ParseHexString(s, NULL); 907370b324cSopenharmony_ci Hash.Alloc(num); 908370b324cSopenharmony_ci ParseHexString(s, Hash); 909370b324cSopenharmony_ci const size_t numChars = num * 2; 910370b324cSopenharmony_ci HashString.SetFrom(s, (unsigned)numChars); 911370b324cSopenharmony_ci s += numChars; 912370b324cSopenharmony_ci } 913370b324cSopenharmony_ci 914370b324cSopenharmony_ci if (IsBSD) 915370b324cSopenharmony_ci { 916370b324cSopenharmony_ci if (*s != 0) 917370b324cSopenharmony_ci return false; 918370b324cSopenharmony_ci if (escape) 919370b324cSopenharmony_ci { 920370b324cSopenharmony_ci const AString temp (Name); 921370b324cSopenharmony_ci return CSum_Name_EscapeToOriginal(temp, Name); 922370b324cSopenharmony_ci } 923370b324cSopenharmony_ci return true; 924370b324cSopenharmony_ci } 925370b324cSopenharmony_ci 926370b324cSopenharmony_ci if (*s == 0) 927370b324cSopenharmony_ci return true; 928370b324cSopenharmony_ci 929370b324cSopenharmony_ci if (*s != ' ') 930370b324cSopenharmony_ci return false; 931370b324cSopenharmony_ci s++; 932370b324cSopenharmony_ci const char c = *s; 933370b324cSopenharmony_ci if (c != ' ' 934370b324cSopenharmony_ci && c != '*' 935370b324cSopenharmony_ci && c != 'U' // shasum Universal 936370b324cSopenharmony_ci && c != '^' // shasum 0/1 937370b324cSopenharmony_ci ) 938370b324cSopenharmony_ci return false; 939370b324cSopenharmony_ci Mode = c; 940370b324cSopenharmony_ci s++; 941370b324cSopenharmony_ci if (escape) 942370b324cSopenharmony_ci return CSum_Name_EscapeToOriginal(s, Name); 943370b324cSopenharmony_ci Name = s; 944370b324cSopenharmony_ci return true; 945370b324cSopenharmony_ci} 946370b324cSopenharmony_ci 947370b324cSopenharmony_ci 948370b324cSopenharmony_cistatic bool GetLine(CByteBuffer &buf, bool zeroMode, bool cr_lf_Mode, size_t &posCur, AString &s) 949370b324cSopenharmony_ci{ 950370b324cSopenharmony_ci s.Empty(); 951370b324cSopenharmony_ci size_t pos = posCur; 952370b324cSopenharmony_ci const Byte *p = buf; 953370b324cSopenharmony_ci unsigned numDigits = 0; 954370b324cSopenharmony_ci for (; pos < buf.Size(); pos++) 955370b324cSopenharmony_ci { 956370b324cSopenharmony_ci const Byte b = p[pos]; 957370b324cSopenharmony_ci if (b == 0) 958370b324cSopenharmony_ci { 959370b324cSopenharmony_ci numDigits = 1; 960370b324cSopenharmony_ci break; 961370b324cSopenharmony_ci } 962370b324cSopenharmony_ci if (zeroMode) 963370b324cSopenharmony_ci continue; 964370b324cSopenharmony_ci if (b == 0x0a) 965370b324cSopenharmony_ci { 966370b324cSopenharmony_ci numDigits = 1; 967370b324cSopenharmony_ci break; 968370b324cSopenharmony_ci } 969370b324cSopenharmony_ci if (!cr_lf_Mode) 970370b324cSopenharmony_ci continue; 971370b324cSopenharmony_ci if (b == 0x0d) 972370b324cSopenharmony_ci { 973370b324cSopenharmony_ci if (pos + 1 >= buf.Size()) 974370b324cSopenharmony_ci { 975370b324cSopenharmony_ci numDigits = 1; 976370b324cSopenharmony_ci break; 977370b324cSopenharmony_ci // return false; 978370b324cSopenharmony_ci } 979370b324cSopenharmony_ci if (p[pos + 1] == 0x0a) 980370b324cSopenharmony_ci { 981370b324cSopenharmony_ci numDigits = 2; 982370b324cSopenharmony_ci break; 983370b324cSopenharmony_ci } 984370b324cSopenharmony_ci } 985370b324cSopenharmony_ci } 986370b324cSopenharmony_ci s.SetFrom((const char *)(p + posCur), (unsigned)(pos - posCur)); 987370b324cSopenharmony_ci posCur = pos + numDigits; 988370b324cSopenharmony_ci return true; 989370b324cSopenharmony_ci} 990370b324cSopenharmony_ci 991370b324cSopenharmony_ci 992370b324cSopenharmony_cistatic bool Is_CR_LF_Data(const Byte *buf, size_t size) 993370b324cSopenharmony_ci{ 994370b324cSopenharmony_ci bool isCrLf = false; 995370b324cSopenharmony_ci for (size_t i = 0; i < size;) 996370b324cSopenharmony_ci { 997370b324cSopenharmony_ci const Byte b = buf[i]; 998370b324cSopenharmony_ci if (b == 0x0a) 999370b324cSopenharmony_ci return false; 1000370b324cSopenharmony_ci if (b == 0x0d) 1001370b324cSopenharmony_ci { 1002370b324cSopenharmony_ci if (i == size - 1) 1003370b324cSopenharmony_ci return false; 1004370b324cSopenharmony_ci if (buf[i + 1] != 0x0a) 1005370b324cSopenharmony_ci return false; 1006370b324cSopenharmony_ci isCrLf = true; 1007370b324cSopenharmony_ci i += 2; 1008370b324cSopenharmony_ci } 1009370b324cSopenharmony_ci else 1010370b324cSopenharmony_ci i++; 1011370b324cSopenharmony_ci } 1012370b324cSopenharmony_ci return isCrLf; 1013370b324cSopenharmony_ci} 1014370b324cSopenharmony_ci 1015370b324cSopenharmony_ci 1016370b324cSopenharmony_cistatic const Byte kArcProps[] = 1017370b324cSopenharmony_ci{ 1018370b324cSopenharmony_ci // kpidComment, 1019370b324cSopenharmony_ci kpidCharacts 1020370b324cSopenharmony_ci}; 1021370b324cSopenharmony_ci 1022370b324cSopenharmony_cistatic const Byte kProps[] = 1023370b324cSopenharmony_ci{ 1024370b324cSopenharmony_ci kpidPath, 1025370b324cSopenharmony_ci kpidSize, 1026370b324cSopenharmony_ci kpidPackSize, 1027370b324cSopenharmony_ci kpidMethod 1028370b324cSopenharmony_ci}; 1029370b324cSopenharmony_ci 1030370b324cSopenharmony_cistatic const Byte kRawProps[] = 1031370b324cSopenharmony_ci{ 1032370b324cSopenharmony_ci kpidChecksum 1033370b324cSopenharmony_ci}; 1034370b324cSopenharmony_ci 1035370b324cSopenharmony_ci 1036370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetParent(UInt32 /* index */ , UInt32 *parent, UInt32 *parentType)) 1037370b324cSopenharmony_ci{ 1038370b324cSopenharmony_ci *parentType = NParentType::kDir; 1039370b324cSopenharmony_ci *parent = (UInt32)(Int32)-1; 1040370b324cSopenharmony_ci return S_OK; 1041370b324cSopenharmony_ci} 1042370b324cSopenharmony_ci 1043370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps)) 1044370b324cSopenharmony_ci{ 1045370b324cSopenharmony_ci *numProps = Z7_ARRAY_SIZE(kRawProps); 1046370b324cSopenharmony_ci return S_OK; 1047370b324cSopenharmony_ci} 1048370b324cSopenharmony_ci 1049370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID)) 1050370b324cSopenharmony_ci{ 1051370b324cSopenharmony_ci *propID = kRawProps[index]; 1052370b324cSopenharmony_ci *name = NULL; 1053370b324cSopenharmony_ci return S_OK; 1054370b324cSopenharmony_ci} 1055370b324cSopenharmony_ci 1056370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)) 1057370b324cSopenharmony_ci{ 1058370b324cSopenharmony_ci *data = NULL; 1059370b324cSopenharmony_ci *dataSize = 0; 1060370b324cSopenharmony_ci *propType = 0; 1061370b324cSopenharmony_ci 1062370b324cSopenharmony_ci if (propID == kpidChecksum) 1063370b324cSopenharmony_ci { 1064370b324cSopenharmony_ci const CHashPair &hp = HashPairs[index]; 1065370b324cSopenharmony_ci if (hp.Hash.Size() > 0) 1066370b324cSopenharmony_ci { 1067370b324cSopenharmony_ci *data = hp.Hash; 1068370b324cSopenharmony_ci *dataSize = (UInt32)hp.Hash.Size(); 1069370b324cSopenharmony_ci *propType = NPropDataType::kRaw; 1070370b324cSopenharmony_ci } 1071370b324cSopenharmony_ci return S_OK; 1072370b324cSopenharmony_ci } 1073370b324cSopenharmony_ci 1074370b324cSopenharmony_ci return S_OK; 1075370b324cSopenharmony_ci} 1076370b324cSopenharmony_ci 1077370b324cSopenharmony_ciIMP_IInArchive_Props 1078370b324cSopenharmony_ciIMP_IInArchive_ArcProps 1079370b324cSopenharmony_ci 1080370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) 1081370b324cSopenharmony_ci{ 1082370b324cSopenharmony_ci *numItems = HashPairs.Size(); 1083370b324cSopenharmony_ci return S_OK; 1084370b324cSopenharmony_ci} 1085370b324cSopenharmony_ci 1086370b324cSopenharmony_cistatic void Add_OptSpace_String(UString &dest, const char *src) 1087370b324cSopenharmony_ci{ 1088370b324cSopenharmony_ci dest.Add_Space_if_NotEmpty(); 1089370b324cSopenharmony_ci dest += src; 1090370b324cSopenharmony_ci} 1091370b324cSopenharmony_ci 1092370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) 1093370b324cSopenharmony_ci{ 1094370b324cSopenharmony_ci NWindows::NCOM::CPropVariant prop; 1095370b324cSopenharmony_ci switch (propID) 1096370b324cSopenharmony_ci { 1097370b324cSopenharmony_ci case kpidPhySize: if (_phySize != 0) prop = _phySize; break; 1098370b324cSopenharmony_ci /* 1099370b324cSopenharmony_ci case kpidErrorFlags: 1100370b324cSopenharmony_ci { 1101370b324cSopenharmony_ci UInt32 v = 0; 1102370b324cSopenharmony_ci if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; 1103370b324cSopenharmony_ci // if (_sres == k_Base64_RES_NeedMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; 1104370b324cSopenharmony_ci if (v != 0) 1105370b324cSopenharmony_ci prop = v; 1106370b324cSopenharmony_ci break; 1107370b324cSopenharmony_ci } 1108370b324cSopenharmony_ci */ 1109370b324cSopenharmony_ci case kpidCharacts: 1110370b324cSopenharmony_ci { 1111370b324cSopenharmony_ci UString s; 1112370b324cSopenharmony_ci if (_hashSize_Defined) 1113370b324cSopenharmony_ci { 1114370b324cSopenharmony_ci s.Add_Space_if_NotEmpty(); 1115370b324cSopenharmony_ci s.Add_UInt32(_hashSize * 8); 1116370b324cSopenharmony_ci s += "-bit"; 1117370b324cSopenharmony_ci } 1118370b324cSopenharmony_ci if (!_nameExtenstion.IsEmpty()) 1119370b324cSopenharmony_ci { 1120370b324cSopenharmony_ci s.Add_Space_if_NotEmpty(); 1121370b324cSopenharmony_ci s += _nameExtenstion; 1122370b324cSopenharmony_ci } 1123370b324cSopenharmony_ci if (_is_PgpMethod) 1124370b324cSopenharmony_ci { 1125370b324cSopenharmony_ci Add_OptSpace_String(s, "PGP"); 1126370b324cSopenharmony_ci if (!_pgpMethod.IsEmpty()) 1127370b324cSopenharmony_ci { 1128370b324cSopenharmony_ci s += ":"; 1129370b324cSopenharmony_ci s += _pgpMethod; 1130370b324cSopenharmony_ci } 1131370b324cSopenharmony_ci } 1132370b324cSopenharmony_ci if (_is_ZeroMode) 1133370b324cSopenharmony_ci Add_OptSpace_String(s, "ZERO"); 1134370b324cSopenharmony_ci if (_are_there_Tags) 1135370b324cSopenharmony_ci Add_OptSpace_String(s, "TAG"); 1136370b324cSopenharmony_ci if (_are_there_Dirs) 1137370b324cSopenharmony_ci Add_OptSpace_String(s, "DIRS"); 1138370b324cSopenharmony_ci prop = s; 1139370b324cSopenharmony_ci break; 1140370b324cSopenharmony_ci } 1141370b324cSopenharmony_ci 1142370b324cSopenharmony_ci case kpidReadOnly: 1143370b324cSopenharmony_ci { 1144370b324cSopenharmony_ci if (_isArc) 1145370b324cSopenharmony_ci if (!CanUpdate()) 1146370b324cSopenharmony_ci prop = true; 1147370b324cSopenharmony_ci break; 1148370b324cSopenharmony_ci } 1149370b324cSopenharmony_ci } 1150370b324cSopenharmony_ci prop.Detach(value); 1151370b324cSopenharmony_ci return S_OK; 1152370b324cSopenharmony_ci} 1153370b324cSopenharmony_ci 1154370b324cSopenharmony_ci 1155370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) 1156370b324cSopenharmony_ci{ 1157370b324cSopenharmony_ci // COM_TRY_BEGIN 1158370b324cSopenharmony_ci NWindows::NCOM::CPropVariant prop; 1159370b324cSopenharmony_ci CHashPair &hp = HashPairs[index]; 1160370b324cSopenharmony_ci switch (propID) 1161370b324cSopenharmony_ci { 1162370b324cSopenharmony_ci case kpidIsDir: 1163370b324cSopenharmony_ci { 1164370b324cSopenharmony_ci prop = hp.IsDir(); 1165370b324cSopenharmony_ci break; 1166370b324cSopenharmony_ci } 1167370b324cSopenharmony_ci case kpidPath: 1168370b324cSopenharmony_ci { 1169370b324cSopenharmony_ci UString path; 1170370b324cSopenharmony_ci hp.Get_UString_Path(path); 1171370b324cSopenharmony_ci 1172370b324cSopenharmony_ci NArchive::NItemName::ReplaceToOsSlashes_Remove_TailSlash(path, 1173370b324cSopenharmony_ci true); // useBackslashReplacement 1174370b324cSopenharmony_ci 1175370b324cSopenharmony_ci prop = path; 1176370b324cSopenharmony_ci break; 1177370b324cSopenharmony_ci } 1178370b324cSopenharmony_ci case kpidSize: 1179370b324cSopenharmony_ci { 1180370b324cSopenharmony_ci // client needs processed size of last file 1181370b324cSopenharmony_ci if (hp.Size_from_Disk_Defined) 1182370b324cSopenharmony_ci prop = (UInt64)hp.Size_from_Disk; 1183370b324cSopenharmony_ci else if (hp.Size_from_Arc_Defined) 1184370b324cSopenharmony_ci prop = (UInt64)hp.Size_from_Arc; 1185370b324cSopenharmony_ci break; 1186370b324cSopenharmony_ci } 1187370b324cSopenharmony_ci case kpidPackSize: 1188370b324cSopenharmony_ci { 1189370b324cSopenharmony_ci prop = (UInt64)hp.Hash.Size(); 1190370b324cSopenharmony_ci break; 1191370b324cSopenharmony_ci } 1192370b324cSopenharmony_ci case kpidMethod: 1193370b324cSopenharmony_ci { 1194370b324cSopenharmony_ci if (!hp.Method.IsEmpty()) 1195370b324cSopenharmony_ci prop = hp.Method; 1196370b324cSopenharmony_ci break; 1197370b324cSopenharmony_ci } 1198370b324cSopenharmony_ci } 1199370b324cSopenharmony_ci prop.Detach(value); 1200370b324cSopenharmony_ci return S_OK; 1201370b324cSopenharmony_ci // COM_TRY_END 1202370b324cSopenharmony_ci} 1203370b324cSopenharmony_ci 1204370b324cSopenharmony_ci 1205370b324cSopenharmony_cistatic HRESULT ReadStream_to_Buf(IInStream *stream, CByteBuffer &buf, IArchiveOpenCallback *openCallback) 1206370b324cSopenharmony_ci{ 1207370b324cSopenharmony_ci buf.Free(); 1208370b324cSopenharmony_ci UInt64 len; 1209370b324cSopenharmony_ci RINOK(InStream_AtBegin_GetSize(stream, len)) 1210370b324cSopenharmony_ci if (len == 0 || len >= ((UInt64)1 << 31)) 1211370b324cSopenharmony_ci return S_FALSE; 1212370b324cSopenharmony_ci buf.Alloc((size_t)len); 1213370b324cSopenharmony_ci UInt64 pos = 0; 1214370b324cSopenharmony_ci // return ReadStream_FALSE(stream, buf, (size_t)len); 1215370b324cSopenharmony_ci for (;;) 1216370b324cSopenharmony_ci { 1217370b324cSopenharmony_ci const UInt32 kBlockSize = ((UInt32)1 << 24); 1218370b324cSopenharmony_ci const UInt32 curSize = (len < kBlockSize) ? (UInt32)len : kBlockSize; 1219370b324cSopenharmony_ci UInt32 processedSizeLoc; 1220370b324cSopenharmony_ci RINOK(stream->Read((Byte *)buf + pos, curSize, &processedSizeLoc)) 1221370b324cSopenharmony_ci if (processedSizeLoc == 0) 1222370b324cSopenharmony_ci return E_FAIL; 1223370b324cSopenharmony_ci len -= processedSizeLoc; 1224370b324cSopenharmony_ci pos += processedSizeLoc; 1225370b324cSopenharmony_ci if (len == 0) 1226370b324cSopenharmony_ci return S_OK; 1227370b324cSopenharmony_ci if (openCallback) 1228370b324cSopenharmony_ci { 1229370b324cSopenharmony_ci const UInt64 files = 0; 1230370b324cSopenharmony_ci RINOK(openCallback->SetCompleted(&files, &pos)) 1231370b324cSopenharmony_ci } 1232370b324cSopenharmony_ci } 1233370b324cSopenharmony_ci} 1234370b324cSopenharmony_ci 1235370b324cSopenharmony_ci 1236370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback)) 1237370b324cSopenharmony_ci{ 1238370b324cSopenharmony_ci COM_TRY_BEGIN 1239370b324cSopenharmony_ci { 1240370b324cSopenharmony_ci Close(); 1241370b324cSopenharmony_ci 1242370b324cSopenharmony_ci CByteBuffer buf; 1243370b324cSopenharmony_ci RINOK(ReadStream_to_Buf(stream, buf, openCallback)) 1244370b324cSopenharmony_ci 1245370b324cSopenharmony_ci CObjectVector<CHashPair> &pairs = HashPairs; 1246370b324cSopenharmony_ci 1247370b324cSopenharmony_ci bool zeroMode = false; 1248370b324cSopenharmony_ci bool cr_lf_Mode = false; 1249370b324cSopenharmony_ci { 1250370b324cSopenharmony_ci for (size_t i = 0; i < buf.Size(); i++) 1251370b324cSopenharmony_ci if (buf[i] == 0) 1252370b324cSopenharmony_ci { 1253370b324cSopenharmony_ci zeroMode = true; 1254370b324cSopenharmony_ci break; 1255370b324cSopenharmony_ci } 1256370b324cSopenharmony_ci } 1257370b324cSopenharmony_ci _is_ZeroMode = zeroMode; 1258370b324cSopenharmony_ci if (!zeroMode) 1259370b324cSopenharmony_ci cr_lf_Mode = Is_CR_LF_Data(buf, buf.Size()); 1260370b324cSopenharmony_ci 1261370b324cSopenharmony_ci if (openCallback) 1262370b324cSopenharmony_ci { 1263370b324cSopenharmony_ci Z7_DECL_CMyComPtr_QI_FROM( 1264370b324cSopenharmony_ci IArchiveOpenVolumeCallback, 1265370b324cSopenharmony_ci openVolumeCallback, openCallback) 1266370b324cSopenharmony_ci if (openVolumeCallback) 1267370b324cSopenharmony_ci { 1268370b324cSopenharmony_ci NCOM::CPropVariant prop; 1269370b324cSopenharmony_ci RINOK(openVolumeCallback->GetProperty(kpidName, &prop)) 1270370b324cSopenharmony_ci if (prop.vt == VT_BSTR) 1271370b324cSopenharmony_ci _nameExtenstion = GetMethod_from_FileName(prop.bstrVal); 1272370b324cSopenharmony_ci } 1273370b324cSopenharmony_ci } 1274370b324cSopenharmony_ci 1275370b324cSopenharmony_ci bool cksumMode = false; 1276370b324cSopenharmony_ci if (_nameExtenstion.IsEqualTo_Ascii_NoCase("cksum")) 1277370b324cSopenharmony_ci cksumMode = true; 1278370b324cSopenharmony_ci _is_CksumMode = cksumMode; 1279370b324cSopenharmony_ci 1280370b324cSopenharmony_ci size_t pos = 0; 1281370b324cSopenharmony_ci AString s; 1282370b324cSopenharmony_ci bool minusMode = false; 1283370b324cSopenharmony_ci unsigned numLines = 0; 1284370b324cSopenharmony_ci 1285370b324cSopenharmony_ci while (pos < buf.Size()) 1286370b324cSopenharmony_ci { 1287370b324cSopenharmony_ci if (!GetLine(buf, zeroMode, cr_lf_Mode, pos, s)) 1288370b324cSopenharmony_ci return S_FALSE; 1289370b324cSopenharmony_ci numLines++; 1290370b324cSopenharmony_ci if (s.IsEmpty()) 1291370b324cSopenharmony_ci continue; 1292370b324cSopenharmony_ci 1293370b324cSopenharmony_ci if (s.IsPrefixedBy_Ascii_NoCase("; ")) 1294370b324cSopenharmony_ci { 1295370b324cSopenharmony_ci if (numLines != 1) 1296370b324cSopenharmony_ci return S_FALSE; 1297370b324cSopenharmony_ci // comment line of FileVerifier++ 1298370b324cSopenharmony_ci continue; 1299370b324cSopenharmony_ci } 1300370b324cSopenharmony_ci 1301370b324cSopenharmony_ci if (s.IsPrefixedBy_Ascii_NoCase("-----")) 1302370b324cSopenharmony_ci { 1303370b324cSopenharmony_ci if (minusMode) 1304370b324cSopenharmony_ci break; // end of pgp mode 1305370b324cSopenharmony_ci minusMode = true; 1306370b324cSopenharmony_ci if (s.IsPrefixedBy_Ascii_NoCase("-----BEGIN PGP SIGNED MESSAGE")) 1307370b324cSopenharmony_ci { 1308370b324cSopenharmony_ci if (_is_PgpMethod) 1309370b324cSopenharmony_ci return S_FALSE; 1310370b324cSopenharmony_ci if (!GetLine(buf, zeroMode, cr_lf_Mode, pos, s)) 1311370b324cSopenharmony_ci return S_FALSE; 1312370b324cSopenharmony_ci const char *kStart = "Hash: "; 1313370b324cSopenharmony_ci if (!s.IsPrefixedBy_Ascii_NoCase(kStart)) 1314370b324cSopenharmony_ci return S_FALSE; 1315370b324cSopenharmony_ci _pgpMethod = s.Ptr((unsigned)strlen(kStart)); 1316370b324cSopenharmony_ci _is_PgpMethod = true; 1317370b324cSopenharmony_ci } 1318370b324cSopenharmony_ci continue; 1319370b324cSopenharmony_ci } 1320370b324cSopenharmony_ci 1321370b324cSopenharmony_ci CHashPair pair; 1322370b324cSopenharmony_ci pair.FullLine = s; 1323370b324cSopenharmony_ci if (cksumMode) 1324370b324cSopenharmony_ci { 1325370b324cSopenharmony_ci if (!pair.ParseCksum(s)) 1326370b324cSopenharmony_ci return S_FALSE; 1327370b324cSopenharmony_ci } 1328370b324cSopenharmony_ci else if (!pair.Parse(s)) 1329370b324cSopenharmony_ci return S_FALSE; 1330370b324cSopenharmony_ci pairs.Add(pair); 1331370b324cSopenharmony_ci } 1332370b324cSopenharmony_ci 1333370b324cSopenharmony_ci { 1334370b324cSopenharmony_ci unsigned hashSize = 0; 1335370b324cSopenharmony_ci bool hashSize_Dismatch = false; 1336370b324cSopenharmony_ci for (unsigned i = 0; i < HashPairs.Size(); i++) 1337370b324cSopenharmony_ci { 1338370b324cSopenharmony_ci const CHashPair &hp = HashPairs[i]; 1339370b324cSopenharmony_ci if (i == 0) 1340370b324cSopenharmony_ci hashSize = (unsigned)hp.Hash.Size(); 1341370b324cSopenharmony_ci else 1342370b324cSopenharmony_ci if (hashSize != hp.Hash.Size()) 1343370b324cSopenharmony_ci hashSize_Dismatch = true; 1344370b324cSopenharmony_ci 1345370b324cSopenharmony_ci if (hp.IsBSD) 1346370b324cSopenharmony_ci _are_there_Tags = true; 1347370b324cSopenharmony_ci if (!_are_there_Dirs && hp.IsDir()) 1348370b324cSopenharmony_ci _are_there_Dirs = true; 1349370b324cSopenharmony_ci } 1350370b324cSopenharmony_ci if (!hashSize_Dismatch && hashSize != 0) 1351370b324cSopenharmony_ci { 1352370b324cSopenharmony_ci _hashSize = hashSize; 1353370b324cSopenharmony_ci _hashSize_Defined = true; 1354370b324cSopenharmony_ci } 1355370b324cSopenharmony_ci } 1356370b324cSopenharmony_ci 1357370b324cSopenharmony_ci _phySize = buf.Size(); 1358370b324cSopenharmony_ci _isArc = true; 1359370b324cSopenharmony_ci return S_OK; 1360370b324cSopenharmony_ci } 1361370b324cSopenharmony_ci COM_TRY_END 1362370b324cSopenharmony_ci} 1363370b324cSopenharmony_ci 1364370b324cSopenharmony_ci 1365370b324cSopenharmony_civoid CHandler::ClearVars() 1366370b324cSopenharmony_ci{ 1367370b324cSopenharmony_ci _phySize = 0; 1368370b324cSopenharmony_ci _isArc = false; 1369370b324cSopenharmony_ci _is_CksumMode = false; 1370370b324cSopenharmony_ci _is_PgpMethod = false; 1371370b324cSopenharmony_ci _is_ZeroMode = false; 1372370b324cSopenharmony_ci _are_there_Tags = false; 1373370b324cSopenharmony_ci _are_there_Dirs = false; 1374370b324cSopenharmony_ci _hashSize_Defined = false; 1375370b324cSopenharmony_ci _hashSize = 0; 1376370b324cSopenharmony_ci} 1377370b324cSopenharmony_ci 1378370b324cSopenharmony_ci 1379370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Close()) 1380370b324cSopenharmony_ci{ 1381370b324cSopenharmony_ci ClearVars(); 1382370b324cSopenharmony_ci _nameExtenstion.Empty(); 1383370b324cSopenharmony_ci _pgpMethod.Empty(); 1384370b324cSopenharmony_ci HashPairs.Clear(); 1385370b324cSopenharmony_ci return S_OK; 1386370b324cSopenharmony_ci} 1387370b324cSopenharmony_ci 1388370b324cSopenharmony_ci 1389370b324cSopenharmony_cistatic bool CheckDigests(const Byte *a, const Byte *b, size_t size) 1390370b324cSopenharmony_ci{ 1391370b324cSopenharmony_ci if (size <= 8) 1392370b324cSopenharmony_ci { 1393370b324cSopenharmony_ci /* we use reversed order for one digest, when text representation 1394370b324cSopenharmony_ci uses big-order for crc-32 and crc-64 */ 1395370b324cSopenharmony_ci for (size_t i = 0; i < size; i++) 1396370b324cSopenharmony_ci if (a[i] != b[size - 1 - i]) 1397370b324cSopenharmony_ci return false; 1398370b324cSopenharmony_ci return true; 1399370b324cSopenharmony_ci } 1400370b324cSopenharmony_ci { 1401370b324cSopenharmony_ci for (size_t i = 0; i < size; i++) 1402370b324cSopenharmony_ci if (a[i] != b[i]) 1403370b324cSopenharmony_ci return false; 1404370b324cSopenharmony_ci return true; 1405370b324cSopenharmony_ci } 1406370b324cSopenharmony_ci} 1407370b324cSopenharmony_ci 1408370b324cSopenharmony_ci 1409370b324cSopenharmony_cistatic void AddDefaultMethod(UStringVector &methods, unsigned size) 1410370b324cSopenharmony_ci{ 1411370b324cSopenharmony_ci const char *m = NULL; 1412370b324cSopenharmony_ci if (size == 32) m = "sha256"; 1413370b324cSopenharmony_ci else if (size == 20) m = "sha1"; 1414370b324cSopenharmony_ci else if (size == 16) m = "md5"; 1415370b324cSopenharmony_ci else if (size == 8) m = "crc64"; 1416370b324cSopenharmony_ci else if (size == 4) m = "crc32"; 1417370b324cSopenharmony_ci else 1418370b324cSopenharmony_ci return; 1419370b324cSopenharmony_ci #ifdef Z7_EXTERNAL_CODECS 1420370b324cSopenharmony_ci const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr; 1421370b324cSopenharmony_ci #endif 1422370b324cSopenharmony_ci CMethodId id; 1423370b324cSopenharmony_ci if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS 1424370b324cSopenharmony_ci AString(m), id)) 1425370b324cSopenharmony_ci methods.Add(UString(m)); 1426370b324cSopenharmony_ci} 1427370b324cSopenharmony_ci 1428370b324cSopenharmony_ci 1429370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, 1430370b324cSopenharmony_ci Int32 testMode, IArchiveExtractCallback *extractCallback)) 1431370b324cSopenharmony_ci{ 1432370b324cSopenharmony_ci COM_TRY_BEGIN 1433370b324cSopenharmony_ci 1434370b324cSopenharmony_ci /* 1435370b324cSopenharmony_ci if (testMode == 0) 1436370b324cSopenharmony_ci return E_NOTIMPL; 1437370b324cSopenharmony_ci */ 1438370b324cSopenharmony_ci 1439370b324cSopenharmony_ci const bool allFilesMode = (numItems == (UInt32)(Int32)-1); 1440370b324cSopenharmony_ci if (allFilesMode) 1441370b324cSopenharmony_ci numItems = HashPairs.Size(); 1442370b324cSopenharmony_ci if (numItems == 0) 1443370b324cSopenharmony_ci return S_OK; 1444370b324cSopenharmony_ci 1445370b324cSopenharmony_ci #ifdef Z7_EXTERNAL_CODECS 1446370b324cSopenharmony_ci const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr; 1447370b324cSopenharmony_ci #endif 1448370b324cSopenharmony_ci 1449370b324cSopenharmony_ci CHashBundle hb_Glob; 1450370b324cSopenharmony_ci // UStringVector methods = options.Methods; 1451370b324cSopenharmony_ci UStringVector methods; 1452370b324cSopenharmony_ci 1453370b324cSopenharmony_ci if (methods.IsEmpty() && !_nameExtenstion.IsEmpty()) 1454370b324cSopenharmony_ci { 1455370b324cSopenharmony_ci AString utf; 1456370b324cSopenharmony_ci ConvertUnicodeToUTF8(_nameExtenstion, utf); 1457370b324cSopenharmony_ci CMethodId id; 1458370b324cSopenharmony_ci if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS utf, id)) 1459370b324cSopenharmony_ci methods.Add(_nameExtenstion); 1460370b324cSopenharmony_ci } 1461370b324cSopenharmony_ci 1462370b324cSopenharmony_ci if (methods.IsEmpty() && !_pgpMethod.IsEmpty()) 1463370b324cSopenharmony_ci { 1464370b324cSopenharmony_ci CMethodId id; 1465370b324cSopenharmony_ci if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS _pgpMethod, id)) 1466370b324cSopenharmony_ci methods.Add(UString(_pgpMethod)); 1467370b324cSopenharmony_ci } 1468370b324cSopenharmony_ci 1469370b324cSopenharmony_ci if (methods.IsEmpty() && _pgpMethod.IsEmpty() && _hashSize_Defined) 1470370b324cSopenharmony_ci AddDefaultMethod(methods, _hashSize); 1471370b324cSopenharmony_ci 1472370b324cSopenharmony_ci RINOK(hb_Glob.SetMethods( 1473370b324cSopenharmony_ci EXTERNAL_CODECS_LOC_VARS 1474370b324cSopenharmony_ci methods)) 1475370b324cSopenharmony_ci 1476370b324cSopenharmony_ci Z7_DECL_CMyComPtr_QI_FROM( 1477370b324cSopenharmony_ci IArchiveUpdateCallbackFile, 1478370b324cSopenharmony_ci updateCallbackFile, extractCallback) 1479370b324cSopenharmony_ci if (!updateCallbackFile) 1480370b324cSopenharmony_ci return E_NOTIMPL; 1481370b324cSopenharmony_ci { 1482370b324cSopenharmony_ci Z7_DECL_CMyComPtr_QI_FROM( 1483370b324cSopenharmony_ci IArchiveGetDiskProperty, 1484370b324cSopenharmony_ci GetDiskProperty, extractCallback) 1485370b324cSopenharmony_ci if (GetDiskProperty) 1486370b324cSopenharmony_ci { 1487370b324cSopenharmony_ci UInt64 totalSize = 0; 1488370b324cSopenharmony_ci UInt32 i; 1489370b324cSopenharmony_ci for (i = 0; i < numItems; i++) 1490370b324cSopenharmony_ci { 1491370b324cSopenharmony_ci const UInt32 index = allFilesMode ? i : indices[i]; 1492370b324cSopenharmony_ci const CHashPair &hp = HashPairs[index]; 1493370b324cSopenharmony_ci if (hp.IsDir()) 1494370b324cSopenharmony_ci continue; 1495370b324cSopenharmony_ci { 1496370b324cSopenharmony_ci NCOM::CPropVariant prop; 1497370b324cSopenharmony_ci RINOK(GetDiskProperty->GetDiskProperty(index, kpidSize, &prop)) 1498370b324cSopenharmony_ci if (prop.vt != VT_UI8) 1499370b324cSopenharmony_ci continue; 1500370b324cSopenharmony_ci totalSize += prop.uhVal.QuadPart; 1501370b324cSopenharmony_ci } 1502370b324cSopenharmony_ci } 1503370b324cSopenharmony_ci RINOK(extractCallback->SetTotal(totalSize)) 1504370b324cSopenharmony_ci // RINOK(Hash_SetTotalUnpacked->Hash_SetTotalUnpacked(indices, numItems)); 1505370b324cSopenharmony_ci } 1506370b324cSopenharmony_ci } 1507370b324cSopenharmony_ci 1508370b324cSopenharmony_ci const UInt32 kBufSize = 1 << 15; 1509370b324cSopenharmony_ci CHashMidBuf buf; 1510370b324cSopenharmony_ci if (!buf.Alloc(kBufSize)) 1511370b324cSopenharmony_ci return E_OUTOFMEMORY; 1512370b324cSopenharmony_ci 1513370b324cSopenharmony_ci CLocalProgress *lps = new CLocalProgress; 1514370b324cSopenharmony_ci CMyComPtr<ICompressProgressInfo> progress = lps; 1515370b324cSopenharmony_ci lps->Init(extractCallback, false); 1516370b324cSopenharmony_ci lps->InSize = lps->OutSize = 0; 1517370b324cSopenharmony_ci 1518370b324cSopenharmony_ci UInt32 i; 1519370b324cSopenharmony_ci for (i = 0; i < numItems; i++) 1520370b324cSopenharmony_ci { 1521370b324cSopenharmony_ci RINOK(lps->SetCur()) 1522370b324cSopenharmony_ci const UInt32 index = allFilesMode ? i : indices[i]; 1523370b324cSopenharmony_ci 1524370b324cSopenharmony_ci CHashPair &hp = HashPairs[index]; 1525370b324cSopenharmony_ci 1526370b324cSopenharmony_ci UString path; 1527370b324cSopenharmony_ci hp.Get_UString_Path(path); 1528370b324cSopenharmony_ci 1529370b324cSopenharmony_ci CMyComPtr<ISequentialInStream> inStream; 1530370b324cSopenharmony_ci const bool isDir = hp.IsDir(); 1531370b324cSopenharmony_ci if (!isDir) 1532370b324cSopenharmony_ci { 1533370b324cSopenharmony_ci RINOK(updateCallbackFile->GetStream2(index, &inStream, NUpdateNotifyOp::kHashRead)) 1534370b324cSopenharmony_ci if (!inStream) 1535370b324cSopenharmony_ci { 1536370b324cSopenharmony_ci continue; // we have shown error in GetStream2() 1537370b324cSopenharmony_ci } 1538370b324cSopenharmony_ci // askMode = NArchive::NExtract::NAskMode::kSkip; 1539370b324cSopenharmony_ci } 1540370b324cSopenharmony_ci 1541370b324cSopenharmony_ci Int32 askMode = testMode ? 1542370b324cSopenharmony_ci NArchive::NExtract::NAskMode::kTest : 1543370b324cSopenharmony_ci NArchive::NExtract::NAskMode::kExtract; 1544370b324cSopenharmony_ci 1545370b324cSopenharmony_ci CMyComPtr<ISequentialOutStream> realOutStream; 1546370b324cSopenharmony_ci RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) 1547370b324cSopenharmony_ci 1548370b324cSopenharmony_ci /* PrepareOperation() can expect kExtract to set 1549370b324cSopenharmony_ci Attrib and security of output file */ 1550370b324cSopenharmony_ci askMode = NArchive::NExtract::NAskMode::kReadExternal; 1551370b324cSopenharmony_ci 1552370b324cSopenharmony_ci extractCallback->PrepareOperation(askMode); 1553370b324cSopenharmony_ci 1554370b324cSopenharmony_ci const bool isAltStream = false; 1555370b324cSopenharmony_ci 1556370b324cSopenharmony_ci UInt64 fileSize = 0; 1557370b324cSopenharmony_ci 1558370b324cSopenharmony_ci CHashBundle hb_Loc; 1559370b324cSopenharmony_ci 1560370b324cSopenharmony_ci CHashBundle *hb_Use = &hb_Glob; 1561370b324cSopenharmony_ci 1562370b324cSopenharmony_ci HRESULT res_SetMethods = S_OK; 1563370b324cSopenharmony_ci 1564370b324cSopenharmony_ci UStringVector methods_loc; 1565370b324cSopenharmony_ci 1566370b324cSopenharmony_ci if (!hp.Method.IsEmpty()) 1567370b324cSopenharmony_ci { 1568370b324cSopenharmony_ci hb_Use = &hb_Loc; 1569370b324cSopenharmony_ci CMethodId id; 1570370b324cSopenharmony_ci if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS hp.Method, id)) 1571370b324cSopenharmony_ci { 1572370b324cSopenharmony_ci methods_loc.Add(UString(hp.Method)); 1573370b324cSopenharmony_ci RINOK(hb_Loc.SetMethods( 1574370b324cSopenharmony_ci EXTERNAL_CODECS_LOC_VARS 1575370b324cSopenharmony_ci methods_loc)) 1576370b324cSopenharmony_ci } 1577370b324cSopenharmony_ci else 1578370b324cSopenharmony_ci res_SetMethods = E_NOTIMPL; 1579370b324cSopenharmony_ci } 1580370b324cSopenharmony_ci else if (methods.IsEmpty()) 1581370b324cSopenharmony_ci { 1582370b324cSopenharmony_ci AddDefaultMethod(methods_loc, (unsigned)hp.Hash.Size()); 1583370b324cSopenharmony_ci if (!methods_loc.IsEmpty()) 1584370b324cSopenharmony_ci { 1585370b324cSopenharmony_ci hb_Use = &hb_Loc; 1586370b324cSopenharmony_ci RINOK(hb_Loc.SetMethods( 1587370b324cSopenharmony_ci EXTERNAL_CODECS_LOC_VARS 1588370b324cSopenharmony_ci methods_loc)) 1589370b324cSopenharmony_ci } 1590370b324cSopenharmony_ci } 1591370b324cSopenharmony_ci 1592370b324cSopenharmony_ci const bool isSupportedMode = hp.IsSupportedMode(); 1593370b324cSopenharmony_ci hb_Use->InitForNewFile(); 1594370b324cSopenharmony_ci 1595370b324cSopenharmony_ci if (inStream) 1596370b324cSopenharmony_ci { 1597370b324cSopenharmony_ci for (UInt32 step = 0;; step++) 1598370b324cSopenharmony_ci { 1599370b324cSopenharmony_ci if ((step & 0xFF) == 0) 1600370b324cSopenharmony_ci { 1601370b324cSopenharmony_ci RINOK(progress->SetRatioInfo(NULL, &fileSize)) 1602370b324cSopenharmony_ci } 1603370b324cSopenharmony_ci UInt32 size; 1604370b324cSopenharmony_ci RINOK(inStream->Read(buf, kBufSize, &size)) 1605370b324cSopenharmony_ci if (size == 0) 1606370b324cSopenharmony_ci break; 1607370b324cSopenharmony_ci hb_Use->Update(buf, size); 1608370b324cSopenharmony_ci if (realOutStream) 1609370b324cSopenharmony_ci { 1610370b324cSopenharmony_ci RINOK(WriteStream(realOutStream, buf, size)) 1611370b324cSopenharmony_ci } 1612370b324cSopenharmony_ci fileSize += size; 1613370b324cSopenharmony_ci } 1614370b324cSopenharmony_ci 1615370b324cSopenharmony_ci hp.Size_from_Disk = fileSize; 1616370b324cSopenharmony_ci hp.Size_from_Disk_Defined = true; 1617370b324cSopenharmony_ci } 1618370b324cSopenharmony_ci 1619370b324cSopenharmony_ci realOutStream.Release(); 1620370b324cSopenharmony_ci inStream.Release(); 1621370b324cSopenharmony_ci 1622370b324cSopenharmony_ci lps->InSize += hp.Hash.Size(); 1623370b324cSopenharmony_ci lps->OutSize += fileSize; 1624370b324cSopenharmony_ci 1625370b324cSopenharmony_ci hb_Use->Final(isDir, isAltStream, path); 1626370b324cSopenharmony_ci 1627370b324cSopenharmony_ci Int32 opRes = NArchive::NExtract::NOperationResult::kUnsupportedMethod; 1628370b324cSopenharmony_ci if (isSupportedMode 1629370b324cSopenharmony_ci && res_SetMethods != E_NOTIMPL 1630370b324cSopenharmony_ci && hb_Use->Hashers.Size() > 0 1631370b324cSopenharmony_ci ) 1632370b324cSopenharmony_ci { 1633370b324cSopenharmony_ci const CHasherState &hs = hb_Use->Hashers[0]; 1634370b324cSopenharmony_ci if (hs.DigestSize == hp.Hash.Size()) 1635370b324cSopenharmony_ci { 1636370b324cSopenharmony_ci opRes = NArchive::NExtract::NOperationResult::kCRCError; 1637370b324cSopenharmony_ci if (CheckDigests(hp.Hash, hs.Digests[0], hs.DigestSize)) 1638370b324cSopenharmony_ci if (!hp.Size_from_Arc_Defined || hp.Size_from_Arc == fileSize) 1639370b324cSopenharmony_ci opRes = NArchive::NExtract::NOperationResult::kOK; 1640370b324cSopenharmony_ci } 1641370b324cSopenharmony_ci } 1642370b324cSopenharmony_ci 1643370b324cSopenharmony_ci RINOK(extractCallback->SetOperationResult(opRes)) 1644370b324cSopenharmony_ci } 1645370b324cSopenharmony_ci 1646370b324cSopenharmony_ci return lps->SetCur(); 1647370b324cSopenharmony_ci 1648370b324cSopenharmony_ci COM_TRY_END 1649370b324cSopenharmony_ci} 1650370b324cSopenharmony_ci 1651370b324cSopenharmony_ci 1652370b324cSopenharmony_ci// ---------- UPDATE ---------- 1653370b324cSopenharmony_ci 1654370b324cSopenharmony_cistruct CUpdateItem 1655370b324cSopenharmony_ci{ 1656370b324cSopenharmony_ci int IndexInArc; 1657370b324cSopenharmony_ci unsigned IndexInClient; 1658370b324cSopenharmony_ci UInt64 Size; 1659370b324cSopenharmony_ci bool NewData; 1660370b324cSopenharmony_ci bool NewProps; 1661370b324cSopenharmony_ci bool IsDir; 1662370b324cSopenharmony_ci UString Path; 1663370b324cSopenharmony_ci 1664370b324cSopenharmony_ci CUpdateItem(): Size(0), IsDir(false) {} 1665370b324cSopenharmony_ci}; 1666370b324cSopenharmony_ci 1667370b324cSopenharmony_ci 1668370b324cSopenharmony_cistatic HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, 1669370b324cSopenharmony_ci UString &res, 1670370b324cSopenharmony_ci bool convertSlash) 1671370b324cSopenharmony_ci{ 1672370b324cSopenharmony_ci NCOM::CPropVariant prop; 1673370b324cSopenharmony_ci RINOK(callback->GetProperty(index, propId, &prop)) 1674370b324cSopenharmony_ci if (prop.vt == VT_BSTR) 1675370b324cSopenharmony_ci { 1676370b324cSopenharmony_ci res = prop.bstrVal; 1677370b324cSopenharmony_ci if (convertSlash) 1678370b324cSopenharmony_ci NArchive::NItemName::ReplaceSlashes_OsToUnix(res); 1679370b324cSopenharmony_ci } 1680370b324cSopenharmony_ci else if (prop.vt != VT_EMPTY) 1681370b324cSopenharmony_ci return E_INVALIDARG; 1682370b324cSopenharmony_ci return S_OK; 1683370b324cSopenharmony_ci} 1684370b324cSopenharmony_ci 1685370b324cSopenharmony_ci 1686370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type)) 1687370b324cSopenharmony_ci{ 1688370b324cSopenharmony_ci *type = NFileTimeType::kUnix; 1689370b324cSopenharmony_ci return S_OK; 1690370b324cSopenharmony_ci} 1691370b324cSopenharmony_ci 1692370b324cSopenharmony_ci 1693370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, 1694370b324cSopenharmony_ci IArchiveUpdateCallback *callback)) 1695370b324cSopenharmony_ci{ 1696370b324cSopenharmony_ci COM_TRY_BEGIN 1697370b324cSopenharmony_ci 1698370b324cSopenharmony_ci if (_isArc && !CanUpdate()) 1699370b324cSopenharmony_ci return E_NOTIMPL; 1700370b324cSopenharmony_ci 1701370b324cSopenharmony_ci /* 1702370b324cSopenharmony_ci Z7_DECL_CMyComPtr_QI_FROM(IArchiveUpdateCallbackArcProp, 1703370b324cSopenharmony_ci reportArcProp, callback) 1704370b324cSopenharmony_ci */ 1705370b324cSopenharmony_ci 1706370b324cSopenharmony_ci CObjectVector<CUpdateItem> updateItems; 1707370b324cSopenharmony_ci 1708370b324cSopenharmony_ci UInt64 complexity = 0; 1709370b324cSopenharmony_ci 1710370b324cSopenharmony_ci UInt32 i; 1711370b324cSopenharmony_ci for (i = 0; i < numItems; i++) 1712370b324cSopenharmony_ci { 1713370b324cSopenharmony_ci CUpdateItem ui; 1714370b324cSopenharmony_ci Int32 newData; 1715370b324cSopenharmony_ci Int32 newProps; 1716370b324cSopenharmony_ci UInt32 indexInArc; 1717370b324cSopenharmony_ci 1718370b324cSopenharmony_ci if (!callback) 1719370b324cSopenharmony_ci return E_FAIL; 1720370b324cSopenharmony_ci 1721370b324cSopenharmony_ci RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc)) 1722370b324cSopenharmony_ci 1723370b324cSopenharmony_ci ui.NewProps = IntToBool(newProps); 1724370b324cSopenharmony_ci ui.NewData = IntToBool(newData); 1725370b324cSopenharmony_ci ui.IndexInArc = (int)indexInArc; 1726370b324cSopenharmony_ci ui.IndexInClient = i; 1727370b324cSopenharmony_ci if (IntToBool(newProps)) 1728370b324cSopenharmony_ci { 1729370b324cSopenharmony_ci { 1730370b324cSopenharmony_ci NCOM::CPropVariant prop; 1731370b324cSopenharmony_ci RINOK(callback->GetProperty(i, kpidIsDir, &prop)) 1732370b324cSopenharmony_ci if (prop.vt == VT_EMPTY) 1733370b324cSopenharmony_ci ui.IsDir = false; 1734370b324cSopenharmony_ci else if (prop.vt != VT_BOOL) 1735370b324cSopenharmony_ci return E_INVALIDARG; 1736370b324cSopenharmony_ci else 1737370b324cSopenharmony_ci ui.IsDir = (prop.boolVal != VARIANT_FALSE); 1738370b324cSopenharmony_ci } 1739370b324cSopenharmony_ci 1740370b324cSopenharmony_ci RINOK(GetPropString(callback, i, kpidPath, ui.Path, 1741370b324cSopenharmony_ci true)) // convertSlash 1742370b324cSopenharmony_ci /* 1743370b324cSopenharmony_ci if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/') 1744370b324cSopenharmony_ci ui.Name += '/'; 1745370b324cSopenharmony_ci */ 1746370b324cSopenharmony_ci } 1747370b324cSopenharmony_ci 1748370b324cSopenharmony_ci if (IntToBool(newData)) 1749370b324cSopenharmony_ci { 1750370b324cSopenharmony_ci NCOM::CPropVariant prop; 1751370b324cSopenharmony_ci RINOK(callback->GetProperty(i, kpidSize, &prop)) 1752370b324cSopenharmony_ci if (prop.vt == VT_UI8) 1753370b324cSopenharmony_ci { 1754370b324cSopenharmony_ci ui.Size = prop.uhVal.QuadPart; 1755370b324cSopenharmony_ci complexity += ui.Size; 1756370b324cSopenharmony_ci } 1757370b324cSopenharmony_ci else if (prop.vt == VT_EMPTY) 1758370b324cSopenharmony_ci ui.Size = (UInt64)(Int64)-1; 1759370b324cSopenharmony_ci else 1760370b324cSopenharmony_ci return E_INVALIDARG; 1761370b324cSopenharmony_ci } 1762370b324cSopenharmony_ci 1763370b324cSopenharmony_ci updateItems.Add(ui); 1764370b324cSopenharmony_ci } 1765370b324cSopenharmony_ci 1766370b324cSopenharmony_ci if (complexity != 0) 1767370b324cSopenharmony_ci { 1768370b324cSopenharmony_ci RINOK(callback->SetTotal(complexity)) 1769370b324cSopenharmony_ci } 1770370b324cSopenharmony_ci 1771370b324cSopenharmony_ci #ifdef Z7_EXTERNAL_CODECS 1772370b324cSopenharmony_ci const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr; 1773370b324cSopenharmony_ci #endif 1774370b324cSopenharmony_ci 1775370b324cSopenharmony_ci CHashBundle hb; 1776370b324cSopenharmony_ci UStringVector methods; 1777370b324cSopenharmony_ci if (!_methods.IsEmpty()) 1778370b324cSopenharmony_ci { 1779370b324cSopenharmony_ci FOR_VECTOR(k, _methods) 1780370b324cSopenharmony_ci { 1781370b324cSopenharmony_ci methods.Add(_methods[k]); 1782370b324cSopenharmony_ci } 1783370b324cSopenharmony_ci } 1784370b324cSopenharmony_ci else if (_crcSize_WasSet) 1785370b324cSopenharmony_ci { 1786370b324cSopenharmony_ci AddDefaultMethod(methods, _crcSize); 1787370b324cSopenharmony_ci } 1788370b324cSopenharmony_ci else 1789370b324cSopenharmony_ci { 1790370b324cSopenharmony_ci Z7_DECL_CMyComPtr_QI_FROM( 1791370b324cSopenharmony_ci IArchiveGetRootProps, 1792370b324cSopenharmony_ci getRootProps, callback) 1793370b324cSopenharmony_ci if (getRootProps) 1794370b324cSopenharmony_ci { 1795370b324cSopenharmony_ci NCOM::CPropVariant prop; 1796370b324cSopenharmony_ci RINOK(getRootProps->GetRootProp(kpidArcFileName, &prop)) 1797370b324cSopenharmony_ci if (prop.vt == VT_BSTR) 1798370b324cSopenharmony_ci { 1799370b324cSopenharmony_ci const UString method = GetMethod_from_FileName(prop.bstrVal); 1800370b324cSopenharmony_ci if (!method.IsEmpty()) 1801370b324cSopenharmony_ci methods.Add(method); 1802370b324cSopenharmony_ci } 1803370b324cSopenharmony_ci } 1804370b324cSopenharmony_ci } 1805370b324cSopenharmony_ci 1806370b324cSopenharmony_ci RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS methods)) 1807370b324cSopenharmony_ci 1808370b324cSopenharmony_ci CLocalProgress *lps = new CLocalProgress; 1809370b324cSopenharmony_ci CMyComPtr<ICompressProgressInfo> progress = lps; 1810370b324cSopenharmony_ci lps->Init(callback, true); 1811370b324cSopenharmony_ci 1812370b324cSopenharmony_ci const UInt32 kBufSize = 1 << 15; 1813370b324cSopenharmony_ci CHashMidBuf buf; 1814370b324cSopenharmony_ci if (!buf.Alloc(kBufSize)) 1815370b324cSopenharmony_ci return E_OUTOFMEMORY; 1816370b324cSopenharmony_ci 1817370b324cSopenharmony_ci CDynLimBuf hashFileString((size_t)1 << 31); 1818370b324cSopenharmony_ci 1819370b324cSopenharmony_ci CHashOptionsLocal options = _options; 1820370b324cSopenharmony_ci 1821370b324cSopenharmony_ci if (_isArc) 1822370b324cSopenharmony_ci { 1823370b324cSopenharmony_ci if (!options.HashMode_Zero.Def && _is_ZeroMode) 1824370b324cSopenharmony_ci options.HashMode_Zero.Val = true; 1825370b324cSopenharmony_ci if (!options.HashMode_Tag.Def && _are_there_Tags) 1826370b324cSopenharmony_ci options.HashMode_Tag.Val = true; 1827370b324cSopenharmony_ci if (!options.HashMode_Dirs.Def && _are_there_Dirs) 1828370b324cSopenharmony_ci options.HashMode_Dirs.Val = true; 1829370b324cSopenharmony_ci } 1830370b324cSopenharmony_ci if (options.HashMode_OnlyHash.Val && updateItems.Size() != 1) 1831370b324cSopenharmony_ci options.HashMode_OnlyHash.Val = false; 1832370b324cSopenharmony_ci 1833370b324cSopenharmony_ci lps->OutSize = 0; 1834370b324cSopenharmony_ci complexity = 0; 1835370b324cSopenharmony_ci 1836370b324cSopenharmony_ci for (i = 0; i < updateItems.Size(); i++) 1837370b324cSopenharmony_ci { 1838370b324cSopenharmony_ci lps->InSize = complexity; 1839370b324cSopenharmony_ci RINOK(lps->SetCur()) 1840370b324cSopenharmony_ci 1841370b324cSopenharmony_ci const CUpdateItem &ui = updateItems[i]; 1842370b324cSopenharmony_ci 1843370b324cSopenharmony_ci /* 1844370b324cSopenharmony_ci CHashPair item; 1845370b324cSopenharmony_ci if (!ui.NewProps) 1846370b324cSopenharmony_ci item = HashPairs[(unsigned)ui.IndexInArc]; 1847370b324cSopenharmony_ci */ 1848370b324cSopenharmony_ci 1849370b324cSopenharmony_ci if (ui.NewData) 1850370b324cSopenharmony_ci { 1851370b324cSopenharmony_ci UInt64 currentComplexity = ui.Size; 1852370b324cSopenharmony_ci UInt64 fileSize = 0; 1853370b324cSopenharmony_ci 1854370b324cSopenharmony_ci CMyComPtr<ISequentialInStream> fileInStream; 1855370b324cSopenharmony_ci bool needWrite = true; 1856370b324cSopenharmony_ci { 1857370b324cSopenharmony_ci HRESULT res = callback->GetStream(ui.IndexInClient, &fileInStream); 1858370b324cSopenharmony_ci 1859370b324cSopenharmony_ci if (res == S_FALSE) 1860370b324cSopenharmony_ci needWrite = false; 1861370b324cSopenharmony_ci else 1862370b324cSopenharmony_ci { 1863370b324cSopenharmony_ci RINOK(res) 1864370b324cSopenharmony_ci 1865370b324cSopenharmony_ci if (fileInStream) 1866370b324cSopenharmony_ci { 1867370b324cSopenharmony_ci Z7_DECL_CMyComPtr_QI_FROM( 1868370b324cSopenharmony_ci IStreamGetSize, 1869370b324cSopenharmony_ci streamGetSize, fileInStream) 1870370b324cSopenharmony_ci if (streamGetSize) 1871370b324cSopenharmony_ci { 1872370b324cSopenharmony_ci UInt64 size; 1873370b324cSopenharmony_ci if (streamGetSize->GetSize(&size) == S_OK) 1874370b324cSopenharmony_ci currentComplexity = size; 1875370b324cSopenharmony_ci } 1876370b324cSopenharmony_ci /* 1877370b324cSopenharmony_ci Z7_DECL_CMyComPtr_QI_FROM( 1878370b324cSopenharmony_ci IStreamGetProps, 1879370b324cSopenharmony_ci getProps, fileInStream) 1880370b324cSopenharmony_ci if (getProps) 1881370b324cSopenharmony_ci { 1882370b324cSopenharmony_ci FILETIME mTime; 1883370b324cSopenharmony_ci UInt64 size2; 1884370b324cSopenharmony_ci if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK) 1885370b324cSopenharmony_ci { 1886370b324cSopenharmony_ci currentComplexity = size2; 1887370b324cSopenharmony_ci // item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);; 1888370b324cSopenharmony_ci } 1889370b324cSopenharmony_ci } 1890370b324cSopenharmony_ci */ 1891370b324cSopenharmony_ci } 1892370b324cSopenharmony_ci else 1893370b324cSopenharmony_ci { 1894370b324cSopenharmony_ci currentComplexity = 0; 1895370b324cSopenharmony_ci } 1896370b324cSopenharmony_ci } 1897370b324cSopenharmony_ci } 1898370b324cSopenharmony_ci 1899370b324cSopenharmony_ci hb.InitForNewFile(); 1900370b324cSopenharmony_ci const bool isDir = ui.IsDir; 1901370b324cSopenharmony_ci 1902370b324cSopenharmony_ci if (needWrite && fileInStream && !isDir) 1903370b324cSopenharmony_ci { 1904370b324cSopenharmony_ci for (UInt32 step = 0;; step++) 1905370b324cSopenharmony_ci { 1906370b324cSopenharmony_ci if ((step & 0xFF) == 0) 1907370b324cSopenharmony_ci { 1908370b324cSopenharmony_ci RINOK(progress->SetRatioInfo(&fileSize, NULL)) 1909370b324cSopenharmony_ci // RINOK(callback->SetCompleted(&completeValue)); 1910370b324cSopenharmony_ci } 1911370b324cSopenharmony_ci UInt32 size; 1912370b324cSopenharmony_ci RINOK(fileInStream->Read(buf, kBufSize, &size)) 1913370b324cSopenharmony_ci if (size == 0) 1914370b324cSopenharmony_ci break; 1915370b324cSopenharmony_ci hb.Update(buf, size); 1916370b324cSopenharmony_ci fileSize += size; 1917370b324cSopenharmony_ci } 1918370b324cSopenharmony_ci currentComplexity = fileSize; 1919370b324cSopenharmony_ci } 1920370b324cSopenharmony_ci 1921370b324cSopenharmony_ci fileInStream.Release(); 1922370b324cSopenharmony_ci const bool isAltStream = false; 1923370b324cSopenharmony_ci hb.Final(isDir, isAltStream, ui.Path); 1924370b324cSopenharmony_ci 1925370b324cSopenharmony_ci if (options.HashMode_Dirs.Val || !isDir) 1926370b324cSopenharmony_ci { 1927370b324cSopenharmony_ci if (!hb.Hashers.IsEmpty()) 1928370b324cSopenharmony_ci lps->OutSize += hb.Hashers[0].DigestSize; 1929370b324cSopenharmony_ci WriteLine(hashFileString, 1930370b324cSopenharmony_ci options, 1931370b324cSopenharmony_ci ui.Path, 1932370b324cSopenharmony_ci isDir, 1933370b324cSopenharmony_ci hb); 1934370b324cSopenharmony_ci if (hashFileString.IsError()) 1935370b324cSopenharmony_ci return E_OUTOFMEMORY; 1936370b324cSopenharmony_ci } 1937370b324cSopenharmony_ci 1938370b324cSopenharmony_ci complexity += currentComplexity; 1939370b324cSopenharmony_ci 1940370b324cSopenharmony_ci /* 1941370b324cSopenharmony_ci if (reportArcProp) 1942370b324cSopenharmony_ci { 1943370b324cSopenharmony_ci PROPVARIANT prop; 1944370b324cSopenharmony_ci prop.vt = VT_EMPTY; 1945370b324cSopenharmony_ci prop.wReserved1 = 0; 1946370b324cSopenharmony_ci 1947370b324cSopenharmony_ci NCOM::PropVarEm_Set_UInt64(&prop, fileSize); 1948370b324cSopenharmony_ci RINOK(reportArcProp->ReportProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, kpidSize, &prop)); 1949370b324cSopenharmony_ci 1950370b324cSopenharmony_ci for (unsigned k = 0; k < hb.Hashers.Size(); k++) 1951370b324cSopenharmony_ci { 1952370b324cSopenharmony_ci const CHasherState &hs = hb.Hashers[k]; 1953370b324cSopenharmony_ci 1954370b324cSopenharmony_ci if (hs.DigestSize == 4 && hs.Name.IsEqualTo_Ascii_NoCase("crc32")) 1955370b324cSopenharmony_ci { 1956370b324cSopenharmony_ci NCOM::PropVarEm_Set_UInt32(&prop, GetUi32(hs.Digests[k_HashCalc_Index_Current])); 1957370b324cSopenharmony_ci RINOK(reportArcProp->ReportProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, kpidCRC, &prop)); 1958370b324cSopenharmony_ci } 1959370b324cSopenharmony_ci else 1960370b324cSopenharmony_ci { 1961370b324cSopenharmony_ci RINOK(reportArcProp->ReportRawProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, 1962370b324cSopenharmony_ci kpidChecksum, hs.Digests[k_HashCalc_Index_Current], 1963370b324cSopenharmony_ci hs.DigestSize, NPropDataType::kRaw)); 1964370b324cSopenharmony_ci } 1965370b324cSopenharmony_ci RINOK(reportArcProp->ReportFinished(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, NArchive::NUpdate::NOperationResult::kOK)); 1966370b324cSopenharmony_ci } 1967370b324cSopenharmony_ci } 1968370b324cSopenharmony_ci */ 1969370b324cSopenharmony_ci RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)) 1970370b324cSopenharmony_ci } 1971370b324cSopenharmony_ci else 1972370b324cSopenharmony_ci { 1973370b324cSopenharmony_ci // old data 1974370b324cSopenharmony_ci const CHashPair &existItem = HashPairs[(unsigned)ui.IndexInArc]; 1975370b324cSopenharmony_ci if (ui.NewProps) 1976370b324cSopenharmony_ci { 1977370b324cSopenharmony_ci WriteLine(hashFileString, 1978370b324cSopenharmony_ci options, 1979370b324cSopenharmony_ci ui.Path, 1980370b324cSopenharmony_ci ui.IsDir, 1981370b324cSopenharmony_ci existItem.Method, existItem.HashString 1982370b324cSopenharmony_ci ); 1983370b324cSopenharmony_ci } 1984370b324cSopenharmony_ci else 1985370b324cSopenharmony_ci { 1986370b324cSopenharmony_ci hashFileString += existItem.FullLine; 1987370b324cSopenharmony_ci Add_LF(hashFileString, options); 1988370b324cSopenharmony_ci } 1989370b324cSopenharmony_ci } 1990370b324cSopenharmony_ci if (hashFileString.IsError()) 1991370b324cSopenharmony_ci return E_OUTOFMEMORY; 1992370b324cSopenharmony_ci } 1993370b324cSopenharmony_ci 1994370b324cSopenharmony_ci RINOK(WriteStream(outStream, hashFileString, hashFileString.Len())) 1995370b324cSopenharmony_ci 1996370b324cSopenharmony_ci return S_OK; 1997370b324cSopenharmony_ci COM_TRY_END 1998370b324cSopenharmony_ci} 1999370b324cSopenharmony_ci 2000370b324cSopenharmony_ci 2001370b324cSopenharmony_ci 2002370b324cSopenharmony_ciHRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) 2003370b324cSopenharmony_ci{ 2004370b324cSopenharmony_ci UString name = nameSpec; 2005370b324cSopenharmony_ci name.MakeLower_Ascii(); 2006370b324cSopenharmony_ci if (name.IsEmpty()) 2007370b324cSopenharmony_ci return E_INVALIDARG; 2008370b324cSopenharmony_ci 2009370b324cSopenharmony_ci if (name.IsEqualTo("m")) // "hm" hash method 2010370b324cSopenharmony_ci { 2011370b324cSopenharmony_ci // COneMethodInfo omi; 2012370b324cSopenharmony_ci // RINOK(omi.ParseMethodFromPROPVARIANT(L"", value)); 2013370b324cSopenharmony_ci // _methods.Add(omi.MethodName); // change it. use omi.PropsString 2014370b324cSopenharmony_ci if (value.vt != VT_BSTR) 2015370b324cSopenharmony_ci return E_INVALIDARG; 2016370b324cSopenharmony_ci UString s (value.bstrVal); 2017370b324cSopenharmony_ci _methods.Add(s); 2018370b324cSopenharmony_ci return S_OK; 2019370b324cSopenharmony_ci } 2020370b324cSopenharmony_ci 2021370b324cSopenharmony_ci if (name.IsEqualTo("flags")) 2022370b324cSopenharmony_ci { 2023370b324cSopenharmony_ci if (value.vt != VT_BSTR) 2024370b324cSopenharmony_ci return E_INVALIDARG; 2025370b324cSopenharmony_ci if (!_options.ParseString(value.bstrVal)) 2026370b324cSopenharmony_ci return E_INVALIDARG; 2027370b324cSopenharmony_ci return S_OK; 2028370b324cSopenharmony_ci } 2029370b324cSopenharmony_ci 2030370b324cSopenharmony_ci if (name.IsPrefixedBy_Ascii_NoCase("crc")) 2031370b324cSopenharmony_ci { 2032370b324cSopenharmony_ci name.Delete(0, 3); 2033370b324cSopenharmony_ci _crcSize = 4; 2034370b324cSopenharmony_ci _crcSize_WasSet = true; 2035370b324cSopenharmony_ci return ParsePropToUInt32(name, value, _crcSize); 2036370b324cSopenharmony_ci } 2037370b324cSopenharmony_ci 2038370b324cSopenharmony_ci // common properties 2039370b324cSopenharmony_ci if (name.IsPrefixedBy_Ascii_NoCase("mt") 2040370b324cSopenharmony_ci || name.IsPrefixedBy_Ascii_NoCase("memuse")) 2041370b324cSopenharmony_ci return S_OK; 2042370b324cSopenharmony_ci 2043370b324cSopenharmony_ci return E_INVALIDARG; 2044370b324cSopenharmony_ci} 2045370b324cSopenharmony_ci 2046370b324cSopenharmony_ci 2047370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) 2048370b324cSopenharmony_ci{ 2049370b324cSopenharmony_ci COM_TRY_BEGIN 2050370b324cSopenharmony_ci 2051370b324cSopenharmony_ci InitProps(); 2052370b324cSopenharmony_ci 2053370b324cSopenharmony_ci for (UInt32 i = 0; i < numProps; i++) 2054370b324cSopenharmony_ci { 2055370b324cSopenharmony_ci RINOK(SetProperty(names[i], values[i])) 2056370b324cSopenharmony_ci } 2057370b324cSopenharmony_ci return S_OK; 2058370b324cSopenharmony_ci COM_TRY_END 2059370b324cSopenharmony_ci} 2060370b324cSopenharmony_ci 2061370b324cSopenharmony_ciCHandler::CHandler() 2062370b324cSopenharmony_ci{ 2063370b324cSopenharmony_ci ClearVars(); 2064370b324cSopenharmony_ci InitProps(); 2065370b324cSopenharmony_ci} 2066370b324cSopenharmony_ci 2067370b324cSopenharmony_ci} 2068370b324cSopenharmony_ci 2069370b324cSopenharmony_ci 2070370b324cSopenharmony_ci 2071370b324cSopenharmony_cistatic IInArchive *CreateHashHandler_In() { return new NHash::CHandler; } 2072370b324cSopenharmony_cistatic IOutArchive *CreateHashHandler_Out() { return new NHash::CHandler; } 2073370b324cSopenharmony_ci 2074370b324cSopenharmony_civoid Codecs_AddHashArcHandler(CCodecs *codecs) 2075370b324cSopenharmony_ci{ 2076370b324cSopenharmony_ci { 2077370b324cSopenharmony_ci CArcInfoEx item; 2078370b324cSopenharmony_ci 2079370b324cSopenharmony_ci item.Name = "Hash"; 2080370b324cSopenharmony_ci item.CreateInArchive = CreateHashHandler_In; 2081370b324cSopenharmony_ci item.CreateOutArchive = CreateHashHandler_Out; 2082370b324cSopenharmony_ci item.IsArcFunc = NULL; 2083370b324cSopenharmony_ci item.Flags = 2084370b324cSopenharmony_ci NArcInfoFlags::kKeepName 2085370b324cSopenharmony_ci | NArcInfoFlags::kStartOpen 2086370b324cSopenharmony_ci | NArcInfoFlags::kByExtOnlyOpen 2087370b324cSopenharmony_ci // | NArcInfoFlags::kPureStartOpen 2088370b324cSopenharmony_ci | NArcInfoFlags::kHashHandler 2089370b324cSopenharmony_ci ; 2090370b324cSopenharmony_ci 2091370b324cSopenharmony_ci // ubuntu uses "SHA256SUMS" file 2092370b324cSopenharmony_ci item.AddExts(UString ( 2093370b324cSopenharmony_ci "sha256 sha512 sha224 sha384 sha1 sha md5" 2094370b324cSopenharmony_ci // "b2sum" 2095370b324cSopenharmony_ci " crc32 crc64" 2096370b324cSopenharmony_ci " asc" 2097370b324cSopenharmony_ci " cksum" 2098370b324cSopenharmony_ci ), 2099370b324cSopenharmony_ci UString()); 2100370b324cSopenharmony_ci 2101370b324cSopenharmony_ci item.UpdateEnabled = (item.CreateOutArchive != NULL); 2102370b324cSopenharmony_ci item.SignatureOffset = 0; 2103370b324cSopenharmony_ci // item.Version = MY_VER_MIX; 2104370b324cSopenharmony_ci item.NewInterface = true; 2105370b324cSopenharmony_ci 2106370b324cSopenharmony_ci item.Signatures.AddNew().CopyFrom(NULL, 0); 2107370b324cSopenharmony_ci 2108370b324cSopenharmony_ci codecs->Formats.Add(item); 2109370b324cSopenharmony_ci } 2110370b324cSopenharmony_ci} 2111