1370b324cSopenharmony_ci// 7zHandlerOut.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#include "../../../Common/ComTry.h" 6370b324cSopenharmony_ci#include "../../../Common/StringToInt.h" 7370b324cSopenharmony_ci#include "../../../Common/Wildcard.h" 8370b324cSopenharmony_ci 9370b324cSopenharmony_ci#include "../Common/ItemNameUtils.h" 10370b324cSopenharmony_ci#include "../Common/ParseProperties.h" 11370b324cSopenharmony_ci 12370b324cSopenharmony_ci#include "7zHandler.h" 13370b324cSopenharmony_ci#include "7zOut.h" 14370b324cSopenharmony_ci#include "7zUpdate.h" 15370b324cSopenharmony_ci 16370b324cSopenharmony_ci#ifndef Z7_EXTRACT_ONLY 17370b324cSopenharmony_ci 18370b324cSopenharmony_ciusing namespace NWindows; 19370b324cSopenharmony_ci 20370b324cSopenharmony_cinamespace NArchive { 21370b324cSopenharmony_cinamespace N7z { 22370b324cSopenharmony_ci 23370b324cSopenharmony_ci#define k_LZMA_Name "LZMA" 24370b324cSopenharmony_ci#define kDefaultMethodName "LZMA2" 25370b324cSopenharmony_ci#define k_Copy_Name "Copy" 26370b324cSopenharmony_ci 27370b324cSopenharmony_ci#define k_MatchFinder_ForHeaders "BT2" 28370b324cSopenharmony_ci 29370b324cSopenharmony_cistatic const UInt32 k_NumFastBytes_ForHeaders = 273; 30370b324cSopenharmony_cistatic const UInt32 k_Level_ForHeaders = 5; 31370b324cSopenharmony_cistatic const UInt32 k_Dictionary_ForHeaders = 32370b324cSopenharmony_ci #ifdef UNDER_CE 33370b324cSopenharmony_ci 1 << 18; 34370b324cSopenharmony_ci #else 35370b324cSopenharmony_ci 1 << 20; 36370b324cSopenharmony_ci #endif 37370b324cSopenharmony_ci 38370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type)) 39370b324cSopenharmony_ci{ 40370b324cSopenharmony_ci *type = NFileTimeType::kWindows; 41370b324cSopenharmony_ci return S_OK; 42370b324cSopenharmony_ci} 43370b324cSopenharmony_ci 44370b324cSopenharmony_ciHRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m) 45370b324cSopenharmony_ci{ 46370b324cSopenharmony_ci bool isFilter; 47370b324cSopenharmony_ci dest.CodecIndex = FindMethod_Index( 48370b324cSopenharmony_ci EXTERNAL_CODECS_VARS 49370b324cSopenharmony_ci m.MethodName, true, 50370b324cSopenharmony_ci dest.Id, dest.NumStreams, isFilter); 51370b324cSopenharmony_ci if (dest.CodecIndex < 0) 52370b324cSopenharmony_ci return E_INVALIDARG; 53370b324cSopenharmony_ci (CProps &)dest = (CProps &)m; 54370b324cSopenharmony_ci return S_OK; 55370b324cSopenharmony_ci} 56370b324cSopenharmony_ci 57370b324cSopenharmony_ciHRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod) 58370b324cSopenharmony_ci{ 59370b324cSopenharmony_ci if (!_compressHeaders) 60370b324cSopenharmony_ci return S_OK; 61370b324cSopenharmony_ci COneMethodInfo m; 62370b324cSopenharmony_ci m.MethodName = k_LZMA_Name; 63370b324cSopenharmony_ci m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders); 64370b324cSopenharmony_ci m.AddProp_Level(k_Level_ForHeaders); 65370b324cSopenharmony_ci m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders); 66370b324cSopenharmony_ci m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders); 67370b324cSopenharmony_ci m.AddProp_NumThreads(1); 68370b324cSopenharmony_ci 69370b324cSopenharmony_ci CMethodFull &methodFull = headerMethod.Methods.AddNew(); 70370b324cSopenharmony_ci return PropsMethod_To_FullMethod(methodFull, m); 71370b324cSopenharmony_ci} 72370b324cSopenharmony_ci 73370b324cSopenharmony_ci 74370b324cSopenharmony_ciHRESULT CHandler::SetMainMethod(CCompressionMethodMode &methodMode) 75370b324cSopenharmony_ci{ 76370b324cSopenharmony_ci methodMode.Bonds = _bonds; 77370b324cSopenharmony_ci 78370b324cSopenharmony_ci // we create local copy of _methods. So we can modify it. 79370b324cSopenharmony_ci CObjectVector<COneMethodInfo> methods = _methods; 80370b324cSopenharmony_ci 81370b324cSopenharmony_ci { 82370b324cSopenharmony_ci FOR_VECTOR (i, methods) 83370b324cSopenharmony_ci { 84370b324cSopenharmony_ci AString &methodName = methods[i].MethodName; 85370b324cSopenharmony_ci if (methodName.IsEmpty()) 86370b324cSopenharmony_ci methodName = kDefaultMethodName; 87370b324cSopenharmony_ci } 88370b324cSopenharmony_ci if (methods.IsEmpty()) 89370b324cSopenharmony_ci { 90370b324cSopenharmony_ci COneMethodInfo &m = methods.AddNew(); 91370b324cSopenharmony_ci m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName); 92370b324cSopenharmony_ci methodMode.DefaultMethod_was_Inserted = true; 93370b324cSopenharmony_ci } 94370b324cSopenharmony_ci } 95370b324cSopenharmony_ci 96370b324cSopenharmony_ci if (!_filterMethod.MethodName.IsEmpty()) 97370b324cSopenharmony_ci { 98370b324cSopenharmony_ci // if (methodMode.Bonds.IsEmpty()) 99370b324cSopenharmony_ci { 100370b324cSopenharmony_ci FOR_VECTOR (k, methodMode.Bonds) 101370b324cSopenharmony_ci { 102370b324cSopenharmony_ci CBond2 &bond = methodMode.Bonds[k]; 103370b324cSopenharmony_ci bond.InCoder++; 104370b324cSopenharmony_ci bond.OutCoder++; 105370b324cSopenharmony_ci } 106370b324cSopenharmony_ci methods.Insert(0, _filterMethod); 107370b324cSopenharmony_ci methodMode.Filter_was_Inserted = true; 108370b324cSopenharmony_ci } 109370b324cSopenharmony_ci } 110370b324cSopenharmony_ci 111370b324cSopenharmony_ci const UInt64 kSolidBytes_Min = (1 << 24); 112370b324cSopenharmony_ci const UInt64 kSolidBytes_Max = ((UInt64)1 << 32); 113370b324cSopenharmony_ci 114370b324cSopenharmony_ci bool needSolid = false; 115370b324cSopenharmony_ci 116370b324cSopenharmony_ci FOR_VECTOR (i, methods) 117370b324cSopenharmony_ci { 118370b324cSopenharmony_ci COneMethodInfo &oneMethodInfo = methods[i]; 119370b324cSopenharmony_ci 120370b324cSopenharmony_ci SetGlobalLevelTo(oneMethodInfo); 121370b324cSopenharmony_ci 122370b324cSopenharmony_ci #ifndef Z7_ST 123370b324cSopenharmony_ci const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0); 124370b324cSopenharmony_ci if (!numThreads_WasSpecifiedInMethod) 125370b324cSopenharmony_ci { 126370b324cSopenharmony_ci // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already 127370b324cSopenharmony_ci CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, methodMode.NumThreads); 128370b324cSopenharmony_ci } 129370b324cSopenharmony_ci #endif 130370b324cSopenharmony_ci 131370b324cSopenharmony_ci CMethodFull &methodFull = methodMode.Methods.AddNew(); 132370b324cSopenharmony_ci RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo)) 133370b324cSopenharmony_ci 134370b324cSopenharmony_ci #ifndef Z7_ST 135370b324cSopenharmony_ci methodFull.Set_NumThreads = true; 136370b324cSopenharmony_ci methodFull.NumThreads = methodMode.NumThreads; 137370b324cSopenharmony_ci #endif 138370b324cSopenharmony_ci 139370b324cSopenharmony_ci if (methodFull.Id != k_Copy) 140370b324cSopenharmony_ci needSolid = true; 141370b324cSopenharmony_ci 142370b324cSopenharmony_ci UInt64 dicSize; 143370b324cSopenharmony_ci switch (methodFull.Id) 144370b324cSopenharmony_ci { 145370b324cSopenharmony_ci case k_LZMA: 146370b324cSopenharmony_ci case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break; 147370b324cSopenharmony_ci case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break; 148370b324cSopenharmony_ci case k_Deflate: dicSize = (UInt32)1 << 15; break; 149370b324cSopenharmony_ci case k_Deflate64: dicSize = (UInt32)1 << 16; break; 150370b324cSopenharmony_ci case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break; 151370b324cSopenharmony_ci // case k_ZSTD: dicSize = 1 << 23; break; 152370b324cSopenharmony_ci default: continue; 153370b324cSopenharmony_ci } 154370b324cSopenharmony_ci 155370b324cSopenharmony_ci UInt64 numSolidBytes; 156370b324cSopenharmony_ci 157370b324cSopenharmony_ci /* 158370b324cSopenharmony_ci if (methodFull.Id == k_ZSTD) 159370b324cSopenharmony_ci { 160370b324cSopenharmony_ci // continue; 161370b324cSopenharmony_ci NCompress::NZstd::CEncoderProps encoderProps; 162370b324cSopenharmony_ci RINOK(oneMethodInfo.Set_PropsTo_zstd(encoderProps)); 163370b324cSopenharmony_ci CZstdEncProps &zstdProps = encoderProps.EncProps; 164370b324cSopenharmony_ci ZstdEncProps_NormalizeFull(&zstdProps); 165370b324cSopenharmony_ci UInt64 cs = (UInt64)(zstdProps.jobSize); 166370b324cSopenharmony_ci UInt32 winSize = (UInt32)(1 << zstdProps.windowLog); 167370b324cSopenharmony_ci if (cs < winSize) 168370b324cSopenharmony_ci cs = winSize; 169370b324cSopenharmony_ci numSolidBytes = cs << 6; 170370b324cSopenharmony_ci const UInt64 kSolidBytes_Zstd_Max = ((UInt64)1 << 34); 171370b324cSopenharmony_ci if (numSolidBytes > kSolidBytes_Zstd_Max) 172370b324cSopenharmony_ci numSolidBytes = kSolidBytes_Zstd_Max; 173370b324cSopenharmony_ci 174370b324cSopenharmony_ci methodFull.Set_NumThreads = false; // we don't use ICompressSetCoderMt::SetNumberOfThreads() for LZMA2 encoder 175370b324cSopenharmony_ci 176370b324cSopenharmony_ci #ifndef Z7_ST 177370b324cSopenharmony_ci if (!numThreads_WasSpecifiedInMethod 178370b324cSopenharmony_ci && !methodMode.NumThreads_WasForced 179370b324cSopenharmony_ci && methodMode.MemoryUsageLimit_WasSet 180370b324cSopenharmony_ci ) 181370b324cSopenharmony_ci { 182370b324cSopenharmony_ci const UInt32 numThreads_Original = methodMode.NumThreads; 183370b324cSopenharmony_ci const UInt32 numThreads_New = ZstdEncProps_GetNumThreads_for_MemUsageLimit( 184370b324cSopenharmony_ci &zstdProps, 185370b324cSopenharmony_ci methodMode.MemoryUsageLimit, 186370b324cSopenharmony_ci numThreads_Original); 187370b324cSopenharmony_ci if (numThreads_Original != numThreads_New) 188370b324cSopenharmony_ci { 189370b324cSopenharmony_ci CMultiMethodProps::SetMethodThreadsTo_Replace(methodFull, numThreads_New); 190370b324cSopenharmony_ci } 191370b324cSopenharmony_ci } 192370b324cSopenharmony_ci #endif 193370b324cSopenharmony_ci } 194370b324cSopenharmony_ci else 195370b324cSopenharmony_ci */ 196370b324cSopenharmony_ci if (methodFull.Id == k_LZMA2) 197370b324cSopenharmony_ci { 198370b324cSopenharmony_ci // he we calculate default chunk Size for LZMA2 as defined in LZMA2 encoder code 199370b324cSopenharmony_ci /* lzma2 code use dictionary up to fake 4 GiB to calculate ChunkSize. 200370b324cSopenharmony_ci So we do same */ 201370b324cSopenharmony_ci UInt64 cs = (UInt64)dicSize << 2; 202370b324cSopenharmony_ci const UInt32 kMinSize = (UInt32)1 << 20; 203370b324cSopenharmony_ci const UInt32 kMaxSize = (UInt32)1 << 28; 204370b324cSopenharmony_ci if (cs < kMinSize) cs = kMinSize; 205370b324cSopenharmony_ci if (cs > kMaxSize) cs = kMaxSize; 206370b324cSopenharmony_ci if (cs < dicSize) cs = dicSize; 207370b324cSopenharmony_ci cs += (kMinSize - 1); 208370b324cSopenharmony_ci cs &= ~(UInt64)(kMinSize - 1); 209370b324cSopenharmony_ci // we want to use at least 64 chunks (threads) per one solid block. 210370b324cSopenharmony_ci 211370b324cSopenharmony_ci // here we don't use chunkSize property 212370b324cSopenharmony_ci numSolidBytes = cs << 6; 213370b324cSopenharmony_ci 214370b324cSopenharmony_ci // here we get real chunkSize 215370b324cSopenharmony_ci cs = oneMethodInfo.Get_Xz_BlockSize(); 216370b324cSopenharmony_ci if (dicSize > cs) 217370b324cSopenharmony_ci dicSize = cs; 218370b324cSopenharmony_ci 219370b324cSopenharmony_ci const UInt64 kSolidBytes_Lzma2_Max = ((UInt64)1 << 34); 220370b324cSopenharmony_ci if (numSolidBytes > kSolidBytes_Lzma2_Max) 221370b324cSopenharmony_ci numSolidBytes = kSolidBytes_Lzma2_Max; 222370b324cSopenharmony_ci 223370b324cSopenharmony_ci methodFull.Set_NumThreads = false; // we don't use ICompressSetCoderMt::SetNumberOfThreads() for LZMA2 encoder 224370b324cSopenharmony_ci 225370b324cSopenharmony_ci #ifndef Z7_ST 226370b324cSopenharmony_ci if (!numThreads_WasSpecifiedInMethod 227370b324cSopenharmony_ci && !methodMode.NumThreads_WasForced 228370b324cSopenharmony_ci && methodMode.MemoryUsageLimit_WasSet 229370b324cSopenharmony_ci ) 230370b324cSopenharmony_ci { 231370b324cSopenharmony_ci const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads(); 232370b324cSopenharmony_ci const UInt32 numBlockThreads_Original = methodMode.NumThreads / lzmaThreads; 233370b324cSopenharmony_ci 234370b324cSopenharmony_ci if (numBlockThreads_Original > 1) 235370b324cSopenharmony_ci { 236370b324cSopenharmony_ci /* 237370b324cSopenharmony_ci const UInt32 kNumThreads_Max = 1024; 238370b324cSopenharmony_ci if (numBlockThreads > kNumMaxThreads) 239370b324cSopenharmony_ci numBlockThreads = kNumMaxThreads; 240370b324cSopenharmony_ci */ 241370b324cSopenharmony_ci 242370b324cSopenharmony_ci UInt32 numBlockThreads = numBlockThreads_Original; 243370b324cSopenharmony_ci const UInt64 lzmaMemUsage = oneMethodInfo.Get_Lzma_MemUsage(false); // solid 244370b324cSopenharmony_ci 245370b324cSopenharmony_ci for (; numBlockThreads > 1; numBlockThreads--) 246370b324cSopenharmony_ci { 247370b324cSopenharmony_ci UInt64 size = numBlockThreads * (lzmaMemUsage + cs); 248370b324cSopenharmony_ci UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1; 249370b324cSopenharmony_ci if (cs < ((UInt32)1 << 26)) numPackChunks++; 250370b324cSopenharmony_ci if (cs < ((UInt32)1 << 24)) numPackChunks++; 251370b324cSopenharmony_ci if (cs < ((UInt32)1 << 22)) numPackChunks++; 252370b324cSopenharmony_ci size += numPackChunks * cs; 253370b324cSopenharmony_ci // printf("\nnumBlockThreads = %d, size = %d\n", (unsigned)(numBlockThreads), (unsigned)(size >> 20)); 254370b324cSopenharmony_ci if (size <= methodMode.MemoryUsageLimit) 255370b324cSopenharmony_ci break; 256370b324cSopenharmony_ci } 257370b324cSopenharmony_ci 258370b324cSopenharmony_ci if (numBlockThreads == 0) 259370b324cSopenharmony_ci numBlockThreads = 1; 260370b324cSopenharmony_ci if (numBlockThreads != numBlockThreads_Original) 261370b324cSopenharmony_ci { 262370b324cSopenharmony_ci const UInt32 numThreads_New = numBlockThreads * lzmaThreads; 263370b324cSopenharmony_ci CMultiMethodProps::SetMethodThreadsTo_Replace(methodFull, numThreads_New); 264370b324cSopenharmony_ci } 265370b324cSopenharmony_ci } 266370b324cSopenharmony_ci } 267370b324cSopenharmony_ci #endif 268370b324cSopenharmony_ci } 269370b324cSopenharmony_ci else 270370b324cSopenharmony_ci { 271370b324cSopenharmony_ci numSolidBytes = (UInt64)dicSize << 7; 272370b324cSopenharmony_ci if (numSolidBytes > kSolidBytes_Max) 273370b324cSopenharmony_ci numSolidBytes = kSolidBytes_Max; 274370b324cSopenharmony_ci } 275370b324cSopenharmony_ci 276370b324cSopenharmony_ci if (_numSolidBytesDefined) 277370b324cSopenharmony_ci continue; 278370b324cSopenharmony_ci 279370b324cSopenharmony_ci if (numSolidBytes < kSolidBytes_Min) 280370b324cSopenharmony_ci numSolidBytes = kSolidBytes_Min; 281370b324cSopenharmony_ci _numSolidBytes = numSolidBytes; 282370b324cSopenharmony_ci _numSolidBytesDefined = true; 283370b324cSopenharmony_ci } 284370b324cSopenharmony_ci 285370b324cSopenharmony_ci if (!_numSolidBytesDefined) 286370b324cSopenharmony_ci { 287370b324cSopenharmony_ci if (needSolid) 288370b324cSopenharmony_ci _numSolidBytes = kSolidBytes_Max; 289370b324cSopenharmony_ci else 290370b324cSopenharmony_ci _numSolidBytes = 0; 291370b324cSopenharmony_ci } 292370b324cSopenharmony_ci _numSolidBytesDefined = true; 293370b324cSopenharmony_ci 294370b324cSopenharmony_ci 295370b324cSopenharmony_ci return S_OK; 296370b324cSopenharmony_ci} 297370b324cSopenharmony_ci 298370b324cSopenharmony_ci 299370b324cSopenharmony_ci 300370b324cSopenharmony_cistatic HRESULT GetTime(IArchiveUpdateCallback *updateCallback, unsigned index, PROPID propID, UInt64 &ft, bool &ftDefined) 301370b324cSopenharmony_ci{ 302370b324cSopenharmony_ci // ft = 0; 303370b324cSopenharmony_ci // ftDefined = false; 304370b324cSopenharmony_ci NCOM::CPropVariant prop; 305370b324cSopenharmony_ci RINOK(updateCallback->GetProperty(index, propID, &prop)) 306370b324cSopenharmony_ci if (prop.vt == VT_FILETIME) 307370b324cSopenharmony_ci { 308370b324cSopenharmony_ci ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32); 309370b324cSopenharmony_ci ftDefined = true; 310370b324cSopenharmony_ci } 311370b324cSopenharmony_ci else if (prop.vt != VT_EMPTY) 312370b324cSopenharmony_ci return E_INVALIDARG; 313370b324cSopenharmony_ci else 314370b324cSopenharmony_ci { 315370b324cSopenharmony_ci ft = 0; 316370b324cSopenharmony_ci ftDefined = false; 317370b324cSopenharmony_ci } 318370b324cSopenharmony_ci return S_OK; 319370b324cSopenharmony_ci} 320370b324cSopenharmony_ci 321370b324cSopenharmony_ci/* 322370b324cSopenharmony_ci 323370b324cSopenharmony_ci#ifdef _WIN32 324370b324cSopenharmony_cistatic const wchar_t kDirDelimiter1 = L'\\'; 325370b324cSopenharmony_ci#endif 326370b324cSopenharmony_cistatic const wchar_t kDirDelimiter2 = L'/'; 327370b324cSopenharmony_ci 328370b324cSopenharmony_cistatic inline bool IsCharDirLimiter(wchar_t c) 329370b324cSopenharmony_ci{ 330370b324cSopenharmony_ci return ( 331370b324cSopenharmony_ci #ifdef _WIN32 332370b324cSopenharmony_ci c == kDirDelimiter1 || 333370b324cSopenharmony_ci #endif 334370b324cSopenharmony_ci c == kDirDelimiter2); 335370b324cSopenharmony_ci} 336370b324cSopenharmony_ci 337370b324cSopenharmony_cistatic int FillSortIndex(CObjectVector<CTreeFolder> &treeFolders, int cur, int curSortIndex) 338370b324cSopenharmony_ci{ 339370b324cSopenharmony_ci CTreeFolder &tf = treeFolders[cur]; 340370b324cSopenharmony_ci tf.SortIndex = curSortIndex++; 341370b324cSopenharmony_ci for (int i = 0; i < tf.SubFolders.Size(); i++) 342370b324cSopenharmony_ci curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex); 343370b324cSopenharmony_ci tf.SortIndexEnd = curSortIndex; 344370b324cSopenharmony_ci return curSortIndex; 345370b324cSopenharmony_ci} 346370b324cSopenharmony_ci 347370b324cSopenharmony_cistatic int FindSubFolder(const CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name, int &insertPos) 348370b324cSopenharmony_ci{ 349370b324cSopenharmony_ci const CIntVector &subFolders = treeFolders[cur].SubFolders; 350370b324cSopenharmony_ci int left = 0, right = subFolders.Size(); 351370b324cSopenharmony_ci insertPos = -1; 352370b324cSopenharmony_ci for (;;) 353370b324cSopenharmony_ci { 354370b324cSopenharmony_ci if (left == right) 355370b324cSopenharmony_ci { 356370b324cSopenharmony_ci insertPos = left; 357370b324cSopenharmony_ci return -1; 358370b324cSopenharmony_ci } 359370b324cSopenharmony_ci int mid = (left + right) / 2; 360370b324cSopenharmony_ci int midFolder = subFolders[mid]; 361370b324cSopenharmony_ci int compare = CompareFileNames(name, treeFolders[midFolder].Name); 362370b324cSopenharmony_ci if (compare == 0) 363370b324cSopenharmony_ci return midFolder; 364370b324cSopenharmony_ci if (compare < 0) 365370b324cSopenharmony_ci right = mid; 366370b324cSopenharmony_ci else 367370b324cSopenharmony_ci left = mid + 1; 368370b324cSopenharmony_ci } 369370b324cSopenharmony_ci} 370370b324cSopenharmony_ci 371370b324cSopenharmony_cistatic int AddFolder(CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name) 372370b324cSopenharmony_ci{ 373370b324cSopenharmony_ci int insertPos; 374370b324cSopenharmony_ci int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos); 375370b324cSopenharmony_ci if (folderIndex < 0) 376370b324cSopenharmony_ci { 377370b324cSopenharmony_ci folderIndex = treeFolders.Size(); 378370b324cSopenharmony_ci CTreeFolder &newFolder = treeFolders.AddNew(); 379370b324cSopenharmony_ci newFolder.Parent = cur; 380370b324cSopenharmony_ci newFolder.Name = name; 381370b324cSopenharmony_ci treeFolders[cur].SubFolders.Insert(insertPos, folderIndex); 382370b324cSopenharmony_ci } 383370b324cSopenharmony_ci // else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234; 384370b324cSopenharmony_ci return folderIndex; 385370b324cSopenharmony_ci} 386370b324cSopenharmony_ci*/ 387370b324cSopenharmony_ci 388370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, 389370b324cSopenharmony_ci IArchiveUpdateCallback *updateCallback)) 390370b324cSopenharmony_ci{ 391370b324cSopenharmony_ci COM_TRY_BEGIN 392370b324cSopenharmony_ci 393370b324cSopenharmony_ci const CDbEx *db = NULL; 394370b324cSopenharmony_ci #ifdef Z7_7Z_VOL 395370b324cSopenharmony_ci if (_volumes.Size() > 1) 396370b324cSopenharmony_ci return E_FAIL; 397370b324cSopenharmony_ci const CVolume *volume = 0; 398370b324cSopenharmony_ci if (_volumes.Size() == 1) 399370b324cSopenharmony_ci { 400370b324cSopenharmony_ci volume = &_volumes.Front(); 401370b324cSopenharmony_ci db = &volume->Database; 402370b324cSopenharmony_ci } 403370b324cSopenharmony_ci #else 404370b324cSopenharmony_ci if (_inStream) 405370b324cSopenharmony_ci db = &_db; 406370b324cSopenharmony_ci #endif 407370b324cSopenharmony_ci 408370b324cSopenharmony_ci if (db && !db->CanUpdate()) 409370b324cSopenharmony_ci return E_NOTIMPL; 410370b324cSopenharmony_ci 411370b324cSopenharmony_ci /* 412370b324cSopenharmony_ci Z7_DECL_CMyComPtr_QI_FROM( 413370b324cSopenharmony_ci IArchiveGetRawProps, 414370b324cSopenharmony_ci getRawProps, updateCallback) 415370b324cSopenharmony_ci 416370b324cSopenharmony_ci CUniqBlocks secureBlocks; 417370b324cSopenharmony_ci secureBlocks.AddUniq(NULL, 0); 418370b324cSopenharmony_ci 419370b324cSopenharmony_ci CObjectVector<CTreeFolder> treeFolders; 420370b324cSopenharmony_ci { 421370b324cSopenharmony_ci CTreeFolder folder; 422370b324cSopenharmony_ci folder.Parent = -1; 423370b324cSopenharmony_ci treeFolders.Add(folder); 424370b324cSopenharmony_ci } 425370b324cSopenharmony_ci */ 426370b324cSopenharmony_ci 427370b324cSopenharmony_ci CObjectVector<CUpdateItem> updateItems; 428370b324cSopenharmony_ci 429370b324cSopenharmony_ci bool need_CTime = (TimeOptions.Write_CTime.Def && TimeOptions.Write_CTime.Val); 430370b324cSopenharmony_ci bool need_ATime = (TimeOptions.Write_ATime.Def && TimeOptions.Write_ATime.Val); 431370b324cSopenharmony_ci bool need_MTime = (TimeOptions.Write_MTime.Def ? TimeOptions.Write_MTime.Val : true); 432370b324cSopenharmony_ci bool need_Attrib = (Write_Attrib.Def ? Write_Attrib.Val : true); 433370b324cSopenharmony_ci 434370b324cSopenharmony_ci if (db && !db->Files.IsEmpty()) 435370b324cSopenharmony_ci { 436370b324cSopenharmony_ci if (!TimeOptions.Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty(); 437370b324cSopenharmony_ci if (!TimeOptions.Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty(); 438370b324cSopenharmony_ci if (!TimeOptions.Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty(); 439370b324cSopenharmony_ci if (!Write_Attrib.Def) need_Attrib = !db->Attrib.Defs.IsEmpty(); 440370b324cSopenharmony_ci } 441370b324cSopenharmony_ci 442370b324cSopenharmony_ci // UString s; 443370b324cSopenharmony_ci UString name; 444370b324cSopenharmony_ci 445370b324cSopenharmony_ci for (UInt32 i = 0; i < numItems; i++) 446370b324cSopenharmony_ci { 447370b324cSopenharmony_ci Int32 newData, newProps; 448370b324cSopenharmony_ci UInt32 indexInArchive; 449370b324cSopenharmony_ci if (!updateCallback) 450370b324cSopenharmony_ci return E_FAIL; 451370b324cSopenharmony_ci RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)) 452370b324cSopenharmony_ci CUpdateItem ui; 453370b324cSopenharmony_ci ui.NewProps = IntToBool(newProps); 454370b324cSopenharmony_ci ui.NewData = IntToBool(newData); 455370b324cSopenharmony_ci ui.IndexInArchive = (int)indexInArchive; 456370b324cSopenharmony_ci ui.IndexInClient = i; 457370b324cSopenharmony_ci ui.IsAnti = false; 458370b324cSopenharmony_ci ui.Size = 0; 459370b324cSopenharmony_ci 460370b324cSopenharmony_ci name.Empty(); 461370b324cSopenharmony_ci // bool isAltStream = false; 462370b324cSopenharmony_ci if (ui.IndexInArchive != -1) 463370b324cSopenharmony_ci { 464370b324cSopenharmony_ci if (!db || (unsigned)ui.IndexInArchive >= db->Files.Size()) 465370b324cSopenharmony_ci return E_INVALIDARG; 466370b324cSopenharmony_ci const CFileItem &fi = db->Files[(unsigned)ui.IndexInArchive]; 467370b324cSopenharmony_ci if (!ui.NewProps) 468370b324cSopenharmony_ci { 469370b324cSopenharmony_ci _db.GetPath((unsigned)ui.IndexInArchive, name); 470370b324cSopenharmony_ci } 471370b324cSopenharmony_ci ui.IsDir = fi.IsDir; 472370b324cSopenharmony_ci ui.Size = fi.Size; 473370b324cSopenharmony_ci // isAltStream = fi.IsAltStream; 474370b324cSopenharmony_ci ui.IsAnti = db->IsItemAnti((unsigned)ui.IndexInArchive); 475370b324cSopenharmony_ci 476370b324cSopenharmony_ci if (!ui.NewProps) 477370b324cSopenharmony_ci { 478370b324cSopenharmony_ci ui.CTimeDefined = db->CTime.GetItem((unsigned)ui.IndexInArchive, ui.CTime); 479370b324cSopenharmony_ci ui.ATimeDefined = db->ATime.GetItem((unsigned)ui.IndexInArchive, ui.ATime); 480370b324cSopenharmony_ci ui.MTimeDefined = db->MTime.GetItem((unsigned)ui.IndexInArchive, ui.MTime); 481370b324cSopenharmony_ci } 482370b324cSopenharmony_ci } 483370b324cSopenharmony_ci 484370b324cSopenharmony_ci if (ui.NewProps) 485370b324cSopenharmony_ci { 486370b324cSopenharmony_ci bool folderStatusIsDefined; 487370b324cSopenharmony_ci if (need_Attrib) 488370b324cSopenharmony_ci { 489370b324cSopenharmony_ci NCOM::CPropVariant prop; 490370b324cSopenharmony_ci RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop)) 491370b324cSopenharmony_ci if (prop.vt == VT_EMPTY) 492370b324cSopenharmony_ci ui.AttribDefined = false; 493370b324cSopenharmony_ci else if (prop.vt != VT_UI4) 494370b324cSopenharmony_ci return E_INVALIDARG; 495370b324cSopenharmony_ci else 496370b324cSopenharmony_ci { 497370b324cSopenharmony_ci ui.Attrib = prop.ulVal; 498370b324cSopenharmony_ci ui.AttribDefined = true; 499370b324cSopenharmony_ci } 500370b324cSopenharmony_ci } 501370b324cSopenharmony_ci 502370b324cSopenharmony_ci // we need MTime to sort files. 503370b324cSopenharmony_ci if (need_CTime) RINOK(GetTime(updateCallback, i, kpidCTime, ui.CTime, ui.CTimeDefined)) 504370b324cSopenharmony_ci if (need_ATime) RINOK(GetTime(updateCallback, i, kpidATime, ui.ATime, ui.ATimeDefined)) 505370b324cSopenharmony_ci if (need_MTime) RINOK(GetTime(updateCallback, i, kpidMTime, ui.MTime, ui.MTimeDefined)) 506370b324cSopenharmony_ci 507370b324cSopenharmony_ci /* 508370b324cSopenharmony_ci if (getRawProps) 509370b324cSopenharmony_ci { 510370b324cSopenharmony_ci const void *data; 511370b324cSopenharmony_ci UInt32 dataSize; 512370b324cSopenharmony_ci UInt32 propType; 513370b324cSopenharmony_ci 514370b324cSopenharmony_ci getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType); 515370b324cSopenharmony_ci if (dataSize != 0 && propType != NPropDataType::kRaw) 516370b324cSopenharmony_ci return E_FAIL; 517370b324cSopenharmony_ci ui.SecureIndex = secureBlocks.AddUniq((const Byte *)data, dataSize); 518370b324cSopenharmony_ci } 519370b324cSopenharmony_ci */ 520370b324cSopenharmony_ci 521370b324cSopenharmony_ci { 522370b324cSopenharmony_ci NCOM::CPropVariant prop; 523370b324cSopenharmony_ci RINOK(updateCallback->GetProperty(i, kpidPath, &prop)) 524370b324cSopenharmony_ci if (prop.vt == VT_EMPTY) 525370b324cSopenharmony_ci { 526370b324cSopenharmony_ci } 527370b324cSopenharmony_ci else if (prop.vt != VT_BSTR) 528370b324cSopenharmony_ci return E_INVALIDARG; 529370b324cSopenharmony_ci else 530370b324cSopenharmony_ci { 531370b324cSopenharmony_ci name = prop.bstrVal; 532370b324cSopenharmony_ci NItemName::ReplaceSlashes_OsToUnix(name); 533370b324cSopenharmony_ci } 534370b324cSopenharmony_ci } 535370b324cSopenharmony_ci { 536370b324cSopenharmony_ci NCOM::CPropVariant prop; 537370b324cSopenharmony_ci RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop)) 538370b324cSopenharmony_ci if (prop.vt == VT_EMPTY) 539370b324cSopenharmony_ci folderStatusIsDefined = false; 540370b324cSopenharmony_ci else if (prop.vt != VT_BOOL) 541370b324cSopenharmony_ci return E_INVALIDARG; 542370b324cSopenharmony_ci else 543370b324cSopenharmony_ci { 544370b324cSopenharmony_ci ui.IsDir = (prop.boolVal != VARIANT_FALSE); 545370b324cSopenharmony_ci folderStatusIsDefined = true; 546370b324cSopenharmony_ci } 547370b324cSopenharmony_ci } 548370b324cSopenharmony_ci 549370b324cSopenharmony_ci { 550370b324cSopenharmony_ci NCOM::CPropVariant prop; 551370b324cSopenharmony_ci RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop)) 552370b324cSopenharmony_ci if (prop.vt == VT_EMPTY) 553370b324cSopenharmony_ci ui.IsAnti = false; 554370b324cSopenharmony_ci else if (prop.vt != VT_BOOL) 555370b324cSopenharmony_ci return E_INVALIDARG; 556370b324cSopenharmony_ci else 557370b324cSopenharmony_ci ui.IsAnti = (prop.boolVal != VARIANT_FALSE); 558370b324cSopenharmony_ci } 559370b324cSopenharmony_ci 560370b324cSopenharmony_ci /* 561370b324cSopenharmony_ci { 562370b324cSopenharmony_ci NCOM::CPropVariant prop; 563370b324cSopenharmony_ci RINOK(updateCallback->GetProperty(i, kpidIsAltStream, &prop)); 564370b324cSopenharmony_ci if (prop.vt == VT_EMPTY) 565370b324cSopenharmony_ci isAltStream = false; 566370b324cSopenharmony_ci else if (prop.vt != VT_BOOL) 567370b324cSopenharmony_ci return E_INVALIDARG; 568370b324cSopenharmony_ci else 569370b324cSopenharmony_ci isAltStream = (prop.boolVal != VARIANT_FALSE); 570370b324cSopenharmony_ci } 571370b324cSopenharmony_ci */ 572370b324cSopenharmony_ci 573370b324cSopenharmony_ci if (ui.IsAnti) 574370b324cSopenharmony_ci { 575370b324cSopenharmony_ci ui.AttribDefined = false; 576370b324cSopenharmony_ci 577370b324cSopenharmony_ci ui.CTimeDefined = false; 578370b324cSopenharmony_ci ui.ATimeDefined = false; 579370b324cSopenharmony_ci ui.MTimeDefined = false; 580370b324cSopenharmony_ci 581370b324cSopenharmony_ci ui.Size = 0; 582370b324cSopenharmony_ci } 583370b324cSopenharmony_ci 584370b324cSopenharmony_ci if (!folderStatusIsDefined && ui.AttribDefined) 585370b324cSopenharmony_ci ui.SetDirStatusFromAttrib(); 586370b324cSopenharmony_ci } 587370b324cSopenharmony_ci else 588370b324cSopenharmony_ci { 589370b324cSopenharmony_ci /* 590370b324cSopenharmony_ci if (_db.SecureIDs.IsEmpty()) 591370b324cSopenharmony_ci ui.SecureIndex = secureBlocks.AddUniq(NULL, 0); 592370b324cSopenharmony_ci else 593370b324cSopenharmony_ci { 594370b324cSopenharmony_ci int id = _db.SecureIDs[ui.IndexInArchive]; 595370b324cSopenharmony_ci size_t offs = _db.SecureOffsets[id]; 596370b324cSopenharmony_ci size_t size = _db.SecureOffsets[id + 1] - offs; 597370b324cSopenharmony_ci ui.SecureIndex = secureBlocks.AddUniq(_db.SecureBuf + offs, size); 598370b324cSopenharmony_ci } 599370b324cSopenharmony_ci */ 600370b324cSopenharmony_ci } 601370b324cSopenharmony_ci 602370b324cSopenharmony_ci /* 603370b324cSopenharmony_ci { 604370b324cSopenharmony_ci int folderIndex = 0; 605370b324cSopenharmony_ci if (_useParents) 606370b324cSopenharmony_ci { 607370b324cSopenharmony_ci int j; 608370b324cSopenharmony_ci s.Empty(); 609370b324cSopenharmony_ci for (j = 0; j < name.Len(); j++) 610370b324cSopenharmony_ci { 611370b324cSopenharmony_ci wchar_t c = name[j]; 612370b324cSopenharmony_ci if (IsCharDirLimiter(c)) 613370b324cSopenharmony_ci { 614370b324cSopenharmony_ci folderIndex = AddFolder(treeFolders, folderIndex, s); 615370b324cSopenharmony_ci s.Empty(); 616370b324cSopenharmony_ci continue; 617370b324cSopenharmony_ci } 618370b324cSopenharmony_ci s += c; 619370b324cSopenharmony_ci } 620370b324cSopenharmony_ci if (isAltStream) 621370b324cSopenharmony_ci { 622370b324cSopenharmony_ci int colonPos = s.Find(':'); 623370b324cSopenharmony_ci if (colonPos < 0) 624370b324cSopenharmony_ci { 625370b324cSopenharmony_ci // isAltStream = false; 626370b324cSopenharmony_ci return E_INVALIDARG; 627370b324cSopenharmony_ci } 628370b324cSopenharmony_ci UString mainName = s.Left(colonPos); 629370b324cSopenharmony_ci int newFolderIndex = AddFolder(treeFolders, folderIndex, mainName); 630370b324cSopenharmony_ci if (treeFolders[newFolderIndex].UpdateItemIndex < 0) 631370b324cSopenharmony_ci { 632370b324cSopenharmony_ci for (int j = updateItems.Size() - 1; j >= 0; j--) 633370b324cSopenharmony_ci { 634370b324cSopenharmony_ci CUpdateItem &ui2 = updateItems[j]; 635370b324cSopenharmony_ci if (ui2.ParentFolderIndex == folderIndex 636370b324cSopenharmony_ci && ui2.Name == mainName) 637370b324cSopenharmony_ci { 638370b324cSopenharmony_ci ui2.TreeFolderIndex = newFolderIndex; 639370b324cSopenharmony_ci treeFolders[newFolderIndex].UpdateItemIndex = j; 640370b324cSopenharmony_ci } 641370b324cSopenharmony_ci } 642370b324cSopenharmony_ci } 643370b324cSopenharmony_ci folderIndex = newFolderIndex; 644370b324cSopenharmony_ci s.Delete(0, colonPos + 1); 645370b324cSopenharmony_ci } 646370b324cSopenharmony_ci ui.Name = s; 647370b324cSopenharmony_ci } 648370b324cSopenharmony_ci else 649370b324cSopenharmony_ci ui.Name = name; 650370b324cSopenharmony_ci ui.IsAltStream = isAltStream; 651370b324cSopenharmony_ci ui.ParentFolderIndex = folderIndex; 652370b324cSopenharmony_ci ui.TreeFolderIndex = -1; 653370b324cSopenharmony_ci if (ui.IsDir && !s.IsEmpty()) 654370b324cSopenharmony_ci { 655370b324cSopenharmony_ci ui.TreeFolderIndex = AddFolder(treeFolders, folderIndex, s); 656370b324cSopenharmony_ci treeFolders[ui.TreeFolderIndex].UpdateItemIndex = updateItems.Size(); 657370b324cSopenharmony_ci } 658370b324cSopenharmony_ci } 659370b324cSopenharmony_ci */ 660370b324cSopenharmony_ci ui.Name = name; 661370b324cSopenharmony_ci 662370b324cSopenharmony_ci if (ui.NewData) 663370b324cSopenharmony_ci { 664370b324cSopenharmony_ci ui.Size = 0; 665370b324cSopenharmony_ci if (!ui.IsDir) 666370b324cSopenharmony_ci { 667370b324cSopenharmony_ci NCOM::CPropVariant prop; 668370b324cSopenharmony_ci RINOK(updateCallback->GetProperty(i, kpidSize, &prop)) 669370b324cSopenharmony_ci if (prop.vt != VT_UI8) 670370b324cSopenharmony_ci return E_INVALIDARG; 671370b324cSopenharmony_ci ui.Size = (UInt64)prop.uhVal.QuadPart; 672370b324cSopenharmony_ci if (ui.Size != 0 && ui.IsAnti) 673370b324cSopenharmony_ci return E_INVALIDARG; 674370b324cSopenharmony_ci } 675370b324cSopenharmony_ci } 676370b324cSopenharmony_ci 677370b324cSopenharmony_ci updateItems.Add(ui); 678370b324cSopenharmony_ci } 679370b324cSopenharmony_ci 680370b324cSopenharmony_ci /* 681370b324cSopenharmony_ci FillSortIndex(treeFolders, 0, 0); 682370b324cSopenharmony_ci for (i = 0; i < (UInt32)updateItems.Size(); i++) 683370b324cSopenharmony_ci { 684370b324cSopenharmony_ci CUpdateItem &ui = updateItems[i]; 685370b324cSopenharmony_ci ui.ParentSortIndex = treeFolders[ui.ParentFolderIndex].SortIndex; 686370b324cSopenharmony_ci ui.ParentSortIndexEnd = treeFolders[ui.ParentFolderIndex].SortIndexEnd; 687370b324cSopenharmony_ci } 688370b324cSopenharmony_ci */ 689370b324cSopenharmony_ci 690370b324cSopenharmony_ci CCompressionMethodMode methodMode, headerMethod; 691370b324cSopenharmony_ci 692370b324cSopenharmony_ci methodMode.MemoryUsageLimit = _memUsage_Compress; 693370b324cSopenharmony_ci methodMode.MemoryUsageLimit_WasSet = _memUsage_WasSet; 694370b324cSopenharmony_ci 695370b324cSopenharmony_ci #ifndef Z7_ST 696370b324cSopenharmony_ci { 697370b324cSopenharmony_ci UInt32 numThreads = _numThreads; 698370b324cSopenharmony_ci const UInt32 kNumThreads_Max = 1024; 699370b324cSopenharmony_ci if (numThreads > kNumThreads_Max) 700370b324cSopenharmony_ci numThreads = kNumThreads_Max; 701370b324cSopenharmony_ci methodMode.NumThreads = numThreads; 702370b324cSopenharmony_ci methodMode.NumThreads_WasForced = _numThreads_WasForced; 703370b324cSopenharmony_ci methodMode.MultiThreadMixer = _useMultiThreadMixer; 704370b324cSopenharmony_ci // headerMethod.NumThreads = 1; 705370b324cSopenharmony_ci headerMethod.MultiThreadMixer = _useMultiThreadMixer; 706370b324cSopenharmony_ci } 707370b324cSopenharmony_ci #endif 708370b324cSopenharmony_ci 709370b324cSopenharmony_ci const HRESULT res = SetMainMethod(methodMode); 710370b324cSopenharmony_ci RINOK(res) 711370b324cSopenharmony_ci 712370b324cSopenharmony_ci RINOK(SetHeaderMethod(headerMethod)) 713370b324cSopenharmony_ci 714370b324cSopenharmony_ci Z7_DECL_CMyComPtr_QI_FROM( 715370b324cSopenharmony_ci ICryptoGetTextPassword2, 716370b324cSopenharmony_ci getPassword2, updateCallback) 717370b324cSopenharmony_ci 718370b324cSopenharmony_ci methodMode.PasswordIsDefined = false; 719370b324cSopenharmony_ci methodMode.Password.Wipe_and_Empty(); 720370b324cSopenharmony_ci if (getPassword2) 721370b324cSopenharmony_ci { 722370b324cSopenharmony_ci CMyComBSTR_Wipe password; 723370b324cSopenharmony_ci Int32 passwordIsDefined; 724370b324cSopenharmony_ci RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password)) 725370b324cSopenharmony_ci methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); 726370b324cSopenharmony_ci if (methodMode.PasswordIsDefined && password) 727370b324cSopenharmony_ci methodMode.Password = password; 728370b324cSopenharmony_ci } 729370b324cSopenharmony_ci 730370b324cSopenharmony_ci bool compressMainHeader = _compressHeaders; // check it 731370b324cSopenharmony_ci 732370b324cSopenharmony_ci bool encryptHeaders = false; 733370b324cSopenharmony_ci 734370b324cSopenharmony_ci #ifndef Z7_NO_CRYPTO 735370b324cSopenharmony_ci if (!methodMode.PasswordIsDefined && _passwordIsDefined) 736370b324cSopenharmony_ci { 737370b324cSopenharmony_ci // if header is compressed, we use that password for updated archive 738370b324cSopenharmony_ci methodMode.PasswordIsDefined = true; 739370b324cSopenharmony_ci methodMode.Password = _password; 740370b324cSopenharmony_ci } 741370b324cSopenharmony_ci #endif 742370b324cSopenharmony_ci 743370b324cSopenharmony_ci if (methodMode.PasswordIsDefined) 744370b324cSopenharmony_ci { 745370b324cSopenharmony_ci if (_encryptHeadersSpecified) 746370b324cSopenharmony_ci encryptHeaders = _encryptHeaders; 747370b324cSopenharmony_ci #ifndef Z7_NO_CRYPTO 748370b324cSopenharmony_ci else 749370b324cSopenharmony_ci encryptHeaders = _passwordIsDefined; 750370b324cSopenharmony_ci #endif 751370b324cSopenharmony_ci compressMainHeader = true; 752370b324cSopenharmony_ci if (encryptHeaders) 753370b324cSopenharmony_ci { 754370b324cSopenharmony_ci headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined; 755370b324cSopenharmony_ci headerMethod.Password = methodMode.Password; 756370b324cSopenharmony_ci } 757370b324cSopenharmony_ci } 758370b324cSopenharmony_ci 759370b324cSopenharmony_ci if (numItems < 2) 760370b324cSopenharmony_ci compressMainHeader = false; 761370b324cSopenharmony_ci 762370b324cSopenharmony_ci const int level = GetLevel(); 763370b324cSopenharmony_ci 764370b324cSopenharmony_ci CUpdateOptions options; 765370b324cSopenharmony_ci options.Need_CTime = need_CTime; 766370b324cSopenharmony_ci options.Need_ATime = need_ATime; 767370b324cSopenharmony_ci options.Need_MTime = need_MTime; 768370b324cSopenharmony_ci options.Need_Attrib = need_Attrib; 769370b324cSopenharmony_ci // options.Need_Crc = (_crcSize != 0); // for debug 770370b324cSopenharmony_ci 771370b324cSopenharmony_ci options.Method = &methodMode; 772370b324cSopenharmony_ci options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL; 773370b324cSopenharmony_ci options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted); 774370b324cSopenharmony_ci options.MaxFilter = (level >= 8); 775370b324cSopenharmony_ci options.AnalysisLevel = GetAnalysisLevel(); 776370b324cSopenharmony_ci 777370b324cSopenharmony_ci options.HeaderOptions.CompressMainHeader = compressMainHeader; 778370b324cSopenharmony_ci /* 779370b324cSopenharmony_ci options.HeaderOptions.WriteCTime = Write_CTime; 780370b324cSopenharmony_ci options.HeaderOptions.WriteATime = Write_ATime; 781370b324cSopenharmony_ci options.HeaderOptions.WriteMTime = Write_MTime; 782370b324cSopenharmony_ci options.HeaderOptions.WriteAttrib = Write_Attrib; 783370b324cSopenharmony_ci */ 784370b324cSopenharmony_ci 785370b324cSopenharmony_ci options.NumSolidFiles = _numSolidFiles; 786370b324cSopenharmony_ci options.NumSolidBytes = _numSolidBytes; 787370b324cSopenharmony_ci options.SolidExtension = _solidExtension; 788370b324cSopenharmony_ci options.UseTypeSorting = _useTypeSorting; 789370b324cSopenharmony_ci 790370b324cSopenharmony_ci options.RemoveSfxBlock = _removeSfxBlock; 791370b324cSopenharmony_ci // options.VolumeMode = _volumeMode; 792370b324cSopenharmony_ci 793370b324cSopenharmony_ci options.MultiThreadMixer = _useMultiThreadMixer; 794370b324cSopenharmony_ci 795370b324cSopenharmony_ci /* 796370b324cSopenharmony_ci if (secureBlocks.Sorted.Size() > 1) 797370b324cSopenharmony_ci { 798370b324cSopenharmony_ci secureBlocks.GetReverseMap(); 799370b324cSopenharmony_ci for (int i = 0; i < updateItems.Size(); i++) 800370b324cSopenharmony_ci { 801370b324cSopenharmony_ci int &secureIndex = updateItems[i].SecureIndex; 802370b324cSopenharmony_ci secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex]; 803370b324cSopenharmony_ci } 804370b324cSopenharmony_ci } 805370b324cSopenharmony_ci */ 806370b324cSopenharmony_ci 807370b324cSopenharmony_ci return Update( 808370b324cSopenharmony_ci EXTERNAL_CODECS_VARS 809370b324cSopenharmony_ci #ifdef Z7_7Z_VOL 810370b324cSopenharmony_ci volume ? volume->Stream: 0, 811370b324cSopenharmony_ci volume ? db : 0, 812370b324cSopenharmony_ci #else 813370b324cSopenharmony_ci _inStream, 814370b324cSopenharmony_ci db, 815370b324cSopenharmony_ci #endif 816370b324cSopenharmony_ci updateItems, 817370b324cSopenharmony_ci // treeFolders, 818370b324cSopenharmony_ci // secureBlocks, 819370b324cSopenharmony_ci outStream, updateCallback, options); 820370b324cSopenharmony_ci 821370b324cSopenharmony_ci COM_TRY_END 822370b324cSopenharmony_ci} 823370b324cSopenharmony_ci 824370b324cSopenharmony_cistatic HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream) 825370b324cSopenharmony_ci{ 826370b324cSopenharmony_ci stream = 0; 827370b324cSopenharmony_ci { 828370b324cSopenharmony_ci const unsigned index = ParseStringToUInt32(srcString, coder); 829370b324cSopenharmony_ci if (index == 0) 830370b324cSopenharmony_ci return E_INVALIDARG; 831370b324cSopenharmony_ci srcString.DeleteFrontal(index); 832370b324cSopenharmony_ci } 833370b324cSopenharmony_ci if (srcString[0] == 's') 834370b324cSopenharmony_ci { 835370b324cSopenharmony_ci srcString.Delete(0); 836370b324cSopenharmony_ci const unsigned index = ParseStringToUInt32(srcString, stream); 837370b324cSopenharmony_ci if (index == 0) 838370b324cSopenharmony_ci return E_INVALIDARG; 839370b324cSopenharmony_ci srcString.DeleteFrontal(index); 840370b324cSopenharmony_ci } 841370b324cSopenharmony_ci return S_OK; 842370b324cSopenharmony_ci} 843370b324cSopenharmony_ci 844370b324cSopenharmony_civoid COutHandler::InitProps7z() 845370b324cSopenharmony_ci{ 846370b324cSopenharmony_ci _removeSfxBlock = false; 847370b324cSopenharmony_ci _compressHeaders = true; 848370b324cSopenharmony_ci _encryptHeadersSpecified = false; 849370b324cSopenharmony_ci _encryptHeaders = false; 850370b324cSopenharmony_ci // _useParents = false; 851370b324cSopenharmony_ci 852370b324cSopenharmony_ci TimeOptions.Init(); 853370b324cSopenharmony_ci Write_Attrib.Init(); 854370b324cSopenharmony_ci 855370b324cSopenharmony_ci _useMultiThreadMixer = true; 856370b324cSopenharmony_ci 857370b324cSopenharmony_ci // _volumeMode = false; 858370b324cSopenharmony_ci 859370b324cSopenharmony_ci InitSolid(); 860370b324cSopenharmony_ci _useTypeSorting = false; 861370b324cSopenharmony_ci} 862370b324cSopenharmony_ci 863370b324cSopenharmony_civoid COutHandler::InitProps() 864370b324cSopenharmony_ci{ 865370b324cSopenharmony_ci CMultiMethodProps::Init(); 866370b324cSopenharmony_ci InitProps7z(); 867370b324cSopenharmony_ci} 868370b324cSopenharmony_ci 869370b324cSopenharmony_ci 870370b324cSopenharmony_ci 871370b324cSopenharmony_ciHRESULT COutHandler::SetSolidFromString(const UString &s) 872370b324cSopenharmony_ci{ 873370b324cSopenharmony_ci UString s2 = s; 874370b324cSopenharmony_ci s2.MakeLower_Ascii(); 875370b324cSopenharmony_ci for (unsigned i = 0; i < s2.Len();) 876370b324cSopenharmony_ci { 877370b324cSopenharmony_ci const wchar_t *start = ((const wchar_t *)s2) + i; 878370b324cSopenharmony_ci const wchar_t *end; 879370b324cSopenharmony_ci UInt64 v = ConvertStringToUInt64(start, &end); 880370b324cSopenharmony_ci if (start == end) 881370b324cSopenharmony_ci { 882370b324cSopenharmony_ci if (s2[i++] != 'e') 883370b324cSopenharmony_ci return E_INVALIDARG; 884370b324cSopenharmony_ci _solidExtension = true; 885370b324cSopenharmony_ci continue; 886370b324cSopenharmony_ci } 887370b324cSopenharmony_ci i += (unsigned)(end - start); 888370b324cSopenharmony_ci if (i == s2.Len()) 889370b324cSopenharmony_ci return E_INVALIDARG; 890370b324cSopenharmony_ci const wchar_t c = s2[i++]; 891370b324cSopenharmony_ci if (c == 'f') 892370b324cSopenharmony_ci { 893370b324cSopenharmony_ci if (v < 1) 894370b324cSopenharmony_ci v = 1; 895370b324cSopenharmony_ci _numSolidFiles = v; 896370b324cSopenharmony_ci } 897370b324cSopenharmony_ci else 898370b324cSopenharmony_ci { 899370b324cSopenharmony_ci unsigned numBits; 900370b324cSopenharmony_ci switch (c) 901370b324cSopenharmony_ci { 902370b324cSopenharmony_ci case 'b': numBits = 0; break; 903370b324cSopenharmony_ci case 'k': numBits = 10; break; 904370b324cSopenharmony_ci case 'm': numBits = 20; break; 905370b324cSopenharmony_ci case 'g': numBits = 30; break; 906370b324cSopenharmony_ci case 't': numBits = 40; break; 907370b324cSopenharmony_ci default: return E_INVALIDARG; 908370b324cSopenharmony_ci } 909370b324cSopenharmony_ci _numSolidBytes = (v << numBits); 910370b324cSopenharmony_ci _numSolidBytesDefined = true; 911370b324cSopenharmony_ci /* 912370b324cSopenharmony_ci if (_numSolidBytes == 0) 913370b324cSopenharmony_ci _numSolidFiles = 1; 914370b324cSopenharmony_ci */ 915370b324cSopenharmony_ci } 916370b324cSopenharmony_ci } 917370b324cSopenharmony_ci return S_OK; 918370b324cSopenharmony_ci} 919370b324cSopenharmony_ci 920370b324cSopenharmony_ciHRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value) 921370b324cSopenharmony_ci{ 922370b324cSopenharmony_ci bool isSolid; 923370b324cSopenharmony_ci switch (value.vt) 924370b324cSopenharmony_ci { 925370b324cSopenharmony_ci case VT_EMPTY: isSolid = true; break; 926370b324cSopenharmony_ci case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; 927370b324cSopenharmony_ci case VT_BSTR: 928370b324cSopenharmony_ci if (StringToBool(value.bstrVal, isSolid)) 929370b324cSopenharmony_ci break; 930370b324cSopenharmony_ci return SetSolidFromString(value.bstrVal); 931370b324cSopenharmony_ci default: return E_INVALIDARG; 932370b324cSopenharmony_ci } 933370b324cSopenharmony_ci if (isSolid) 934370b324cSopenharmony_ci InitSolid(); 935370b324cSopenharmony_ci else 936370b324cSopenharmony_ci _numSolidFiles = 1; 937370b324cSopenharmony_ci return S_OK; 938370b324cSopenharmony_ci} 939370b324cSopenharmony_ci 940370b324cSopenharmony_cistatic HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest) 941370b324cSopenharmony_ci{ 942370b324cSopenharmony_ci RINOK(PROPVARIANT_to_bool(prop, dest.Val)) 943370b324cSopenharmony_ci dest.Def = true; 944370b324cSopenharmony_ci return S_OK; 945370b324cSopenharmony_ci} 946370b324cSopenharmony_ci 947370b324cSopenharmony_ciHRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) 948370b324cSopenharmony_ci{ 949370b324cSopenharmony_ci UString name = nameSpec; 950370b324cSopenharmony_ci name.MakeLower_Ascii(); 951370b324cSopenharmony_ci if (name.IsEmpty()) 952370b324cSopenharmony_ci return E_INVALIDARG; 953370b324cSopenharmony_ci 954370b324cSopenharmony_ci if (name[0] == L's') 955370b324cSopenharmony_ci { 956370b324cSopenharmony_ci name.Delete(0); 957370b324cSopenharmony_ci if (name.IsEmpty()) 958370b324cSopenharmony_ci return SetSolidFromPROPVARIANT(value); 959370b324cSopenharmony_ci if (value.vt != VT_EMPTY) 960370b324cSopenharmony_ci return E_INVALIDARG; 961370b324cSopenharmony_ci return SetSolidFromString(name); 962370b324cSopenharmony_ci } 963370b324cSopenharmony_ci 964370b324cSopenharmony_ci UInt32 number; 965370b324cSopenharmony_ci const unsigned index = ParseStringToUInt32(name, number); 966370b324cSopenharmony_ci // UString realName = name.Ptr(index); 967370b324cSopenharmony_ci if (index == 0) 968370b324cSopenharmony_ci { 969370b324cSopenharmony_ci if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock); 970370b324cSopenharmony_ci if (name.IsEqualTo("hc")) return PROPVARIANT_to_bool(value, _compressHeaders); 971370b324cSopenharmony_ci // if (name.IsEqualToNoCase(L"HS")) return PROPVARIANT_to_bool(value, _useParents); 972370b324cSopenharmony_ci 973370b324cSopenharmony_ci if (name.IsEqualTo("hcf")) 974370b324cSopenharmony_ci { 975370b324cSopenharmony_ci bool compressHeadersFull = true; 976370b324cSopenharmony_ci RINOK(PROPVARIANT_to_bool(value, compressHeadersFull)) 977370b324cSopenharmony_ci return compressHeadersFull ? S_OK: E_INVALIDARG; 978370b324cSopenharmony_ci } 979370b324cSopenharmony_ci 980370b324cSopenharmony_ci if (name.IsEqualTo("he")) 981370b324cSopenharmony_ci { 982370b324cSopenharmony_ci RINOK(PROPVARIANT_to_bool(value, _encryptHeaders)) 983370b324cSopenharmony_ci _encryptHeadersSpecified = true; 984370b324cSopenharmony_ci return S_OK; 985370b324cSopenharmony_ci } 986370b324cSopenharmony_ci 987370b324cSopenharmony_ci { 988370b324cSopenharmony_ci bool processed; 989370b324cSopenharmony_ci RINOK(TimeOptions.Parse(name, value, processed)) 990370b324cSopenharmony_ci if (processed) 991370b324cSopenharmony_ci { 992370b324cSopenharmony_ci if ( TimeOptions.Prec != (UInt32)(Int32)-1 993370b324cSopenharmony_ci && TimeOptions.Prec != k_PropVar_TimePrec_0 994370b324cSopenharmony_ci && TimeOptions.Prec != k_PropVar_TimePrec_HighPrec 995370b324cSopenharmony_ci && TimeOptions.Prec != k_PropVar_TimePrec_100ns) 996370b324cSopenharmony_ci return E_INVALIDARG; 997370b324cSopenharmony_ci return S_OK; 998370b324cSopenharmony_ci } 999370b324cSopenharmony_ci } 1000370b324cSopenharmony_ci 1001370b324cSopenharmony_ci if (name.IsEqualTo("tr")) return PROPVARIANT_to_BoolPair(value, Write_Attrib); 1002370b324cSopenharmony_ci 1003370b324cSopenharmony_ci if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer); 1004370b324cSopenharmony_ci 1005370b324cSopenharmony_ci if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting); 1006370b324cSopenharmony_ci 1007370b324cSopenharmony_ci // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode); 1008370b324cSopenharmony_ci } 1009370b324cSopenharmony_ci return CMultiMethodProps::SetProperty(name, value); 1010370b324cSopenharmony_ci} 1011370b324cSopenharmony_ci 1012370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) 1013370b324cSopenharmony_ci{ 1014370b324cSopenharmony_ci COM_TRY_BEGIN 1015370b324cSopenharmony_ci _bonds.Clear(); 1016370b324cSopenharmony_ci InitProps(); 1017370b324cSopenharmony_ci 1018370b324cSopenharmony_ci for (UInt32 i = 0; i < numProps; i++) 1019370b324cSopenharmony_ci { 1020370b324cSopenharmony_ci UString name = names[i]; 1021370b324cSopenharmony_ci name.MakeLower_Ascii(); 1022370b324cSopenharmony_ci if (name.IsEmpty()) 1023370b324cSopenharmony_ci return E_INVALIDARG; 1024370b324cSopenharmony_ci 1025370b324cSopenharmony_ci const PROPVARIANT &value = values[i]; 1026370b324cSopenharmony_ci 1027370b324cSopenharmony_ci if (name.Find(L':') >= 0) // 'b' was used as NCoderPropID::kBlockSize2 before v23 1028370b324cSopenharmony_ci if (name[0] == 'b') 1029370b324cSopenharmony_ci { 1030370b324cSopenharmony_ci if (value.vt != VT_EMPTY) 1031370b324cSopenharmony_ci return E_INVALIDARG; 1032370b324cSopenharmony_ci name.Delete(0); 1033370b324cSopenharmony_ci 1034370b324cSopenharmony_ci CBond2 bond; 1035370b324cSopenharmony_ci RINOK(ParseBond(name, bond.OutCoder, bond.OutStream)) 1036370b324cSopenharmony_ci if (name[0] != ':') 1037370b324cSopenharmony_ci return E_INVALIDARG; 1038370b324cSopenharmony_ci name.Delete(0); 1039370b324cSopenharmony_ci UInt32 inStream = 0; 1040370b324cSopenharmony_ci RINOK(ParseBond(name, bond.InCoder, inStream)) 1041370b324cSopenharmony_ci if (inStream != 0) 1042370b324cSopenharmony_ci return E_INVALIDARG; 1043370b324cSopenharmony_ci if (!name.IsEmpty()) 1044370b324cSopenharmony_ci return E_INVALIDARG; 1045370b324cSopenharmony_ci _bonds.Add(bond); 1046370b324cSopenharmony_ci continue; 1047370b324cSopenharmony_ci } 1048370b324cSopenharmony_ci 1049370b324cSopenharmony_ci RINOK(SetProperty(name, value)) 1050370b324cSopenharmony_ci } 1051370b324cSopenharmony_ci 1052370b324cSopenharmony_ci unsigned numEmptyMethods = GetNumEmptyMethods(); 1053370b324cSopenharmony_ci if (numEmptyMethods > 0) 1054370b324cSopenharmony_ci { 1055370b324cSopenharmony_ci unsigned k; 1056370b324cSopenharmony_ci for (k = 0; k < _bonds.Size(); k++) 1057370b324cSopenharmony_ci { 1058370b324cSopenharmony_ci const CBond2 &bond = _bonds[k]; 1059370b324cSopenharmony_ci if (bond.InCoder < (UInt32)numEmptyMethods || 1060370b324cSopenharmony_ci bond.OutCoder < (UInt32)numEmptyMethods) 1061370b324cSopenharmony_ci return E_INVALIDARG; 1062370b324cSopenharmony_ci } 1063370b324cSopenharmony_ci for (k = 0; k < _bonds.Size(); k++) 1064370b324cSopenharmony_ci { 1065370b324cSopenharmony_ci CBond2 &bond = _bonds[k]; 1066370b324cSopenharmony_ci bond.InCoder -= (UInt32)numEmptyMethods; 1067370b324cSopenharmony_ci bond.OutCoder -= (UInt32)numEmptyMethods; 1068370b324cSopenharmony_ci } 1069370b324cSopenharmony_ci _methods.DeleteFrontal(numEmptyMethods); 1070370b324cSopenharmony_ci } 1071370b324cSopenharmony_ci 1072370b324cSopenharmony_ci FOR_VECTOR (k, _bonds) 1073370b324cSopenharmony_ci { 1074370b324cSopenharmony_ci const CBond2 &bond = _bonds[k]; 1075370b324cSopenharmony_ci if (bond.InCoder >= (UInt32)_methods.Size() || 1076370b324cSopenharmony_ci bond.OutCoder >= (UInt32)_methods.Size()) 1077370b324cSopenharmony_ci return E_INVALIDARG; 1078370b324cSopenharmony_ci } 1079370b324cSopenharmony_ci 1080370b324cSopenharmony_ci return S_OK; 1081370b324cSopenharmony_ci COM_TRY_END 1082370b324cSopenharmony_ci} 1083370b324cSopenharmony_ci 1084370b324cSopenharmony_ci}} 1085370b324cSopenharmony_ci 1086370b324cSopenharmony_ci#endif 1087