Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/CPP/7zip
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2021-11-29 06:03:01 +0300
committerfn ⌃ ⌥ <70830482+FnControlOption@users.noreply.github.com>2021-11-29 06:03:01 +0300
commit1194dc935382931bbfdd4e49004bd755e6165df1 (patch)
tree60354d8832278528f74c48ca3b5e446175747409 /CPP/7zip
parentd789d4137d8a7c16696c5bc1b13f24bb887eb7ea (diff)
21.0421.04
Diffstat (limited to 'CPP/7zip')
-rw-r--r--CPP/7zip/Archive/7z/7zCompressionMode.h11
-rw-r--r--CPP/7zip/Archive/7z/7zEncode.cpp6
-rw-r--r--CPP/7zip/Archive/7z/7zExtract.cpp2
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.h7
-rw-r--r--CPP/7zip/Archive/7z/7zHandlerOut.cpp135
-rw-r--r--CPP/7zip/Archive/Common/HandlerOut.cpp32
-rw-r--r--CPP/7zip/Archive/Common/HandlerOut.h25
-rw-r--r--CPP/7zip/Archive/HfsHandler.cpp3
-rw-r--r--CPP/7zip/Archive/IArchive.h15
-rw-r--r--CPP/7zip/Archive/Tar/TarHandler.cpp3
-rw-r--r--CPP/7zip/Archive/Udf/UdfIn.cpp2
-rw-r--r--CPP/7zip/Archive/Wim/WimHandler.cpp6
-rw-r--r--CPP/7zip/Archive/XarHandler.cpp3
-rw-r--r--CPP/7zip/Archive/XzHandler.cpp78
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandler.cpp2
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.cpp51
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.h2
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.cpp46
-rw-r--r--CPP/7zip/Bundles/Alone/Alone.dsp8
-rw-r--r--CPP/7zip/Bundles/Alone/makefile1
-rw-r--r--CPP/7zip/Bundles/Alone/makefile.gcc1
-rw-r--r--CPP/7zip/Bundles/Alone7z/Alone.dsp8
-rw-r--r--CPP/7zip/Bundles/Alone7z/makefile1
-rw-r--r--CPP/7zip/Bundles/Alone7z/makefile.gcc1
-rw-r--r--CPP/7zip/Bundles/Fm/FM.dsp52
-rw-r--r--CPP/7zip/Bundles/SFXWin/SFXWin.dsp16
-rw-r--r--CPP/7zip/Bundles/SFXWin/makefile2
-rw-r--r--CPP/7zip/Common/CreateCoder.cpp1
-rw-r--r--CPP/7zip/Common/CreateCoder.h3
-rw-r--r--CPP/7zip/Common/MethodProps.cpp150
-rw-r--r--CPP/7zip/Common/MethodProps.h46
-rw-r--r--CPP/7zip/Compress/BZip2Crc.h4
-rw-r--r--CPP/7zip/Compress/CodecExports.cpp3
-rw-r--r--CPP/7zip/Guid.txt4
-rw-r--r--CPP/7zip/ICoder.h3
-rw-r--r--CPP/7zip/PropID.h3
-rw-r--r--CPP/7zip/UI/Agent/Agent.cpp40
-rw-r--r--CPP/7zip/UI/Agent/Agent.h6
-rw-r--r--CPP/7zip/UI/Agent/AgentOut.cpp3
-rw-r--r--CPP/7zip/UI/Agent/ArchiveFolderOut.cpp3
-rw-r--r--CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp2
-rw-r--r--CPP/7zip/UI/Client7z/Client7z.cpp4
-rw-r--r--CPP/7zip/UI/Common/ArchiveCommandLine.cpp57
-rw-r--r--CPP/7zip/UI/Common/ArchiveCommandLine.h3
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.cpp128
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.h26
-rw-r--r--CPP/7zip/UI/Common/Bench.cpp126
-rw-r--r--CPP/7zip/UI/Common/CompressCall.cpp38
-rw-r--r--CPP/7zip/UI/Common/CompressCall.h9
-rw-r--r--CPP/7zip/UI/Common/CompressCall2.cpp49
-rw-r--r--CPP/7zip/UI/Common/DirItem.h11
-rw-r--r--CPP/7zip/UI/Common/EnumDirItems.cpp52
-rw-r--r--CPP/7zip/UI/Common/Extract.cpp37
-rw-r--r--CPP/7zip/UI/Common/Extract.h11
-rw-r--r--CPP/7zip/UI/Common/HashCalc.cpp1727
-rw-r--r--CPP/7zip/UI/Common/HashCalc.h222
-rw-r--r--CPP/7zip/UI/Common/IFileExtractCallback.h4
-rw-r--r--CPP/7zip/UI/Common/LoadCodecs.cpp122
-rw-r--r--CPP/7zip/UI/Common/LoadCodecs.h40
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.cpp74
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.h15
-rw-r--r--CPP/7zip/UI/Common/Update.cpp64
-rw-r--r--CPP/7zip/UI/Common/UpdateCallback.cpp26
-rw-r--r--CPP/7zip/UI/Common/UpdateCallback.h6
-rw-r--r--CPP/7zip/UI/Console/Console.dsp16
-rw-r--r--CPP/7zip/UI/Console/ExtractCallbackConsole.cpp10
-rw-r--r--CPP/7zip/UI/Console/HashCon.cpp221
-rw-r--r--CPP/7zip/UI/Console/HashCon.h27
-rw-r--r--CPP/7zip/UI/Console/List.cpp9
-rw-r--r--CPP/7zip/UI/Console/List.h23
-rw-r--r--CPP/7zip/UI/Console/Main.cpp37
-rw-r--r--CPP/7zip/UI/Console/UpdateCallbackConsole.cpp17
-rw-r--r--CPP/7zip/UI/Console/UpdateCallbackConsole.h2
-rw-r--r--CPP/7zip/UI/Console/makefile2
-rw-r--r--CPP/7zip/UI/Console/makefile.gcc5
-rw-r--r--CPP/7zip/UI/Explorer/ContextMenu.cpp596
-rw-r--r--CPP/7zip/UI/Explorer/ContextMenu.h72
-rw-r--r--CPP/7zip/UI/Explorer/ContextMenuFlags.h1
-rw-r--r--CPP/7zip/UI/Explorer/DllExportsExplorer.cpp27
-rw-r--r--CPP/7zip/UI/Explorer/Explorer.dsp20
-rw-r--r--CPP/7zip/UI/Explorer/MyExplorerCommand.h173
-rw-r--r--CPP/7zip/UI/Explorer/makefile1
-rw-r--r--CPP/7zip/UI/Explorer/resource.rc2
-rw-r--r--CPP/7zip/UI/Far/ExtractEngine.cpp2
-rw-r--r--CPP/7zip/UI/Far/Far.dsp32
-rw-r--r--CPP/7zip/UI/Far/Plugin.cpp25
-rw-r--r--CPP/7zip/UI/Far/PluginDelete.cpp2
-rw-r--r--CPP/7zip/UI/Far/PluginRead.cpp6
-rw-r--r--CPP/7zip/UI/Far/PluginWrite.cpp16
-rw-r--r--CPP/7zip/UI/Far/makefile4
-rw-r--r--CPP/7zip/UI/FileManager/ClassDefs.cpp1
-rw-r--r--CPP/7zip/UI/FileManager/ExtractCallback.cpp12
-rw-r--r--CPP/7zip/UI/FileManager/ExtractCallback.h1
-rw-r--r--CPP/7zip/UI/FileManager/FM.dsp24
-rw-r--r--CPP/7zip/UI/FileManager/ListViewDialog.rc2
-rw-r--r--CPP/7zip/UI/FileManager/MenuPage.cpp10
-rw-r--r--CPP/7zip/UI/FileManager/MenuPage.rc2
-rw-r--r--CPP/7zip/UI/FileManager/MyCom2.h8
-rw-r--r--CPP/7zip/UI/FileManager/MyLoadMenu.cpp25
-rw-r--r--CPP/7zip/UI/FileManager/MyLoadMenu.h4
-rw-r--r--CPP/7zip/UI/FileManager/Panel.cpp12
-rw-r--r--CPP/7zip/UI/FileManager/Panel.h1
-rw-r--r--CPP/7zip/UI/FileManager/PanelCopy.cpp11
-rw-r--r--CPP/7zip/UI/FileManager/PanelItemOpen.cpp6
-rw-r--r--CPP/7zip/UI/FileManager/PanelListNotify.cpp21
-rw-r--r--CPP/7zip/UI/FileManager/PanelMenu.cpp28
-rw-r--r--CPP/7zip/UI/FileManager/PanelOperations.cpp8
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.cpp129
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.h4
-rw-r--r--CPP/7zip/UI/FileManager/VerCtrl.cpp22
-rw-r--r--CPP/7zip/UI/FileManager/makefile5
-rw-r--r--CPP/7zip/UI/GUI/CompressDialog.cpp977
-rw-r--r--CPP/7zip/UI/GUI/CompressDialog.h167
-rw-r--r--CPP/7zip/UI/GUI/ExtractGUI.cpp20
-rw-r--r--CPP/7zip/UI/GUI/ExtractGUI.h1
-rw-r--r--CPP/7zip/UI/GUI/GUI.cpp27
-rw-r--r--CPP/7zip/UI/GUI/GUI.dsp16
-rw-r--r--CPP/7zip/UI/GUI/HashGUI.cpp6
-rw-r--r--CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp2
-rw-r--r--CPP/7zip/UI/GUI/UpdateGUI.cpp26
-rw-r--r--CPP/7zip/UI/GUI/makefile2
121 files changed, 5698 insertions, 871 deletions
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
index 44c90226..9e846345 100644
--- a/CPP/7zip/Archive/7z/7zCompressionMode.h
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.h
@@ -14,8 +14,10 @@ struct CMethodFull: public CMethodProps
CMethodId Id;
UInt32 NumStreams;
int CodecIndex;
+ UInt32 NumThreads;
+ bool Set_NumThreads;
- CMethodFull(): CodecIndex(-1) {}
+ CMethodFull(): CodecIndex(-1), NumThreads(1), Set_NumThreads(false) {}
bool IsSimpleCoder() const { return NumStreams == 1; }
};
@@ -53,8 +55,12 @@ struct CCompressionMethodMode
#ifndef _7ZIP_ST
UInt32 NumThreads;
+ bool NumThreads_WasForced;
bool MultiThreadMixer;
#endif
+
+ UInt64 MemoryUsageLimit;
+ bool MemoryUsageLimit_WasSet;
bool PasswordIsDefined;
UString Password; // _Wipe
@@ -65,8 +71,11 @@ struct CCompressionMethodMode
, Filter_was_Inserted(false)
#ifndef _7ZIP_ST
, NumThreads(1)
+ , NumThreads_WasForced(false)
, MultiThreadMixer(true)
#endif
+ , MemoryUsageLimit((UInt64)1 << 30)
+ , MemoryUsageLimit_WasSet(false)
, PasswordIsDefined(false)
{}
diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
index 49963241..83b0f18f 100644
--- a/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -175,12 +175,16 @@ HRESULT CEncoder::CreateMixerCoder(
CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
#ifndef _7ZIP_ST
+ if (methodFull.Set_NumThreads)
{
CMyComPtr<ICompressSetCoderMt> setCoderMt;
encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
if (setCoderMt)
{
- RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads));
+ RINOK(setCoderMt->SetNumberOfThreads(
+ /* _options.NumThreads */
+ methodFull.NumThreads
+ ));
}
}
#endif
diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
index 95eba9af..8ca815d4 100644
--- a/CPP/7zip/Archive/7z/7zExtract.cpp
+++ b/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -374,7 +374,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
_7Z_DECODER_CRYPRO_VARS
#if !defined(_7ZIP_ST)
- , true, _numThreads, _memUsage
+ , true, _numThreads, _memUsage_Decompress
#endif
);
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
index cad1ae61..cbc2d028 100644
--- a/CPP/7zip/Archive/7z/7zHandler.h
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -158,12 +158,7 @@ private:
HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);
HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);
- HRESULT SetMainMethod(CCompressionMethodMode &method
- #ifndef _7ZIP_ST
- , UInt32 numThreads
- #endif
- );
-
+ HRESULT SetMainMethod(CCompressionMethodMode &method);
#endif
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index 8bb87341..923ad105 100644
--- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -69,15 +69,12 @@ HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
return PropsMethod_To_FullMethod(methodFull, m);
}
-HRESULT CHandler::SetMainMethod(
- CCompressionMethodMode &methodMode
- #ifndef _7ZIP_ST
- , UInt32 numThreads
- #endif
- )
+
+HRESULT CHandler::SetMainMethod(CCompressionMethodMode &methodMode)
{
methodMode.Bonds = _bonds;
+ // we create local copy of _methods. So we can modify it.
CObjectVector<COneMethodInfo> methods = _methods;
{
@@ -120,19 +117,25 @@ HRESULT CHandler::SetMainMethod(
COneMethodInfo &oneMethodInfo = methods[i];
SetGlobalLevelTo(oneMethodInfo);
+
#ifndef _7ZIP_ST
- CMultiMethodProps::SetMethodThreadsTo(oneMethodInfo, numThreads);
+ const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0);
+ if (!numThreads_WasSpecifiedInMethod)
+ {
+ // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already
+ CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, methodMode.NumThreads);
+ }
#endif
CMethodFull &methodFull = methodMode.Methods.AddNew();
RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
+ methodFull.Set_NumThreads = true;
+ methodFull.NumThreads = methodMode.NumThreads;
+
if (methodFull.Id != k_Copy)
needSolid = true;
- if (_numSolidBytesDefined)
- continue;
-
UInt64 dicSize;
switch (methodFull.Id)
{
@@ -145,9 +148,13 @@ HRESULT CHandler::SetMainMethod(
default: continue;
}
+ UInt64 numSolidBytes;
+
if (methodFull.Id == k_LZMA2)
{
// he we calculate default chunk Size for LZMA2 as defined in LZMA2 encoder code
+ /* lzma2 code use dictionary upo to fake 4 GiB to calculate ChunkSize.
+ So we do same */
UInt64 cs = (UInt64)dicSize << 2;
const UInt32 kMinSize = (UInt32)1 << 20;
const UInt32 kMaxSize = (UInt32)1 << 28;
@@ -157,20 +164,78 @@ HRESULT CHandler::SetMainMethod(
cs += (kMinSize - 1);
cs &= ~(UInt64)(kMinSize - 1);
// we want to use at least 64 chunks (threads) per one solid block.
- _numSolidBytes = cs << 6;
+
+ // here we don't use chunckSize property
+ numSolidBytes = cs << 6;
+
+ // here we get real chunckSize
+ cs = oneMethodInfo.Get_Xz_BlockSize();
+ if (dicSize > cs)
+ dicSize = cs;
+
const UInt64 kSolidBytes_Lzma2_Max = ((UInt64)1 << 34);
- if (_numSolidBytes > kSolidBytes_Lzma2_Max)
- _numSolidBytes = kSolidBytes_Lzma2_Max;
+ if (numSolidBytes > kSolidBytes_Lzma2_Max)
+ numSolidBytes = kSolidBytes_Lzma2_Max;
+
+ methodFull.Set_NumThreads = false; // we don't use ICompressSetCoderMt::SetNumberOfThreads() for LZMA2 encoder
+
+ #ifndef _7ZIP_ST
+ if (!numThreads_WasSpecifiedInMethod
+ && !methodMode.NumThreads_WasForced
+ && methodMode.MemoryUsageLimit_WasSet
+ )
+ {
+ const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads();
+ const UInt32 numBlockThreads_Original = methodMode.NumThreads / lzmaThreads;
+
+ if (numBlockThreads_Original > 1)
+ {
+ /*
+ const UInt32 kNumThreads_Max = 1024;
+ if (numBlockThreads > kNumMaxThreads)
+ numBlockThreads = kNumMaxThreads;
+ */
+
+ UInt32 numBlockThreads = numBlockThreads_Original;
+ const UInt64 lzmaMemUsage = oneMethodInfo.Get_Lzma_MemUsage(false); // solid
+
+ for (; numBlockThreads > 1; numBlockThreads--)
+ {
+ UInt64 size = numBlockThreads * (lzmaMemUsage + cs);
+ UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1;
+ if (cs < ((UInt32)1 << 26)) numPackChunks++;
+ if (cs < ((UInt32)1 << 24)) numPackChunks++;
+ if (cs < ((UInt32)1 << 22)) numPackChunks++;
+ size += numPackChunks * cs;
+ // printf("\nnumBlockThreads = %d, size = %d\n", (unsigned)(numBlockThreads), (unsigned)(size >> 20));
+ if (size <= methodMode.MemoryUsageLimit)
+ break;
+ }
+
+ if (numBlockThreads == 0)
+ numBlockThreads = 1;
+ if (numBlockThreads != numBlockThreads_Original)
+ {
+ const UInt32 numThreads_New = numBlockThreads * lzmaThreads;
+ CMultiMethodProps::SetMethodThreadsTo_Replace(methodFull, numThreads_New);
+ }
+ }
+ }
+ #endif
}
else
{
- _numSolidBytes = (UInt64)dicSize << 7;
- if (_numSolidBytes > kSolidBytes_Max)
- _numSolidBytes = kSolidBytes_Max;
+ numSolidBytes = (UInt64)dicSize << 7;
+ if (numSolidBytes > kSolidBytes_Max)
+ numSolidBytes = kSolidBytes_Max;
}
- if (_numSolidBytes < kSolidBytes_Min)
- _numSolidBytes = kSolidBytes_Min;
+ if (_numSolidBytesDefined)
+ continue;
+
+ if (numSolidBytes < kSolidBytes_Min)
+ numSolidBytes = kSolidBytes_Min;
+ _numSolidBytes = numSolidBytes;
_numSolidBytesDefined = true;
}
@@ -182,9 +247,13 @@ HRESULT CHandler::SetMainMethod(
_numSolidBytes = 0;
}
_numSolidBytesDefined = true;
+
+
return S_OK;
}
+
+
static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, unsigned index, PROPID propID, UInt64 &ft, bool &ftDefined)
{
// ft = 0;
@@ -576,22 +645,28 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CCompressionMethodMode methodMode, headerMethod;
- HRESULT res = SetMainMethod(methodMode
- #ifndef _7ZIP_ST
- , _numThreads
- #endif
- );
- RINOK(res);
+ methodMode.MemoryUsageLimit = _memUsage_Compress;
+ methodMode.MemoryUsageLimit_WasSet = _memUsage_WasSet;
- RINOK(SetHeaderMethod(headerMethod));
-
#ifndef _7ZIP_ST
- methodMode.NumThreads = _numThreads;
- methodMode.MultiThreadMixer = _useMultiThreadMixer;
- headerMethod.NumThreads = 1;
- headerMethod.MultiThreadMixer = _useMultiThreadMixer;
+ {
+ UInt32 numThreads = _numThreads;
+ const UInt32 kNumThreads_Max = 1024;
+ if (numThreads > kNumThreads_Max)
+ numThreads = kNumThreads_Max;
+ methodMode.NumThreads = numThreads;
+ methodMode.NumThreads_WasForced = _numThreads_WasForced;
+ methodMode.MultiThreadMixer = _useMultiThreadMixer;
+ // headerMethod.NumThreads = 1;
+ headerMethod.MultiThreadMixer = _useMultiThreadMixer;
+ }
#endif
+ HRESULT res = SetMainMethod(methodMode);
+ RINOK(res);
+
+ RINOK(SetHeaderMethod(headerMethod));
+
CMyComPtr<ICryptoGetTextPassword2> getPassword2;
updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2);
diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp
index 972a766a..bd673fcc 100644
--- a/CPP/7zip/Archive/Common/HandlerOut.cpp
+++ b/CPP/7zip/Archive/Common/HandlerOut.cpp
@@ -70,15 +70,22 @@ bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIAN
if (name.IsPrefixedBy_Ascii_NoCase("mt"))
{
#ifndef _7ZIP_ST
- hres = ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads);
+ _numThreads = _numProcessors;
+ _numThreads_WasForced = false;
+ hres = ParseMtProp2(name.Ptr(2), value, _numThreads, _numThreads_WasForced);
+ // "mt" means "_numThreads_WasForced = false" here
#endif
return true;
}
if (name.IsPrefixedBy_Ascii_NoCase("memuse"))
{
- if (!ParseSizeString(name.Ptr(6), value, _memAvail, _memUsage))
+ UInt64 v;
+ if (!ParseSizeString(name.Ptr(6), value, _memAvail, v))
hres = E_INVALIDARG;
+ _memUsage_Decompress = v;
+ _memUsage_Compress = v;
+ _memUsage_WasSet = true;
return true;
}
@@ -88,12 +95,24 @@ bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIAN
#ifndef EXTRACT_ONLY
-static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value)
+static void SetMethodProp32(CMethodProps &m, PROPID propID, UInt32 value)
{
if (m.FindProp(propID) < 0)
m.AddProp32(propID, value);
}
+static void SetMethodProp32_Replace(CMethodProps &m, PROPID propID, UInt32 value)
+{
+ const int i = m.FindProp(propID);
+ if (i >= 0)
+ {
+ NWindows::NCOM::CPropVariant &val = m.Props[(unsigned)i].Value;
+ val = (UInt32)value;
+ return;
+ }
+ m.AddProp32(propID, value);
+}
+
void CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const
{
UInt32 level = _level;
@@ -102,10 +121,15 @@ void CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const
}
#ifndef _7ZIP_ST
-void CMultiMethodProps::SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads)
+void CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(CMethodProps &oneMethodInfo, UInt32 numThreads)
{
SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
}
+
+void CMultiMethodProps::SetMethodThreadsTo_Replace(CMethodProps &oneMethodInfo, UInt32 numThreads)
+{
+ SetMethodProp32_Replace(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
+}
#endif
void CMultiMethodProps::InitMulti()
diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h
index bbb4336e..619def42 100644
--- a/CPP/7zip/Archive/Common/HandlerOut.h
+++ b/CPP/7zip/Archive/Common/HandlerOut.h
@@ -18,15 +18,26 @@ protected:
{
#ifndef _7ZIP_ST
_numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
+ _numThreads_WasForced = false;
#endif
UInt64 memAvail = (UInt64)(sizeof(size_t)) << 28;
_memAvail = memAvail;
- _memUsage = memAvail;
- if (NWindows::NSystem::GetRamSize(memAvail))
+ _memUsage_Compress = memAvail;
+ _memUsage_Decompress = memAvail;
+ _memUsage_WasSet = NWindows::NSystem::GetRamSize(memAvail);
+ if (_memUsage_WasSet)
{
_memAvail = memAvail;
- _memUsage = memAvail / 32 * 17;
+ unsigned bits = sizeof(size_t) * 8;
+ if (bits == 32)
+ {
+ const UInt32 limit2 = (UInt32)7 << 28;
+ if (memAvail > limit2)
+ memAvail = limit2;
+ }
+ _memUsage_Compress = memAvail / 32 * 28;
+ _memUsage_Decompress = memAvail / 32 * 17;
}
}
@@ -34,9 +45,12 @@ public:
#ifndef _7ZIP_ST
UInt32 _numThreads;
UInt32 _numProcessors;
+ bool _numThreads_WasForced;
#endif
- UInt64 _memUsage;
+ bool _memUsage_WasSet;
+ UInt64 _memUsage_Compress;
+ UInt64 _memUsage_Decompress;
UInt64 _memAvail;
bool SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres);
@@ -63,7 +77,8 @@ public:
void SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const;
#ifndef _7ZIP_ST
- static void SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads);
+ static void SetMethodThreadsTo_IfNotFinded(CMethodProps &props, UInt32 numThreads);
+ static void SetMethodThreadsTo_Replace(CMethodProps &props, UInt32 numThreads);
#endif
diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp
index 57313280..b70a291f 100644
--- a/CPP/7zip/Archive/HfsHandler.cpp
+++ b/CPP/7zip/Archive/HfsHandler.cpp
@@ -1513,6 +1513,9 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
*propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE;
return S_OK;
}
+ #else
+ UNUSED_VAR(index);
+ UNUSED_VAR(propID);
#endif
return S_OK;
}
diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h
index 8290c735..6df76d26 100644
--- a/CPP/7zip/Archive/IArchive.h
+++ b/CPP/7zip/Archive/IArchive.h
@@ -59,6 +59,7 @@ namespace NArcInfoFlags
const UInt32 kSymLinks = 1 << 10; // the handler supports symbolic links
const UInt32 kHardLinks = 1 << 11; // the handler supports hard links
const UInt32 kByExtOnlyOpen = 1 << 12; // call handler only if file extension matches
+ const UInt32 kHashHandler = 1 << 13; // the handler contains the hashes (checksums)
}
namespace NArchive
@@ -91,7 +92,8 @@ namespace NArchive
{
kExtract = 0,
kTest,
- kSkip
+ kSkip,
+ kReadExternal
};
}
@@ -458,7 +460,8 @@ namespace NUpdateNotifyOp
kRepack,
kSkip,
kDelete,
- kHeader
+ kHeader,
+ kHashRead
// kNumDefined
};
@@ -481,6 +484,14 @@ ARCHIVE_INTERFACE(IArchiveUpdateCallbackFile, 0x83)
};
+#define INTERFACE_IArchiveGetDiskProperty(x) \
+ STDMETHOD(GetDiskProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
+
+ARCHIVE_INTERFACE(IArchiveGetDiskProperty, 0x84)
+{
+ INTERFACE_IArchiveGetDiskProperty(PURE);
+};
+
/*
UpdateItems()
-------------
diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp
index bc00e3fc..c1073092 100644
--- a/CPP/7zip/Archive/Tar/TarHandler.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandler.cpp
@@ -763,6 +763,9 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
_forceCodePage = true;
_curCodePage = _specifiedCodePage = cp;
}
+ else if (name.IsPrefixedBy_Ascii_NoCase("mt"))
+ {
+ }
else
return E_INVALIDARG;
}
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp
index 520ceeea..04d9228f 100644
--- a/CPP/7zip/Archive/Udf/UdfIn.cpp
+++ b/CPP/7zip/Archive/Udf/UdfIn.cpp
@@ -109,7 +109,7 @@ static UString ParseDString(const Byte *data, unsigned size)
}
}
else
- return UString("[unknow]");
+ return UString("[unknown]");
*p = 0;
res.ReleaseBuf_SetLen((unsigned)(p - (const wchar_t *)res));
}
diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp
index 2553c175..b25d51c2 100644
--- a/CPP/7zip/Archive/Wim/WimHandler.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandler.cpp
@@ -877,8 +877,10 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal
curStream = inStream;
else
{
- UString fullName = seqName.GetNextName(i);
- HRESULT result = openVolumeCallback->GetStream(fullName, &curStream);
+ if (!openVolumeCallback)
+ continue;
+ const UString fullName = seqName.GetNextName(i);
+ const HRESULT result = openVolumeCallback->GetStream(fullName, &curStream);
if (result == S_FALSE)
continue;
if (result != S_OK)
diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp
index 35dd607a..b5a1972d 100644
--- a/CPP/7zip/Archive/XarHandler.cpp
+++ b/CPP/7zip/Archive/XarHandler.cpp
@@ -151,7 +151,8 @@ IMP_IInArchive_ArcProps
#define PARSE_NUM(_num_, _dest_) \
{ const char *end; _dest_ = ConvertStringToUInt32(p, &end); \
- if ((unsigned)(end - p) != _num_) return 0; p += _num_ + 1; }
+ if ((unsigned)(end - p) != _num_) return 0; \
+ p += _num_ + 1; }
static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res)
{
diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
index 2803f6a8..f1afab66 100644
--- a/CPP/7zip/Archive/XzHandler.cpp
+++ b/CPP/7zip/Archive/XzHandler.cpp
@@ -117,7 +117,7 @@ class CHandler:
#ifndef _7ZIP_ST
decoder._numThreads = _numThreads;
#endif
- decoder._memUsage = _memUsage;
+ decoder._memUsage = _memUsage_Decompress;
HRESULT hres = decoder.Decode(seqInStream, outStream,
NULL, // *outSizeLimit
@@ -1129,14 +1129,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (IntToBool(newData))
{
- UInt64 size;
+ UInt64 dataSize;
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
if (prop.vt != VT_UI8)
return E_INVALIDARG;
- size = prop.uhVal.QuadPart;
- RINOK(updateCallback->SetTotal(size));
+ dataSize = prop.uhVal.QuadPart;
+ RINOK(updateCallback->SetTotal(dataSize));
}
NCompress::NXz::CEncoder *encoderSpec = new NCompress::NXz::CEncoder;
@@ -1147,17 +1147,79 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
lzma2Props.lzmaProps.level = GetLevel();
- xzProps.reduceSize = size;
+ xzProps.reduceSize = dataSize;
/*
{
- NCOM::CPropVariant prop = (UInt64)size;
+ NCOM::CPropVariant prop = (UInt64)dataSize;
RINOK(encoderSpec->SetCoderProp(NCoderPropID::kReduceSize, prop));
}
*/
#ifndef _7ZIP_ST
- xzProps.numTotalThreads = (int)_numThreads;
- #endif
+
+ UInt32 numThreads = _numThreads;
+
+ const UInt32 kNumThreads_Max = 1024;
+ if (numThreads > kNumThreads_Max)
+ numThreads = kNumThreads_Max;
+
+ if (!_numThreads_WasForced
+ && _numThreads >= 1
+ && _memUsage_WasSet)
+ {
+ COneMethodInfo oneMethodInfo;
+ if (!_methods.IsEmpty())
+ oneMethodInfo = _methods[0];
+
+ SetGlobalLevelTo(oneMethodInfo);
+
+ const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0);
+ if (!numThreads_WasSpecifiedInMethod)
+ {
+ // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already
+ CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, numThreads);
+ }
+
+ UInt64 cs = _numSolidBytes;
+ if (cs != XZ_PROPS__BLOCK_SIZE__AUTO)
+ oneMethodInfo.AddProp_BlockSize2(cs);
+ cs = oneMethodInfo.Get_Xz_BlockSize();
+
+ if (cs != XZ_PROPS__BLOCK_SIZE__AUTO &&
+ cs != XZ_PROPS__BLOCK_SIZE__SOLID)
+ {
+ const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads();
+ const UInt32 numBlockThreads_Original = numThreads / lzmaThreads;
+
+ if (numBlockThreads_Original > 1)
+ {
+ UInt32 numBlockThreads = numBlockThreads_Original;
+ {
+ const UInt64 lzmaMemUsage = oneMethodInfo.Get_Lzma_MemUsage(false);
+ for (; numBlockThreads > 1; numBlockThreads--)
+ {
+ UInt64 size = numBlockThreads * (lzmaMemUsage + cs);
+ UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1;
+ if (cs < ((UInt32)1 << 26)) numPackChunks++;
+ if (cs < ((UInt32)1 << 24)) numPackChunks++;
+ if (cs < ((UInt32)1 << 22)) numPackChunks++;
+ size += numPackChunks * cs;
+ // printf("\nnumBlockThreads = %d, size = %d\n", (unsigned)(numBlockThreads), (unsigned)(size >> 20));
+ if (size <= _memUsage_Compress)
+ break;
+ }
+ }
+ if (numBlockThreads == 0)
+ numBlockThreads = 1;
+ if (numBlockThreads != numBlockThreads_Original)
+ numThreads = numBlockThreads * lzmaThreads;
+ }
+ }
+ }
+ xzProps.numTotalThreads = (int)numThreads;
+
+ #endif // _7ZIP_ST
+
xzProps.blockSize = _numSolidBytes;
if (_numSolidBytes == XZ_PROPS__BLOCK_SIZE__SOLID)
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp
index 72a77cb7..d8168bbe 100644
--- a/CPP/7zip/Archive/Zip/ZipHandler.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp
@@ -1665,7 +1665,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
m_Archive, item, realOutStream, extractCallback,
progress,
#ifndef _7ZIP_ST
- _props._numThreads, _props._memUsage,
+ _props._numThreads, _props._memUsage_Decompress,
#endif
res);
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
index 880ff218..076d6bb5 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.cpp
+++ b/CPP/7zip/Archive/Zip/ZipIn.cpp
@@ -989,7 +989,8 @@ bool CInArchive::ReadFileName(unsigned size, AString &s)
bool CInArchive::ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlock &extra,
- UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk)
+ UInt64 &unpackSize, UInt64 &packSize,
+ CItem *cdItem)
{
extra.Clear();
@@ -1017,18 +1018,40 @@ bool CInArchive::ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlo
{
extra.IsZip64 = true;
bool isOK = true;
+
+ if (!cdItem
+ && size == 16
+ && !ZIP64_IS_32_MAX(unpackSize)
+ && !ZIP64_IS_32_MAX(packSize))
+ {
+ /* Win10 Explorer's "Send to Zip" for big (3500 MiB) files
+ creates Zip64 Extra in local file header.
+ But if both uncompressed and compressed sizes are smaller than 4 GiB,
+ Win10 doesn't store 0xFFFFFFFF in 32-bit fields as expected by zip specification.
+ 21.04: we ignore these minor errors in Win10 zip archives. */
+ if (ReadUInt64() != unpackSize)
+ isOK = false;
+ if (ReadUInt64() != packSize)
+ isOK = false;
+ size = 0;
+ }
+ else
+ {
+ if (ZIP64_IS_32_MAX(unpackSize))
+ { if (size < 8) isOK = false; else { size -= 8; unpackSize = ReadUInt64(); }}
- if (ZIP64_IS_32_MAX(unpackSize))
- { if (size < 8) isOK = false; else { size -= 8; unpackSize = ReadUInt64(); }}
-
- if (isOK && ZIP64_IS_32_MAX(packSize))
- { if (size < 8) isOK = false; else { size -= 8; packSize = ReadUInt64(); }}
-
- if (isOK && ZIP64_IS_32_MAX(localOffset))
- { if (size < 8) isOK = false; else { size -= 8; localOffset = ReadUInt64(); }}
+ if (isOK && ZIP64_IS_32_MAX(packSize))
+ { if (size < 8) isOK = false; else { size -= 8; packSize = ReadUInt64(); }}
- if (isOK && ZIP64_IS_16_MAX(disk))
- { if (size < 4) isOK = false; else { size -= 4; disk = ReadUInt32(); }}
+ if (cdItem)
+ {
+ if (isOK && ZIP64_IS_32_MAX(cdItem->LocalHeaderPos))
+ { if (size < 8) isOK = false; else { size -= 8; cdItem->LocalHeaderPos = ReadUInt64(); }}
+
+ if (isOK && ZIP64_IS_16_MAX(cdItem->Disk))
+ { if (size < 4) isOK = false; else { size -= 4; cdItem->Disk = ReadUInt32(); }}
+ }
+ }
if (!isOK || size != 0)
{
@@ -1100,9 +1123,7 @@ bool CInArchive::ReadLocalItem(CItemEx &item)
if (extraSize > 0)
{
- UInt64 localOffset = 0;
- UInt32 disk = 0;
- if (!ReadExtra(item, extraSize, item.LocalExtra, item.Size, item.PackSize, localOffset, disk))
+ if (!ReadExtra(item, extraSize, item.LocalExtra, item.Size, item.PackSize, NULL))
{
/* Most of archives are OK for Extra. But there are some rare cases
that have error. And if error in first item, it can't open archive.
@@ -1557,7 +1578,7 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item)
ReadFileName(nameSize, item.Name);
if (extraSize > 0)
- ReadExtra(item, extraSize, item.CentralExtra, item.Size, item.PackSize, item.LocalHeaderPos, item.Disk);
+ ReadExtra(item, extraSize, item.CentralExtra, item.Size, item.PackSize, &item);
// May be these strings must be deleted
/*
diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h
index 31e524b6..1498afed 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.h
+++ b/CPP/7zip/Archive/Zip/ZipIn.h
@@ -312,7 +312,7 @@ class CInArchive
bool ReadFileName(unsigned nameSize, AString &dest);
bool ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlock &extra,
- UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk);
+ UInt64 &unpackSize, UInt64 &packSize, CItem *cdItem);
bool ReadLocalItem(CItemEx &item);
HRESULT FindDescriptor(CItemEx &item, unsigned numFiles);
HRESULT ReadCdItem(CItemEx &item);
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index 4468c7c5..26636c78 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -773,7 +773,7 @@ static HRESULT Update2(
if (numThreads < 1)
numThreads = 1;
- const size_t kMemPerThread = (size_t)1 << 25;
+ const size_t kMemPerThread = (size_t)sizeof(size_t) << 23;
const size_t kBlockSize = 1 << 16;
bool mtMode = (numThreads > 1);
@@ -791,6 +791,7 @@ static HRESULT Update2(
if (onem.FindProp(NCoderPropID::kNumThreads) < 0)
{
+ // fixme: we should check the number of threads for xz mehod also
// fixed for 9.31. bzip2 default is just one thread.
onem.AddProp_NumThreads(numThreads);
}
@@ -801,8 +802,8 @@ static HRESULT Update2(
if (method == NFileHeader::NCompressionMethod::kStore && !options.PasswordIsDefined)
numThreads = 1;
- if (oneMethodMain)
- {
+ if (oneMethodMain)
+ {
if (method == NFileHeader::NCompressionMethod::kBZip2)
{
@@ -828,6 +829,7 @@ static HRESULT Update2(
int numXzThreads = oneMethodMain->Get_Xz_NumThreads(numLzmaThreads);
if (numXzThreads < 0)
{
+ // numXzThreads is unknown
const UInt64 averageSize = numBytesToCompress / numFilesToCompress;
const UInt64 blockSize = oneMethodMain->Get_Xz_BlockSize();
UInt64 averageNumberOfBlocks = 1;
@@ -844,18 +846,52 @@ static HRESULT Update2(
}
numThreads /= (unsigned)numXzThreads;
}
+ else if (
+ method == NFileHeader::NCompressionMethod::kDeflate
+ || method == NFileHeader::NCompressionMethod::kDeflate64
+ || method == NFileHeader::NCompressionMethod::kPPMd)
+ {
+ if (numThreads > 1
+ && options._memUsage_WasSet
+ && !options._numThreads_WasForced)
+ {
+ UInt64 methodMemUsage;
+ if (method == NFileHeader::NCompressionMethod::kPPMd)
+ methodMemUsage = oneMethodMain->Get_Ppmd_MemSize();
+ else
+ methodMemUsage = (4 << 20); // for deflate
+ const UInt64 threadMemUsage = kMemPerThread + methodMemUsage;
+ const UInt64 numThreads64 = options._memUsage_Compress / threadMemUsage;
+ if (numThreads64 < numThreads)
+ numThreads = (UInt32)numThreads64;
+ }
+ }
else if (method == NFileHeader::NCompressionMethod::kLZMA)
{
// we suppose that default LZMA is 2 thread. So we don't change it
- UInt32 numLZMAThreads = oneMethodMain->Get_Lzma_NumThreads();
+ const UInt32 numLZMAThreads = oneMethodMain->Get_Lzma_NumThreads();
numThreads /= numLZMAThreads;
+
+ if (numThreads > 1
+ && options._memUsage_WasSet
+ && !options._numThreads_WasForced)
+ {
+ const UInt64 methodMemUsage = oneMethodMain->Get_Lzma_MemUsage(true);
+ const UInt64 threadMemUsage = kMemPerThread + methodMemUsage;
+ const UInt64 numThreads64 = options._memUsage_Compress / threadMemUsage;
+ if (numThreads64 < numThreads)
+ numThreads = (UInt32)numThreads64;
+ }
}
- }
+ } // (oneMethodMain)
if (numThreads > numFilesToCompress)
numThreads = (UInt32)numFilesToCompress;
if (numThreads <= 1)
+ {
mtMode = false;
+ numThreads = 1;
+ }
}
// mtMode = true; // to test mtMode for seqMode
diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp
index 7a1f79df..84d3cdf7 100644
--- a/CPP/7zip/Bundles/Alone/Alone.dsp
+++ b/CPP/7zip/Bundles/Alone/Alone.dsp
@@ -294,6 +294,14 @@ SOURCE=..\..\..\Common\DynamicBuffer.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\DynLimBuf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\DynLimBuf.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\IntToString.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile
index ca3392db..cc4b29ed 100644
--- a/CPP/7zip/Bundles/Alone/makefile
+++ b/CPP/7zip/Bundles/Alone/makefile
@@ -7,6 +7,7 @@ COMMON_OBJS = \
$O\CommandLineParser.obj \
$O\CRC.obj \
$O\CrcReg.obj \
+ $O\DynLimBuf.obj \
$O\IntToString.obj \
$O\ListFileUtils.obj \
$O\LzFindPrepare.obj \
diff --git a/CPP/7zip/Bundles/Alone/makefile.gcc b/CPP/7zip/Bundles/Alone/makefile.gcc
index 182e9a7c..38f8d593 100644
--- a/CPP/7zip/Bundles/Alone/makefile.gcc
+++ b/CPP/7zip/Bundles/Alone/makefile.gcc
@@ -108,6 +108,7 @@ COMMON_OBJS = \
$O/CommandLineParser.o \
$O/CRC.o \
$O/CrcReg.o \
+ $O/DynLimBuf.o \
$O/IntToString.o \
$O/ListFileUtils.o \
$O/LzFindPrepare.o \
diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsp b/CPP/7zip/Bundles/Alone7z/Alone.dsp
index a15a5bfa..76607fdd 100644
--- a/CPP/7zip/Bundles/Alone7z/Alone.dsp
+++ b/CPP/7zip/Bundles/Alone7z/Alone.dsp
@@ -290,6 +290,14 @@ SOURCE=..\..\..\Common\DynamicBuffer.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\DynLimBuf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\DynLimBuf.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\IntToString.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile
index 0a68e141..f87684c7 100644
--- a/CPP/7zip/Bundles/Alone7z/makefile
+++ b/CPP/7zip/Bundles/Alone7z/makefile
@@ -8,6 +8,7 @@ COMMON_OBJS = \
$O\CommandLineParser.obj \
$O\CRC.obj \
$O\CrcReg.obj \
+ $O\DynLimBuf.obj \
$O\IntToString.obj \
$O\ListFileUtils.obj \
$O\LzFindPrepare.obj \
diff --git a/CPP/7zip/Bundles/Alone7z/makefile.gcc b/CPP/7zip/Bundles/Alone7z/makefile.gcc
index c1d6ac50..8565452b 100644
--- a/CPP/7zip/Bundles/Alone7z/makefile.gcc
+++ b/CPP/7zip/Bundles/Alone7z/makefile.gcc
@@ -73,6 +73,7 @@ LOCAL_FLAGS = \
CONSOLE_OBJS = \
$O/BenchCon.o \
$O/ConsoleClose.o \
+ $O/DynLimBuf.o \
$O/ExtractCallbackConsole.o \
$O/HashCon.o \
$O/List.o \
diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp
index 86d788f0..54efba98 100644
--- a/CPP/7zip/Bundles/Fm/FM.dsp
+++ b/CPP/7zip/Bundles/Fm/FM.dsp
@@ -1084,6 +1084,20 @@ SOURCE=..\..\..\..\C\MtDec.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Sha1.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Sha1.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Sha1Opt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Sha256.c
!IF "$(CFG)" == "FM - Win32 Release"
@@ -1133,6 +1147,16 @@ SOURCE=..\..\..\..\C\Threads.c
SOURCE=..\..\..\..\C\Threads.h
# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\XzCrc64.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\XzCrc64Opt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
# End Group
# Begin Group "Windows"
@@ -1483,6 +1507,14 @@ SOURCE=..\..\..\Common\DynamicBuffer.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\DynLimBuf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\DynLimBuf.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\Exception.h
# End Source File
# Begin Source File
@@ -1563,10 +1595,22 @@ SOURCE=..\..\..\Common\Random.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\Sha1Prepare.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Sha1Reg.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\Sha256Prepare.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\Sha256Reg.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\StringConvert.cpp
# End Source File
# Begin Source File
@@ -1601,6 +1645,14 @@ SOURCE=..\..\..\Common\Wildcard.cpp
SOURCE=..\..\..\Common\Wildcard.h
# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\XzCrc64Init.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\XzCrc64Reg.cpp
+# End Source File
# End Group
# Begin Group "UI"
diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
index c80736de..8e1a70d2 100644
--- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
+++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp
@@ -537,6 +537,14 @@ SOURCE=..\..\..\Windows\Control\ListView.h
# End Group
# Begin Source File
+SOURCE=..\..\..\Windows\Clipboard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Clipboard.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Windows\CommonDialog.cpp
# End Source File
# Begin Source File
@@ -593,6 +601,14 @@ SOURCE=..\..\..\Windows\FileName.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Windows\MemoryGlobal.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\MemoryGlobal.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Windows\PropVariant.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile
index 57d922fb..0ed36f8a 100644
--- a/CPP/7zip/Bundles/SFXWin/makefile
+++ b/CPP/7zip/Bundles/SFXWin/makefile
@@ -31,6 +31,7 @@ COMMON_OBJS = \
$O\Wildcard.obj \
WIN_OBJS = \
+ $O\Clipboard.obj \
$O\CommonDialog.obj \
$O\DLL.obj \
$O\ErrorMsg.obj \
@@ -38,6 +39,7 @@ WIN_OBJS = \
$O\FileFind.obj \
$O\FileIO.obj \
$O\FileName.obj \
+ $O\MemoryGlobal.obj \
$O\PropVariant.obj \
$O\PropVariantConv.obj \
$O\ResourceString.obj \
diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp
index e62bb0b4..872f17fc 100644
--- a/CPP/7zip/Common/CreateCoder.cpp
+++ b/CPP/7zip/Common/CreateCoder.cpp
@@ -118,6 +118,7 @@ HRESULT CExternalCodecs::Load()
}
RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));
RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));
+ RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kIsFilter, info.IsFilter));
Codecs.Add(info);
}
diff --git a/CPP/7zip/Common/CreateCoder.h b/CPP/7zip/Common/CreateCoder.h
index 20d0ef33..24e6b663 100644
--- a/CPP/7zip/Common/CreateCoder.h
+++ b/CPP/7zip/Common/CreateCoder.h
@@ -35,8 +35,9 @@ struct CCodecInfoEx
UInt32 NumStreams;
bool EncoderIsAssigned;
bool DecoderIsAssigned;
+ bool IsFilter; // it's unused
- CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {}
+ CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false), IsFilter(false) {}
};
struct CHasherInfoEx
diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp
index 3ab89ddb..a55c49f9 100644
--- a/CPP/7zip/Common/MethodProps.cpp
+++ b/CPP/7zip/Common/MethodProps.cpp
@@ -53,7 +53,7 @@ static unsigned ParseStringToUInt64(const UString &srcString, UInt64 &number)
HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
{
// =VT_UI4
- // =VT_EMPTY
+ // =VT_EMPTY : it doesn't change (resValue), and returns S_OK
// {stringUInt32}=VT_EMPTY
if (prop.vt == VT_UI4)
@@ -74,31 +74,92 @@ HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &
return S_OK;
}
-HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)
+
+
+HRESULT ParseMtProp2(const UString &name, const PROPVARIANT &prop, UInt32 &numThreads, bool &force)
{
+ force = false;
+ UString s;
if (name.IsEmpty())
{
- switch (prop.vt)
+ if (prop.vt == VT_UI4)
{
- case VT_UI4:
- numThreads = prop.ulVal;
- break;
- default:
+ numThreads = prop.ulVal;
+ force = true;
+ return S_OK;
+ }
+ bool val;
+ HRESULT res = PROPVARIANT_to_bool(prop, val);
+ if (res == S_OK)
+ {
+ if (!val)
{
- bool val;
- RINOK(PROPVARIANT_to_bool(prop, val));
- numThreads = (val ? defaultNumThreads : 1);
- break;
+ numThreads = 1;
+ force = true;
}
+ // force = true; for debug
+ // "(VT_BOOL = VARIANT_TRUE)" set "force = false" and doesn't change numThreads
+ return S_OK;
}
- return S_OK;
+ if (prop.vt != VT_BSTR)
+ return res;
+ s.SetFromBstr(prop.bstrVal);
+ if (s.IsEmpty())
+ return E_INVALIDARG;
}
- if (prop.vt != VT_EMPTY)
- return E_INVALIDARG;
- return ParsePropToUInt32(name, prop, numThreads);
+ else
+ {
+ if (prop.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ s = name;
+ }
+
+ s.MakeLower_Ascii();
+ const wchar_t *start = s;
+ UInt32 v = numThreads;
+
+ /* we force up, if threads number specified
+ only `d` will force it down */
+ bool force_loc = true;
+ for (;;)
+ {
+ const wchar_t c = *start;
+ if (!c)
+ break;
+ if (c == 'd')
+ {
+ force_loc = false; // force down
+ start++;
+ continue;
+ }
+ if (c == 'u')
+ {
+ force_loc = true; // force up
+ start++;
+ continue;
+ }
+ bool isPercent = false;
+ if (c == 'p')
+ {
+ isPercent = true;
+ start++;
+ }
+ const wchar_t *end;
+ v = ConvertStringToUInt32(start, &end);
+ if (end == start)
+ return E_INVALIDARG;
+ if (isPercent)
+ v = numThreads * v / 100;
+ start = end;
+ }
+
+ numThreads = v;
+ force = force_loc;
+ return S_OK;
}
+
static HRESULT SetLogSizeProp(UInt64 number, NCOM::CPropVariant &destProp)
{
if (number >= 64)
@@ -263,9 +324,9 @@ HRESULT CProps::SetCoderProps_DSReduce_Aff(
int CMethodProps::FindProp(PROPID id) const
{
- for (int i = (int)Props.Size() - 1; i >= 0; i--)
- if (Props[(unsigned)i].Id == id)
- return i;
+ for (unsigned i = Props.Size(); i != 0;)
+ if (Props[--i].Id == id)
+ return (int)i;
return -1;
}
@@ -511,6 +572,59 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const
return S_OK;
}
+
+static UInt64 GetMemoryUsage_LZMA(UInt32 dict, bool isBt, UInt32 numThreads)
+{
+ UInt32 hs = dict - 1;
+ hs |= (hs >> 1);
+ hs |= (hs >> 2);
+ hs |= (hs >> 4);
+ hs |= (hs >> 8);
+ hs >>= 1;
+ if (hs >= (1 << 24))
+ hs >>= 1;
+ hs |= (1 << 16) - 1;
+ // if (numHashBytes >= 5)
+ if (!isBt)
+ hs |= (256 << 10) - 1;
+ hs++;
+ UInt64 size1 = (UInt64)hs * 4;
+ size1 += (UInt64)dict * 4;
+ if (isBt)
+ size1 += (UInt64)dict * 4;
+ size1 += (2 << 20);
+
+ if (numThreads > 1 && isBt)
+ size1 += (2 << 20) + (4 << 20);
+ return size1;
+}
+
+static const UInt32 kLzmaMaxDictSize = (UInt32)15 << 28;
+
+UInt64 CMethodProps::Get_Lzma_MemUsage(bool addSlidingWindowSize) const
+{
+ const UInt64 dicSize = Get_Lzma_DicSize();
+ const bool isBt = Get_Lzma_MatchFinder_IsBt();
+ const UInt32 dict32 = (dicSize >= kLzmaMaxDictSize ? kLzmaMaxDictSize : (UInt32)dicSize);
+ const UInt32 numThreads = Get_Lzma_NumThreads();
+ UInt64 size = GetMemoryUsage_LZMA(dict32, isBt, numThreads);
+
+ if (addSlidingWindowSize)
+ {
+ const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)(1 << 16);
+ UInt64 blockSize = (UInt64)dict32 + (1 << 16)
+ + (numThreads > 1 ? (1 << 20) : 0);
+ blockSize += (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2));
+ if (blockSize >= kBlockSizeMax)
+ blockSize = kBlockSizeMax;
+ size += blockSize;
+ }
+ return size;
+}
+
+
+
+
HRESULT COneMethodInfo::ParseMethodFromString(const UString &s)
{
MethodName.Empty();
diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h
index bd9283f0..aea75a3e 100644
--- a/CPP/7zip/Common/MethodProps.h
+++ b/CPP/7zip/Common/MethodProps.h
@@ -12,12 +12,27 @@
#include "../ICoder.h"
+// UInt64 GetMemoryUsage_LZMA(UInt32 dict, bool isBt, UInt32 numThreads);
+
bool StringToBool(const wchar_t *s, bool &res);
HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest);
unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number);
+
+/*
+if (name.IsEmpty() && prop.vt == VT_EMPTY), it doesn't change (resValue) and returns S_OK.
+ So you must set (resValue) for default value before calling */
HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
-HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);
+/* input: (numThreads = the_number_of_processors) */
+HRESULT ParseMtProp2(const UString &name, const PROPVARIANT &prop, UInt32 &numThreads, bool &force);
+
+inline HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 numCPUs, UInt32 &numThreads)
+{
+ bool forced = false;
+ numThreads = numCPUs;
+ return ParseMtProp2(name, prop, numThreads, forced);
+}
+
struct CProp
{
@@ -123,9 +138,21 @@ public:
return dictSize;
}
+ bool Get_Lzma_MatchFinder_IsBt() const
+ {
+ const int i = FindProp(NCoderPropID::kMatchFinder);
+ if (i >= 0)
+ {
+ const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;
+ if (val.vt == VT_BSTR)
+ return ((val.bstrVal[0] | 0x20) != 'h'); // check for "hc"
+ }
+ return GetLevel() >= 5;
+ }
+
bool Get_Lzma_Eos() const
{
- int i = FindProp(NCoderPropID::kEndMarker);
+ const int i = FindProp(NCoderPropID::kEndMarker);
if (i >= 0)
{
const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;
@@ -153,6 +180,9 @@ public:
return 2;
}
+ UInt64 Get_Lzma_MemUsage(bool addSlidingWindowSize) const;
+
+ /* returns -1, if numThreads is unknown */
int Get_Xz_NumThreads(UInt32 &lzmaThreads) const
{
lzmaThreads = 1;
@@ -191,6 +221,7 @@ public:
const UInt32 kMinSize = (UInt32)1 << 20;
const UInt32 kMaxSize = (UInt32)1 << 28;
const UInt64 dictSize = Get_Lzma_DicSize();
+ /* lzma2 code uses fake 4 GiB to calculate ChunkSize. So we do same */
UInt64 blockSize = (UInt64)dictSize << 2;
if (blockSize < kMinSize) blockSize = kMinSize;
if (blockSize > kMaxSize) blockSize = kMaxSize;
@@ -268,6 +299,17 @@ public:
AddPropBool(NCoderPropID::kEndMarker, eos);
}
+ void AddProp_BlockSize2(UInt64 blockSize2)
+ {
+ if (FindProp(NCoderPropID::kBlockSize2) < 0)
+ {
+ CProp &prop = Props.AddNew();
+ prop.IsOptional = true;
+ prop.Id = NCoderPropID::kBlockSize2;
+ prop.Value = blockSize2;
+ }
+ }
+
HRESULT ParseParamsFromString(const UString &srcString);
HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);
};
diff --git a/CPP/7zip/Compress/BZip2Crc.h b/CPP/7zip/Compress/BZip2Crc.h
index 1b5755b5..3b16c60b 100644
--- a/CPP/7zip/Compress/BZip2Crc.h
+++ b/CPP/7zip/Compress/BZip2Crc.h
@@ -11,8 +11,8 @@ class CBZip2Crc
static UInt32 Table[256];
public:
static void InitTable();
- CBZip2Crc(): _value(0xFFFFFFFF) {};
- void Init() { _value = 0xFFFFFFFF; }
+ CBZip2Crc(UInt32 initVal = 0xFFFFFFFF): _value(initVal) {};
+ void Init(UInt32 initVal = 0xFFFFFFFF) { _value = initVal; }
void UpdateByte(Byte b) { _value = Table[(_value >> 24) ^ b] ^ (_value << 8); }
void UpdateByte(unsigned int b) { _value = Table[(_value >> 24) ^ b] ^ (_value << 8); }
UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; }
diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp
index 2aea7b33..5bb6ff8d 100644
--- a/CPP/7zip/Compress/CodecExports.cpp
+++ b/CPP/7zip/Compress/CodecExports.cpp
@@ -230,15 +230,12 @@ STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
value->ulVal = (ULONG)codec.NumStreams;
}
break;
- /*
case NMethodPropID::kIsFilter:
- // if (codec.IsFilter)
{
value->vt = VT_BOOL;
value->boolVal = BoolToVARIANT_BOOL(codec.IsFilter);
}
break;
- */
/*
case NMethodPropID::kDecoderFlags:
{
diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt
index f28afcd1..754c9df5 100644
--- a/CPP/7zip/Guid.txt
+++ b/CPP/7zip/Guid.txt
@@ -21,7 +21,8 @@
11 IFolderScanProgress
20 IFileExtractCallback.h::IGetProp
- 30 IFileExtractCallback.h::IFolderExtractToStreamCallback
+ 30 IFileExtractCallback.h::IFolderExtractToStreamCallback (old)
+ 31 IFileExtractCallback.h::IFolderExtractToStreamCallback (new 21.04)
03 IStream.h
@@ -104,6 +105,7 @@
80 IArchiveUpdateCallback
82 IArchiveUpdateCallback2
83 IArchiveUpdateCallbackFile
+ 84 IArchiveGetDiskProperty
A0 IOutArchive
diff --git a/CPP/7zip/ICoder.h b/CPP/7zip/ICoder.h
index 314d33d4..9177f5e5 100644
--- a/CPP/7zip/ICoder.h
+++ b/CPP/7zip/ICoder.h
@@ -394,7 +394,8 @@ namespace NMethodPropID
kDescription,
kDecoderIsAssigned,
kEncoderIsAssigned,
- kDigestSize
+ kDigestSize,
+ kIsFilter
};
}
diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h
index 1822f402..b818954f 100644
--- a/CPP/7zip/PropID.h
+++ b/CPP/7zip/PropID.h
@@ -103,6 +103,9 @@ enum
kpidReadOnly,
kpidOutName,
kpidCopyLink,
+ kpidArcFileName,
+ kpidIsHash,
+
kpid_NUM_DEFINED,
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp
index 76b243f2..31c91e29 100644
--- a/CPP/7zip/UI/Agent/Agent.cpp
+++ b/CPP/7zip/UI/Agent/Agent.cpp
@@ -27,6 +27,7 @@ CCodecs *g_CodecsObj;
#ifdef EXTERNAL_CODECS
CExternalCodecs g_ExternalCodecs;
+ const CExternalCodecs *g_ExternalCodecs_Ptr;
static CCodecs::CReleaser g_CodecsReleaser;
#else
extern
@@ -53,6 +54,7 @@ void FreeGlobalCodecs()
g_CodecsReleaser.Set(NULL);
g_CodecsObj = NULL;
g_ExternalCodecs.ClearAndRelease();
+ g_ExternalCodecs_Ptr = NULL;
#else
g_CodecsRef.Release();
#endif
@@ -83,8 +85,11 @@ HRESULT LoadGlobalCodecs()
return E_NOTIMPL;
}
+ Codecs_AddHashArcHandler(g_CodecsObj);
+
#ifdef EXTERNAL_CODECS
RINOK(g_ExternalCodecs.Load());
+ g_ExternalCodecs_Ptr = &g_ExternalCodecs;
#endif
return S_OK;
@@ -1223,7 +1228,11 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
if (_agentSpec->Is_Attrib_ReadOnly())
prop = true;
else
- prop = _agentSpec->IsThereReadOnlyArc();
+ prop = _agentSpec->IsThere_ReadOnlyArc();
+ }
+ else if (propID == kpidIsHash)
+ {
+ prop = _agentSpec->_isHashHandler;
}
else if (_proxy2)
{
@@ -1446,6 +1455,10 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
IFolderArchiveExtractCallback *extractCallback2)
{
COM_TRY_BEGIN
+
+ if (!testMode && _agentSpec->_isHashHandler)
+ return E_NOTIMPL;
+
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
UStringVector pathParts;
@@ -1500,6 +1513,9 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
if (_proxy2)
extractCallbackSpec->SetBaseParentFolderIndex(_proxy2->Dirs[_proxyDirIndex].ArcIndex);
+ // do we need another base folder for subfolders ?
+ extractCallbackSpec->DirPathPrefix_for_HashFiles = _agentSpec->_hashBaseFolderPrefix;
+
CUIntVector realIndices;
GetRealIndices(indices, numItems, IntToBool(includeAltStreams),
false, // includeFolderSubItemsInFlatMode
@@ -1536,7 +1552,8 @@ CAgent::CAgent():
_proxy(NULL),
_proxy2(NULL),
_updatePathPrefix_is_AltFolder(false),
- _isDeviceFile(false)
+ _isDeviceFile(false),
+ _isHashHandler(false)
{
}
@@ -1571,9 +1588,11 @@ STDMETHODIMP CAgent::Open(
{
COM_TRY_BEGIN
_archiveFilePath = filePath;
+ _hashBaseFolderPrefix.Empty();
_attrib = 0;
- NFile::NFind::CFileInfo fi;
_isDeviceFile = false;
+ _isHashHandler = false;
+ NFile::NFind::CFileInfo fi;
if (!inStream)
{
if (!fi.Find(us2fs(_archiveFilePath)))
@@ -1582,6 +1601,12 @@ STDMETHODIMP CAgent::Open(
return E_FAIL;
_attrib = fi.Attrib;
_isDeviceFile = fi.IsDevice;
+ FString dirPrefix, fileName;
+ if (NFile::NDir::GetFullPathAndSplit(us2fs(_archiveFilePath), dirPrefix, fileName))
+ {
+ NFile::NName::NormalizeDirPathPrefix(dirPrefix);
+ _hashBaseFolderPrefix = dirPrefix;
+ }
}
CArcInfoEx archiverInfo0, archiverInfo1;
@@ -1629,6 +1654,9 @@ STDMETHODIMP CAgent::Open(
{
RINOK(StringToBstr(ArchiveType, archiveType));
}
+
+ if (arc.IsHashHandler(options))
+ _isHashHandler = true;
}
return res;
@@ -1745,6 +1773,10 @@ STDMETHODIMP CAgent::Extract(
IFolderArchiveExtractCallback *extractCallback2)
{
COM_TRY_BEGIN
+
+ if (!testMode && _isHashHandler)
+ return E_NOTIMPL;
+
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
extractCallbackSpec->InitForMulti(
@@ -1769,6 +1801,8 @@ STDMETHODIMP CAgent::Extract(
UStringVector(), false,
(UInt64)(Int64)-1);
+ extractCallbackSpec->DirPathPrefix_for_HashFiles = _hashBaseFolderPrefix;
+
#ifdef SUPPORT_LINKS
if (!testMode)
diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h
index 498e7d0c..e9fe4103 100644
--- a/CPP/7zip/UI/Agent/Agent.h
+++ b/CPP/7zip/UI/Agent/Agent.h
@@ -234,7 +234,7 @@ public:
UString ArchiveType;
FStringVector _names;
- FString _folderPrefix;
+ FString _folderPrefix; // for new files from disk
bool _updatePathPrefix_is_AltFolder;
UString _updatePathPrefix;
@@ -243,6 +243,8 @@ public:
UString _archiveFilePath;
DWORD _attrib;
bool _isDeviceFile;
+ bool _isHashHandler;
+ FString _hashBaseFolderPrefix;
#ifndef EXTRACT_ONLY
CObjectVector<UString> m_PropNames;
@@ -258,7 +260,7 @@ public:
return _attrib != INVALID_FILE_ATTRIBUTES && (_attrib & FILE_ATTRIBUTE_READONLY);
}
- bool IsThereReadOnlyArc() const
+ bool IsThere_ReadOnlyArc() const
{
FOR_VECTOR (i, _archiveLink.Arcs)
{
diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp
index 8dfb63a2..fae0e224 100644
--- a/CPP/7zip/UI/Agent/AgentOut.cpp
+++ b/CPP/7zip/UI/Agent/AgentOut.cpp
@@ -158,6 +158,8 @@ static void SetInArchiveInterfaces(CAgent *agent, CArchiveUpdateCallback *upd)
const CArc &arc = agent->GetArc();
upd->Arc = &arc;
upd->Archive = arc.Archive;
+
+ upd->ArcFileName = ExtractFileNameFromPath(arc.Path);
}
struct CDirItemsCallback_AgentOut: public IDirItemsCallback
@@ -190,6 +192,7 @@ struct CDirItemsCallback_AgentOut: public IDirItemsCallback
}
};
+
STDMETHODIMP CAgent::DoOperation(
FStringVector *requestedPaths,
FStringVector *processedPaths,
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
index ba52f4e7..4a10ebec 100644
--- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
+++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
@@ -70,6 +70,9 @@ HRESULT CAgentFolder::CommonUpdateOperation(
const UInt32 *indices, UInt32 numItems,
IProgress *progress)
{
+ if (moveMode && _agentSpec->_isHashHandler)
+ return E_NOTIMPL;
+
if (!_agentSpec->CanUpdate())
return E_NOTIMPL;
diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
index d450eefe..53a13bb9 100644
--- a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
+++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
@@ -153,7 +153,7 @@ HRESULT CUpdateCallbackAgent::ReportExtractResult(Int32 opRes, Int32 isEncrypted
return S_OK;
}
-HRESULT CUpdateCallbackAgent::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir)
+HRESULT CUpdateCallbackAgent::ReportUpdateOperation(UInt32 op, const wchar_t *name, bool isDir)
{
if (Callback2)
{
diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp
index 0c69bdc0..0fa4cdad 100644
--- a/CPP/7zip/UI/Client7z/Client7z.cpp
+++ b/CPP/7zip/UI/Client7z/Client7z.cpp
@@ -217,6 +217,7 @@ static const char * const kIncorrectCommand = "incorrect command";
static const char * const kTestingString = "Testing ";
static const char * const kExtractingString = "Extracting ";
static const char * const kSkippingString = "Skipping ";
+static const char * const kReadingString = "Reading ";
static const char * const kUnsupportedMethod = "Unsupported Method";
static const char * const kCRCFailed = "CRC Failed";
@@ -419,6 +420,9 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
case NArchive::NExtract::NAskMode::kExtract: Print(kExtractingString); break;
case NArchive::NExtract::NAskMode::kTest: Print(kTestingString); break;
case NArchive::NExtract::NAskMode::kSkip: Print(kSkippingString); break;
+ case NArchive::NExtract::NAskMode::kReadExternal: Print(kReadingString); break;
+ default:
+ Print("??? "); break;
};
Print(_filePath);
return S_OK;
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
index 00df80e9..47e4a852 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
@@ -133,6 +133,8 @@ enum Enum
kSfx,
kEmail,
kHash,
+ // kHashGenFile,
+ kHashDir,
kStdIn,
kStdOut,
@@ -141,6 +143,7 @@ enum Enum
kListfileCharSet,
kConsoleCharSet,
kTechMode,
+ kListFields,
kPreserveATime,
kShareForWrite,
@@ -273,6 +276,8 @@ static const CSwitchForm kSwitchForms[] =
{ "sfx", SWFRM_STRING },
{ "seml", SWFRM_STRING_SINGL(0) },
{ "scrc", SWFRM_STRING_MULT(0) },
+ // { "scrf", SWFRM_STRING_SINGL(1) },
+ { "shd", SWFRM_STRING_SINGL(1) },
{ "si", SWFRM_STRING },
{ "so", SWFRM_SIMPLE },
@@ -281,6 +286,7 @@ static const CSwitchForm kSwitchForms[] =
{ "scs", SWFRM_STRING },
{ "scc", SWFRM_STRING },
{ "slt", SWFRM_SIMPLE },
+ { "slf", SWFRM_STRING_SINGL(1) },
{ "ssp", SWFRM_SIMPLE },
{ "ssw", SWFRM_SIMPLE },
@@ -626,7 +632,21 @@ static void AddSwitchWildcardsToCensor(
errorMessage = "Too short switch";
break;
}
-
+
+ if (!include)
+ {
+ if (name.IsEqualTo_Ascii_NoCase("td"))
+ {
+ censor.ExcludeDirItems = true;
+ continue;
+ }
+ if (name.IsEqualTo_Ascii_NoCase("tf"))
+ {
+ censor.ExcludeFileItems = true;
+ continue;
+ }
+ }
+
if (::MyCharLower_Ascii(name[pos]) == kRecursedIDChar)
{
pos++;
@@ -875,6 +895,11 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
options.StdInMode = parser[NKey::kStdIn].ThereIs;
options.StdOutMode = parser[NKey::kStdOut].ThereIs;
options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;
+ if (parser[NKey::kListFields].ThereIs)
+ {
+ const UString &s = parser[NKey::kListFields].PostStrings[0];
+ options.ListFields = GetAnsiString(s);
+ }
options.TechMode = parser[NKey::kTechMode].ThereIs;
options.ShowTime = parser[NKey::kShowTime].ThereIs;
@@ -1094,6 +1119,27 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
if (parser[NKey::kHash].ThereIs)
options.HashMethods = parser[NKey::kHash].PostStrings;
+
+ /*
+ if (parser[NKey::kHashGenFile].ThereIs)
+ {
+ const UString &s = parser[NKey::kHashGenFile].PostStrings[0];
+ for (unsigned i = 0 ; i < s.Len();)
+ {
+ const wchar_t c = s[i++];
+ if (!options.HashOptions.ParseFlagCharOption(c, true))
+ {
+ if (c != '=')
+ throw CArcCmdLineException("Unsupported hash mode switch:", s);
+ options.HashOptions.HashFilePath = s.Ptr(i);
+ break;
+ }
+ }
+ }
+ */
+
+ if (parser[NKey::kHashDir].ThereIs)
+ options.ExtractOptions.HashDir = parser[NKey::kHashDir].PostStrings[0];
if (parser[NKey::kElimDup].ThereIs)
{
@@ -1232,6 +1278,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
{
CExtractOptionsBase &eo = options.ExtractOptions;
+ eo.ExcludeDirItems = options.Censor.ExcludeDirItems;
+ eo.ExcludeFileItems = options.Censor.ExcludeFileItems;
+
{
CExtractNtOptions &nt = eo.NtOptions;
nt.NtSecurity = options.NtSecurity;
@@ -1252,6 +1301,11 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs;
nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs;
+
+ if (parser[NKey::kPreserveATime].ThereIs)
+ nt.PreserveATime = true;
+ if (parser[NKey::kShareForWrite].ThereIs)
+ nt.OpenShareForWrite = true;
}
options.Censor.AddPathsToCensor(NWildcard::k_AbsPath);
@@ -1422,6 +1476,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
CHashOptions &hashOptions = options.HashOptions;
hashOptions.PathMode = censorPathMode;
hashOptions.Methods = options.HashMethods;
+ // hashOptions.HashFilePath = options.HashFilePath;
if (parser[NKey::kPreserveATime].ThereIs)
hashOptions.PreserveATime = true;
if (parser[NKey::kShareForWrite].ThereIs)
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h
index 1e488d8c..ff4f28ca 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.h
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h
@@ -66,6 +66,8 @@ struct CArcCmdLineOptions
bool TechMode;
bool ShowTime;
+ AString ListFields;
+
int ConsoleCodePage;
NWildcard::CCensor Censor;
@@ -79,6 +81,7 @@ struct CArcCmdLineOptions
#endif
UStringVector HashMethods;
+ // UString HashFilePath;
bool AppendName;
// UStringVector ArchivePathsSorted;
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
index 40e43d2a..b85a0ae6 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -47,6 +47,7 @@ static const char * const kCantRenameFile = "Cannot rename existing file";
static const char * const kCantDeleteOutputFile = "Cannot delete output file";
static const char * const kCantDeleteOutputDir = "Cannot delete output folder";
static const char * const kCantOpenOutFile = "Cannot open output file";
+static const char * const kCantOpenInFile = "Cannot open input file";
static const char * const kCantSetFileLen = "Cannot set length for output file";
#ifdef SUPPORT_LINKS
static const char * const kCantCreateHardLink = "Cannot create hard link";
@@ -889,7 +890,8 @@ void CArchiveExtractCallback::CorrectPathParts()
void CArchiveExtractCallback::CreateFolders()
{
- UStringVector &pathParts = _item.PathParts;
+ // 21.04 : we don't change original (_item.PathParts) here
+ UStringVector pathParts = _item.PathParts;
if (!_item.IsDir)
{
@@ -1078,18 +1080,19 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
IInArchive *archive = _arc->Archive;
#endif
- const UStringVector &pathParts = _item.PathParts;
const UInt32 index = _index;
bool isAnti = false;
RINOK(_arc->IsItemAnti(index, isAnti));
CorrectPathParts();
-
- UString processedPath (MakePathFromParts(pathParts));
+ UString processedPath (MakePathFromParts(_item.PathParts));
if (!isAnti)
+ {
+ // 21.04: CreateFolders doesn't change (_item.PathParts)
CreateFolders();
+ }
FString fullProcessedPath (us2fs(processedPath));
if (_pathMode != NExtract::NPathMode::kAbsPaths
@@ -1295,7 +1298,25 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
+HRESULT CArchiveExtractCallback::GetItem(UInt32 index)
+{
+ #ifndef _SFX
+ _item._use_baseParentFolder_mode = _use_baseParentFolder_mode;
+ if (_use_baseParentFolder_mode)
+ {
+ _item._baseParentFolder = (int)_baseParentFolder;
+ if (_pathMode == NExtract::NPathMode::kFullPaths ||
+ _pathMode == NExtract::NPathMode::kAbsPaths)
+ _item._baseParentFolder = -1;
+ }
+ #endif // _SFX
+
+ #ifdef SUPPORT_ALT_STREAMS
+ _item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon;
+ #endif
+ return _arc->GetItem(index, _item);
+}
STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
@@ -1339,22 +1360,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
IInArchive *archive = _arc->Archive;
- #ifndef _SFX
- _item._use_baseParentFolder_mode = _use_baseParentFolder_mode;
- if (_use_baseParentFolder_mode)
- {
- _item._baseParentFolder = (int)_baseParentFolder;
- if (_pathMode == NExtract::NPathMode::kFullPaths ||
- _pathMode == NExtract::NPathMode::kAbsPaths)
- _item._baseParentFolder = -1;
- }
- #endif // _SFX
-
- #ifdef SUPPORT_ALT_STREAMS
- _item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon;
- #endif
-
- RINOK(_arc->GetItem(index, _item));
+ RINOK(GetItem(index));
{
NCOM::CPropVariant prop;
@@ -1382,6 +1388,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
return S_OK;
#endif // SUPPORT_ALT_STREAMS
+ // we can change (_item.PathParts) in this function
UStringVector &pathParts = _item.PathParts;
if (_wildcardCensor)
@@ -1974,7 +1981,10 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
#ifndef _SFX
if (ExtractToStreamCallback)
- return ExtractToStreamCallback->SetOperationResult7(opRes, BoolToInt(_encrypted));
+ {
+ GetUnpackSize();
+ return ExtractToStreamCallback->SetOperationResult8(opRes, BoolToInt(_encrypted), _curSize);
+ }
#endif
#ifndef _SFX
@@ -2103,6 +2113,82 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
}
+// ---------- HASH functions ----------
+
+FString CArchiveExtractCallback::Hash_GetFullFilePath()
+{
+ // this function changes _item.PathParts.
+ CorrectPathParts();
+ const UStringVector &pathParts = _item.PathParts;
+ const UString processedPath (MakePathFromParts(pathParts));
+ FString fullProcessedPath (us2fs(processedPath));
+ if (_pathMode != NExtract::NPathMode::kAbsPaths
+ || !NName::IsAbsolutePath(processedPath))
+ {
+ fullProcessedPath = MakePath_from_2_Parts(
+ DirPathPrefix_for_HashFiles,
+ // _dirPathPrefix,
+ fullProcessedPath);
+ }
+ return fullProcessedPath;
+}
+
+
+STDMETHODIMP CArchiveExtractCallback::GetDiskProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop;
+ if (propID == kpidSize)
+ {
+ RINOK(GetItem(index));
+ const FString fullProcessedPath = Hash_GetFullFilePath();
+ NFile::NFind::CFileInfo fi;
+ if (fi.Find_FollowLink(fullProcessedPath))
+ if (!fi.IsDir())
+ prop = (UInt64)fi.Size;
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CArchiveExtractCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode)
+{
+ COM_TRY_BEGIN
+ *inStream = NULL;
+ // if (index != _index) return E_FAIL;
+ if (mode != NUpdateNotifyOp::kHashRead)
+ return E_FAIL;
+
+ RINOK(GetItem(index));
+ const FString fullProcessedPath = Hash_GetFullFilePath();
+
+ CInFileStream *inStreamSpec = new CInFileStream;
+ CMyComPtr<ISequentialInStream> inStreamRef = inStreamSpec;
+ inStreamSpec->File.PreserveATime = _ntOptions.PreserveATime;
+ if (!inStreamSpec->OpenShared(fullProcessedPath, _ntOptions.OpenShareForWrite))
+ {
+ RINOK(SendMessageError_with_LastError(kCantOpenInFile, fullProcessedPath));
+ return S_OK;
+ }
+ *inStream = inStreamRef.Detach();
+ return S_OK;
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CArchiveExtractCallback::ReportOperation(
+ UInt32 /* indexType */, UInt32 /* index */, UInt32 /* op */)
+{
+ // COM_TRY_BEGIN
+ return S_OK;
+ // COM_TRY_END
+}
+
+
+// ------------ After Extracting functions ------------
+
void CDirPathSortPair::SetNumSlashes(const FChar *s)
{
for (unsigned numSlashes = 0;;)
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
index 25eb6444..e44801de 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -62,9 +62,15 @@ struct CExtractNtOptions
bool PreAllocateOutFile;
+ // used for hash arcs only, when we open external files
+ bool PreserveATime;
+ bool OpenShareForWrite;
+
CExtractNtOptions():
ReplaceColonForAltStream(false),
- WriteToAltStreamIfColon(false)
+ WriteToAltStreamIfColon(false),
+ PreserveATime(false),
+ OpenShareForWrite(false)
{
SymLinks.Val = true;
SymLinks_AllowDangerous.Val = false;
@@ -205,6 +211,8 @@ class CArchiveExtractCallback:
public IArchiveExtractCallbackMessage,
public ICryptoGetTextPassword,
public ICompressProgressInfo,
+ public IArchiveUpdateCallbackFile,
+ public IArchiveGetDiskProperty,
public CMyUnknownImp
{
const CArc *_arc;
@@ -342,6 +350,9 @@ class CArchiveExtractCallback:
HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
HRESULT GetUnpackSize();
+ FString Hash_GetFullFilePath();
+
+public:
HRESULT SendMessageError(const char *message, const FString &path);
HRESULT SendMessageError_with_LastError(const char *message, const FString &path);
HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2);
@@ -356,10 +367,20 @@ public:
UInt64 UnpackSize;
UInt64 AltStreams_UnpackSize;
- MY_UNKNOWN_IMP3(IArchiveExtractCallbackMessage, ICryptoGetTextPassword, ICompressProgressInfo)
+ FString DirPathPrefix_for_HashFiles;
+
+ MY_UNKNOWN_IMP5(
+ IArchiveExtractCallbackMessage,
+ ICryptoGetTextPassword,
+ ICompressProgressInfo,
+ IArchiveUpdateCallbackFile,
+ IArchiveGetDiskProperty
+ )
INTERFACE_IArchiveExtractCallback(;)
INTERFACE_IArchiveExtractCallbackMessage(;)
+ INTERFACE_IArchiveUpdateCallbackFile(;)
+ INTERFACE_IArchiveGetDiskProperty(;)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
@@ -453,6 +474,7 @@ private:
bool _isRenamed;
HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit);
HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit);
+ HRESULT GetItem(UInt32 index);
HRESULT CloseFile();
HRESULT CloseReparseAndFile();
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp
index fb4c1726..2ee29913 100644
--- a/CPP/7zip/UI/Common/Bench.cpp
+++ b/CPP/7zip/UI/Common/Bench.cpp
@@ -639,15 +639,22 @@ STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64
static const unsigned kSubBits = 8;
-static UInt32 GetLogSize(UInt64 size)
+static unsigned GetLogSize(UInt64 size)
+{
+ unsigned i = 0;
+ for (;;)
+ {
+ i++; size >>= 1; if (size == 0) break;
+ }
+ return i;
+}
+
+
+static UInt32 GetLogSize_Sub(UInt64 size)
{
if (size <= 1)
return 0;
- unsigned i;
- for (i = 2; i < 64; i++)
- if (size < ((UInt64)1 << i))
- break;
- i--;
+ const unsigned i = GetLogSize(size) - 1;
UInt32 v;
if (i <= kSubBits)
v = (UInt32)(size) << (kSubBits - i);
@@ -656,60 +663,101 @@ static UInt32 GetLogSize(UInt64 size)
return ((UInt32)i << kSubBits) + (v & (((UInt32)1 << kSubBits) - 1));
}
-static void NormalizeVals(UInt64 &v1, UInt64 &v2)
+
+static UInt64 Get_UInt64_from_double(double v)
+{
+ const UInt64 kMaxVal = (UInt64)1 << 62;
+ if (v > (double)(Int64)kMaxVal)
+ return kMaxVal;
+ return (UInt64)v;
+}
+
+static UInt64 MyMultDiv64(UInt64 m1, UInt64 m2, UInt64 d)
{
- while (v1 >= ((UInt32)1 << ((64 - kBenchmarkUsageMultBits) / 2)))
+ if (d == 0)
+ d = 1;
+ const double v =
+ (double)(Int64)m1 *
+ (double)(Int64)m2 /
+ (double)(Int64)d;
+ return Get_UInt64_from_double(v);
+ /*
+ unsigned n1 = GetLogSize(m1);
+ unsigned n2 = GetLogSize(m2);
+ while (n1 + n2 > 64)
{
- v1 >>= 1;
- v2 >>= 1;
+ if (n1 >= n2)
+ {
+ m1 >>= 1;
+ n1--;
+ }
+ else
+ {
+ m2 >>= 1;
+ n2--;
+ }
+ d >>= 1;
}
+
+ if (d == 0)
+ d = 1;
+ return m1 * m2 / d;
+ */
}
+
UInt64 CBenchInfo::GetUsage() const
{
UInt64 userTime = UserTime;
UInt64 userFreq = UserFreq;
UInt64 globalTime = GlobalTime;
UInt64 globalFreq = GlobalFreq;
- NormalizeVals(userTime, userFreq);
- NormalizeVals(globalFreq, globalTime);
+
if (userFreq == 0)
userFreq = 1;
if (globalTime == 0)
globalTime = 1;
- return userTime * globalFreq * kBenchmarkUsageMult / userFreq / globalTime;
+
+ const double v =
+ ((double)(Int64)userTime / (double)(Int64)userFreq)
+ * ((double)(Int64)globalFreq / (double)(Int64)globalTime)
+ * (double)(Int64)kBenchmarkUsageMult;
+ return Get_UInt64_from_double(v);
+ /*
+ return MyMultDiv64(
+ MyMultDiv64(kBenchmarkUsageMult, userTime, userFreq),
+ globalFreq, globalTime);
+ */
}
+
UInt64 CBenchInfo::GetRatingPerUsage(UInt64 rating) const
{
- UInt64 userTime = UserTime;
- UInt64 userFreq = UserFreq;
- UInt64 globalTime = GlobalTime;
- UInt64 globalFreq = GlobalFreq;
- NormalizeVals(userFreq, userTime);
- NormalizeVals(globalTime, globalFreq);
- if (globalFreq == 0)
- globalFreq = 1;
- if (userTime == 0)
+ if (UserTime == 0)
{
return 0;
// userTime = 1;
}
- return userFreq * globalTime / globalFreq * rating / userTime;
-}
+ UInt64 globalFreq = GlobalFreq;
+ if (globalFreq == 0)
+ globalFreq = 1;
-static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)
-{
- UInt64 elTime = elapsedTime;
- NormalizeVals(freq, elTime);
- if (elTime == 0)
- elTime = 1;
- return value * freq / elTime;
+ const double v =
+ ((double)(Int64)GlobalTime / (double)(Int64)globalFreq)
+ * ((double)(Int64)UserFreq / (double)(Int64)UserTime)
+ * (double)(Int64)rating;
+ return Get_UInt64_from_double(v);
+ /*
+ return MyMultDiv64(
+ MyMultDiv64(rating, UserFreq, UserTime),
+ GlobalTime, globalFreq);
+ */
}
+
UInt64 CBenchInfo::GetSpeed(UInt64 numUnits) const
{
- return MyMultDiv64(numUnits, GlobalTime, GlobalFreq);
+ return MyMultDiv64(numUnits, GlobalFreq, GlobalTime);
}
struct CBenchProps
@@ -764,24 +812,24 @@ UInt64 CBenchProps::GetCompressRating(UInt64 dictSize, UInt64 elapsedTime, UInt6
/*
for (UInt64 uu = 0; uu < (UInt64)0xf << 60;)
{
- unsigned rr = GetLogSize(uu);
+ unsigned rr = GetLogSize_Sub(uu);
printf("\n%16I64x , log = %4x", uu, rr);
uu += 1;
uu += uu / 50;
}
*/
// throw 1;
- const UInt32 t = GetLogSize(dictSize) - (kBenchMinDicLogSize << kSubBits);
+ const UInt32 t = GetLogSize_Sub(dictSize) - (kBenchMinDicLogSize << kSubBits);
encComplex = 870 + ((t * t * 5) >> (2 * kSubBits));
}
const UInt64 numCommands = (UInt64)size * encComplex;
- return MyMultDiv64(numCommands, elapsedTime, freq);
+ return MyMultDiv64(numCommands, freq, elapsedTime);
}
UInt64 CBenchProps::GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations)
{
const UInt64 numCommands = (inSize * DecComplexCompr + outSize * DecComplexUnc) * numIterations;
- return MyMultDiv64(numCommands, elapsedTime, freq);
+ return MyMultDiv64(numCommands, freq, elapsedTime);
}
@@ -2675,8 +2723,8 @@ void CTotalBenchRes::Mult_For_Weight(unsigned weight)
NumIterations2 *= weight;
RPU *= weight;
Rating *= weight;
- Usage += weight;
- Speed += weight;
+ Usage *= weight;
+ Speed *= weight;
}
void CTotalBenchRes::Update_With_Res(const CTotalBenchRes &r)
@@ -3712,7 +3760,7 @@ HRESULT Bench(
start = 1;
const UInt64 freq = GetFreq();
// mips is constant in some compilers
- const UInt64 hz = MyMultDiv64(numMilCommands * 1000000, start, freq);
+ const UInt64 hz = MyMultDiv64(numMilCommands * 1000000, freq, start);
const UInt64 mipsVal = numMilCommands * freq / start;
if (printCallback)
{
diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp
index 72a61685..84a8d22f 100644
--- a/CPP/7zip/UI/Common/CompressCall.cpp
+++ b/CPP/7zip/UI/Common/CompressCall.cpp
@@ -265,22 +265,56 @@ void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bo
MY_TRY_FINISH_VOID
}
-void TestArchives(const UStringVector &arcPaths)
+
+void TestArchives(const UStringVector &arcPaths, bool hashMode)
{
MY_TRY_BEGIN
UString params ('t');
+ if (hashMode)
+ {
+ params += kArchiveTypeSwitch;
+ params += "hash";
+ }
ExtractGroupCommand(arcPaths, params, false);
MY_TRY_FINISH_VOID
}
-void CalcChecksum(const UStringVector &paths, const UString &methodName)
+
+void CalcChecksum(const UStringVector &paths,
+ const UString &methodName,
+ const UString &arcPathPrefix,
+ const UString &arcFileName)
{
MY_TRY_BEGIN
+
+ if (!arcFileName.IsEmpty())
+ {
+ CompressFiles(
+ arcPathPrefix,
+ arcFileName,
+ UString("hash"),
+ false, // addExtension,
+ paths,
+ false, // email,
+ false, // showDialog,
+ false // waitFinish
+ );
+ return;
+ }
+
UString params ('h');
if (!methodName.IsEmpty())
{
params += " -scrc";
params += methodName;
+ /*
+ if (!arcFileName.IsEmpty())
+ {
+ // not used alternate method of generating file
+ params += " -scrf=";
+ params += GetQuotedString(arcPathPrefix + arcFileName);
+ }
+ */
}
ExtractGroupCommand(paths, params, true);
MY_TRY_FINISH_VOID
diff --git a/CPP/7zip/UI/Common/CompressCall.h b/CPP/7zip/UI/Common/CompressCall.h
index c71c21f7..b817df0f 100644
--- a/CPP/7zip/UI/Common/CompressCall.h
+++ b/CPP/7zip/UI/Common/CompressCall.h
@@ -16,8 +16,13 @@ HRESULT CompressFiles(
bool email, bool showDialog, bool waitFinish);
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup);
-void TestArchives(const UStringVector &arcPaths);
-void CalcChecksum(const UStringVector &paths, const UString &methodName);
+void TestArchives(const UStringVector &arcPaths, bool hashMode = false);
+
+void CalcChecksum(const UStringVector &paths,
+ const UString &methodName,
+ const UString &arcPathPrefix,
+ const UString &arcFileName);
+
void Benchmark(bool totalMode);
#endif
diff --git a/CPP/7zip/UI/Common/CompressCall2.cpp b/CPP/7zip/UI/Common/CompressCall2.cpp
index 8943e7d9..e6e42d64 100644
--- a/CPP/7zip/UI/Common/CompressCall2.cpp
+++ b/CPP/7zip/UI/Common/CompressCall2.cpp
@@ -38,7 +38,8 @@ static void ThrowException_if_Error(HRESULT res)
#define CREATE_CODECS \
CCodecs *codecs = new CCodecs; \
CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs; \
- ThrowException_if_Error(codecs->Load());
+ ThrowException_if_Error(codecs->Load()); \
+ Codecs_AddHashArcHandler(codecs);
#define LOAD_EXTERNAL_CODECS \
CExternalCodecs __externalCodecs; \
@@ -51,7 +52,8 @@ static void ThrowException_if_Error(HRESULT res)
#define CREATE_CODECS \
CCodecs *codecs = new CCodecs; \
CMyComPtr<IUnknown> compressCodecsInfo = codecs; \
- ThrowException_if_Error(codecs->Load());
+ ThrowException_if_Error(codecs->Load()); \
+ Codecs_AddHashArcHandler(codecs);
#define LOAD_EXTERNAL_CODECS
@@ -150,7 +152,8 @@ HRESULT CompressFiles(
static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
- bool showDialog, const UString &outFolder, bool testMode, bool elimDup = false)
+ bool showDialog, const UString &outFolder, bool testMode, bool elimDup = false,
+ const char *kType = NULL)
{
MY_TRY_BEGIN
@@ -187,6 +190,15 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
}
CObjectVector<COpenType> formatIndices;
+ if (kType)
+ {
+ if (!ParseOpenTypes(*codecs, UString(kType), formatIndices))
+ {
+ throw CSystemException(E_INVALIDARG);
+ // ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE);
+ // return E_INVALIDARG;
+ }
+ }
NWildcard::CCensor censor;
{
@@ -221,14 +233,34 @@ void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bo
ExtractGroupCommand(arcPaths, showDialog, outFolder, false, elimDup);
}
-void TestArchives(const UStringVector &arcPaths)
+void TestArchives(const UStringVector &arcPaths, bool hashMode)
{
- ExtractGroupCommand(arcPaths, true, UString(), true);
+ ExtractGroupCommand(arcPaths, true, UString(), true,
+ false, // elimDup
+ hashMode ? "hash" : NULL);
}
-void CalcChecksum(const UStringVector &paths, const UString &methodName)
+void CalcChecksum(const UStringVector &paths,
+ const UString &methodName,
+ const UString &arcPathPrefix,
+ const UString &arcFileName)
{
MY_TRY_BEGIN
+
+ if (!arcFileName.IsEmpty())
+ {
+ CompressFiles(
+ arcPathPrefix,
+ arcFileName,
+ UString("hash"),
+ false, // addExtension,
+ paths,
+ false, // email,
+ false, // showDialog,
+ false // waitFinish
+ );
+ return;
+ }
CREATE_CODECS
LOAD_EXTERNAL_CODECS
@@ -245,6 +277,11 @@ void CalcChecksum(const UStringVector &paths, const UString &methodName)
CHashOptions options;
options.Methods.Add(methodName);
+ /*
+ if (!arcFileName.IsEmpty())
+ options.HashFilePath = arcPathPrefix + arcFileName;
+ */
+
result = HashCalcGUI(EXTERNAL_CODECS_VARS_L censor, options, messageWasDisplayed);
if (result != S_OK)
{
diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h
index 337cd1a7..55b2872c 100644
--- a/CPP/7zip/UI/Common/DirItem.h
+++ b/CPP/7zip/UI/Common/DirItem.h
@@ -141,7 +141,16 @@ public:
bool SymLinks;
bool ScanAltStreams;
-
+ bool ExcludeDirItems;
+ bool ExcludeFileItems;
+
+ /* it must be called after anotrher checks */
+ bool CanIncludeItem(bool isDir) const
+ {
+ return isDir ? !ExcludeDirItems : !ExcludeFileItems;
+ }
+
+
CDirItemsStat Stat;
#if !defined(UNDER_CE)
diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp
index 7a2dd008..59baa092 100644
--- a/CPP/7zip/UI/Common/EnumDirItems.cpp
+++ b/CPP/7zip/UI/Common/EnumDirItems.cpp
@@ -146,6 +146,8 @@ bool InitLocalPrivileges();
CDirItems::CDirItems():
SymLinks(false),
ScanAltStreams(false)
+ , ExcludeDirItems(false)
+ , ExcludeFileItems(false)
#ifdef _USE_SECURITY_CODE
, ReadSecure(false)
#endif
@@ -318,6 +320,8 @@ HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phy
*/
#endif
+ if (CanIncludeItem(fi.IsDir()))
+ {
int secureIndex = -1;
#ifdef _USE_SECURITY_CODE
if (ReadSecure)
@@ -325,8 +329,8 @@ HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phy
RINOK(AddSecurityItem(phyPrefix + fi.Name, secureIndex));
}
#endif
-
AddDirFileInfo(phyParent, logParent, secureIndex, fi);
+ }
if (Callback && (i & kScanProgressStepMask) == kScanProgressStepMask)
{
@@ -392,6 +396,8 @@ HRESULT CDirItems::EnumerateItems2(
phyParentCur = (int)AddPrefix(phyParent, logParent, fs2us(phyPrefixCur));
}
+ if (CanIncludeItem(fi.IsDir()))
+ {
int secureIndex = -1;
#ifdef _USE_SECURITY_CODE
if (ReadSecure)
@@ -399,8 +405,8 @@ HRESULT CDirItems::EnumerateItems2(
RINOK(AddSecurityItem(phyPath, secureIndex));
}
#endif
-
AddDirFileInfo(phyParentCur, logParent, secureIndex, fi);
+ }
if (fi.IsDir())
{
@@ -470,6 +476,9 @@ static HRESULT EnumerateAltStreams(
bool addAllSubStreams,
CDirItems &dirItems)
{
+ // we don't use (ExcludeFileItems) rules for AltStreams
+ // if (dirItems.ExcludeFileItems) return S_OK;
+
NFind::CStreamEnumerator enumerator(phyPath);
for (;;)
{
@@ -560,29 +569,42 @@ static HRESULT EnumerateForItem(
int dirItemIndex = -1;
#if defined(_WIN32)
bool addAllSubStreams = false;
+ bool needAltStreams = true;
#endif // _WIN32
#endif // !defined(UNDER_CE)
// check the path in inlcude rules
if (curNode.CheckPathToRoot(true, newParts, !fi.IsDir()))
{
- int secureIndex = -1;
- #ifdef _USE_SECURITY_CODE
- if (dirItems.ReadSecure)
- {
- RINOK(dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex));
- }
- #endif
-
#if !defined(UNDER_CE)
- dirItemIndex = (int)dirItems.Items.Size();
+ // dirItemIndex = (int)dirItems.Items.Size();
#if defined(_WIN32)
// we will not check include rules for substreams.
addAllSubStreams = true;
#endif // _WIN32
#endif // !defined(UNDER_CE)
- dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);
+ if (dirItems.CanIncludeItem(fi.IsDir()))
+ {
+ int secureIndex = -1;
+ #ifdef _USE_SECURITY_CODE
+ if (dirItems.ReadSecure)
+ {
+ RINOK(dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex));
+ }
+ #endif
+ #if !defined(UNDER_CE)
+ dirItemIndex = (int)dirItems.Items.Size();
+ #endif // !defined(UNDER_CE)
+ dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);
+ }
+ else
+ {
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ needAltStreams = false;
+ #endif
+ }
+
if (fi.IsDir())
enterToSubFolders = true;
}
@@ -600,7 +622,7 @@ static HRESULT EnumerateForItem(
}
#if defined(_WIN32)
- if (dirItems.ScanAltStreams)
+ if (needAltStreams && dirItems.ScanAltStreams)
{
RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
phyPrefix + fi.Name, // with (fi.Name)
@@ -814,6 +836,9 @@ static HRESULT EnumerateDirItems(
continue;
}
+
+ if (dirItems.CanIncludeItem(fi.IsDir()))
+ {
int secureIndex = -1;
#ifdef _USE_SECURITY_CODE
if (needSecurity && dirItems.ReadSecure)
@@ -848,6 +873,7 @@ static HRESULT EnumerateDirItems(
#endif // defined(_WIN32)
#endif // !defined(UNDER_CE)
+ }
#ifndef _WIN32
diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp
index 18bd1037..de2aeb26 100644
--- a/CPP/7zip/UI/Common/Extract.cpp
+++ b/CPP/7zip/UI/Common/Extract.cpp
@@ -7,11 +7,13 @@
#include "../../../Common/StringConvert.h"
#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileName.h"
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Windows/PropVariantConv.h"
#include "../Common/ExtractingFilePath.h"
+#include "../Common/HashCalc.h"
#include "Extract.h"
#include "SetProperties.h"
@@ -87,7 +89,7 @@ static HRESULT DecompressArchive(
}
}
- bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();
+ const bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();
if (!options.StdInMode)
{
@@ -98,9 +100,14 @@ static HRESULT DecompressArchive(
for (UInt32 i = 0; i < numItems; i++)
{
- if (elimIsPossible || !allFilesAreAllowed)
+ if (elimIsPossible
+ || !allFilesAreAllowed
+ || options.ExcludeDirItems
+ || options.ExcludeFileItems)
{
RINOK(arc.GetItem(i, item));
+ if (item.IsDir ? options.ExcludeDirItems : options.ExcludeFileItems)
+ continue;
}
else
{
@@ -254,6 +261,7 @@ int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &n
HRESULT Extract(
+ // DECL_EXTERNAL_CODECS_LOC_VARS
CCodecs *codecs,
const CObjectVector<COpenType> &types,
const CIntVector &excludedFormats,
@@ -409,6 +417,31 @@ HRESULT Extract(
continue;
}
+ if (arcLink.Arcs.Size() != 0)
+ {
+ if (arcLink.GetArc()->IsHashHandler(op))
+ {
+ if (!options.TestMode)
+ {
+ /* real Extracting to files is possible.
+ But user can think that hash archive contains real files.
+ So we block extracting here. */
+ return E_NOTIMPL;
+ }
+ FString dirPrefix = us2fs(options.HashDir);
+ if (dirPrefix.IsEmpty())
+ {
+ if (!NFile::NDir::GetOnlyDirPrefix(us2fs(arcPath), dirPrefix))
+ {
+ // return GetLastError_noZero_HRESULT();
+ }
+ }
+ if (!dirPrefix.IsEmpty())
+ NName::NormalizeDirPathPrefix(dirPrefix);
+ ecs->DirPathPrefix_for_HashFiles = dirPrefix;
+ }
+ }
+
if (!options.StdInMode)
{
// numVolumes += arcLink.VolumePaths.Size();
diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h
index bfabe195..10e06dad 100644
--- a/CPP/7zip/UI/Common/Extract.h
+++ b/CPP/7zip/UI/Common/Extract.h
@@ -17,7 +17,10 @@
struct CExtractOptionsBase
{
CBoolPair ElimDup;
-
+
+ bool ExcludeDirItems;
+ bool ExcludeFileItems;
+
bool PathMode_Force;
bool OverwriteMode_Force;
NExtract::NPathMode::EEnum PathMode;
@@ -25,8 +28,11 @@ struct CExtractOptionsBase
FString OutputDir;
CExtractNtOptions NtOptions;
+ UString HashDir;
CExtractOptionsBase():
+ ExcludeDirItems(false),
+ ExcludeFileItems(false),
PathMode_Force(false),
OverwriteMode_Force(false),
PathMode(NExtract::NPathMode::kFullPaths),
@@ -48,9 +54,11 @@ struct CExtractOptions: public CExtractOptionsBase
CObjectVector<CProperty> Properties;
#endif
+ /*
#ifdef EXTERNAL_CODECS
CCodecs *Codecs;
#endif
+ */
CExtractOptions():
StdInMode(false),
@@ -77,6 +85,7 @@ struct CDecompressStat
};
HRESULT Extract(
+ // DECL_EXTERNAL_CODECS_LOC_VARS
CCodecs *codecs,
const CObjectVector<COpenType> &types,
const CIntVector &excludedFormats,
diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp
index c87be443..654da86b 100644
--- a/CPP/7zip/UI/Common/HashCalc.cpp
+++ b/CPP/7zip/UI/Common/HashCalc.cpp
@@ -3,30 +3,40 @@
#include "StdAfx.h"
#include "../../../../C/Alloc.h"
+#include "../../../../C/CpuArch.h"
+#include "../../../Common/DynLimBuf.h"
+#include "../../../Common/IntToString.h"
#include "../../../Common/StringToInt.h"
#include "../../Common/FileStreams.h"
-#include "../../Common/StreamUtils.h"
+#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../../Archive/Common/ItemNameUtils.h"
#include "EnumDirItems.h"
#include "HashCalc.h"
using namespace NWindows;
+#ifdef EXTERNAL_CODECS
+extern const CExternalCodecs *g_ExternalCodecs_Ptr;
+#endif
+
class CHashMidBuf
{
void *_data;
public:
- CHashMidBuf(): _data(0) {}
+ CHashMidBuf(): _data(NULL) {}
operator void *() { return _data; }
bool Alloc(size_t size)
{
- if (_data != 0)
+ if (_data)
return false;
_data = ::MidAlloc(size);
- return _data != 0;
+ return _data != NULL;
}
~CHashMidBuf() { ::MidFree(_data); }
};
@@ -91,15 +101,15 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto
if (scp)
RINOK(m.SetCoderProps(scp, NULL));
}
- UInt32 digestSize = hasher->GetDigestSize();
+ const UInt32 digestSize = hasher->GetDigestSize();
if (digestSize > k_HashCalc_DigestSize_Max)
return E_NOTIMPL;
CHasherState &h = Hashers.AddNew();
+ h.DigestSize = digestSize;
h.Hasher = hasher;
h.Name = name;
- h.DigestSize = digestSize;
for (unsigned k = 0; k < k_HashCalc_NumGroups; k++)
- memset(h.Digests[k], 0, digestSize);
+ h.InitDigestGroup(k);
}
return S_OK;
@@ -112,7 +122,7 @@ void CHashBundle::InitForNewFile()
{
CHasherState &h = Hashers[i];
h.Hasher->Init();
- memset(h.Digests[k_HashCalc_Index_Current], 0, h.DigestSize);
+ h.InitDigestGroup(k_HashCalc_Index_Current);
}
}
@@ -131,14 +141,46 @@ void CHashBundle::SetSize(UInt64 size)
static void AddDigests(Byte *dest, const Byte *src, UInt32 size)
{
unsigned next = 0;
- for (UInt32 i = 0; i < size; i++)
+ /*
+ // we could use big-endian addition for sha-1 and sha-256
+ // but another hashers are little-endian
+ if (size > 8)
+ {
+ for (unsigned i = size; i != 0;)
+ {
+ i--;
+ next += (unsigned)dest[i] + (unsigned)src[i];
+ dest[i] = (Byte)next;
+ next >>= 8;
+ }
+ }
+ else
+ */
{
- next += (unsigned)dest[i] + (unsigned)src[i];
+ for (unsigned i = 0; i < size; i++)
+ {
+ next += (unsigned)dest[i] + (unsigned)src[i];
+ dest[i] = (Byte)next;
+ next >>= 8;
+ }
+ }
+
+ // we use little-endian to store extra bytes
+ dest += k_HashCalc_DigestSize_Max;
+ for (unsigned i = 0; i < k_HashCalc_ExtraSize; i++)
+ {
+ next += (unsigned)dest[i];
dest[i] = (Byte)next;
next >>= 8;
}
}
+void CHasherState::AddDigest(unsigned groupIndex, const Byte *data)
+{
+ NumSums[groupIndex]++;
+ AddDigests(Digests[groupIndex], data, DigestSize);
+}
+
void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path)
{
if (isDir)
@@ -164,9 +206,9 @@ void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path)
CHasherState &h = Hashers[i];
if (!isDir)
{
- h.Hasher->Final(h.Digests[0]);
+ h.Hasher->Final(h.Digests[0]); // k_HashCalc_Index_Current
if (!isAltStream)
- AddDigests(h.Digests[k_HashCalc_Index_DataSum], h.Digests[0], h.DigestSize);
+ h.AddDigest(k_HashCalc_Index_DataSum, h.Digests[0]);
}
h.Hasher->Init();
@@ -176,6 +218,15 @@ void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path)
for (unsigned k = 0; k < path.Len(); k++)
{
wchar_t c = path[k];
+
+ // 21.04: we want same hash for linux and windows paths
+ #if CHAR_PATH_SEPARATOR != '/'
+ if (c == CHAR_PATH_SEPARATOR)
+ c = '/';
+ // if (c == (wchar_t)('\\' + 0xf000)) c = '\\'; // to debug WSL
+ // if (c > 0xf000 && c < 0xf080) c -= 0xf000; // to debug WSL
+ #endif
+
Byte temp[2] = { (Byte)(c & 0xFF), (Byte)((c >> 8) & 0xFF) };
h.Hasher->Update(temp, 2);
}
@@ -183,12 +234,221 @@ void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path)
Byte tempDigest[k_HashCalc_DigestSize_Max];
h.Hasher->Final(tempDigest);
if (!isAltStream)
- AddDigests(h.Digests[k_HashCalc_Index_NamesSum], tempDigest, h.DigestSize);
- AddDigests(h.Digests[k_HashCalc_Index_StreamsSum], tempDigest, h.DigestSize);
+ h.AddDigest(k_HashCalc_Index_NamesSum, tempDigest);
+ h.AddDigest(k_HashCalc_Index_StreamsSum, tempDigest);
}
}
+static void CSum_Name_OriginalToEscape(const AString &src, AString &dest)
+{
+ dest.Empty();
+ for (unsigned i = 0; i < src.Len();)
+ {
+ char c = src[i++];
+ if (c == '\n')
+ {
+ dest += '\\';
+ c = 'n';
+ }
+ else if (c == '\\')
+ dest += '\\';
+ dest += c;
+ }
+}
+
+
+static bool CSum_Name_EscapeToOriginal(const char *s, AString &dest)
+{
+ bool isOK = true;
+ dest.Empty();
+ for (;;)
+ {
+ char c = *s++;
+ if (c == 0)
+ break;
+ if (c == '\\')
+ {
+ const char c1 = *s;
+ if (c1 == 'n')
+ {
+ c = '\n';
+ s++;
+ }
+ else if (c1 == '\\')
+ {
+ c = c1;
+ s++;
+ }
+ else
+ {
+ // original md5sum returns NULL for such bad strings
+ isOK = false;
+ }
+ }
+ dest += c;
+ }
+ return isOK;
+}
+
+
+
+static void SetSpacesAndNul(char *s, unsigned num)
+{
+ for (unsigned i = 0; i < num; i++)
+ s[i] = ' ';
+ s[num] = 0;
+}
+
+static const unsigned kHashColumnWidth_Min = 4 * 2;
+
+static unsigned GetColumnWidth(unsigned digestSize)
+{
+ const unsigned width = digestSize * 2;
+ return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width;
+}
+
+
+void HashHexToString(char *dest, const Byte *data, UInt32 size);
+
+static void AddHashResultLine(
+ AString &_s,
+ // bool showHash,
+ // UInt64 fileSize, bool showSize,
+ const CObjectVector<CHasherState> &hashers
+ // unsigned digestIndex, = k_HashCalc_Index_Current
+ )
+{
+ FOR_VECTOR (i, hashers)
+ {
+ const CHasherState &h = hashers[i];
+ char s[k_HashCalc_DigestSize_Max * 2 + 64];
+ s[0] = 0;
+ // if (showHash)
+ HashHexToString(s, h.Digests[k_HashCalc_Index_Current], h.DigestSize);
+ const unsigned pos = (unsigned)strlen(s);
+ const int numSpaces = (int)GetColumnWidth(h.DigestSize) - (int)pos;
+ if (numSpaces > 0)
+ SetSpacesAndNul(s + pos, (unsigned)numSpaces);
+ if (i != 0)
+ _s += ' ';
+ _s += s;
+ }
+
+ /*
+ if (showSize)
+ {
+ _s += ' ';
+ static const unsigned kSizeField_Len = 13; // same as in HashCon.cpp
+ char s[kSizeField_Len + 32];
+ char *p = s;
+ SetSpacesAndNul(s, kSizeField_Len);
+ p = s + kSizeField_Len;
+ ConvertUInt64ToString(fileSize, p);
+ int numSpaces = (int)kSizeField_Len - (int)strlen(p);
+ if (numSpaces > 0)
+ p -= (unsigned)numSpaces;
+ _s += p;
+ }
+ */
+}
+
+
+static void Add_LF(CDynLimBuf &hashFileString, const CHashOptionsLocal &options)
+{
+ hashFileString += (char)(options.HashMode_Zero.Val ? 0 : '\n');
+}
+
+
+
+
+static void WriteLine(CDynLimBuf &hashFileString,
+ const CHashOptionsLocal &options,
+ const UString &path2,
+ bool isDir,
+ const AString &methodName,
+ const AString &hashesString)
+{
+ if (options.HashMode_OnlyHash.Val)
+ {
+ hashFileString += hashesString;
+ Add_LF(hashFileString, options);
+ return;
+ }
+
+ UString path = path2;
+
+ bool isBin = false;
+ const bool zeroMode = options.HashMode_Zero.Val;
+ const bool tagMode = options.HashMode_Tag.Val;
+
+#if CHAR_PATH_SEPARATOR != '/'
+ path.Replace(WCHAR_PATH_SEPARATOR, L'/');
+ // path.Replace((wchar_t)('\\' + 0xf000), L'\\'); // to debug WSL
+#endif
+
+ AString utf8;
+ ConvertUnicodeToUTF8(path, utf8);
+
+ AString esc;
+ CSum_Name_OriginalToEscape(utf8, esc);
+
+ if (!zeroMode)
+ {
+ if (esc != utf8)
+ {
+ /* Original md5sum writes escape in that case.
+ We do same for compatibility with original md5sum. */
+ hashFileString += '\\';
+ }
+ }
+
+ if (isDir && !esc.IsEmpty() && esc.Back() != '/')
+ esc += '/';
+
+ if (tagMode)
+ {
+ if (!methodName.IsEmpty())
+ {
+ hashFileString += methodName;
+ hashFileString += ' ';
+ }
+ hashFileString += '(';
+ hashFileString += esc;
+ hashFileString += ')';
+ hashFileString += " = ";
+ }
+
+ hashFileString += hashesString;
+
+ if (!tagMode)
+ {
+ hashFileString += ' ';
+ hashFileString += (char)(isBin ? '*' : ' ');
+ hashFileString += esc;
+ }
+
+ Add_LF(hashFileString, options);
+}
+
+
+
+static void WriteLine(CDynLimBuf &hashFileString,
+ const CHashOptionsLocal &options,
+ const UString &path,
+ bool isDir,
+ const CHashBundle &hb)
+{
+ AString methodName;
+ if (!hb.Hashers.IsEmpty())
+ methodName = hb.Hashers[0].Name;
+
+ AString hashesString;
+ AddHashResultLine(hashesString, hb.Hashers);
+ WriteLine(hashFileString, options, path, isDir, methodName, hashesString);
+}
+
+
HRESULT HashCalc(
DECL_EXTERNAL_CODECS_LOC_VARS
const NWildcard::CCensor &censor,
@@ -215,6 +475,8 @@ HRESULT HashCalc(
dirItems.SymLinks = options.SymLinks.Val;
dirItems.ScanAltStreams = options.AltStreamsMode;
+ dirItems.ExcludeDirItems = censor.ExcludeDirItems;
+ dirItems.ExcludeFileItems = censor.ExcludeFileItems;
HRESULT res = EnumerateItems(censor,
options.PathMode,
@@ -255,6 +517,11 @@ HRESULT HashCalc(
RINOK(callback->BeforeFirstFile(hb));
+ /*
+ CDynLimBuf hashFileString((size_t)1 << 31);
+ const bool needGenerate = !options.HashFilePath.IsEmpty();
+ */
+
for (i = 0; i < dirItems.Items.Size(); i++)
{
CMyComPtr<ISequentialInStream> inStream;
@@ -306,12 +573,15 @@ HRESULT HashCalc(
UInt64 fileSize = 0;
hb.InitForNewFile();
+
if (!isDir)
{
for (UInt32 step = 0;; step++)
{
if ((step & 0xFF) == 0)
+ {
RINOK(callback->SetCompleted(&completeValue));
+ }
UInt32 size;
RINOK(inStream->Read(buf, kBufSize, &size));
if (size == 0)
@@ -321,20 +591,54 @@ HRESULT HashCalc(
completeValue += size;
}
}
+
hb.Final(isDir, isAltStream, path);
+
+ /*
+ if (needGenerate
+ && (options.HashMode_Dirs.Val || !isDir))
+ {
+ WriteLine(hashFileString,
+ options,
+ path, // change it
+ isDir,
+ hb);
+
+ if (hashFileString.IsError())
+ return E_OUTOFMEMORY;
+ }
+ */
+
RINOK(callback->SetOperationResult(fileSize, hb, !isDir));
RINOK(callback->SetCompleted(&completeValue));
}
+
+ /*
+ if (needGenerate)
+ {
+ NFile::NIO::COutFile file;
+ if (!file.Create(us2fs(options.HashFilePath), true)) // createAlways
+ return GetLastError_noZero_HRESULT();
+ if (!file.WriteFull(hashFileString, hashFileString.Len()))
+ return GetLastError_noZero_HRESULT();
+ }
+ */
+
return callback->AfterLastFile(hb);
}
-static inline char GetHex(unsigned v)
+static inline char GetHex_Upper(unsigned v)
{
return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10)));
}
-void AddHashHexToString(char *dest, const Byte *data, UInt32 size)
+static inline char GetHex_Lower(unsigned v)
+{
+ return (char)((v < 10) ? ('0' + v) : ('a' + (v - 10)));
+}
+
+void HashHexToString(char *dest, const Byte *data, UInt32 size)
{
dest[size * 2] = 0;
@@ -349,18 +653,1393 @@ void AddHashHexToString(char *dest, const Byte *data, UInt32 size)
return;
}
- int step = 2;
if (size <= 8)
{
- step = -2;
- dest += size * 2 - 2;
+ dest += size * 2;
+ for (UInt32 i = 0; i < size; i++)
+ {
+ const unsigned b = data[i];
+ dest -= 2;
+ dest[0] = GetHex_Upper((b >> 4) & 0xF);
+ dest[1] = GetHex_Upper(b & 0xF);
+ }
+ }
+ else
+ {
+ for (UInt32 i = 0; i < size; i++)
+ {
+ const unsigned b = data[i];
+ dest[0] = GetHex_Lower((b >> 4) & 0xF);
+ dest[1] = GetHex_Lower(b & 0xF);
+ dest += 2;
+ }
+ }
+}
+
+void CHasherState::WriteToString(unsigned digestIndex, char *s) const
+{
+ HashHexToString(s, Digests[digestIndex], DigestSize);
+
+ if (digestIndex != 0 && NumSums[digestIndex] != 1)
+ {
+ unsigned numExtraBytes = GetNumExtraBytes_for_Group(digestIndex);
+ if (numExtraBytes > 4)
+ numExtraBytes = 8;
+ else // if (numExtraBytes >= 0)
+ numExtraBytes = 4;
+ // if (numExtraBytes != 0)
+ {
+ s += strlen(s);
+ *s++ = '-';
+ // *s = 0;
+ HashHexToString(s, GetExtraData_for_Group(digestIndex), numExtraBytes);
+ }
+ }
+}
+
+
+
+// ---------- Hash Handler ----------
+
+namespace NHash {
+
+static size_t ParseHexString(const char *s, Byte *dest) throw()
+{
+ size_t num;
+ for (num = 0;; num++, s += 2)
+ {
+ unsigned c = (Byte)s[0];
+ unsigned v0;
+ if (c >= '0' && c <= '9') v0 = (c - '0');
+ else if (c >= 'A' && c <= 'F') v0 = 10 + (c - 'A');
+ else if (c >= 'a' && c <= 'f') v0 = 10 + (c - 'a');
+ else
+ return num;
+ c = (Byte)s[1];
+ unsigned v1;
+ if (c >= '0' && c <= '9') v1 = (c - '0');
+ else if (c >= 'A' && c <= 'F') v1 = 10 + (c - 'A');
+ else if (c >= 'a' && c <= 'f') v1 = 10 + (c - 'a');
+ else
+ return num;
+ if (dest)
+ dest[num] = (Byte)(v1 | (v0 << 4));
+ }
+}
+
+
+#define IsWhite(c) ((c) == ' ' || (c) == '\t')
+
+bool CHashPair::IsDir() const
+{
+ if (Name.IsEmpty() || Name.Back() != '/')
+ return false;
+ // here we expect that Dir items contain only zeros or no Hash
+ for (size_t i = 0; i < Hash.Size(); i++)
+ if (Hash[i] != 0)
+ return false;
+ return true;
+}
+
+
+bool CHashPair::ParseCksum(const char *s)
+{
+ const char *end;
+
+ const UInt32 crc = ConvertStringToUInt32(s, &end);
+ if (*end != ' ')
+ return false;
+ end++;
+
+ const UInt64 size = ConvertStringToUInt64(end, &end);
+ if (*end != ' ')
+ return false;
+ end++;
+
+ Name = end;
+
+ Hash.Alloc(4);
+ SetBe32(Hash, crc);
+
+ Size_from_Arc = size;
+ Size_from_Arc_Defined = true;
+
+ return true;
+}
+
+
+
+static const char *SkipWhite(const char *s)
+{
+ while (IsWhite(*s))
+ s++;
+ return s;
+}
+
+static const char * const k_CsumMethodNames[] =
+{
+ "sha256"
+ , "sha224"
+// , "sha512/224"
+// , "sha512/256"
+ , "sha512"
+ , "sha384"
+ , "sha1"
+ , "md5"
+ , "blake2b"
+ , "crc64"
+ , "crc32"
+ , "cksum"
+};
+
+static UString GetMethod_from_FileName(const UString &name)
+{
+ AString s;
+ ConvertUnicodeToUTF8(name, s);
+ const int dotPos = s.ReverseFind_Dot();
+ const char *src = s.Ptr();
+ bool isExtension = false;
+ if (dotPos >= 0)
+ {
+ isExtension = true;
+ src = s.Ptr(dotPos + 1);
+ }
+ const char *m = "";
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(k_CsumMethodNames); i++)
+ {
+ m = k_CsumMethodNames[i];
+ if (isExtension)
+ {
+ if (StringsAreEqual_Ascii(src, m))
+ break;
+ }
+ else if (IsString1PrefixedByString2_NoCase_Ascii(src, m))
+ if (StringsAreEqual_Ascii(src + strlen(m), "sums"))
+ break;
+ }
+ UString res;
+ if (i != ARRAY_SIZE(k_CsumMethodNames))
+ res = m;
+ return res;
+}
+
+
+bool CHashPair::Parse(const char *s)
+{
+ // here we keep compatibility with original md5sum / shasum
+ bool escape = false;
+
+ s = SkipWhite(s);
+
+ if (*s == '\\')
+ {
+ s++;
+ escape = true;
+ }
+
+ // const char *kMethod = GetMethod_from_FileName(s);
+ // if (kMethod)
+ if (ParseHexString(s, NULL) < 4)
+ {
+ // BSD-style checksum line
+ {
+ const char *s2 = s;
+ for (; *s2 != 0; s2++)
+ {
+ const char c = *s2;
+ if (c == 0)
+ return false;
+ if (c == ' ' || c == '(')
+ break;
+ }
+ Method.SetFrom(s, (unsigned)(s2 - s));
+ s = s2;
+ }
+ IsBSD = true;
+ if (*s == ' ')
+ s++;
+ if (*s != '(')
+ return false;
+ s++;
+ {
+ const char *s2 = s;
+ for (; *s2 != 0; s2++)
+ {}
+ for (;;)
+ {
+ s2--;
+ if (s2 < s)
+ return false;
+ if (*s2 == ')')
+ break;
+ }
+ Name.SetFrom(s, (unsigned)(s2 - s));
+ s = s2 + 1;
+ }
+
+ s = SkipWhite(s);
+ if (*s != '=')
+ return false;
+ s++;
+ s = SkipWhite(s);
+ }
+
+ {
+ const size_t num = ParseHexString(s, NULL);
+ Hash.Alloc(num);
+ ParseHexString(s, Hash);
+ const size_t numChars = num * 2;
+ HashString.SetFrom(s, (unsigned)numChars);
+ s += numChars;
+ }
+
+ if (IsBSD)
+ {
+ if (*s != 0)
+ return false;
+ if (escape)
+ {
+ AString temp = Name;
+ return CSum_Name_EscapeToOriginal(temp, Name);
+ }
+ return true;
+ }
+
+ if (*s == 0)
+ return true;
+
+ if (*s != ' ')
+ return false;
+ s++;
+ const char c = *s;
+ if (c != ' '
+ && c != '*'
+ && c != 'U' // shasum Universal
+ && c != '^' // shasum 0/1
+ )
+ return false;
+ Mode = c;
+ s++;
+ if (escape)
+ return CSum_Name_EscapeToOriginal(s, Name);
+ Name = s;
+ return true;
+}
+
+
+static bool GetLine(CByteBuffer &buf, bool zeroMode, bool cr_lf_Mode, size_t &posCur, AString &s)
+{
+ s.Empty();
+ size_t pos = posCur;
+ const Byte *p = buf;
+ unsigned numDigits = 0;
+ for (; pos < buf.Size(); pos++)
+ {
+ const Byte b = p[pos];
+ if (b == 0)
+ {
+ numDigits = 1;
+ break;
+ }
+ if (zeroMode)
+ continue;
+ if (b == 0x0a)
+ {
+ numDigits = 1;
+ break;
+ }
+ if (!cr_lf_Mode)
+ continue;
+ if (b == 0x0d)
+ {
+ if (pos + 1 >= buf.Size())
+ {
+ numDigits = 1;
+ break;
+ // return false;
+ }
+ if (p[pos + 1] == 0x0a)
+ {
+ numDigits = 2;
+ break;
+ }
+ }
+ }
+ s.SetFrom((const char *)(p + posCur), (unsigned)(pos - posCur));
+ posCur = pos + numDigits;
+ return true;
+}
+
+
+static bool Is_CR_LF_Data(const Byte *buf, size_t size)
+{
+ bool isCrLf = false;
+ for (size_t i = 0; i < size;)
+ {
+ const Byte b = buf[i];
+ if (b == 0x0a)
+ return false;
+ if (b == 0x0d)
+ {
+ if (i == size - 1)
+ return false;
+ if (buf[i + 1] != 0x0a)
+ return false;
+ isCrLf = true;
+ i += 2;
+ }
+ else
+ i++;
+ }
+ return isCrLf;
+}
+
+
+static const Byte kArcProps[] =
+{
+ // kpidComment,
+ kpidCharacts
+};
+
+static const Byte kProps[] =
+{
+ kpidPath,
+ kpidSize,
+ kpidPackSize,
+ kpidMethod
+};
+
+static const Byte kRawProps[] =
+{
+ kpidChecksum
+};
+
+
+STDMETHODIMP CHandler::GetParent(UInt32 /* index */ , UInt32 *parent, UInt32 *parentType)
+{
+ *parentType = NParentType::kDir;
+ *parent = (UInt32)(Int32)-1;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
+{
+ *numProps = ARRAY_SIZE(kRawProps);
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID)
+{
+ *propID = kRawProps[index];
+ *name = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
+{
+ *data = NULL;
+ *dataSize = 0;
+ *propType = 0;
+
+ if (propID == kpidChecksum)
+ {
+ const CHashPair &hp = HashPairs[index];
+ if (hp.Hash.Size() > 0)
+ {
+ *data = hp.Hash;
+ *dataSize = (UInt32)hp.Hash.Size();
+ *propType = NPropDataType::kRaw;
+ }
+ return S_OK;
+ }
+
+ return S_OK;
+}
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = HashPairs.Size();
+ return S_OK;
+}
+
+static void Add_OptSpace_String(UString &dest, const char *src)
+{
+ dest.Add_Space_if_NotEmpty();
+ dest += src;
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ NWindows::NCOM::CPropVariant prop;
+ switch (propID)
+ {
+ case kpidPhySize: if (_phySize != 0) prop = _phySize; break;
+ /*
+ case kpidErrorFlags:
+ {
+ UInt32 v = 0;
+ if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
+ // if (_sres == k_Base64_RES_NeedMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
+ if (v != 0)
+ prop = v;
+ break;
+ }
+ */
+ case kpidCharacts:
+ {
+ UString s;
+ if (_hashSize_Defined)
+ {
+ s.Add_Space_if_NotEmpty();
+ s.Add_UInt32(_hashSize * 8);
+ s += "-bit";
+ }
+ if (!_nameExtenstion.IsEmpty())
+ {
+ s.Add_Space_if_NotEmpty();
+ s += _nameExtenstion;
+ }
+ if (_is_PgpMethod)
+ {
+ Add_OptSpace_String(s, "PGP");
+ if (!_pgpMethod.IsEmpty())
+ {
+ s += ":";
+ s += _pgpMethod;
+ }
+ }
+ if (_is_ZeroMode)
+ Add_OptSpace_String(s, "ZERO");
+ if (_are_there_Tags)
+ Add_OptSpace_String(s, "TAG");
+ if (_are_there_Dirs)
+ Add_OptSpace_String(s, "DIRS");
+ prop = s;
+ break;
+ }
+
+ case kpidReadOnly:
+ {
+ if (_isArc)
+ if (!CanUpdate())
+ prop = true;
+ break;
+ }
+ }
+ prop.Detach(value);
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ // COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant prop;
+ CHashPair &hp = HashPairs[index];
+ switch (propID)
+ {
+ case kpidIsDir:
+ {
+ prop = hp.IsDir();
+ break;
+ }
+ case kpidPath:
+ {
+ UString path;
+ hp.Get_UString_Path(path);
+
+ NArchive::NItemName::ReplaceToOsSlashes_Remove_TailSlash(path,
+ true); // useBackslashReplacement
+
+ prop = path;
+ break;
+ }
+ case kpidSize:
+ {
+ // client needs processed size of last file
+ if (hp.Size_from_Disk_Defined)
+ prop = (UInt64)hp.Size_from_Disk;
+ else if (hp.Size_from_Arc_Defined)
+ prop = (UInt64)hp.Size_from_Arc;
+ break;
+ }
+ case kpidPackSize:
+ {
+ prop = (UInt64)hp.Hash.Size();
+ break;
+ }
+ case kpidMethod:
+ {
+ if (!hp.Method.IsEmpty())
+ prop = hp.Method;
+ break;
+ }
+ }
+ prop.Detach(value);
+ return S_OK;
+ // COM_TRY_END
+}
+
+
+static HRESULT ReadStream_to_Buf(IInStream *stream, CByteBuffer &buf, IArchiveOpenCallback *openCallback)
+{
+ buf.Free();
+ UInt64 len;
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &len));
+ if (len == 0 || len >= ((UInt64)1 << 31))
+ return S_FALSE;
+ RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
+ buf.Alloc((size_t)len);
+ UInt64 pos = 0;
+ // return ReadStream_FALSE(stream, buf, (size_t)len);
+ for (;;)
+ {
+ const UInt32 kBlockSize = ((UInt32)1 << 24);
+ const UInt32 curSize = (len < kBlockSize) ? (UInt32)len : kBlockSize;
+ UInt32 processedSizeLoc;
+ RINOK(stream->Read((Byte *)buf + pos, curSize, &processedSizeLoc));
+ if (processedSizeLoc == 0)
+ return E_FAIL;
+ len -= processedSizeLoc;
+ pos += processedSizeLoc;
+ if (len == 0)
+ return S_OK;
+ if (openCallback)
+ {
+ const UInt64 files = 0;
+ RINOK(openCallback->SetCompleted(&files, &pos));
+ }
+ }
+}
+
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback)
+{
+ COM_TRY_BEGIN
+ {
+ Close();
+
+ CByteBuffer buf;
+ RINOK(ReadStream_to_Buf(stream, buf, openCallback))
+
+ CObjectVector<CHashPair> &pairs = HashPairs;
+
+ bool zeroMode = false;
+ bool cr_lf_Mode = false;
+ {
+ for (size_t i = 0; i < buf.Size(); i++)
+ if (buf[i] == 0)
+ {
+ zeroMode = true;
+ break;
+ }
+ }
+ _is_ZeroMode = zeroMode;
+ if (!zeroMode)
+ cr_lf_Mode = Is_CR_LF_Data(buf, buf.Size());
+
+ if (openCallback)
+ {
+ CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+ openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
+ NCOM::CPropVariant prop;
+ if (openVolumeCallback)
+ {
+ RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
+ if (prop.vt == VT_BSTR)
+ _nameExtenstion = GetMethod_from_FileName(prop.bstrVal);
+ }
+ }
+
+ bool cksumMode = false;
+ if (_nameExtenstion.IsEqualTo_Ascii_NoCase("cksum"))
+ cksumMode = true;
+ _is_CksumMode = cksumMode;
+
+ size_t pos = 0;
+ AString s;
+ bool minusMode = false;
+ unsigned numLines = 0;
+
+ while (pos < buf.Size())
+ {
+ if (!GetLine(buf, zeroMode, cr_lf_Mode, pos, s))
+ return S_FALSE;
+ numLines++;
+ if (s.IsEmpty())
+ continue;
+
+ if (s.IsPrefixedBy_Ascii_NoCase("; "))
+ {
+ if (numLines != 1)
+ return S_FALSE;
+ // comment line of FileVerifier++
+ continue;
+ }
+
+ if (s.IsPrefixedBy_Ascii_NoCase("-----"))
+ {
+ if (minusMode)
+ break; // end of pgp mode
+ minusMode = true;
+ if (s.IsPrefixedBy_Ascii_NoCase("-----BEGIN PGP SIGNED MESSAGE"))
+ {
+ if (_is_PgpMethod)
+ return S_FALSE;
+ if (!GetLine(buf, zeroMode, cr_lf_Mode, pos, s))
+ return S_FALSE;
+ const char *kStart = "Hash: ";
+ if (!s.IsPrefixedBy_Ascii_NoCase(kStart))
+ return S_FALSE;
+ _pgpMethod = s.Ptr((unsigned)strlen(kStart));
+ _is_PgpMethod = true;
+ }
+ continue;
+ }
+
+ CHashPair pair;
+ pair.FullLine = s;
+ if (cksumMode)
+ {
+ if (!pair.ParseCksum(s))
+ return S_FALSE;
+ }
+ else if (!pair.Parse(s))
+ return S_FALSE;
+ pairs.Add(pair);
+ }
+
+ {
+ unsigned hashSize = 0;
+ bool hashSize_Dismatch = false;
+ for (unsigned i = 0; i < HashPairs.Size(); i++)
+ {
+ const CHashPair &hp = HashPairs[i];
+ if (i == 0)
+ hashSize = (unsigned)hp.Hash.Size();
+ else
+ if (hashSize != hp.Hash.Size())
+ hashSize_Dismatch = true;
+
+ if (hp.IsBSD)
+ _are_there_Tags = true;
+ if (!_are_there_Dirs && hp.IsDir())
+ _are_there_Dirs = true;
+ }
+ if (!hashSize_Dismatch && hashSize != 0)
+ {
+ _hashSize = hashSize;
+ _hashSize_Defined = true;
+ }
+ }
+
+ _phySize = buf.Size();
+ _isArc = true;
+ return S_OK;
+ }
+ COM_TRY_END
+}
+
+
+void CHandler::ClearVars()
+{
+ _phySize = 0;
+ _isArc = false;
+ _is_CksumMode = false;
+ _is_PgpMethod = false;
+ _is_ZeroMode = false;
+ _are_there_Tags = false;
+ _are_there_Dirs = false;
+ _hashSize_Defined = false;
+ _hashSize = 0;
+}
+
+
+STDMETHODIMP CHandler::Close()
+{
+ ClearVars();
+ _nameExtenstion.Empty();
+ _pgpMethod.Empty();
+ HashPairs.Clear();
+ return S_OK;
+}
+
+
+static bool CheckDigests(const Byte *a, const Byte *b, size_t size)
+{
+ if (size <= 8)
+ {
+ /* we use reversed order for one digest, when text representation
+ uses big-order for crc-32 and crc-64 */
+ for (size_t i = 0; i < size; i++)
+ if (a[i] != b[size - 1 - i])
+ return false;
+ return true;
+ }
+ {
+ for (size_t i = 0; i < size; i++)
+ if (a[i] != b[i])
+ return false;
+ return true;
+ }
+}
+
+
+static void AddDefaultMethod(UStringVector &methods, unsigned size)
+{
+ const char *m = NULL;
+ if (size == 32) m = "sha256";
+ else if (size == 20) m = "sha1";
+ else if (size == 16) m = "md5";
+ else if (size == 8) m = "crc64";
+ else if (size == 4) m = "crc32";
+ else
+ return;
+ #ifdef EXTERNAL_CODECS
+ const CExternalCodecs *__externalCodecs = g_ExternalCodecs_Ptr;
+ #endif
+ CMethodId id;
+ if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS
+ AString(m), id))
+ methods.Add(UString(m));
+}
+
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+
+ /*
+ if (testMode == 0)
+ return E_NOTIMPL;
+ */
+
+ const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
+ if (allFilesMode)
+ numItems = HashPairs.Size();
+ if (numItems == 0)
+ return S_OK;
+
+ #ifdef EXTERNAL_CODECS
+ const CExternalCodecs *__externalCodecs = g_ExternalCodecs_Ptr;
+ #endif
+
+ CHashBundle hb_Glob;
+ // UStringVector methods = options.Methods;
+ UStringVector methods;
+
+ if (methods.IsEmpty() && !_nameExtenstion.IsEmpty())
+ {
+ AString utf;
+ ConvertUnicodeToUTF8(_nameExtenstion, utf);
+ CMethodId id;
+ if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS utf, id))
+ methods.Add(_nameExtenstion);
}
- for (UInt32 i = 0; i < size; i++)
+ if (methods.IsEmpty() && !_pgpMethod.IsEmpty())
{
- unsigned b = data[i];
- dest[0] = GetHex((b >> 4) & 0xF);
- dest[1] = GetHex(b & 0xF);
- dest += step;
+ CMethodId id;
+ if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS _pgpMethod, id))
+ methods.Add(UString(_pgpMethod));
+ }
+
+ if (methods.IsEmpty() && _pgpMethod.IsEmpty() && _hashSize_Defined)
+ AddDefaultMethod(methods, _hashSize);
+
+ RINOK(hb_Glob.SetMethods(
+ EXTERNAL_CODECS_LOC_VARS
+ methods));
+
+ CMyComPtr<IArchiveUpdateCallbackFile> updateCallbackFile;
+ extractCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&updateCallbackFile);
+ if (!updateCallbackFile)
+ return E_NOTIMPL;
+ {
+ CMyComPtr<IArchiveGetDiskProperty> GetDiskProperty;
+ extractCallback->QueryInterface(IID_IArchiveGetDiskProperty, (void **)&GetDiskProperty);
+ if (GetDiskProperty)
+ {
+ UInt64 totalSize = 0;
+ UInt32 i;
+ for (i = 0; i < numItems; i++)
+ {
+ const UInt32 index = allFilesMode ? i : indices[i];
+ const CHashPair &hp = HashPairs[index];
+ if (hp.IsDir())
+ continue;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(GetDiskProperty->GetDiskProperty(index, kpidSize, &prop));
+ if (prop.vt != VT_UI8)
+ continue;
+ totalSize += prop.uhVal.QuadPart;
+ }
+ }
+ RINOK(extractCallback->SetTotal(totalSize));
+ // RINOK(Hash_SetTotalUnpacked->Hash_SetTotalUnpacked(indices, numItems));
+ }
+ }
+
+ const UInt32 kBufSize = 1 << 15;
+ CHashMidBuf buf;
+ if (!buf.Alloc(kBufSize))
+ return E_OUTOFMEMORY;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+ lps->InSize = lps->OutSize = 0;
+
+ UInt32 i;
+ for (i = 0; i < numItems; i++)
+ {
+ RINOK(lps->SetCur());
+ const UInt32 index = allFilesMode ? i : indices[i];
+
+ CHashPair &hp = HashPairs[index];
+
+ UString path;
+ hp.Get_UString_Path(path);
+
+ CMyComPtr<ISequentialInStream> inStream;
+ const bool isDir = hp.IsDir();
+ if (!isDir)
+ {
+ RINOK(updateCallbackFile->GetStream2(index, &inStream, NUpdateNotifyOp::kHashRead));
+ if (!inStream)
+ {
+ continue; // we have shown error in GetStream2()
+ }
+ // askMode = NArchive::NExtract::NAskMode::kSkip;
+ }
+
+ Int32 askMode = testMode ?
+ NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ /* PrepareOperation() can expect kExtract to set
+ Attrib and security of output file */
+ askMode = NArchive::NExtract::NAskMode::kReadExternal;
+
+ extractCallback->PrepareOperation(askMode);
+
+ const bool isAltStream = false;
+
+ UInt64 fileSize = 0;
+
+ CHashBundle hb_Loc;
+
+ CHashBundle *hb_Use = &hb_Glob;
+
+ HRESULT res_SetMethods = S_OK;
+
+ UStringVector methods_loc;
+
+ if (!hp.Method.IsEmpty())
+ {
+ hb_Use = &hb_Loc;
+ CMethodId id;
+ if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS hp.Method, id))
+ {
+ methods_loc.Add(UString(hp.Method));
+ RINOK(hb_Loc.SetMethods(
+ EXTERNAL_CODECS_LOC_VARS
+ methods_loc));
+ }
+ else
+ res_SetMethods = E_NOTIMPL;
+ }
+ else if (methods.IsEmpty())
+ {
+ AddDefaultMethod(methods_loc, (unsigned)hp.Hash.Size());
+ if (!methods_loc.IsEmpty())
+ {
+ hb_Use = &hb_Loc;
+ RINOK(hb_Loc.SetMethods(
+ EXTERNAL_CODECS_LOC_VARS
+ methods_loc));
+ }
+ }
+
+ const bool isSupportedMode = hp.IsSupportedMode();
+ hb_Use->InitForNewFile();
+
+ if (inStream)
+ {
+ for (UInt32 step = 0;; step++)
+ {
+ if ((step & 0xFF) == 0)
+ {
+ RINOK(lps->SetRatioInfo(NULL, &fileSize));
+ }
+ UInt32 size;
+ RINOK(inStream->Read(buf, kBufSize, &size));
+ if (size == 0)
+ break;
+ hb_Use->Update(buf, size);
+ if (realOutStream)
+ {
+ RINOK(WriteStream(realOutStream, buf, size));
+ }
+ fileSize += size;
+ }
+
+ hp.Size_from_Disk = fileSize;
+ hp.Size_from_Disk_Defined = true;
+ }
+
+ realOutStream.Release();
+ inStream.Release();
+
+ lps->InSize += hp.Hash.Size();
+ lps->OutSize += fileSize;
+
+ hb_Use->Final(isDir, isAltStream, path);
+
+ Int32 opRes = NArchive::NExtract::NOperationResult::kUnsupportedMethod;
+ if (isSupportedMode
+ && res_SetMethods != E_NOTIMPL
+ && hb_Use->Hashers.Size() > 0
+ )
+ {
+ const CHasherState &hs = hb_Use->Hashers[0];
+ if (hs.DigestSize == hp.Hash.Size())
+ {
+ opRes = NArchive::NExtract::NOperationResult::kCRCError;
+ if (CheckDigests(hp.Hash, hs.Digests[0], hs.DigestSize))
+ if (!hp.Size_from_Arc_Defined || hp.Size_from_Arc == fileSize)
+ opRes = NArchive::NExtract::NOperationResult::kOK;
+ }
+ }
+
+ RINOK(extractCallback->SetOperationResult(opRes));
+ }
+
+ return lps->SetCur();
+
+ COM_TRY_END
+}
+
+
+// ---------- UPDATE ----------
+
+struct CUpdateItem
+{
+ int IndexInArc;
+ unsigned IndexInClient;
+ UInt64 Size;
+ bool NewData;
+ bool NewProps;
+ bool IsDir;
+ UString Path;
+
+ CUpdateItem(): Size(0), IsDir(false) {}
+};
+
+
+static HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId,
+ UString &res,
+ bool convertSlash)
+{
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(index, propId, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ res = prop.bstrVal;
+ if (convertSlash)
+ NArchive::NItemName::ReplaceSlashes_OsToUnix(res);
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
+{
+ *type = NFileTimeType::kUnix;
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *callback)
+{
+ COM_TRY_BEGIN
+
+ if (_isArc && !CanUpdate())
+ return E_NOTIMPL;
+
+ // const UINT codePage = CP_UTF8; // // (_forceCodePage ? _specifiedCodePage : _openCodePage);
+ // const unsigned utfFlags = g_Unicode_To_UTF8_Flags;
+ CObjectVector<CUpdateItem> updateItems;
+
+ UInt64 complexity = 0;
+
+ UInt32 i;
+ for (i = 0; i < numItems; i++)
+ {
+ CUpdateItem ui;
+ Int32 newData;
+ Int32 newProps;
+ UInt32 indexInArc;
+
+ if (!callback)
+ return E_FAIL;
+
+ RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc));
+
+ ui.NewProps = IntToBool(newProps);
+ ui.NewData = IntToBool(newData);
+ ui.IndexInArc = (int)indexInArc;
+ ui.IndexInClient = i;
+ if (IntToBool(newProps))
+ {
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidIsDir, &prop));
+ if (prop.vt == VT_EMPTY)
+ ui.IsDir = false;
+ else if (prop.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ ui.IsDir = (prop.boolVal != VARIANT_FALSE);
+ }
+
+ RINOK(GetPropString(callback, i, kpidPath, ui.Path,
+ true)); // convertSlash
+ /*
+ if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/')
+ ui.Name += '/';
+ */
+ }
+
+ if (IntToBool(newData))
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidSize, &prop));
+ if (prop.vt == VT_UI8)
+ {
+ ui.Size = prop.uhVal.QuadPart;
+ complexity += ui.Size;
+ }
+ else if (prop.vt == VT_EMPTY)
+ ui.Size = (UInt64)(Int64)-1;
+ else
+ return E_INVALIDARG;
+ }
+
+ updateItems.Add(ui);
+ }
+
+ if (complexity != 0)
+ {
+ RINOK(callback->SetTotal(complexity));
+ }
+
+ #ifdef EXTERNAL_CODECS
+ const CExternalCodecs *__externalCodecs = g_ExternalCodecs_Ptr;
+ #endif
+
+ CHashBundle hb;
+ UStringVector methods;
+ if (!_methods.IsEmpty())
+ {
+ FOR_VECTOR(k, _methods)
+ {
+ methods.Add(_methods[k]);
+ }
+ }
+ else if (_crcSize_WasSet)
+ {
+ AddDefaultMethod(methods, _crcSize);
+ }
+ else
+ {
+ CMyComPtr<IArchiveGetRootProps> getRootProps;
+ callback->QueryInterface(IID_IArchiveGetRootProps, (void **)&getRootProps);
+
+ NCOM::CPropVariant prop;
+ if (getRootProps)
+ {
+ RINOK(getRootProps->GetRootProp(kpidArcFileName, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ const UString method = GetMethod_from_FileName(prop.bstrVal);
+ if (!method.IsEmpty())
+ methods.Add(method);
+ }
+ }
+ }
+
+ RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS methods));
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(callback, true);
+
+ const UInt32 kBufSize = 1 << 15;
+ CHashMidBuf buf;
+ if (!buf.Alloc(kBufSize))
+ return E_OUTOFMEMORY;
+
+ CDynLimBuf hashFileString((size_t)1 << 31);
+
+ CHashOptionsLocal options = _options;
+
+ if (_isArc)
+ {
+ if (!options.HashMode_Zero.Def && _is_ZeroMode)
+ options.HashMode_Zero.Val = true;
+ if (!options.HashMode_Tag.Def && _are_there_Tags)
+ options.HashMode_Tag.Val = true;
+ if (!options.HashMode_Dirs.Def && _are_there_Dirs)
+ options.HashMode_Dirs.Val = true;
+ }
+ if (options.HashMode_OnlyHash.Val && updateItems.Size() != 1)
+ options.HashMode_OnlyHash.Val = false;
+
+ lps->OutSize = 0;
+ complexity = 0;
+
+ for (i = 0; i < updateItems.Size(); i++)
+ {
+ lps->InSize = complexity;
+ RINOK(lps->SetCur());
+
+ const CUpdateItem &ui = updateItems[i];
+
+ /*
+ CHashPair item;
+ if (!ui.NewProps)
+ item = HashPairs[(unsigned)ui.IndexInArc];
+ */
+
+ if (ui.NewData)
+ {
+ UInt64 currentComplexity = ui.Size;
+ CMyComPtr<ISequentialInStream> fileInStream;
+ bool needWrite = true;
+ {
+ HRESULT res = callback->GetStream(ui.IndexInClient, &fileInStream);
+
+ if (res == S_FALSE)
+ needWrite = false;
+ else
+ {
+ RINOK(res);
+
+ if (fileInStream)
+ {
+ CMyComPtr<IStreamGetProps> getProps;
+ fileInStream->QueryInterface(IID_IStreamGetProps, (void **)&getProps);
+ if (getProps)
+ {
+ FILETIME mTime;
+ UInt64 size2;
+ if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK)
+ {
+ currentComplexity = size2;
+ // item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);;
+ }
+ }
+ }
+ else
+ {
+ currentComplexity = 0;
+ }
+ }
+ }
+
+ hb.InitForNewFile();
+ const bool isDir = ui.IsDir;
+
+ if (needWrite && fileInStream && !isDir)
+ {
+ UInt64 fileSize = 0;
+ for (UInt32 step = 0;; step++)
+ {
+ if ((step & 0xFF) == 0)
+ {
+ RINOK(lps->SetRatioInfo(&fileSize, NULL));
+ // RINOK(callback->SetCompleted(&completeValue));
+ }
+ UInt32 size;
+ RINOK(fileInStream->Read(buf, kBufSize, &size));
+ if (size == 0)
+ break;
+ hb.Update(buf, size);
+ fileSize += size;
+ }
+ currentComplexity = fileSize;
+ }
+
+ fileInStream.Release();
+ const bool isAltStream = false;
+ hb.Final(isDir, isAltStream, ui.Path);
+
+ if (options.HashMode_Dirs.Val || !isDir)
+ {
+ if (!hb.Hashers.IsEmpty())
+ lps->OutSize += hb.Hashers[0].DigestSize;
+ WriteLine(hashFileString,
+ options,
+ ui.Path,
+ isDir,
+ hb);
+ if (hashFileString.IsError())
+ return E_OUTOFMEMORY;
+ }
+
+ complexity += currentComplexity;
+ RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+ }
+ else
+ {
+ // old data
+ const CHashPair &existItem = HashPairs[(unsigned)ui.IndexInArc];
+ if (ui.NewProps)
+ {
+ WriteLine(hashFileString,
+ options,
+ ui.Path,
+ ui.IsDir,
+ existItem.Method, existItem.HashString
+ );
+ }
+ else
+ {
+ hashFileString += existItem.FullLine;
+ Add_LF(hashFileString, options);
+ }
+ }
+ if (hashFileString.IsError())
+ return E_OUTOFMEMORY;
+ }
+
+ RINOK(WriteStream(outStream, hashFileString, hashFileString.Len()));
+
+ return S_OK;
+ COM_TRY_END
+}
+
+
+
+HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
+{
+ UString name = nameSpec;
+ name.MakeLower_Ascii();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+
+ if (name.IsEqualTo("m")) // "hm" hash method
+ {
+ // COneMethodInfo omi;
+ // RINOK(omi.ParseMethodFromPROPVARIANT(L"", value));
+ // _methods.Add(omi.MethodName); // change it. use omi.PropsString
+ if (value.vt != VT_BSTR)
+ return E_INVALIDARG;
+ UString s (value.bstrVal);
+ _methods.Add(s);
+ return S_OK;
+ }
+
+ if (name.IsEqualTo("flags"))
+ {
+ if (value.vt != VT_BSTR)
+ return E_INVALIDARG;
+ if (!_options.ParseString(value.bstrVal))
+ return E_INVALIDARG;
+ return S_OK;
+ }
+
+ if (name.IsPrefixedBy_Ascii_NoCase("crc"))
+ {
+ name.Delete(0, 3);
+ _crcSize = 4;
+ _crcSize_WasSet = true;
+ return ParsePropToUInt32(name, value, _crcSize);
+ }
+
+ // common properties
+ if (name.IsPrefixedBy_Ascii_NoCase("mt")
+ || name.IsPrefixedBy_Ascii_NoCase("memuse"))
+ return S_OK;
+
+ return E_INVALIDARG;
+}
+
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
+{
+ COM_TRY_BEGIN
+
+ InitProps();
+
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ RINOK(SetProperty(names[i], values[i]));
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+CHandler::CHandler()
+{
+ ClearVars();
+ InitProps();
+}
+
+}
+
+
+
+static IInArchive *CreateHashHandler_In() { return new NHash::CHandler; }
+static IOutArchive *CreateHashHandler_Out() { return new NHash::CHandler; }
+
+void Codecs_AddHashArcHandler(CCodecs *codecs)
+{
+ {
+ CArcInfoEx item;
+
+ item.Name = "Hash";
+ item.CreateInArchive = CreateHashHandler_In;
+ item.CreateOutArchive = CreateHashHandler_Out;
+ item.IsArcFunc = NULL;
+ item.Flags =
+ NArcInfoFlags::kKeepName
+ | NArcInfoFlags::kStartOpen
+ | NArcInfoFlags::kByExtOnlyOpen
+ // | NArcInfoFlags::kPureStartOpen
+ | NArcInfoFlags::kHashHandler
+ ;
+
+ // ubuntu uses "SHA256SUMS" file
+ item.AddExts(UString (
+ "sha256 sha512 sha224 sha384 sha1 sha md5"
+ // "b2sum"
+ " crc32 crc64"
+ " asc"
+ " cksum"
+ ),
+ UString());
+
+ item.UpdateEnabled = (item.CreateOutArchive != NULL);
+ item.SignatureOffset = 0;
+ // item.Version = MY_VER_MIX;
+ item.NewInterface = true;
+
+ item.Signatures.AddNew().CopyFrom(NULL, 0);
+
+ codecs->Formats.Add(item);
}
}
diff --git a/CPP/7zip/UI/Common/HashCalc.h b/CPP/7zip/UI/Common/HashCalc.h
index b6d320b5..80a55653 100644
--- a/CPP/7zip/UI/Common/HashCalc.h
+++ b/CPP/7zip/UI/Common/HashCalc.h
@@ -3,15 +3,17 @@
#ifndef __HASH_CALC_H
#define __HASH_CALC_H
+#include "../../../Common/UTFConvert.h"
#include "../../../Common/Wildcard.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/MethodProps.h"
#include "DirItem.h"
+#include "IFileExtractCallback.h"
const unsigned k_HashCalc_DigestSize_Max = 64;
-
+const unsigned k_HashCalc_ExtraSize = 8;
const unsigned k_HashCalc_NumGroups = 4;
enum
@@ -27,9 +29,37 @@ struct CHasherState
CMyComPtr<IHasher> Hasher;
AString Name;
UInt32 DigestSize;
- Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max];
+ UInt64 NumSums[k_HashCalc_NumGroups];
+ Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max + k_HashCalc_ExtraSize];
+
+ void InitDigestGroup(unsigned groupIndex)
+ {
+ NumSums[groupIndex] = 0;
+ memset(Digests[groupIndex], 0, sizeof(Digests[groupIndex]));
+ }
+
+ const Byte *GetExtraData_for_Group(unsigned groupIndex) const
+ {
+ return Digests[groupIndex] + k_HashCalc_DigestSize_Max;
+ }
+
+ unsigned GetNumExtraBytes_for_Group(unsigned groupIndex) const
+ {
+ const Byte *p = GetExtraData_for_Group(groupIndex);
+ // we use little-endian to read extra bytes
+ for (unsigned i = k_HashCalc_ExtraSize; i != 0; i--)
+ if (p[i - 1] != 0)
+ return i;
+ return 0;
+ }
+
+ void AddDigest(unsigned groupIndex, const Byte *data);
+
+ void WriteToString(unsigned digestIndex, char *s) const;
};
+
+
struct IHashCalc
{
virtual void InitForNewFile() = 0;
@@ -89,9 +119,68 @@ struct IHashCallbackUI: public IDirItemsCallback
INTERFACE_IHashCallbackUI(=0)
};
+
+struct CHashOptionsLocal
+{
+ CBoolPair HashMode_Zero;
+ CBoolPair HashMode_Tag;
+ CBoolPair HashMode_Dirs;
+ CBoolPair HashMode_OnlyHash;
+
+ void Init_HashOptionsLocal()
+ {
+ HashMode_Zero.Init();
+ HashMode_Tag.Init();
+ HashMode_Dirs.Init();
+ HashMode_OnlyHash.Init();
+ // HashMode_Dirs = true; // for debug
+ }
+
+ CHashOptionsLocal()
+ {
+ Init_HashOptionsLocal();
+ }
+
+ bool ParseFlagCharOption(wchar_t c, bool val)
+ {
+ c = MyCharLower_Ascii(c);
+ if (c == 'z') HashMode_Zero.SetVal_as_Defined(val);
+ else if (c == 't') HashMode_Tag.SetVal_as_Defined(val);
+ else if (c == 'd') HashMode_Dirs.SetVal_as_Defined(val);
+ else if (c == 'h') HashMode_OnlyHash.SetVal_as_Defined(val);
+ else return false;
+ return true;
+ }
+
+ bool ParseString(const UString &s)
+ {
+ for (unsigned i = 0; i < s.Len();)
+ {
+ const wchar_t c = s[i++];
+ bool val = true;
+ if (i < s.Len())
+ {
+ const wchar_t next = s[i];
+ if (next == '-')
+ {
+ val = false;
+ i++;
+ }
+ }
+ if (!ParseFlagCharOption(c, val))
+ return false;
+ }
+ return true;
+ }
+};
+
+
struct CHashOptions
+ // : public CHashOptionsLocal
{
UStringVector Methods;
+ // UString HashFilePath;
+
bool PreserveATime;
bool OpenShareForWrite;
bool StdInMode;
@@ -99,7 +188,7 @@ struct CHashOptions
CBoolPair SymLinks;
NWildcard::ECensorPathMode PathMode;
-
+
CHashOptions():
PreserveATime(false),
OpenShareForWrite(false),
@@ -108,6 +197,7 @@ struct CHashOptions
PathMode(NWildcard::k_RelatPath) {};
};
+
HRESULT HashCalc(
DECL_EXTERNAL_CODECS_LOC_VARS
const NWildcard::CCensor &censor,
@@ -115,6 +205,130 @@ HRESULT HashCalc(
AString &errorInfo,
IHashCallbackUI *callback);
-void AddHashHexToString(char *dest, const Byte *data, UInt32 size);
+
+
+#ifndef _SFX
+
+namespace NHash {
+
+struct CHashPair
+{
+ CByteBuffer Hash;
+ char Mode;
+ bool IsBSD;
+ bool Size_from_Arc_Defined;
+ bool Size_from_Disk_Defined;
+ AString Method;
+ AString Name;
+
+ AString FullLine;
+ AString HashString;
+ // unsigned HashLengthInBits;
+
+ // AString MethodName;
+ UInt64 Size_from_Arc;
+ UInt64 Size_from_Disk;
+
+ bool IsDir() const;
+
+ void Get_UString_Path(UString &path) const
+ {
+ path.Empty();
+ if (!ConvertUTF8ToUnicode(Name, path))
+ return;
+ }
+
+ bool ParseCksum(const char *s);
+ bool Parse(const char *s);
+
+ bool IsSupportedMode() const
+ {
+ return Mode != 'U' && Mode != '^';
+ }
+
+ CHashPair():
+ Mode(0)
+ , IsBSD(false)
+ , Size_from_Arc_Defined(false)
+ , Size_from_Disk_Defined(false)
+ // , HashLengthInBits(0)
+ , Size_from_Arc(0)
+ , Size_from_Disk(0)
+ {}
+};
+
+
+class CHandler:
+ public IInArchive,
+ public IArchiveGetRawProps,
+ // public IGetArchiveHashHandler,
+ public IOutArchive,
+ public ISetProperties,
+ public CMyUnknownImp
+{
+ bool _isArc;
+ UInt64 _phySize;
+ CObjectVector<CHashPair> HashPairs;
+ UString _nameExtenstion;
+ // UString _method_fromName;
+ AString _pgpMethod;
+ bool _is_CksumMode;
+ bool _is_PgpMethod;
+ bool _is_ZeroMode;
+ bool _are_there_Tags;
+ bool _are_there_Dirs;
+ bool _hashSize_Defined;
+ unsigned _hashSize;
+
+ bool _crcSize_WasSet;
+ UInt32 _crcSize;
+ UStringVector _methods;
+
+ void ClearVars();
+
+ void InitProps()
+ {
+ _crcSize_WasSet = false;
+ _crcSize = 4;
+ _methods.Clear();
+ _options.Init_HashOptionsLocal();
+ }
+
+ CHashOptionsLocal _options;
+
+ bool CanUpdate() const
+ {
+ if (!_isArc || _is_PgpMethod || _is_CksumMode)
+ return false;
+ return true;
+
+ }
+
+ HRESULT SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value);
+
+public:
+
+ CHandler();
+
+ MY_UNKNOWN_IMP4(
+ IInArchive,
+ IArchiveGetRawProps,
+ IOutArchive,
+ ISetProperties
+ /*, IGetArchiveHashHandler */
+ )
+ INTERFACE_IInArchive(;)
+ INTERFACE_IOutArchive(;)
+ INTERFACE_IArchiveGetRawProps(;)
+ // STDMETHOD(GetArchiveHashHandler)(CHandler **handler);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
+};
+
+}
+
+void Codecs_AddHashArcHandler(CCodecs *codecs);
+
+#endif
+
#endif
diff --git a/CPP/7zip/UI/Common/IFileExtractCallback.h b/CPP/7zip/UI/Common/IFileExtractCallback.h
index c456c862..e6a85c6d 100644
--- a/CPP/7zip/UI/Common/IFileExtractCallback.h
+++ b/CPP/7zip/UI/Common/IFileExtractCallback.h
@@ -103,9 +103,9 @@ DECL_INTERFACE_SUB(IGetProp, IUnknown, 0x01, 0x20)
STDMETHOD(UseExtractToStream)(Int32 *res) x; \
STDMETHOD(GetStream7)(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp) x; \
STDMETHOD(PrepareOperation7)(Int32 askExtractMode) x; \
- STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, Int32 encrypted) x; \
+ STDMETHOD(SetOperationResult8)(Int32 resultEOperationResult, Int32 encrypted, UInt64 size) x; \
-DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30)
+DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x31)
{
INTERFACE_IFolderExtractToStreamCallback(PURE)
};
diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp
index b94720c5..377963aa 100644
--- a/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -53,6 +53,7 @@ using namespace NWindows;
#include "../../ICoder.h"
#include "../../Common/RegisterArc.h"
+#include "../../Common/RegisterCodec.h"
#ifdef EXTERNAL_CODECS
@@ -193,9 +194,9 @@ void CArcInfoEx::AddExts(const UString &ext, const UString &addExt)
static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector<CByteBuffer> &signatures)
{
signatures.Clear();
- while (size > 0)
+ while (size != 0)
{
- unsigned len = *data++;
+ const unsigned len = *data++;
size--;
if (len > size)
return false;
@@ -252,6 +253,25 @@ static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 in
return S_OK;
}
+
+static HRESULT GetMethodBoolProp(Func_GetMethodProperty getMethodProperty, UInt32 index,
+ PROPID propId, bool &resVal, bool &isAssigned)
+{
+ NCOM::CPropVariant prop;
+ resVal = false;
+ isAssigned = false;
+ RINOK(getMethodProperty(index, propId, &prop));
+ if (prop.vt == VT_BOOL)
+ {
+ isAssigned = true;
+ resVal = VARIANT_BOOLToBool(prop.boolVal);
+ }
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+
#define MY_GET_FUNC(dest, type, func) *(void **)(&dest) = (func);
// #define MY_GET_FUNC(dest, type, func) dest = (type)(func);
@@ -279,6 +299,7 @@ HRESULT CCodecs::LoadCodecs()
info.CodecIndex = i;
RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned));
RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned));
+ RINOK(GetMethodBoolProp(lib.GetMethodProperty, i, NMethodPropID::kIsFilter, info.IsFilter, info.IsFilter_Assigned));
Codecs.Add(info);
}
}
@@ -647,8 +668,14 @@ HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPath)
}
if (!found)
break;
+ #ifdef _WIN32
if (fi.IsDir())
continue;
+ #else
+ if (enumerator.DirEntry_IsDir(fi, true)) // followLink
+ continue;
+ #endif
+
RINOK(LoadDll(folderPrefix + fi.Name, true));
}
return S_OK;
@@ -725,7 +752,10 @@ HRESULT CCodecs::Load()
if (arc.IsMultiSignature())
ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures);
else
- item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize);
+ {
+ if (arc.SignatureSize != 0) // 21.04
+ item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize);
+ }
#endif
@@ -776,6 +806,8 @@ HRESULT CCodecs::Load()
#endif
+ // we sort Formats to get fixed order of Formats after compilation.
+ Formats.Sort();
return S_OK;
}
@@ -952,6 +984,15 @@ STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *valu
prop.Detach(value);
return S_OK;
}
+
+ if (propID == NMethodPropID::kIsFilter && ci.IsFilter_Assigned)
+ {
+ NCOM::CPropVariant prop;
+ prop = (bool)ci.IsFilter;
+ prop.Detach(value);
+ return S_OK;
+ }
+
const CCodecLib &lib = Libs[ci.LibIndex];
return lib.GetMethodProperty(ci.CodecIndex, propID, value);
#else
@@ -1096,6 +1137,7 @@ bool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const
#endif
}
+
bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const
{
#ifdef EXPORT_CODECS
@@ -1118,6 +1160,38 @@ bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const
#endif
}
+
+bool CCodecs::GetCodec_IsFilter(UInt32 index, bool &isAssigned) const
+{
+ isAssigned = false;
+ #ifdef EXPORT_CODECS
+ if (index < g_NumCodecs)
+ {
+ NCOM::CPropVariant prop;
+ if (GetProperty(index, NMethodPropID::kIsFilter, &prop) == S_OK)
+ {
+ if (prop.vt == VT_BOOL)
+ {
+ isAssigned = true;
+ return VARIANT_BOOLToBool(prop.boolVal);
+ }
+ }
+ return false;
+ }
+ #endif
+
+ #ifdef EXTERNAL_CODECS
+ {
+ const CDllCodecInfo &c = Codecs[index - NUM_EXPORT_CODECS];
+ isAssigned = c.IsFilter_Assigned;
+ return c.IsFilter;
+ }
+ #else
+ return false;
+ #endif
+}
+
+
UInt32 CCodecs::GetCodec_NumStreams(UInt32 index)
{
NCOM::CPropVariant prop;
@@ -1203,3 +1277,45 @@ void CCodecs::GetCodecsErrorMessage(UString &s)
}
#endif // EXTERNAL_CODECS
+
+#ifndef _SFX
+
+extern unsigned g_NumCodecs;
+extern const CCodecInfo *g_Codecs[];
+
+void CCodecs::Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v)
+{
+ v.Clear();
+ {
+ for (unsigned i = 0; i < g_NumCodecs; i++)
+ {
+ const CCodecInfo &cod = *g_Codecs[i];
+ CCodecInfoUser &u = v.AddNew();
+ u.EncoderIsAssigned = (cod.CreateEncoder != NULL);
+ u.DecoderIsAssigned = (cod.CreateDecoder != NULL);
+ u.IsFilter_Assigned = true;
+ u.IsFilter = cod.IsFilter;
+ u.NumStreams = cod.NumStreams;
+ u.Name = cod.Name;
+ }
+ }
+
+
+ #ifdef EXTERNAL_CODECS
+ {
+ UInt32 numMethods;
+ if (GetNumMethods(&numMethods) == S_OK)
+ for (UInt32 j = 0; j < numMethods; j++)
+ {
+ CCodecInfoUser &u = v.AddNew();
+ u.EncoderIsAssigned = GetCodec_EncoderIsAssigned(j);
+ u.DecoderIsAssigned = GetCodec_DecoderIsAssigned(j);
+ u.IsFilter = GetCodec_IsFilter(j, u.IsFilter_Assigned);
+ u.NumStreams = GetCodec_NumStreams(j);
+ u.Name = GetCodec_Name(j);
+ }
+ }
+ #endif
+}
+
+#endif
diff --git a/CPP/7zip/UI/Common/LoadCodecs.h b/CPP/7zip/UI/Common/LoadCodecs.h
index 660ddee4..829472d0 100644
--- a/CPP/7zip/UI/Common/LoadCodecs.h
+++ b/CPP/7zip/UI/Common/LoadCodecs.h
@@ -68,6 +68,8 @@ struct CDllCodecInfo
UInt32 CodecIndex;
bool EncoderIsAssigned;
bool DecoderIsAssigned;
+ bool IsFilter;
+ bool IsFilter_Assigned;
CLSID Encoder;
CLSID Decoder;
};
@@ -119,6 +121,23 @@ struct CArcInfoEx
CLSID ClassID;
#endif
+ int Compare(const CArcInfoEx &a) const
+ {
+ int res = Name.Compare(a.Name);
+ if (res != 0)
+ return res;
+ #ifdef EXTERNAL_CODECS
+ return MyCompare(LibIndex, a.LibIndex);
+ #else
+ return 0;
+ #endif
+ /*
+ if (LibIndex < a.LibIndex) return -1;
+ if (LibIndex > a.LibIndex) return 1;
+ return 0;
+ */
+ }
+
bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; }
bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; }
@@ -133,6 +152,7 @@ struct CArcInfoEx
bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; }
bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; }
bool Flags_ByExtOnlyOpen() const { return (Flags & NArcInfoFlags::kByExtOnlyOpen) != 0; }
+ bool Flags_HashHandler() const { return (Flags & NArcInfoFlags::kHashHandler) != 0; }
UString GetMainExt() const
{
@@ -236,6 +256,21 @@ struct CCodecError
CCodecError(): ErrorCode(0) {}
};
+
+struct CCodecInfoUser
+{
+ // unsigned LibIndex;
+ // UInt32 CodecIndex;
+ // UInt64 id;
+ bool EncoderIsAssigned;
+ bool DecoderIsAssigned;
+ bool IsFilter;
+ bool IsFilter_Assigned;
+ UInt32 NumStreams;
+ AString Name;
+};
+
+
class CCodecs:
#ifdef EXTERNAL_CODECS
public ICompressCodecsInfo,
@@ -353,6 +388,7 @@ public:
int GetCodec_LibIndex(UInt32 index) const;
bool GetCodec_DecoderIsAssigned(UInt32 index) const;
bool GetCodec_EncoderIsAssigned(UInt32 index) const;
+ bool GetCodec_IsFilter(UInt32 index, bool &isAssigned) const;
UInt32 GetCodec_NumStreams(UInt32 index);
HRESULT GetCodec_Id(UInt32 index, UInt64 &id);
AString GetCodec_Name(UInt32 index);
@@ -416,6 +452,8 @@ public:
return -1;
}
+ void Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v);
+
#endif // _SFX
};
@@ -432,5 +470,5 @@ public:
CCodecs *codecs = new CCodecs; \
CMyComPtr<IUnknown> __codecsRef = codecs;
#endif
-
+
#endif
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
index 7bec9d53..331793f1 100644
--- a/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -1026,30 +1026,33 @@ static void MakeCheckOrder(CCodecs *codecs,
{
for (unsigned i = 0; i < numTypes; i++)
{
- int index = orderIndices[i];
+ const int index = orderIndices[i];
if (index < 0)
continue;
const CArcInfoEx &ai = codecs->Formats[(unsigned)index];
- if (ai.SignatureOffset != 0)
+ if (ai.SignatureOffset == 0)
{
- orderIndices2.Add(index);
- orderIndices[i] = -1;
- continue;
- }
-
- const CObjectVector<CByteBuffer> &sigs = ai.Signatures;
- FOR_VECTOR (k, sigs)
- {
- const CByteBuffer &sig = sigs[k];
- if ((sig.Size() == 0 && dataSize == 0)
- || (sig.Size() != 0 && sig.Size() <= dataSize
- && TestSignature(data, sig, sig.Size())))
+ if (ai.Signatures.IsEmpty())
{
- orderIndices2.Add(index);
- orderIndices[i] = -1;
- break;
+ if (dataSize != 0) // 21.04: no Sinature means Empty Signature
+ continue;
+ }
+ else
+ {
+ unsigned k;
+ const CObjectVector<CByteBuffer> &sigs = ai.Signatures;
+ for (k = 0; k < sigs.Size(); k++)
+ {
+ const CByteBuffer &sig = sigs[k];
+ if (sig.Size() <= dataSize && TestSignature(data, sig, sig.Size()))
+ break;
+ }
+ if (k == sigs.Size())
+ continue;
}
}
+ orderIndices2.Add(index);
+ orderIndices[i] = -1;
}
}
@@ -2143,7 +2146,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
continue;
}
- bool isNewStyleSignature = IsNewStyleSignature(ai);
+ const bool isNewStyleSignature = IsNewStyleSignature(ai);
bool needCheck = !isNewStyleSignature
|| ai.Signatures.IsEmpty()
|| ai.Flags_PureStartOpen()
@@ -2156,13 +2159,12 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
for (k = 0; k < ai.Signatures.Size(); k++)
{
const CByteBuffer &sig = ai.Signatures[k];
- UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size();
- if (processedSize < signatureEnd)
+ if (processedSize < ai.SignatureOffset + sig.Size())
{
if (!endOfFile)
needCheck = true;
}
- else if (memcmp(sig, byteBuffer + ai.SignatureOffset, sig.Size()) == 0)
+ else if (TestSignature(sig, byteBuffer + ai.SignatureOffset, sig.Size()))
break;
}
if (k != ai.Signatures.Size())
@@ -3390,7 +3392,7 @@ HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI)
return S_OK;
}
-HRESULT CArc::ReOpen(const COpenOptions &op)
+HRESULT CArc::ReOpen(const COpenOptions &op, IArchiveOpenCallback *openCallback_Additional)
{
ErrorInfo.ClearErrors();
ErrorInfo.ErrorFormatIndex = -1;
@@ -3420,7 +3422,10 @@ HRESULT CArc::ReOpen(const COpenOptions &op)
// There are archives with embedded STUBs (like ZIP), so we must support signature scanning
// But for another archives we can use 0 here. So the code can be fixed !!!
UInt64 maxStartPosition = kMaxCheckStartPosition;
- HRESULT res = Archive->Open(stream2, &maxStartPosition, op.callback);
+ IArchiveOpenCallback *openCallback = openCallback_Additional;
+ if (!openCallback)
+ openCallback = op.callback;
+ HRESULT res = Archive->Open(stream2, &maxStartPosition, openCallback);
if (res == S_OK)
{
@@ -3476,7 +3481,7 @@ HRESULT CArchiveLink::ReOpen(COpenOptions &op)
op.stream = stream;
CArc &arc = Arcs[0];
- HRESULT res = arc.ReOpen(op);
+ HRESULT res = arc.ReOpen(op, openCallbackNew);
PasswordWasAsked = openCallbackSpec->PasswordWasAsked;
// Password = openCallbackSpec->Password;
@@ -3579,6 +3584,12 @@ static bool ParseType(CCodecs &codecs, const UString &s, COpenType &type)
type.CanReturnArc = false;
type.CanReturnParser = true;
}
+ else if (name.IsEqualTo_Ascii_NoCase("hash"))
+ {
+ // type.CanReturnArc = false;
+ // type.CanReturnParser = false;
+ type.IsHashType = true;
+ }
else
return false;
}
@@ -3606,6 +3617,7 @@ static bool ParseType(CCodecs &codecs, const UString &s, COpenType &type)
bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types)
{
types.Clear();
+ bool isHashType = false;
for (unsigned pos = 0; pos < s.Len();)
{
int pos2 = s.Find(L'.', pos);
@@ -3617,10 +3629,24 @@ bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType>
COpenType type;
if (!ParseType(codecs, name, type))
return false;
+ if (isHashType)
+ return false;
+ if (type.IsHashType)
+ isHashType = true;
types.Add(type);
pos = (unsigned)pos2 + 1;
}
return true;
}
+/*
+bool IsHashType(const CObjectVector<COpenType> &types)
+{
+ if (types.Size() != 1)
+ return false;
+ return types[0].IsHashType;
+}
+*/
+
+
#endif
diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h
index ebeb91d1..4e1192cf 100644
--- a/CPP/7zip/UI/Common/OpenArchive.h
+++ b/CPP/7zip/UI/Common/OpenArchive.h
@@ -70,6 +70,7 @@ struct COpenType
bool CanReturnArc;
bool CanReturnParser;
+ bool IsHashType;
bool EachPos;
// bool SkipSfxStub;
@@ -90,6 +91,7 @@ struct COpenType
Recursive(true),
CanReturnArc(true),
CanReturnParser(false),
+ IsHashType(false),
EachPos(false),
// SkipSfxStub(true),
// ExeAsUnknown(true),
@@ -285,7 +287,7 @@ public:
UString Path;
UString filePath;
UString DefaultName;
- int FormatIndex; // - 1 means Parser.
+ int FormatIndex; // -1 means Parser
UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile
FILETIME MTime;
bool MTimeDefined;
@@ -358,9 +360,16 @@ public:
HRESULT OpenStream(const COpenOptions &options);
HRESULT OpenStreamOrFile(COpenOptions &options);
- HRESULT ReOpen(const COpenOptions &options);
+ HRESULT ReOpen(const COpenOptions &options, IArchiveOpenCallback *openCallback_Additional);
HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);
+
+ bool IsHashHandler(const COpenOptions &options) const
+ {
+ if (FormatIndex < 0)
+ return false;
+ return options.codecs->Formats[(unsigned)FormatIndex].Flags_HashHandler();
+ }
};
struct CArchiveLink
@@ -421,6 +430,8 @@ struct CArchiveLink
bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
+// bool IsHashType(const CObjectVector<COpenType> &types);
+
struct CDirPathSortPair
{
diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp
index fc922a70..4bd690d6 100644
--- a/CPP/7zip/UI/Common/Update.cpp
+++ b/CPP/7zip/UI/Common/Update.cpp
@@ -542,9 +542,9 @@ static HRESULT Compress(
#endif
}
- if (outArchive == 0)
+ if (!outArchive)
throw kUpdateIsNotSupoorted;
-
+
NFileTimeType::EEnum fileTimeType;
{
UInt32 value;
@@ -568,6 +568,8 @@ static HRESULT Compress(
return E_NOTIMPL;
if (options.NtSecurity.Val && !arcInfo.Flags_NtSecure())
return E_NOTIMPL;
+ if (options.DeleteAfterCompressing && arcInfo.Flags_HashHandler())
+ return E_NOTIMPL;
}
CRecordVector<CUpdatePair2> updatePairs2;
@@ -745,6 +747,11 @@ static HRESULT Compress(
updateCallbackSpec->ProcessedItemsStatuses = processedItemsStatuses;
+ {
+ const UString arcPath = archivePath.GetFinalPath();
+ updateCallbackSpec->ArcFileName = ExtractFileNameFromPath(arcPath);
+ }
+
if (options.RenamePairs.Size() != 0)
updateCallbackSpec->NewNames = &newNames;
@@ -907,7 +914,7 @@ static HRESULT Compress(
ft.dwHighDateTime = 0;
FOR_VECTOR (i, updatePairs2)
{
- CUpdatePair2 &pair2 = updatePairs2[i];
+ const CUpdatePair2 &pair2 = updatePairs2[i];
const FILETIME *ft2 = NULL;
if (pair2.NewProps && pair2.DirIndex >= 0)
ft2 = &dirItems.Items[(unsigned)pair2.DirIndex].MTime;
@@ -945,9 +952,28 @@ static HRESULT Compress(
result = outStreamSpec->Close();
else if (volStreamSpec)
result = volStreamSpec->Close();
+
+ RINOK(result)
+
+ if (processedItemsStatuses)
+ {
+ FOR_VECTOR (i, updatePairs2)
+ {
+ const CUpdatePair2 &up = updatePairs2[i];
+ if (up.NewData && up.DirIndex >= 0)
+ {
+ const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex];
+ if (di.AreReparseData() || (!di.IsDir() && di.Size == 0))
+ processedItemsStatuses[(unsigned)up.DirIndex] = 1;
+ }
+ }
+ }
+
return result;
}
+
+
bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include);
static bool Censor_CheckPath(const NWildcard::CCensor &censor, const CReadArcItem &item)
@@ -1288,6 +1314,8 @@ HRESULT UpdateArchive(
#endif
dirItems.ScanAltStreams = options.AltStreams.Val;
+ dirItems.ExcludeDirItems = censor.ExcludeDirItems;
+ dirItems.ExcludeFileItems = censor.ExcludeFileItems;
HRESULT res = EnumerateItems(censor,
options.PathMode,
@@ -1440,7 +1468,7 @@ HRESULT UpdateArchive(
CByteBuffer processedItems;
if (options.DeleteAfterCompressing)
{
- unsigned num = dirItems.Items.Size();
+ const unsigned num = dirItems.Items.Size();
processedItems.Alloc(num);
for (unsigned i = 0; i < num; i++)
processedItems[i] = 0;
@@ -1654,17 +1682,27 @@ HRESULT UpdateArchive(
}
else
{
- if (processedItems[i] != 0 || dirItem.Size == 0)
+ // 21.04: we have set processedItems[*] before for all required items
+ if (processedItems[i] != 0
+ // || dirItem.Size == 0
+ // || dirItem.AreReparseData()
+ )
{
NFind::CFileInfo fileInfo;
- /* here we compare Raw FileInfo that can be link with actual file info that was processed.
- we can fix it. */
- if (fileInfo.Find(phyPath))
+ /* if (!SymLinks), we follow link here, similar to (dirItem) filling */
+ if (fileInfo.Find(phyPath, !options.SymLinks.Val))
{
- // FIXME: here we can check Find_FollowLink() also;
+ bool is_SameSize = false;
+ if (options.SymLinks.Val && dirItem.AreReparseData())
+ {
+ /* (dirItem.Size = dirItem.ReparseData.Size()) was set before.
+ So we don't compare sizes for that case here */
+ is_SameSize = fileInfo.IsOsSymLink();
+ }
+ else
+ is_SameSize = (fileInfo.Size == dirItem.Size);
- // maybe we must exclude also files with archive name: "a a.7z * -sdel"
- if (fileInfo.Size == dirItem.Size
+ if (is_SameSize
&& CompareFileTime(&fileInfo.MTime, &dirItem.MTime) == 0
&& CompareFileTime(&fileInfo.CTime, &dirItem.CTime) == 0)
{
@@ -1675,11 +1713,11 @@ HRESULT UpdateArchive(
}
else
{
- // file was skipped
+ // file was skipped by some reason. We can throw error for debug:
/*
errorInfo.SystemError = 0;
errorInfo.Message = "file was not processed";
- errorInfo.FileName = phyPath;
+ errorInfo.FileNames.Add(phyPath);
return E_FAIL;
*/
}
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp
index 69cde093..7b705ba3 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.cpp
+++ b/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -144,6 +144,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *val
case kpidCTime: if (ParentDirItem) prop = ParentDirItem->CTime; break;
case kpidATime: if (ParentDirItem) prop = ParentDirItem->ATime; break;
case kpidMTime: if (ParentDirItem) prop = ParentDirItem->MTime; break;
+ case kpidArcFileName: if (!ArcFileName.IsEmpty()) prop = ArcFileName; break;
}
prop.Detach(value);
return S_OK;
@@ -475,6 +476,17 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
static NSynchronization::CCriticalSection CS;
#endif
+void CArchiveUpdateCallback::UpdateProcessedItemStatus(unsigned dirIndex)
+{
+ if (ProcessedItemsStatuses)
+ {
+ #ifndef _7ZIP_ST
+ NSynchronization::CCriticalSectionLock lock(CS);
+ #endif
+ ProcessedItemsStatuses[dirIndex] = 1;
+ }
+}
+
STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode)
{
COM_TRY_BEGIN
@@ -544,6 +556,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea
CMyComPtr<ISequentialInStream> inStreamLoc = inStreamSpec;
inStreamSpec->Init(di.ReparseData, di.ReparseData.Size());
*inStream = inStreamLoc.Detach();
+
+ UpdateProcessedItemStatus((unsigned)up.DirIndex);
return S_OK;
}
#endif // !defined(UNDER_CE)
@@ -600,13 +614,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea
}
// #endif
- if (ProcessedItemsStatuses)
- {
- #ifndef _7ZIP_ST
- NSynchronization::CCriticalSectionLock lock(CS);
- #endif
- ProcessedItemsStatuses[(unsigned)up.DirIndex] = 1;
- }
+ UpdateProcessedItemStatus((unsigned)up.DirIndex);
*inStream = inStreamLoc.Detach();
}
@@ -649,7 +657,7 @@ STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 in
isDir = DirItems->Items[(unsigned)up.DirIndex].IsDir();
}
}
- return Callback->ReportUpdateOpeartion(op, name.IsEmpty() ? NULL : name.Ptr(), isDir);
+ return Callback->ReportUpdateOperation(op, name.IsEmpty() ? NULL : name.Ptr(), isDir);
}
wchar_t temp[16];
@@ -684,7 +692,7 @@ STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 in
if (!s)
s = L"";
- return Callback->ReportUpdateOpeartion(op, s, isDir);
+ return Callback->ReportUpdateOperation(op, s, isDir);
COM_TRY_END
}
diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h
index 3fe0a647..d27776ef 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.h
+++ b/CPP/7zip/UI/Common/UpdateCallback.h
@@ -40,7 +40,7 @@ struct CArcToDoStat
virtual HRESULT ReadingFileError(const FString &path, DWORD systemError) x; \
virtual HRESULT SetOperationResult(Int32 opRes) x; \
virtual HRESULT ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) x; \
- virtual HRESULT ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir) x; \
+ virtual HRESULT ReportUpdateOperation(UInt32 op, const wchar_t *name, bool isDir) x; \
/* virtual HRESULT SetPassword(const UString &password) x; */ \
virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \
virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \
@@ -87,6 +87,8 @@ class CArchiveUpdateCallback:
UInt32 _hardIndex_From;
UInt32 _hardIndex_To;
+ void UpdateProcessedItemStatus(unsigned dirIndex);
+
public:
MY_QUERYINTERFACE_BEGIN2(IArchiveUpdateCallback2)
MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackFile)
@@ -121,6 +123,7 @@ public:
CRecordVector<UInt64> VolumesSizes;
FString VolName;
FString VolExt;
+ UString ArcFileName; // without path prefix
IUpdateCallbackUI *Callback;
@@ -147,7 +150,6 @@ public:
Byte *ProcessedItemsStatuses;
-
CArchiveUpdateCallback();
bool IsDir(const CUpdatePair2 &up) const
diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp
index 53ec5525..f6a32547 100644
--- a/CPP/7zip/UI/Console/Console.dsp
+++ b/CPP/7zip/UI/Console/Console.dsp
@@ -405,6 +405,14 @@ SOURCE=..\..\..\Common\Defs.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\DynLimBuf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\DynLimBuf.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\IntToString.cpp
# End Source File
# Begin Source File
@@ -886,6 +894,14 @@ SOURCE=..\..\..\..\C\Threads.h
# PROP Default_Filter ""
# Begin Source File
+SOURCE=..\..\Archive\Common\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ItemNameUtils.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
index 23eab615..24c21e8d 100644
--- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
@@ -187,6 +187,7 @@ static NSynchronization::CCriticalSection g_CriticalSection;
static const char * const kTestString = "T";
static const char * const kExtractString = "-";
static const char * const kSkipString = ".";
+static const char * const kReadString = "H";
// static const char * const kCantAutoRename = "cannot create file with auto name\n";
// static const char * const kCantRenameFile = "cannot rename existing file\n";
@@ -317,7 +318,7 @@ STDMETHODIMP CExtractCallbackConsole::AskOverwrite(
return CheckBreak2();
}
-STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 /* isFolder */, Int32 askExtractMode, const UInt64 *position)
+STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position)
{
MT_LOCK
@@ -331,6 +332,7 @@ STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int3
case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break;
case NArchive::NExtract::NAskMode::kTest: s = kTestString; break;
case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; requiredLevel = 2; break;
+ case NArchive::NExtract::NAskMode::kReadExternal: s = kReadString; requiredLevel = 0; break;
default: s = "???"; requiredLevel = 2;
};
@@ -350,6 +352,12 @@ STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int3
{
_tempU = name;
_so->Normalize_UString(_tempU);
+ // 21.04
+ if (isFolder)
+ {
+ if (!_tempU.IsEmpty() && _tempU.Back() != WCHAR_PATH_SEPARATOR)
+ _tempU.Add_PathSepar();
+ }
}
_so->PrintUString(_tempU, _tempA);
if (position)
diff --git a/CPP/7zip/UI/Console/HashCon.cpp b/CPP/7zip/UI/Console/HashCon.cpp
index a70f5f8a..1bd75c15 100644
--- a/CPP/7zip/UI/Console/HashCon.cpp
+++ b/CPP/7zip/UI/Console/HashCon.cpp
@@ -4,6 +4,8 @@
#include "../../../Common/IntToString.h"
+#include "../../../Windows/FileName.h"
+
#include "ConsoleClose.h"
#include "HashCon.h"
@@ -33,13 +35,15 @@ HRESULT CHashCallbackConsole::StartScanning()
return CheckBreak2();
}
-HRESULT CHashCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
+HRESULT CHashCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir)
{
if (NeedPercents())
{
_percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams;
_percent.Completed = st.GetTotalBytes();
_percent.FileName = fs2us(path);
+ if (isDir)
+ NWindows::NFile::NName::NormalizeDirPathPrefix(_percent.FileName);
_percent.Print();
}
return CheckBreak2();
@@ -111,6 +115,15 @@ static void SetSpacesAndNul(char *s, unsigned num)
s[num] = 0;
}
+static void SetSpacesAndNul_if_Positive(char *s, int num)
+{
+ if (num < 0)
+ return;
+ for (int i = 0; i < num; i++)
+ s[i] = ' ';
+ s[num] = 0;
+}
+
static const unsigned kSizeField_Len = 13;
static const unsigned kNameField_Len = 12;
@@ -122,61 +135,83 @@ static unsigned GetColumnWidth(unsigned digestSize)
return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width;
}
-void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector<CHasherState> &hashers)
+
+AString CHashCallbackConsole::GetFields() const
{
- _s.Empty();
-
- for (unsigned i = 0; i < hashers.Size(); i++)
- {
- if (i != 0)
- _s.Add_Space();
- const CHasherState &h = hashers[i];
- AddMinuses(_s, GetColumnWidth(h.DigestSize));
- }
+ AString s = PrintFields;
+ if (s.IsEmpty())
+ s = "hsn";
+ s.MakeLower_Ascii();
+ return s;
+}
- if (PrintSize)
- {
- _s.Add_Space();
- AddMinuses(_s, kSizeField_Len);
- }
- if (PrintName)
+void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector<CHasherState> &hashers)
+{
+ _s.Empty();
+ const AString fields = GetFields();
+ for (unsigned pos = 0; pos < fields.Len(); pos++)
{
- AddSpacesBeforeName();
- AddMinuses(_s, kNameField_Len);
+ const char c = fields[pos];
+ if (c == 'h')
+ {
+ for (unsigned i = 0; i < hashers.Size(); i++)
+ {
+ AddSpace();
+ const CHasherState &h = hashers[i];
+ AddMinuses(_s, GetColumnWidth(h.DigestSize));
+ }
+ }
+ else if (c == 's')
+ {
+ AddSpace();
+ AddMinuses(_s, kSizeField_Len);
+ }
+ else if (c == 'n')
+ {
+ AddSpacesBeforeName();
+ AddMinuses(_s, kNameField_Len);
+ }
}
*_so << _s << endl;
}
+
HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb)
{
if (PrintHeaders && _so)
{
_s.Empty();
ClosePercents_for_so();
-
- FOR_VECTOR (i, hb.Hashers)
- {
- if (i != 0)
- _s.Add_Space();
- const CHasherState &h = hb.Hashers[i];
- _s += h.Name;
- AddSpaces_if_Positive(_s, (int)GetColumnWidth(h.DigestSize) - (int)h.Name.Len());
- }
-
- if (PrintSize)
- {
- _s.Add_Space();
- const AString s2 ("Size");
- AddSpaces_if_Positive(_s, (int)kSizeField_Len - (int)s2.Len());
- _s += s2;
- }
-
- if (PrintName)
+
+ const AString fields = GetFields();
+ for (unsigned pos = 0; pos < fields.Len(); pos++)
{
- AddSpacesBeforeName();
- _s += "Name";
+ const char c = fields[pos];
+ if (c == 'h')
+ {
+ FOR_VECTOR (i, hb.Hashers)
+ {
+ AddSpace();
+ const CHasherState &h = hb.Hashers[i];
+ _s += h.Name;
+ AddSpaces_if_Positive(_s, (int)GetColumnWidth(h.DigestSize) - (int)h.Name.Len());
+ }
+ }
+
+ else if (c == 's')
+ {
+ AddSpace();
+ const AString s2 ("Size");
+ AddSpaces_if_Positive(_s, (int)kSizeField_Len - (int)s2.Len());
+ _s += s2;
+ }
+ else if (c == 'n')
+ {
+ AddSpacesBeforeName();
+ _s += "Name";
+ }
}
*_so << _s << endl;
@@ -191,9 +226,11 @@ HRESULT CHashCallbackConsole::OpenFileError(const FString &path, DWORD systemErr
return OpenFileError_Base(path, systemError);
}
-HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool /* isFolder */)
+HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool isDir)
{
_fileName = name;
+ if (isDir)
+ NWindows::NFile::NName::NormalizeDirPathPrefix(_fileName);
if (NeedPercents())
{
@@ -208,57 +245,81 @@ HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool /* isFolder */
return CheckBreak2();
}
+
+static const unsigned k_DigestStringSize = k_HashCalc_DigestSize_Max * 2 + k_HashCalc_ExtraSize * 2 + 16;
+
+
+
void CHashCallbackConsole::PrintResultLine(UInt64 fileSize,
- const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash)
+ const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash,
+ const AString &path)
{
ClosePercents_for_so();
_s.Empty();
-
- FOR_VECTOR (i, hashers)
- {
- const CHasherState &h = hashers[i];
- char s[k_HashCalc_DigestSize_Max * 2 + 64];
- s[0] = 0;
- if (showHash)
- AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize);
- const unsigned pos = (unsigned)strlen(s);
- SetSpacesAndNul(s + pos, GetColumnWidth(h.DigestSize) - pos);
- if (i != 0)
- _s.Add_Space();
- _s += s;
- }
+ const AString fields = GetFields();
- if (PrintSize)
+ for (unsigned pos = 0; pos < fields.Len(); pos++)
{
- _s.Add_Space();
-
- char s[kSizeField_Len + 32];
- char *p = s;
-
- SetSpacesAndNul(s, kSizeField_Len);
- if (showHash)
+ const char c = fields[pos];
+ if (c == 'h')
{
- p = s + kSizeField_Len;
- ConvertUInt64ToString(fileSize, p);
- int numSpaces = (int)kSizeField_Len - (int)strlen(p);
- if (numSpaces > 0)
- p -= (unsigned)numSpaces;
+ FOR_VECTOR (i, hashers)
+ {
+ AddSpace();
+ const CHasherState &h = hashers[i];
+ char s[k_DigestStringSize];
+ s[0] = 0;
+ if (showHash)
+ h.WriteToString(digestIndex, s);
+ const unsigned len = (unsigned)strlen(s);
+ SetSpacesAndNul_if_Positive(s + len, (int)GetColumnWidth(h.DigestSize) - (int)len);
+ _s += s;
+ }
+ }
+ else if (c == 's')
+ {
+ AddSpace();
+ char s[kSizeField_Len + 32];
+ char *p = s;
+ SetSpacesAndNul(s, kSizeField_Len);
+ if (showHash)
+ {
+ p = s + kSizeField_Len;
+ ConvertUInt64ToString(fileSize, p);
+ const int numSpaces = (int)kSizeField_Len - (int)strlen(p);
+ if (numSpaces > 0)
+ p -= (unsigned)numSpaces;
+ }
+ _s += p;
+ }
+ else if (c == 'n')
+ {
+ AddSpacesBeforeName();
+ _s += path;
}
-
- _s += p;
}
-
- if (PrintName)
- AddSpacesBeforeName();
*_so << _s;
}
+
HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash)
{
if (_so)
{
+ AString s;
+ if (_fileName.IsEmpty())
+ s = kEmptyFileAlias;
+ else
+ {
+ UString temp = _fileName;
+ _so->Normalize_UString(temp);
+ _so->Convert_UString_to_AString(temp, s);
+ }
+ PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash, s);
+
+ /*
PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash);
if (PrintName)
{
@@ -267,7 +328,9 @@ HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBun
else
_so->NormalizePrint_UString(_fileName);
}
- *_so << endl;
+ */
+ // if (PrintNewLine)
+ *_so << endl;
}
if (NeedPercents())
@@ -299,9 +362,9 @@ static void PrintSum(CStdOutStream &so, const CHasherState &h, unsigned digestIn
so << k_DigestTitles[digestIndex];
- char s[k_HashCalc_DigestSize_Max * 2 + 64];
- s[0] = 0;
- AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize);
+ char s[k_DigestStringSize];
+ // s[0] = 0;
+ h.WriteToString(digestIndex, s);
so << s << endl;
}
@@ -336,7 +399,7 @@ HRESULT CHashCallbackConsole::AfterLastFile(CHashBundle &hb)
{
PrintSeparatorLine(hb.Hashers);
- PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true);
+ PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true, AString());
*_so << endl << endl;
diff --git a/CPP/7zip/UI/Console/HashCon.h b/CPP/7zip/UI/Console/HashCon.h
index 0731bd18..f926d4d3 100644
--- a/CPP/7zip/UI/Console/HashCon.h
+++ b/CPP/7zip/UI/Console/HashCon.h
@@ -12,15 +12,23 @@ class CHashCallbackConsole: public IHashCallbackUI, public CCallbackConsoleBase
UString _fileName;
AString _s;
+ void AddSpace()
+ {
+ _s.Add_Space_if_NotEmpty();
+ }
+
void AddSpacesBeforeName()
{
- _s.Add_Space();
- _s.Add_Space();
+ if (!_s.IsEmpty())
+ {
+ _s.Add_Space();
+ _s.Add_Space();
+ }
}
void PrintSeparatorLine(const CObjectVector<CHasherState> &hashers);
void PrintResultLine(UInt64 fileSize,
- const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash);
+ const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash, const AString &path);
void PrintProperty(const char *name, UInt64 value);
public:
@@ -28,14 +36,17 @@ public:
bool PrintHeaders;
- bool PrintSize;
- bool PrintName;
+ // bool PrintSize;
+ // bool PrintNewLine; // set it too (false), if you need only hash for single file without LF char.
+ AString PrintFields;
+
+ AString GetFields() const;
CHashCallbackConsole():
PrintNameInPercents(true),
- PrintHeaders(false),
- PrintSize(true),
- PrintName(true)
+ PrintHeaders(false)
+ // , PrintSize(true),
+ // , PrintNewLine(true)
{}
virtual ~CHashCallbackConsole() {}
diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp
index d6cb9825..14d83eb9 100644
--- a/CPP/7zip/UI/Console/List.cpp
+++ b/CPP/7zip/UI/Console/List.cpp
@@ -505,7 +505,7 @@ static void PrintTime(char *dest, const FILETIME *ft)
static inline char GetHex(Byte value)
{
- return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+ return (char)((value < 10) ? ('0' + value) : ('a' + (value - 10)));
}
static void HexToString(char *dest, const Byte *data, UInt32 size)
@@ -1019,7 +1019,9 @@ HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const
bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
-HRESULT ListArchives(CCodecs *codecs,
+HRESULT ListArchives(
+ const CListOptions &listOptions,
+ CCodecs *codecs,
const CObjectVector<COpenType> &types,
const CIntVector &excludedFormats,
bool stdInMode,
@@ -1271,6 +1273,9 @@ HRESULT ListArchives(CCodecs *codecs,
RINOK(Archive_IsItem_Dir(archive, i, fp.IsDir));
+ if (fp.IsDir ? listOptions.ExcludeDirItems : listOptions.ExcludeFileItems)
+ continue;
+
if (!allFilesAreAllowed)
{
if (isAltStream)
diff --git a/CPP/7zip/UI/Console/List.h b/CPP/7zip/UI/Console/List.h
index 462c4710..79d2ed48 100644
--- a/CPP/7zip/UI/Console/List.h
+++ b/CPP/7zip/UI/Console/List.h
@@ -7,7 +7,20 @@
#include "../Common/LoadCodecs.h"
-HRESULT ListArchives(CCodecs *codecs,
+struct CListOptions
+{
+ bool ExcludeDirItems;
+ bool ExcludeFileItems;
+
+ CListOptions():
+ ExcludeDirItems(false),
+ ExcludeFileItems(false)
+ {}
+};
+
+HRESULT ListArchives(
+ const CListOptions &listOptions,
+ CCodecs *codecs,
const CObjectVector<COpenType> &types,
const CIntVector &excludedFormats,
bool stdInMode,
@@ -15,12 +28,12 @@ HRESULT ListArchives(CCodecs *codecs,
bool processAltStreams, bool showAltStreams,
const NWildcard::CCensorNode &wildcardCensor,
bool enableHeaders, bool techMode,
- #ifndef _NO_CRYPTO
+ #ifndef _NO_CRYPTO
bool &passwordEnabled, UString &password,
- #endif
- #ifndef _SFX
+ #endif
+ #ifndef _SFX
const CObjectVector<CProperty> *props,
- #endif
+ #endif
UInt64 &errors,
UInt64 &numWarnings);
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
index e7d9fd1b..0455ed5d 100644
--- a/CPP/7zip/UI/Console/Main.cpp
+++ b/CPP/7zip/UI/Console/Main.cpp
@@ -71,6 +71,9 @@ extern const CCodecInfo *g_Codecs[];
extern unsigned g_NumHashers;
extern const CHasherInfo *g_Hashers[];
+#ifdef EXTERNAL_CODECS
+const CExternalCodecs *g_ExternalCodecs_Ptr;
+#endif
#if defined(PROG_VARIANT_Z)
#define PROG_POSTFIX "z"
@@ -859,9 +862,11 @@ int Main2(
codecs->CaseSensitiveChange = options.CaseSensitiveChange;
codecs->CaseSensitive = options.CaseSensitive;
ThrowException_if_Error(codecs->Load());
+ Codecs_AddHashArcHandler(codecs);
#ifdef EXTERNAL_CODECS
{
+ g_ExternalCodecs_Ptr = &__externalCodecs;
UString s;
codecs->GetCodecsErrorMessage(s);
if (!s.IsEmpty())
@@ -872,8 +877,7 @@ int Main2(
}
#endif
-
- bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
+ const bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
if (codecs->Formats.Size() == 0 &&
(isExtractGroupCommand
@@ -888,13 +892,15 @@ int Main2(
throw s;
}
#endif
-
throw kNoFormats;
}
CObjectVector<COpenType> types;
if (!ParseOpenTypes(*codecs, options.ArcType, types))
+ {
throw kUnsupportedArcTypeMessage;
+ }
+
CIntVector excludedFormats;
FOR_VECTOR (k, options.ExcludedArcTypes)
@@ -903,13 +909,16 @@ int Main2(
if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices)
|| tempIndices.Size() != 1)
throw kUnsupportedArcTypeMessage;
+
+
+
excludedFormats.AddToUniqueSorted(tempIndices[0]);
// excludedFormats.Sort();
}
-
#ifdef EXTERNAL_CODECS
if (isExtractGroupCommand
+ || options.Command.IsFromUpdateGroup()
|| options.Command.CommandType == NCommandType::kHash
|| options.Command.CommandType == NCommandType::kBenchmark)
ThrowException_if_Error(__externalCodecs.Load());
@@ -943,7 +952,7 @@ int Main2(
so << endl << "Formats:" << endl;
- const char * const kArcFlags = "KSNFMGOPBELHX";
+ const char * const kArcFlags = "KSNFMGOPBELHXC";
const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags);
for (i = 0; i < codecs->Formats.Size(); i++)
@@ -953,7 +962,7 @@ int Main2(
#ifdef EXTERNAL_CODECS
PrintLibIndex(so, arc.LibIndex);
#else
- so << " ";
+ so << " ";
#endif
so << (char)(arc.UpdateEnabled ? 'C' : ' ');
@@ -989,6 +998,8 @@ int Main2(
if (arc.SignatureOffset != 0)
so << "offset=" << arc.SignatureOffset << ' ';
+ // so << "numSignatures = " << arc.Signatures.Size() << " ";
+
FOR_VECTOR(si, arc.Signatures)
{
if (si != 0)
@@ -1030,6 +1041,7 @@ int Main2(
so << (char)(cod.CreateEncoder ? 'E' : ' ');
so << (char)(cod.CreateDecoder ? 'D' : ' ');
+ so << (char)(cod.IsFilter ? 'F' : ' ');
so << ' ';
PrintHexId(so, cod.Id);
@@ -1053,6 +1065,12 @@ int Main2(
so << (char)(codecs->GetCodec_EncoderIsAssigned(j) ? 'E' : ' ');
so << (char)(codecs->GetCodec_DecoderIsAssigned(j) ? 'D' : ' ');
+ {
+ bool isFilter_Assigned;
+ const bool isFilter = codecs->GetCodec_IsFilter(j, isFilter_Assigned);
+ so << (char)(isFilter ? 'F' : isFilter_Assigned ? ' ' : '*');
+ }
+
so << ' ';
UInt64 id;
@@ -1215,6 +1233,7 @@ int Main2(
}
hresultMain = Extract(
+ // EXTERNAL_CODECS_VARS_L
codecs,
types,
excludedFormats,
@@ -1329,7 +1348,12 @@ int Main2(
// options.ExtractNtOptions.StoreAltStreams = true, if -sns[-] is not definmed
+ CListOptions lo;
+ lo.ExcludeDirItems = options.Censor.ExcludeDirItems;
+ lo.ExcludeFileItems = options.Censor.ExcludeFileItems;
+
hresultMain = ListArchives(
+ lo,
codecs,
types,
excludedFormats,
@@ -1429,6 +1453,7 @@ int Main2(
callback.Init(g_StdStream, g_ErrStream, percentsStream);
callback.PrintHeaders = options.EnableHeaders;
+ callback.PrintFields = options.ListFields;
AString errorInfoString;
hresultMain = HashCalc(EXTERNAL_CODECS_VARS_L
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
index 24056072..0a25c225 100644
--- a/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
@@ -5,6 +5,7 @@
#include "../../../Common/IntToString.h"
#include "../../../Windows/ErrorMsg.h"
+#include "../../../Windows/FileName.h"
#ifndef _7ZIP_ST
#include "../../../Windows/Synchronization.h"
@@ -470,7 +471,7 @@ HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const
return CheckBreak2();
}
-HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog)
+HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, bool isDir, const char *command, bool showInLog)
{
MT_LOCK
@@ -489,6 +490,8 @@ HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *com
if (name)
{
_tempU = name;
+ if (isDir)
+ NWindows::NFile::NName::NormalizeDirPathPrefix(_tempU);
_so->Normalize_UString(_tempU);
}
_so->PrintUString(_tempU, _tempA);
@@ -516,7 +519,7 @@ HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *com
return CheckBreak2();
}
-HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode)
+HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode)
{
if (StdOutMode)
return S_OK;
@@ -546,7 +549,7 @@ HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */,
s = "Reading";
}
- return PrintProgress(name, s, LogLevel >= requiredLevel);
+ return PrintProgress(name, isDir, s, LogLevel >= requiredLevel);
}
HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
@@ -594,7 +597,7 @@ HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypt
}
-HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */)
+HRESULT CUpdateCallbackConsole::ReportUpdateOperation(UInt32 op, const wchar_t *name, bool isDir)
{
// if (StdOutMode) return S_OK;
@@ -622,7 +625,7 @@ HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *
}
}
- return PrintProgress(name, s, LogLevel >= requiredLevel);
+ return PrintProgress(name, isDir, s, LogLevel >= requiredLevel);
}
/*
@@ -694,7 +697,7 @@ HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
COM_TRY_END
}
-HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
+HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool isDir)
{
if (StdOutMode)
return S_OK;
@@ -703,7 +706,7 @@ HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDi
{
if (!name || name[0] == 0)
name = kEmptyFileAlias;
- return PrintProgress(name, "D", true);
+ return PrintProgress(name, isDir, "D", true);
}
return S_OK;
}
diff --git a/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
index 5c205aad..700d511c 100644
--- a/CPP/7zip/UI/Console/UpdateCallbackConsole.h
+++ b/CPP/7zip/UI/Console/UpdateCallbackConsole.h
@@ -87,7 +87,7 @@ public:
CErrorPathCodes ScanErrors;
UInt64 NumNonOpenFiles;
- HRESULT PrintProgress(const wchar_t *name, const char *command, bool showInLog);
+ HRESULT PrintProgress(const wchar_t *name, bool isDir, const char *command, bool showInLog);
};
diff --git a/CPP/7zip/UI/Console/makefile b/CPP/7zip/UI/Console/makefile
index ada782b0..acc3f107 100644
--- a/CPP/7zip/UI/Console/makefile
+++ b/CPP/7zip/UI/Console/makefile
@@ -5,6 +5,7 @@ CFLAGS = $(CFLAGS) \
COMMON_OBJS = \
$O\CommandLineParser.obj \
$O\CRC.obj \
+ $O\DynLimBuf.obj \
$O\IntToString.obj \
$O\ListFileUtils.obj \
$O\NewHandler.obj \
@@ -48,6 +49,7 @@ WIN_OBJS = \
$O\UniqBlocks.obj \
AR_COMMON_OBJS = \
+ $O\ItemNameUtils.obj \
$O\OutStreamWithCRC.obj \
COMPRESS_OBJS = \
diff --git a/CPP/7zip/UI/Console/makefile.gcc b/CPP/7zip/UI/Console/makefile.gcc
index e0d996c1..ed05a142 100644
--- a/CPP/7zip/UI/Console/makefile.gcc
+++ b/CPP/7zip/UI/Console/makefile.gcc
@@ -100,6 +100,7 @@ COMMON_OBJS = \
$O/CommandLineParser.o \
$O/CRC.o \
$O/CrcReg.o \
+ $O/DynLimBuf.o \
$O/IntToString.o \
$O/ListFileUtils.o \
$O/NewHandler.o \
@@ -148,6 +149,9 @@ WIN_OBJS = \
COMPRESS_OBJS = \
$O/CopyCoder.o \
+AR_COMMON_OBJS = \
+ $O/ItemNameUtils.o \
+
C_OBJS = \
$O/Alloc.o \
$O/CpuArch.o \
@@ -163,6 +167,7 @@ OBJS = \
$(WIN_OBJS) \
$(SYS_OBJS) \
$(COMPRESS_OBJS) \
+ $(AR_COMMON_OBJS) \
$(7ZIP_COMMON_OBJS) \
$(UI_COMMON_OBJS) \
$(CONSOLE_OBJS) \
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp
index 0334942a..8a0842e1 100644
--- a/CPP/7zip/UI/Explorer/ContextMenu.cpp
+++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp
@@ -3,6 +3,7 @@
#include "StdAfx.h"
#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
#include "../../../Windows/COM.h"
@@ -15,12 +16,15 @@
#include "../../../Windows/ProcessUtils.h"
#include "../../../Windows/Shell.h"
+#include "../../PropID.h"
+
#include "../Common/ArchiveName.h"
#include "../Common/CompressCall.h"
#include "../Common/ExtractingFilePath.h"
#include "../Common/ZipRegistry.h"
#include "../FileManager/FormatUtils.h"
+#include "../FileManager/PropertyName.h"
#ifdef LANG
#include "../FileManager/LangUtils.h"
@@ -52,16 +56,65 @@ extern LONG g_DllRefCount;
extern HINSTANCE g_hInstance;
#endif
+#ifdef SHOW_DEBUG_CTX_MENU
+
+void Print_Ptr(void *p, char *s)
+{
+ char temp[64];
+ ConvertUInt64ToHex((UInt64)(void *)p, temp);
+ AString s2;
+ s2 += temp;
+ s2.Add_Space();
+ s2 += s;
+ OutputDebugStringA(s2);
+}
+
+void Print_Number(UInt32 number, char *s)
+{
+ char temp[64];
+ ConvertUInt64ToString(number, temp);
+ AString s2;
+ s2 += temp;
+ s2.Add_Space();
+ s2 += s;
+ OutputDebugStringA(s2);
+}
+
+#define ODS(sz) Print_Ptr(this, sz)
+#define ODS_U(s) OutputDebugStringW(s);
+// #define ODS(sz)
+// #define ODS_U(s)
+
+#define ODS2(sz) Print_Ptr(this, sz)
+
+#else
+
+#define Print_Number(number, s)
+#define ODS(sz)
+#define ODS_U(s)
+#define ODS2(sz)
+
+#endif
+
+
+
CZipContextMenu::CZipContextMenu():
_isMenuForFM(false),
- _bitmap(NULL)
+ _dropMode(false),
+ _bitmap(NULL),
+ IsSeparator(false),
+ IsRoot(true),
+ CurrentSubCommand(0)
{
+ ODS("-- CZipContextMenu()");
+
InterlockedIncrement(&g_DllRefCount);
_bitmap = ::LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_MENU_LOGO));
}
CZipContextMenu::~CZipContextMenu()
{
+ ODS("== ~CZipContextMenu");
if (_bitmap != NULL)
DeleteObject(_bitmap);
InterlockedDecrement(&g_DllRefCount);
@@ -184,7 +237,9 @@ static const CHashCommand g_HashCommands[] =
{ CZipContextMenu::kHash_CRC64, "CRC-64", "CRC64" },
{ CZipContextMenu::kHash_SHA1, "SHA-1", "SHA1" },
{ CZipContextMenu::kHash_SHA256, "SHA-256", "SHA256" },
- { CZipContextMenu::kHash_All, "*", "*" }
+ { CZipContextMenu::kHash_All, "*", "*" },
+ { CZipContextMenu::kHash_Generate_SHA256, "SHA-256 -> file.sha256", "SHA256" },
+ { CZipContextMenu::kHash_TestArc, "Checksum : Test", "Hash" }
};
@@ -209,9 +264,19 @@ void CZipContextMenu::FillCommand(ECommandInternalID id, UString &mainString, CC
cmi.Verb += command.Verb;
// cmi.HelpString = cmi.Verb;
LangString(command.ResourceID, mainString);
+ cmi.UserString = mainString;
// return true;
}
+
+static UString LangStringAlt(UInt32 id, const char *altString)
+{
+ UString s = LangString(id);
+ if (s.IsEmpty())
+ s = altString;
+ return s;
+}
+
void CZipContextMenu::AddCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &cmi)
{
@@ -222,6 +287,8 @@ void CZipContextMenu::AddCommand(ECommandInternalID id, UString &mainString, CCo
static void MyInsertMenu(CMenu &menu, int pos, UINT id, const UString &s, HBITMAP bitmap)
{
+ if (!menu)
+ return;
CMenuItem mi;
mi.fType = MFT_STRING;
mi.fMask = MIIM_TYPE | MIIM_ID;
@@ -247,9 +314,14 @@ static void MyAddSubMenu(
CZipContextMenu::CCommandMapItem cmi;
cmi.CommandInternalID = CZipContextMenu::kCommandNULL;
cmi.Verb = verb;
+ cmi.IsPopup = true;
// cmi.HelpString = verb;
+ cmi.UserString = s;
_commandMap.Add(cmi);
+ if (!menu)
+ return;
+
CMenuItem mi;
mi.fType = MFT_STRING;
mi.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
@@ -329,7 +401,7 @@ static void MyFormatNew_ReducedName(UString &s, const UString &name)
s = MyFormatNew(s, GetQuotedReducedString(name));
}
-static const char * const kExtractExludeExtensions =
+static const char * const kExtractExcludeExtensions =
" 3gp"
" aac ans ape asc asm asp aspx avi awk"
" bas bat bmp"
@@ -403,7 +475,7 @@ static bool FindExt(const char *p, const FString &name)
static bool DoNeedExtract(const FString &name)
{
- return !FindExt(kExtractExludeExtensions, name);
+ return !FindExt(kExtractExcludeExtensions, name);
}
// we must use diferent Verbs for Popup subMenu.
@@ -427,12 +499,12 @@ static HRESULT RETURN_WIN32_LastError_AS_HRESULT()
/*
- we add CCommandMapItem to _commandMap for each new Mene ID.
+ we add CCommandMapItem to _commandMap for each new Menu ID.
so then we use _commandMap[offset].
That way we can execute commands that have menu item.
Another non-implemented way:
- We can return the number off all possible commnad in QueryContextMenu().
- so the caller could call InvokeCommand() via string verb aven
+ We can return the number off all possible commands in QueryContextMenu().
+ so the caller could call InvokeCommand() via string verb even
without using menu items.
*/
@@ -441,6 +513,7 @@ static HRESULT RETURN_WIN32_LastError_AS_HRESULT()
STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
UINT commandIDFirst, UINT commandIDLast, UINT flags)
{
+ ODS("+ QueryContextMenu()");
COM_TRY_BEGIN
try {
@@ -493,9 +566,12 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
bitmap = _bitmap;
UINT subIndex = indexMenu;
+
+ ODS("### 50");
if (ci.Cascaded.Val)
{
+ if (hMenu)
if (!popupMenu.CreatePopup())
return RETURN_WIN32_LastError_AS_HRESULT();
menuDestroyer.Attach(popupMenu);
@@ -514,6 +590,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
CMenuItem mi;
mi.fType = MFT_SEPARATOR;
mi.fMask = MIIM_TYPE;
+ if (hMenu)
popupMenu.InsertItem(subIndex++, true, mi);
}
@@ -551,6 +628,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
}
}
+ ODS("### 100");
+
UString mainString;
if (_fileNames.Size() == 1 && currentCommandID + 14 <= commandIDLast)
@@ -567,13 +646,15 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
}
if ((contextMenuFlags & NContextMenuFlags::kOpenAs) != 0
// && (!thereIsMainOpenItem || !FindExt(kNoOpenAsExtensions, fi0.Name))
+ && hMenu // we want to reduce number of menu items below 16
)
{
CMenu subMenu;
- if (subMenu.CreatePopup())
+ if (!hMenu || subMenu.CreatePopup())
{
MyAddSubMenu(_commandMap, kOpenCascadedVerb, popupMenu, subIndex++, currentCommandID++, LangString(IDS_CONTEXT_OPEN), subMenu, bitmap);
-
+ _commandMap.Back().CtxCommandType = CtxCommandType_OpenRoot;
+
UINT subIndex2 = 0;
for (unsigned i = (thereIsMainOpenItem ? 1 : 0); i < ARRAY_SIZE(kOpenTypes); i++)
{
@@ -589,8 +670,10 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
cmi.Verb += mainString;
// cmi.HelpString = cmi.Verb;
cmi.ArcType = mainString;
+ cmi.CtxCommandType = CtxCommandType_OpenChild;
}
_commandMap.Add(cmi);
+ Set_UserString_in_LastCommand(mainString);
MyInsertMenu(subMenu, subIndex2++, currentCommandID++, mainString, bitmap);
}
@@ -662,6 +745,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
cmi.Folder = baseFolder + specFolder;
AddCommand(kExtractTo, s, cmi);
MyFormatNew_ReducedName(s, specFolder);
+ Set_UserString_in_LastCommand(s);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap);
}
}
@@ -720,6 +804,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
cmi.ArcType = "7z";
AddCommand(kCompressTo7z, s, cmi);
MyFormatNew_ReducedName(s, arcName7z);
+ Set_UserString_in_LastCommand(s);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap);
}
@@ -733,6 +818,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
cmi.ArcType = "7z";
AddCommand(kCompressTo7zEmail, s, cmi);
MyFormatNew_ReducedName(s, arcName7z);
+ Set_UserString_in_LastCommand(s);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap);
}
#endif
@@ -751,6 +837,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
cmi.ArcType = "zip";
AddCommand(kCompressToZip, s, cmi);
MyFormatNew_ReducedName(s, arcNameZip);
+ Set_UserString_in_LastCommand(s);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap);
}
@@ -764,6 +851,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
cmi.ArcType = "zip";
AddCommand(kCompressToZipEmail, s, cmi);
MyFormatNew_ReducedName(s, arcNameZip);
+ Set_UserString_in_LastCommand(s);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap);
}
#endif
@@ -779,32 +867,56 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
CMenu menu;
menu.Attach(hMenu);
menuDestroyer.Disable();
- MyAddSubMenu(_commandMap, kMainVerb, menu, indexMenu++, currentCommandID++, (UString)"7-Zip", popupMenu.Detach(), bitmap);
+ MyAddSubMenu(_commandMap, kMainVerb, menu, indexMenu++, currentCommandID++, (UString)"7-Zip",
+ popupMenu, // popupMenu.Detach(),
+ bitmap);
}
else
{
- popupMenu.Detach();
+ // popupMenu.Detach();
indexMenu = subIndex;
}
+ const bool needCrc = ((contextMenuFlags &
+ (NContextMenuFlags::kCRC |
+ NContextMenuFlags::kCRC_Cascaded)) != 0);
- if (!_isMenuForFM &&
- ((contextMenuFlags & NContextMenuFlags::kCRC) != 0
- && currentCommandID + 1 < commandIDLast))
+ if (
+ // !_isMenuForFM && // 21.04: we don't hide CRC SHA menu in 7-Zip FM
+ needCrc
+ && currentCommandID + 1 < commandIDLast)
{
CMenu subMenu;
// CMenuDestroyer menuDestroyer_CRC;
-
+
UINT subIndex_CRC = 0;
- if (subMenu.CreatePopup())
+ if (!hMenu || subMenu.CreatePopup())
{
// menuDestroyer_CRC.Attach(subMenu);
+ const bool insertHashMenuTo7zipMenu = (ci.Cascaded.Val
+ && (contextMenuFlags & NContextMenuFlags::kCRC_Cascaded) != 0);
CMenu menu;
- menu.Attach(hMenu);
- // menuDestroyer_CRC.Disable();
- MyAddSubMenu(_commandMap, kCheckSumCascadedVerb, menu, indexMenu++, currentCommandID++, (UString)"CRC SHA", subMenu, bitmap);
+ {
+ int indexInParent;
+ if (insertHashMenuTo7zipMenu)
+ {
+ indexInParent = subIndex;
+ menu.Attach(popupMenu);
+ }
+ else
+ {
+ indexInParent = indexMenu;
+ menu.Attach(hMenu);
+ // menuDestroyer_CRC.Disable();
+ }
+ MyAddSubMenu(_commandMap, kCheckSumCascadedVerb, menu, indexInParent++, currentCommandID++, (UString)"CRC SHA", subMenu,
+ /* insertHashMenuTo7zipMenu ? NULL : */ bitmap);
+ _commandMap.Back().CtxCommandType = CtxCommandType_CrcRoot;
+ if (!insertHashMenuTo7zipMenu)
+ indexMenu = indexInParent;
+ }
for (unsigned i = 0; i < ARRAY_SIZE(g_HashCommands); i++)
{
@@ -816,15 +928,57 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
cmi.Verb = kCheckSumCascadedVerb;
cmi.Verb += '.';
cmi.Verb += hc.MethodName;
+ UString s;
+ s += hc.UserName;
+
+ if (hc.CommandInternalID == kHash_Generate_SHA256)
+ {
+ {
+ popupMenu.Attach(hMenu);
+ CMenuItem mi;
+ mi.fType = MFT_SEPARATOR;
+ mi.fMask = MIIM_TYPE;
+ subMenu.InsertItem(subIndex_CRC++, true, mi);
+ }
+
+ UString name;
+ if (_fileNames.Size() > 1)
+ name = CreateArchiveName(_fileNames, _fileNames.Size() == 1 ? &fi0 : NULL);
+ else
+ name = fs2us(fi0.Name);
+ name += ".sha256";
+ cmi.Folder= folderPrefix;
+ cmi.ArcName = name;
+ s = "SHA-256 -> ";
+ s += name;
+ }
+ else if (hc.CommandInternalID == kHash_TestArc)
+ {
+ s = LangStringAlt(IDS_CONTEXT_TEST, "Test archive");
+ s += " : ";
+ s += GetNameOfProperty(kpidChecksum, UString("Checksum"));
+ }
+
// cmi.HelpString = cmi.Verb;
+ cmi.UserString = s;
+ cmi.CtxCommandType = CtxCommandType_CrcChild;
_commandMap.Add(cmi);
- MyInsertMenu(subMenu, subIndex_CRC++, currentCommandID++, (UString)hc.UserName, bitmap);
+ MyInsertMenu(subMenu, subIndex_CRC++, currentCommandID++, s, bitmap);
}
subMenu.Detach();
}
}
+ popupMenu.Detach();
+
+ /*
+ if (!ci.Cascaded.Val)
+ indexMenu = subIndex;
+ */
+
+ ODS("### 400");
+
#ifdef SHOW_DEBUG_CTX_MENU
{ char s[256]; sprintf(s, "Commands=%d currentCommandID - commandIDFirst = %d",
_commandMap.Size(), currentCommandID - commandIDFirst); OutputDebugStringA(s); }
@@ -981,9 +1135,15 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo)
if (commandOffset < 0 || (unsigned)commandOffset >= _commandMap.Size())
return E_INVALIDARG;
-
const CCommandMapItem &cmi = _commandMap[(unsigned)commandOffset];
- ECommandInternalID cmdID = cmi.CommandInternalID;
+ return InvokeCommandCommon(cmi);
+ COM_TRY_END
+}
+
+
+HRESULT CZipContextMenu::InvokeCommandCommon(const CCommandMapItem &cmi)
+{
+ const ECommandInternalID cmdID = cmi.CommandInternalID;
try
{
@@ -1023,18 +1183,20 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo)
case kCompressToZip:
case kCompressToZipEmail:
{
- bool email =
+ const bool email =
(cmdID == kCompressEmail) ||
(cmdID == kCompressTo7zEmail) ||
(cmdID == kCompressToZipEmail);
- bool showDialog =
+ const bool showDialog =
(cmdID == kCompress) ||
(cmdID == kCompressEmail);
- bool addExtension = (cmdID == kCompress || cmdID == kCompressEmail);
+ const bool addExtension = (cmdID == kCompress || cmdID == kCompressEmail);
CompressFiles(cmi.Folder,
cmi.ArcName, cmi.ArcType,
addExtension,
- _fileNames, email, showDialog, false);
+ _fileNames, email, showDialog,
+ false // waitFinish
+ );
break;
}
@@ -1043,13 +1205,24 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo)
case kHash_SHA1:
case kHash_SHA256:
case kHash_All:
+ case kHash_Generate_SHA256:
+ case kHash_TestArc:
{
for (unsigned i = 0; i < ARRAY_SIZE(g_HashCommands); i++)
{
const CHashCommand &hc = g_HashCommands[i];
if (hc.CommandInternalID == cmdID)
{
- CalcChecksum(_fileNames, (UString)hc.MethodName);
+ if (cmdID == kHash_TestArc)
+ {
+ TestArchives(_fileNames, true); // hashMode
+ break;
+ }
+ UString generateName;
+ if (cmdID == kHash_Generate_SHA256)
+ generateName = cmi.ArcName;
+ CalcChecksum(_fileNames, (UString)hc.MethodName,
+ cmi.Folder, generateName);
break;
}
}
@@ -1064,7 +1237,6 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo)
::MessageBoxW(0, L"Error", L"7-Zip", MB_ICONERROR);
}
return S_OK;
- COM_TRY_END
}
@@ -1136,3 +1308,371 @@ STDMETHODIMP CZipContextMenu::GetCommandString(UINT_PTR commandOffset, UINT uTyp
COM_TRY_END
}
+
+
+
+// ---------- IExplorerCommand ----------
+
+static HRESULT WINAPI My_SHStrDupW(LPCWSTR src, LPWSTR *dest)
+{
+ if (src)
+ {
+ const SIZE_T size = (wcslen(src) + 1) * sizeof(WCHAR);
+ WCHAR *p = (WCHAR *)CoTaskMemAlloc(size);
+ if (p)
+ {
+ memcpy(p, src, size);
+ *dest = p;
+ return S_OK;
+ }
+ }
+ *dest = NULL;
+ return E_OUTOFMEMORY;
+}
+
+
+#define CZipExplorerCommand CZipContextMenu
+
+class CCoTaskWSTR
+{
+ LPWSTR m_str;
+ CLASS_NO_COPY(CCoTaskWSTR)
+public:
+ CCoTaskWSTR(): m_str(NULL) {}
+ ~CCoTaskWSTR() { ::CoTaskMemFree(m_str); }
+ LPWSTR* operator&() { return &m_str; }
+ operator LPCWSTR () const { return m_str; }
+ // operator LPCOLESTR() const { return m_str; }
+ operator bool() const { return m_str != NULL; }
+ // bool operator!() const { return m_str == NULL; }
+
+ /*
+ void Wipe_and_Free()
+ {
+ if (m_str)
+ {
+ memset(m_str, 0, ::SysStringLen(m_str) * sizeof(*m_str));
+ Empty();
+ }
+ }
+ */
+
+private:
+ /*
+ CCoTaskWSTR(LPCOLESTR src) { m_str = ::CoTaskMemAlloc(src); }
+
+ CCoTaskWSTR& operator=(LPCOLESTR src)
+ {
+ ::CoTaskMemFree(m_str);
+ m_str = ::SysAllocString(src);
+ return *this;
+ }
+
+
+ void Empty()
+ {
+ ::CoTaskMemFree(m_str);
+ m_str = NULL;
+ }
+ */
+};
+
+static void LoadPaths(IShellItemArray *psiItemArray, UStringVector &paths)
+{
+ if (psiItemArray)
+ {
+ DWORD numItems = 0;
+ if (psiItemArray->GetCount(&numItems) == S_OK)
+ {
+ for (DWORD i = 0; i < numItems; i++)
+ {
+ CMyComPtr<IShellItem> item;
+ if (psiItemArray->GetItemAt(i, &item) == S_OK && item)
+ {
+ CCoTaskWSTR displayName;
+ if (item->GetDisplayName(SIGDN_FILESYSPATH, &displayName) == S_OK
+ && (bool)displayName)
+ {
+ OutputDebugStringW(displayName);
+ paths.Add((LPCWSTR)displayName);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void CZipExplorerCommand::LoadItems(IShellItemArray *psiItemArray)
+{
+ SubCommands.Clear();
+
+ UStringVector paths;
+ LoadPaths(psiItemArray, paths);
+ _fileNames = paths;
+
+ HRESULT res = QueryContextMenu(
+ NULL, // hMenu,
+ 0, // indexMenu,
+ 0, // commandIDFirst,
+ 0 + 999, // commandIDLast,
+ CMF_NORMAL);
+
+ if (FAILED(res))
+ return /* res */;
+
+
+ CZipExplorerCommand *crcHandler = NULL;
+ CZipExplorerCommand *openHandler = NULL;
+
+ bool useCascadedCrc = true; // false;
+ bool useCascadedOpen = true; // false;
+
+ for (unsigned i = 0; i < _commandMap.Size(); i++)
+ {
+ const CCommandMapItem &cmi = _commandMap[i];
+
+
+ if (cmi.IsPopup)
+ if (!cmi.IsSubMenu())
+ continue;
+
+ // if (cmi.IsSubMenu()) continue // for debug
+
+ CZipContextMenu *shellExt = new CZipContextMenu();
+ shellExt->IsRoot = false;
+
+ if (cmi.CtxCommandType == CtxCommandType_CrcRoot && !useCascadedCrc)
+ shellExt->IsSeparator = true;
+
+ {
+ CZipExplorerCommand *handler = this;
+ if (cmi.CtxCommandType == CtxCommandType_CrcChild && crcHandler)
+ handler = crcHandler;
+ else if (cmi.CtxCommandType == CtxCommandType_OpenChild && openHandler)
+ handler = openHandler;
+ handler->SubCommands.AddNew() = shellExt;
+ }
+
+ shellExt->_commandMap_Cur.Add(cmi);
+
+ ODS_U(cmi.UserString);
+
+ if (cmi.CtxCommandType == CtxCommandType_CrcRoot && useCascadedCrc)
+ crcHandler = shellExt;
+ if (cmi.CtxCommandType == CtxCommandType_OpenRoot && useCascadedOpen)
+ {
+ // ODS2("cmi.CtxCommandType == CtxCommandType_OpenRoot");
+ openHandler = shellExt;
+ }
+ }
+}
+
+
+STDMETHODIMP CZipExplorerCommand::GetTitle(IShellItemArray *psiItemArray, LPWSTR *ppszName)
+{
+ ODS("- GetTitle()");
+ // COM_TRY_BEGIN
+ if (IsSeparator)
+ {
+ *ppszName = NULL;
+ return S_FALSE;
+ }
+
+ UString name;
+ if (IsRoot)
+ {
+ LoadItems(psiItemArray);
+ name = "7-Zip"; // "New"
+ }
+ else
+ name = "7-Zip item";
+
+ if (!_commandMap_Cur.IsEmpty())
+ {
+ const CCommandMapItem &mi = _commandMap_Cur[0];
+ // s += mi.Verb;
+ // s += " : ";
+ name = mi.UserString;
+ }
+
+ return My_SHStrDupW(name, ppszName);
+ // return S_OK;
+ // COM_TRY_END
+}
+
+
+STDMETHODIMP CZipExplorerCommand::GetIcon(IShellItemArray * /* psiItemArray */, LPWSTR *ppszIcon)
+{
+ ODS("- GetIcon()");
+ // COM_TRY_BEGIN
+ *ppszIcon = NULL;
+ // return E_NOTIMPL;
+ UString imageName = fs2us(NWindows::NDLL::GetModuleDirPrefix());
+ // imageName += "7zG.exe";
+ imageName += "7-zip.dll";
+ // imageName += ",190";
+ return My_SHStrDupW(imageName, ppszIcon);
+ // COM_TRY_END
+}
+
+
+STDMETHODIMP CZipExplorerCommand::GetToolTip (IShellItemArray * /* psiItemArray */, LPWSTR *ppszInfotip)
+{
+ // COM_TRY_BEGIN
+ ODS("- GetToolTip()");
+ *ppszInfotip = NULL;
+ return E_NOTIMPL;
+ // COM_TRY_END
+}
+
+
+STDMETHODIMP CZipExplorerCommand::GetCanonicalName(GUID *pguidCommandName)
+{
+ // COM_TRY_BEGIN
+ ODS("- GetCanonicalName()");
+ *pguidCommandName = GUID_NULL;
+ return E_NOTIMPL;
+ // COM_TRY_END
+}
+
+
+STDMETHODIMP CZipExplorerCommand::GetState(IShellItemArray * /* psiItemArray */, BOOL /* fOkToBeSlow */, EXPCMDSTATE *pCmdState)
+{
+ // COM_TRY_BEGIN
+ ODS("- GetState()");
+ *pCmdState = ECS_ENABLED;
+ return S_OK;
+ // COM_TRY_END
+}
+
+
+
+
+STDMETHODIMP CZipExplorerCommand::Invoke(IShellItemArray *psiItemArray, IBindCtx * /* pbc */)
+{
+ COM_TRY_BEGIN
+
+ if (_commandMap_Cur.IsEmpty())
+ return E_INVALIDARG;
+
+ ODS("- Invoke()");
+ UStringVector paths;
+ LoadPaths(psiItemArray, paths);
+ _fileNames = paths;
+ return InvokeCommandCommon(_commandMap_Cur[0]);
+
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CZipExplorerCommand::GetFlags(EXPCMDFLAGS *pFlags)
+{
+ ODS("- GetFlags()");
+ // COM_TRY_BEGIN
+ EXPCMDFLAGS f = ECF_DEFAULT;
+ if (IsSeparator)
+ f = ECF_ISSEPARATOR;
+ else if (IsRoot)
+ f = ECF_HASSUBCOMMANDS;
+ else
+ {
+ if (!_commandMap_Cur.IsEmpty())
+ {
+ // const CCommandMapItem &cmi = ;
+ if (_commandMap_Cur[0].IsSubMenu())
+ {
+ // ODS("ECF_HASSUBCOMMANDS");
+ f = ECF_HASSUBCOMMANDS;
+ }
+ }
+ }
+ *pFlags = f;
+ return S_OK;
+ // COM_TRY_END
+}
+
+
+STDMETHODIMP CZipExplorerCommand::EnumSubCommands(IEnumExplorerCommand **ppEnum)
+{
+ ODS("- EnumSubCommands()");
+ // COM_TRY_BEGIN
+ *ppEnum = NULL;
+
+ if (!_commandMap_Cur.IsEmpty() && _commandMap_Cur[0].IsSubMenu())
+ {
+ }
+ else
+ {
+ if (!IsRoot)
+ return E_NOTIMPL;
+ if (SubCommands.IsEmpty())
+ {
+ return E_NOTIMPL;
+ }
+ }
+
+ // shellExt->
+ return QueryInterface(IID_IEnumExplorerCommand, (void **)ppEnum);
+
+ // return S_OK;
+ // COM_TRY_END
+}
+
+
+STDMETHODIMP CZipContextMenu::Next(ULONG celt, IExplorerCommand **pUICommand, ULONG *pceltFetched)
+{
+ ODS("CZipContextMenu::Next()");
+ Print_Number(celt, "celt");
+ Print_Number(CurrentSubCommand, "CurrentSubCommand");
+ Print_Number(SubCommands.Size(), "SubCommands.Size()");
+
+ COM_TRY_BEGIN
+ ULONG fetched = 0;
+
+ ULONG i;
+ for (i = 0; i < celt; i++)
+ {
+ pUICommand[i] = NULL;
+ }
+
+ for (i = 0; i < celt && CurrentSubCommand < SubCommands.Size(); i++)
+ {
+ pUICommand[i] = SubCommands[CurrentSubCommand++];
+ pUICommand[i]->AddRef();
+ fetched++;
+ }
+
+ if (pceltFetched)
+ *pceltFetched = fetched;
+
+ ODS(fetched == celt ? " === OK === " : "=== ERROR ===");
+
+ // we return S_FALSE for (fetched == 0)
+ return (fetched == celt) ? S_OK : S_FALSE;
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CZipContextMenu::Skip(ULONG celt)
+{
+ ODS("CZipContextMenu::Skip()");
+ celt = celt;
+ return E_NOTIMPL;
+}
+
+
+STDMETHODIMP CZipContextMenu::Reset(void)
+{
+ ODS("CZipContextMenu::Reset()");
+ CurrentSubCommand = 0;
+ return S_OK;
+}
+
+
+STDMETHODIMP CZipContextMenu::Clone(IEnumExplorerCommand **ppenum)
+{
+ ODS("CZipContextMenu::Clone()");
+ *ppenum = NULL;
+ return E_NOTIMPL;
+}
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h
index dddb9fd1..285044e7 100644
--- a/CPP/7zip/UI/Explorer/ContextMenu.h
+++ b/CPP/7zip/UI/Explorer/ContextMenu.h
@@ -7,13 +7,27 @@
#include <ShlObj.h>
+#include "MyExplorerCommand.h"
+
#include "../../../Common/MyString.h"
#include "../FileManager/MyCom2.h"
+enum ECtxCommandType
+{
+ CtxCommandType_Normal,
+ CtxCommandType_OpenRoot,
+ CtxCommandType_OpenChild,
+ CtxCommandType_CrcRoot,
+ CtxCommandType_CrcChild,
+};
+
+
class CZipContextMenu:
public IContextMenu,
public IShellExtInit,
+ public IExplorerCommand,
+ public IEnumExplorerCommand,
public CMyUnknownImp
{
public:
@@ -36,10 +50,17 @@ public:
kHash_CRC64,
kHash_SHA1,
kHash_SHA256,
- kHash_All
+ kHash_All,
+ kHash_Generate_SHA256,
+ kHash_TestArc
};
- MY_UNKNOWN_IMP2_MT(IContextMenu, IShellExtInit)
+ MY_UNKNOWN_IMP4_MT(
+ IContextMenu,
+ IShellExtInit,
+ IExplorerCommand,
+ IEnumExplorerCommand
+ )
// IShellExtInit
STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, LPDATAOBJECT dataObject, HKEY hkeyProgID);
@@ -51,6 +72,24 @@ public:
HRESULT InitContextMenu(const wchar_t *folder, const wchar_t * const *names, unsigned numFiles);
+ void LoadItems(IShellItemArray *psiItemArray);
+
+ // IExplorerCommand
+ STDMETHOD (GetTitle) (IShellItemArray *psiItemArray, LPWSTR *ppszName);
+ STDMETHOD (GetIcon) (IShellItemArray *psiItemArray, LPWSTR *ppszIcon);
+ STDMETHOD (GetToolTip) (IShellItemArray *psiItemArray, LPWSTR *ppszInfotip);
+ STDMETHOD (GetCanonicalName) (GUID *pguidCommandName);
+ STDMETHOD (GetState) (IShellItemArray *psiItemArray, BOOL fOkToBeSlow, EXPCMDSTATE *pCmdState);
+ STDMETHOD (Invoke) (IShellItemArray *psiItemArray, IBindCtx *pbc);
+ STDMETHOD (GetFlags) (EXPCMDFLAGS *pFlags);
+ STDMETHOD (EnumSubCommands) (IEnumExplorerCommand **ppEnum);
+
+ // IEnumExplorerCommand
+ STDMETHOD (Next) (ULONG celt, IExplorerCommand **pUICommand, ULONG *pceltFetched);
+ STDMETHOD (Skip) (ULONG celt);
+ STDMETHOD (Reset) (void);
+ STDMETHOD (Clone) (IEnumExplorerCommand **ppenum);
+
CZipContextMenu();
~CZipContextMenu();
@@ -58,10 +97,25 @@ public:
{
ECommandInternalID CommandInternalID;
UString Verb;
+ UString UserString;
// UString HelpString;
UString Folder;
UString ArcName;
UString ArcType;
+ bool IsPopup;
+ ECtxCommandType CtxCommandType;
+
+ CCommandMapItem():
+ IsPopup(false),
+ CtxCommandType(CtxCommandType_Normal)
+ {}
+
+ bool IsSubMenu() const
+ {
+ return
+ CtxCommandType == CtxCommandType_CrcRoot ||
+ CtxCommandType == CtxCommandType_OpenRoot;
+ }
};
private:
@@ -71,16 +125,28 @@ private:
bool _dropMode;
UString _dropPath;
CObjectVector<CCommandMapItem> _commandMap;
+ CObjectVector<CCommandMapItem> _commandMap_Cur;
HBITMAP _bitmap;
-
CBoolPair _elimDup;
+ bool IsSeparator;
+ bool IsRoot;
+ CObjectVector< CMyComPtr<IExplorerCommand> > SubCommands;
+ ULONG CurrentSubCommand;
+
+ void Set_UserString_in_LastCommand(const UString &s)
+ {
+ _commandMap.Back().UserString = s;
+ }
+
HRESULT GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames);
int FindVerb(const UString &verb);
void FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &cmi);
void AddCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &cmi);
void AddMapItem_ForSubMenu(const char *ver);
+
+ HRESULT InvokeCommandCommon(const CCommandMapItem &cmi);
};
#endif
diff --git a/CPP/7zip/UI/Explorer/ContextMenuFlags.h b/CPP/7zip/UI/Explorer/ContextMenuFlags.h
index f739cdc6..42b25f3a 100644
--- a/CPP/7zip/UI/Explorer/ContextMenuFlags.h
+++ b/CPP/7zip/UI/Explorer/ContextMenuFlags.h
@@ -20,6 +20,7 @@ namespace NContextMenuFlags
const UInt32 kCompressToZip = 1 << 12;
const UInt32 kCompressToZipEmail = 1 << 13;
+ const UInt32 kCRC_Cascaded = (UInt32)1 << 30;
const UInt32 kCRC = (UInt32)1 << 31;
}
diff --git a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
index cb4da016..91b0da52 100644
--- a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
+++ b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
@@ -9,6 +9,7 @@
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
+// #include "../../../Common/IntToString.h"
#include <OleCtl.h>
@@ -52,7 +53,8 @@ LONG g_DllRefCount;
LONG g_DllRefCount = 0; // Reference count of this DLL.
-// #define ODS(sz) OutputDebugString(L#sz)
+// #define ODS(sz) OutputDebugStringW(L#sz)
+#define ODS(sz)
class CShellExtClassFactory:
public IClassFactory,
@@ -71,7 +73,12 @@ public:
STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,
REFIID riid, void **ppvObj)
{
- // ODS("CShellExtClassFactory::CreateInstance()\r\n");
+ ODS("CShellExtClassFactory::CreateInstance()\r\n");
+ /*
+ char s[64];
+ ConvertUInt32ToHex(riid.Data1, s);
+ OutputDebugStringA(s);
+ */
*ppvObj = NULL;
if (pUnkOuter)
return CLASS_E_NOAGGREGATION;
@@ -123,12 +130,12 @@ BOOL WINAPI DllMain(
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hInstance = (HINSTANCE)hInstance;
- // ODS("In DLLMain, DLL_PROCESS_ATTACH\r\n");
+ ODS("In DLLMain, DLL_PROCESS_ATTACH\r\n");
NT_CHECK
}
else if (dwReason == DLL_PROCESS_DETACH)
{
- // ODS("In DLLMain, DLL_PROCESS_DETACH\r\n");
+ ODS("In DLLMain, DLL_PROCESS_DETACH\r\n");
}
return TRUE;
}
@@ -138,13 +145,19 @@ BOOL WINAPI DllMain(
STDAPI DllCanUnloadNow(void)
{
- // ODS("In DLLCanUnloadNow\r\n");
+ ODS("In DLLCanUnloadNow\r\n");
+ /*
+ if (g_DllRefCount == 0)
+ ODS( "g_DllRefCount == 0");
+ else
+ ODS( "g_DllRefCount != 0");
+ */
return (g_DllRefCount == 0 ? S_OK : S_FALSE);
}
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
- // ODS("In DllGetClassObject\r\n");
+ ODS("In DllGetClassObject\r\n");
*ppv = NULL;
if (IsEqualIID(rclsid, CLSID_CZipContextMenu))
{
@@ -168,6 +181,7 @@ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
static BOOL RegisterServer()
{
+ ODS("RegisterServer\r\n");
FString modulePath;
if (!NDLL::MyGetModuleFileName(modulePath))
return FALSE;
@@ -197,6 +211,7 @@ static BOOL RegisterServer()
key.SetValue(k_Clsid, k_ShellExtName);
}
+ ODS("RegisterServer :: return TRUE");
return TRUE;
}
diff --git a/CPP/7zip/UI/Explorer/Explorer.dsp b/CPP/7zip/UI/Explorer/Explorer.dsp
index bd91e546..e3909176 100644
--- a/CPP/7zip/UI/Explorer/Explorer.dsp
+++ b/CPP/7zip/UI/Explorer/Explorer.dsp
@@ -55,7 +55,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /opt:NOWIN98
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Util\7-Zip.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "Explorer - Win32 Debug"
@@ -82,7 +82,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\7-Zip.dll" /pdbtype:sept
!ELSEIF "$(CFG)" == "Explorer - Win32 ReleaseU"
@@ -110,7 +110,7 @@ BSC32=bscmake.exe
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /opt:NOWIN98
# SUBTRACT BASE LINK32 /pdb:none
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zipn.dll" /opt:NOWIN98
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /machine:I386 /out:"C:\Util\7-Zip.dll" /opt:NOWIN98
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "Explorer - Win32 DebugU"
@@ -138,7 +138,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-ZIP\7-Zip.dll" /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib htmlhelp.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\7-Zip.dll" /pdbtype:sept
!ENDIF
@@ -226,6 +226,10 @@ SOURCE=.\ContextMenu.h
# End Source File
# Begin Source File
+SOURCE=.\MyExplorerCommand.h
+# End Source File
+# Begin Source File
+
SOURCE=.\MyMessages.cpp
# End Source File
# Begin Source File
@@ -274,6 +278,14 @@ SOURCE=..\FileManager\ProgramLocation.h
# End Source File
# Begin Source File
+SOURCE=..\FileManager\PropertyName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\FileManager\PropertyName.h
+# End Source File
+# Begin Source File
+
SOURCE=..\FileManager\RegistryUtils.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/UI/Explorer/MyExplorerCommand.h b/CPP/7zip/UI/Explorer/MyExplorerCommand.h
new file mode 100644
index 00000000..6004d929
--- /dev/null
+++ b/CPP/7zip/UI/Explorer/MyExplorerCommand.h
@@ -0,0 +1,173 @@
+// MyExplorerCommand.h
+
+#ifndef __MY_EXPLORER_COMMAND_H
+#define __MY_EXPLORER_COMMAND_H
+
+#if _MSC_VER >= 1910
+#define USE_SYS_shobjidl_core
+#endif
+
+#ifdef USE_SYS_shobjidl_core
+
+// #include <shobjidl_core.h>
+
+#else
+
+#ifndef __IShellItemArray_INTERFACE_DEFINED__
+#define __IShellItemArray_INTERFACE_DEFINED__
+
+// propsys.h
+
+typedef /* [v1_enum] */
+enum GETPROPERTYSTOREFLAGS
+{
+ GPS_DEFAULT = 0,
+ GPS_HANDLERPROPERTIESONLY = 0x1,
+ GPS_READWRITE = 0x2,
+ GPS_TEMPORARY = 0x4,
+ GPS_FASTPROPERTIESONLY = 0x8,
+ GPS_OPENSLOWITEM = 0x10,
+ GPS_DELAYCREATION = 0x20,
+ GPS_BESTEFFORT = 0x40,
+ GPS_NO_OPLOCK = 0x80,
+ GPS_PREFERQUERYPROPERTIES = 0x100,
+ GPS_EXTRINSICPROPERTIES = 0x200,
+ GPS_EXTRINSICPROPERTIESONLY = 0x400,
+ GPS_VOLATILEPROPERTIES = 0x800,
+ GPS_VOLATILEPROPERTIESONLY = 0x1000,
+ GPS_MASK_VALID = 0x1fff
+} GETPROPERTYSTOREFLAGS;
+
+// DEFINE_ENUM_FLAG_OPERATORS(GETPROPERTYSTOREFLAGS)
+
+
+#ifndef PROPERTYKEY_DEFINED
+#define PROPERTYKEY_DEFINED
+
+typedef
+struct _tagpropertykey
+{
+ GUID fmtid;
+ DWORD pid;
+} PROPERTYKEY;
+
+#endif // PROPERTYKEY_DEFINED
+
+// propkeydef.h
+#define REFPROPERTYKEY const PROPERTYKEY &
+
+#ifdef INITGUID
+#define DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) EXTERN_C const PROPERTYKEY DECLSPEC_SELECTANY name = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid }
+#else
+#define DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) EXTERN_C const PROPERTYKEY name
+#endif // INITGUID
+
+
+// <shobjidl_core.h>
+typedef /* [v1_enum] */
+enum SIATTRIBFLAGS
+{
+ SIATTRIBFLAGS_AND = 0x1,
+ SIATTRIBFLAGS_OR = 0x2,
+ SIATTRIBFLAGS_APPCOMPAT = 0x3,
+ SIATTRIBFLAGS_MASK = 0x3,
+ SIATTRIBFLAGS_ALLITEMS = 0x4000
+} SIATTRIBFLAGS;
+
+// DEFINE_ENUM_FLAG_OPERATORS(SIATTRIBFLAGS)
+
+
+// MIDL_INTERFACE("70629033-e363-4a28-a567-0db78006e6d7")
+DEFINE_GUID(IID_IEnumShellItems, 0x70629033, 0xe363, 0xe363, 0xa5, 0x67, 0x0d, 0xb7, 0x80, 0x06, 0xe6, 0xd7);
+
+struct IEnumShellItems : public IUnknown
+{
+ STDMETHOD (Next) (ULONG celt, IShellItem **rgelt, ULONG *pceltFetched) = 0;
+ STDMETHOD (Skip) (ULONG celt) = 0;
+ STDMETHOD (Reset) (void) = 0;
+ STDMETHOD (Clone) (IEnumShellItems **ppenum) = 0;
+};
+
+
+// MIDL_INTERFACE("b63ea76d-1f85-456f-a19c-48159efa858b")
+DEFINE_GUID(IID_IShellItemArray, 0xb63ea76d, 0x1f85, 0x456f, 0xa1, 0x9c, 0x48, 0x15, 0x9e, 0xfa, 0x85, 0x8b);
+
+struct IShellItemArray : public IUnknown
+{
+ STDMETHOD (BindToHandler) (IBindCtx *pbc, REFGUID bhid, REFIID riid, void **ppvOut) = 0;
+ STDMETHOD (GetPropertyStore) (GETPROPERTYSTOREFLAGS flags, REFIID riid, void **ppv) = 0;
+ STDMETHOD (GetPropertyDescriptionList) (REFPROPERTYKEY keyType, REFIID riid, void **ppv) = 0;
+ STDMETHOD (GetAttributes) ( SIATTRIBFLAGS AttribFlags, SFGAOF sfgaoMask, SFGAOF *psfgaoAttribs) = 0;
+ STDMETHOD (GetCount) (DWORD *pdwNumItems) = 0;
+ STDMETHOD (GetItemAt) (DWORD dwIndex, IShellItem **ppsi) = 0;
+ STDMETHOD (EnumItems) (IEnumShellItems **ppenumShellItems) = 0;
+};
+
+
+#ifndef __IEnumExplorerCommand_INTERFACE_DEFINED__
+#define __IEnumExplorerCommand_INTERFACE_DEFINED__
+
+struct IExplorerCommand;
+
+// MIDL_INTERFACE("a88826f8-186f-4987-aade-ea0cef8fbfe8")
+DEFINE_GUID(IID_IEnumExplorerCommand , 0xa88826f8, 0x186f, 0x4987, 0xaa, 0xde, 0xea, 0x0c, 0xef, 0x8f, 0xbf, 0xe8);
+
+struct IEnumExplorerCommand : public IUnknown
+{
+ STDMETHOD (Next) (ULONG celt, IExplorerCommand **pUICommand, ULONG *pceltFetched) = 0;
+ STDMETHOD (Skip) (ULONG celt) = 0;
+ STDMETHOD (Reset) (void) = 0;
+ STDMETHOD (Clone) (IEnumExplorerCommand **ppenum) = 0;
+};
+
+
+enum _EXPCMDSTATE
+{
+ ECS_ENABLED = 0,
+ ECS_DISABLED = 0x1,
+ ECS_HIDDEN = 0x2,
+ ECS_CHECKBOX = 0x4,
+ ECS_CHECKED = 0x8,
+ ECS_RADIOCHECK = 0x10
+};
+
+typedef DWORD EXPCMDSTATE;
+
+/* [v1_enum] */
+enum _EXPCMDFLAGS
+{
+ ECF_DEFAULT = 0,
+ ECF_HASSUBCOMMANDS = 0x1,
+ ECF_HASSPLITBUTTON = 0x2,
+ ECF_HIDELABEL = 0x4,
+ ECF_ISSEPARATOR = 0x8,
+ ECF_HASLUASHIELD = 0x10,
+ ECF_SEPARATORBEFORE = 0x20,
+ ECF_SEPARATORAFTER = 0x40,
+ ECF_ISDROPDOWN = 0x80,
+ ECF_TOGGLEABLE = 0x100,
+ ECF_AUTOMENUICONS = 0x200
+};
+typedef DWORD EXPCMDFLAGS;
+
+
+// MIDL_INTERFACE("a08ce4d0-fa25-44ab-b57c-c7b1c323e0b9")
+DEFINE_GUID(IID_IExplorerCommand, 0xa08ce4d0, 0xfa25, 0x44ab, 0xb5, 0x7c, 0xc7, 0xb1, 0xc3, 0x23, 0xe0, 0xb9);
+
+struct IExplorerCommand : public IUnknown
+{
+ STDMETHOD (GetTitle) (IShellItemArray *psiItemArray, LPWSTR *ppszName) = 0;
+ STDMETHOD (GetIcon) (IShellItemArray *psiItemArray, LPWSTR *ppszIcon) = 0;
+ STDMETHOD (GetToolTip) (IShellItemArray *psiItemArray, LPWSTR *ppszInfotip) = 0;
+ STDMETHOD (GetCanonicalName) (GUID *pguidCommandName) = 0;
+ STDMETHOD (GetState) (IShellItemArray *psiItemArray, BOOL fOkToBeSlow, EXPCMDSTATE *pCmdState) = 0;
+ STDMETHOD (Invoke) (IShellItemArray *psiItemArray, IBindCtx *pbc) = 0;
+ STDMETHOD (GetFlags) (EXPCMDFLAGS *pFlags) = 0;
+ STDMETHOD (EnumSubCommands) (IEnumExplorerCommand **ppEnum) = 0;
+};
+
+#endif // IShellItemArray
+#endif // __IEnumExplorerCommand_INTERFACE_DEFINED__
+#endif // USE_SYS_shobjidl_core
+
+#endif // __MY_EXPLORER_COMMAND_H
diff --git a/CPP/7zip/UI/Explorer/makefile b/CPP/7zip/UI/Explorer/makefile
index 541122ab..1e79cc82 100644
--- a/CPP/7zip/UI/Explorer/makefile
+++ b/CPP/7zip/UI/Explorer/makefile
@@ -65,6 +65,7 @@ FM_OBJS = \
$O\HelpUtils.obj \
$O\LangUtils.obj \
$O\ProgramLocation.obj \
+ $O\PropertyName.obj \
$O\RegistryUtils.obj \
C_OBJS = \
diff --git a/CPP/7zip/UI/Explorer/resource.rc b/CPP/7zip/UI/Explorer/resource.rc
index 80018b45..66592908 100644
--- a/CPP/7zip/UI/Explorer/resource.rc
+++ b/CPP/7zip/UI/Explorer/resource.rc
@@ -6,3 +6,5 @@ MY_VERSION_INFO_DLL("7-Zip Shell Extension", "7-zip")
#ifndef UNDER_CE
1 24 MOVEABLE PURE "7-zip.dll.manifest"
#endif
+
+IDI_ICON ICON "..\FileManager\FM.ico"
diff --git a/CPP/7zip/UI/Far/ExtractEngine.cpp b/CPP/7zip/UI/Far/ExtractEngine.cpp
index e6fe2d01..ab5c0def 100644
--- a/CPP/7zip/UI/Far/ExtractEngine.cpp
+++ b/CPP/7zip/UI/Far/ExtractEngine.cpp
@@ -130,6 +130,7 @@ STDMETHODIMP CExtractCallbackImp::AskOverwrite(
static const char * const kTestString = "Testing";
static const char * const kExtractString = "Extracting";
static const char * const kSkipString = "Skipping";
+static const char * const kReadString = "Reading";
STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 /* isFolder */, Int32 askExtractMode, const UInt64 * /* position */)
{
@@ -143,6 +144,7 @@ STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 /*
case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break;
case NArchive::NExtract::NAskMode::kTest: s = kTestString; break;
case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; break;
+ case NArchive::NExtract::NAskMode::kReadExternal: s = kReadString; break;
default: s = "???"; // return E_FAIL;
};
diff --git a/CPP/7zip/UI/Far/Far.dsp b/CPP/7zip/UI/Far/Far.dsp
index b32ae6fa..bd6d8fd4 100644
--- a/CPP/7zip/UI/Far/Far.dsp
+++ b/CPP/7zip/UI/Far/Far.dsp
@@ -118,6 +118,14 @@ SOURCE=..\..\..\Common\CRC.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\DynLimBuf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\DynLimBuf.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\IntToString.cpp
# End Source File
# Begin Source File
@@ -430,6 +438,14 @@ SOURCE=..\Common\HandlerLoader.h
# End Source File
# Begin Source File
+SOURCE=..\Common\HashCalc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\HashCalc.h
+# End Source File
+# Begin Source File
+
SOURCE=..\Common\LoadCodecs.cpp
# End Source File
# Begin Source File
@@ -622,6 +638,14 @@ SOURCE=..\..\Common\LimitedStreams.h
# End Source File
# Begin Source File
+SOURCE=..\..\Common\MethodProps.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\MethodProps.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Common\ProgressUtils.cpp
# End Source File
# Begin Source File
@@ -712,6 +736,14 @@ SOURCE=..\..\..\..\C\Threads.h
# PROP Default_Filter ""
# Begin Source File
+SOURCE=..\..\Archive\Common\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ItemNameUtils.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp
index 92b62369..8dc1375a 100644
--- a/CPP/7zip/UI/Far/Plugin.cpp
+++ b/CPP/7zip/UI/Far/Plugin.cpp
@@ -686,9 +686,14 @@ struct CArchiveItemProperty
VARTYPE Type;
};
-static inline char GetHex(Byte value)
+static inline char GetHex_Upper(unsigned v)
{
- return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+ return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10)));
+}
+
+static inline char GetHex_Lower(unsigned v)
+{
+ return (char)((v < 10) ? ('0' + v) : ('a' + (v - 10)));
}
HRESULT CPlugin::ShowAttributesWindow()
@@ -810,11 +815,21 @@ HRESULT CPlugin::ShowAttributesWindow()
}
else
{
+ const bool needUpper = (dataSize <= 8)
+ && (property.ID == kpidCRC || property.ID == kpidChecksum);
for (UInt32 k = 0; k < dataSize; k++)
{
- Byte b = ((const Byte *)data)[k];
- s += GetHex((Byte)((b >> 4) & 0xF));
- s += GetHex((Byte)(b & 0xF));
+ unsigned b = ((const Byte *)data)[k];
+ if (needUpper)
+ {
+ s += GetHex_Upper((b >> 4) & 0xF);
+ s += GetHex_Upper(b & 0xF);
+ }
+ else
+ {
+ s += GetHex_Lower((b >> 4) & 0xF);
+ s += GetHex_Lower(b & 0xF);
+ }
}
}
}
diff --git a/CPP/7zip/UI/Far/PluginDelete.cpp b/CPP/7zip/UI/Far/PluginDelete.cpp
index 0d19c6e7..939a3558 100644
--- a/CPP/7zip/UI/Far/PluginDelete.cpp
+++ b/CPP/7zip/UI/Far/PluginDelete.cpp
@@ -17,7 +17,7 @@ int CPlugin::DeleteFiles(PluginPanelItem *panelItems, int numItems, int opMode)
{
if (numItems == 0)
return FALSE;
- if (_agent->IsThereReadOnlyArc())
+ if (_agent->IsThere_ReadOnlyArc())
{
g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
return FALSE;
diff --git a/CPP/7zip/UI/Far/PluginRead.cpp b/CPP/7zip/UI/Far/PluginRead.cpp
index 9df4a09f..70e7e141 100644
--- a/CPP/7zip/UI/Far/PluginRead.cpp
+++ b/CPP/7zip/UI/Far/PluginRead.cpp
@@ -37,6 +37,12 @@ HRESULT CPlugin::ExtractFiles(
const UString &destPath,
bool passwordIsDefined, const UString &password)
{
+ if (_agent->_isHashHandler)
+ {
+ g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported);
+ return NFileOperationReturnCode::kError;
+ }
+
CScreenRestorer screenRestorer;
CProgressBox progressBox;
CProgressBox *progressBoxPointer = NULL;
diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp
index bf1d13df..8a76bb4e 100644
--- a/CPP/7zip/UI/Far/PluginWrite.cpp
+++ b/CPP/7zip/UI/Far/PluginWrite.cpp
@@ -81,18 +81,17 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles(
struct PluginPanelItem *panelItems, int numItems,
int moveMode, int opMode)
{
- /*
- if (moveMode != 0)
+ if (moveMode != 0
+ && _agent->_isHashHandler)
{
g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported);
return NFileOperationReturnCode::kError;
}
- */
if (numItems <= 0)
return NFileOperationReturnCode::kError;
- if (_agent->IsThereReadOnlyArc())
+ if (_agent->IsThere_ReadOnlyArc())
{
g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
return NFileOperationReturnCode::kError;
@@ -231,8 +230,11 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles(
updateCallbackSpec->PasswordIsDefined = PasswordIsDefined;
updateCallbackSpec->Password = Password;
- if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK)
- return NFileOperationReturnCode::kError;
+ if (!_agent->_isHashHandler)
+ {
+ if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK)
+ return NFileOperationReturnCode::kError;
+ }
/*
outArchive->SetFolder(_folder);
@@ -726,7 +728,7 @@ static const char * const k_CreateFolder_History = "NewFolder"; // we use defaul
HRESULT CPlugin::CreateFolder()
{
- if (_agent->IsThereReadOnlyArc())
+ if (_agent->IsThere_ReadOnlyArc())
{
g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
return TRUE;
diff --git a/CPP/7zip/UI/Far/makefile b/CPP/7zip/UI/Far/makefile
index 14be13d6..0db22749 100644
--- a/CPP/7zip/UI/Far/makefile
+++ b/CPP/7zip/UI/Far/makefile
@@ -22,6 +22,7 @@ CURRENT_OBJS = \
$O\UpdateCallbackFar.obj \
COMMON_OBJS = \
+ $O\DynLimBuf.obj \
$O\IntToString.obj \
$O\NewHandler.obj \
$O\MyString.obj \
@@ -52,6 +53,7 @@ WIN_OBJS = \
$O\FileStreams.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
+ $O\MethodProps.obj \
$O\ProgressUtils.obj \
$O\PropId.obj \
$O\StreamObjects.obj \
@@ -64,6 +66,7 @@ UI_COMMON_OBJS = \
$O\DefaultName.obj \
$O\EnumDirItems.obj \
$O\ExtractingFilePath.obj \
+ $O\HashCalc.obj \
$O\LoadCodecs.obj \
$O\OpenArchive.obj \
$O\PropIDUtils.obj \
@@ -77,6 +80,7 @@ UI_COMMON_OBJS = \
$O\ZipRegistry.obj \
AR_COMMON_OBJS = \
+ $O\ItemNameUtils.obj \
$O\OutStreamWithCRC.obj \
AGENT_OBJS = \
diff --git a/CPP/7zip/UI/FileManager/ClassDefs.cpp b/CPP/7zip/UI/FileManager/ClassDefs.cpp
index 33197fc3..5c269043 100644
--- a/CPP/7zip/UI/FileManager/ClassDefs.cpp
+++ b/CPP/7zip/UI/FileManager/ClassDefs.cpp
@@ -9,3 +9,4 @@
#include "../Agent/Agent.h"
#include "MyWindowsNew.h"
+#include "../Explorer/MyExplorerCommand.h"
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
index 0e285f04..232717f8 100644
--- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
@@ -44,6 +44,7 @@ void CExtractCallbackImp::Init()
_lang_Extracting = LangString(IDS_PROGRESS_EXTRACTING);
_lang_Testing = LangString(IDS_PROGRESS_TESTING);
_lang_Skipping = LangString(IDS_PROGRESS_SKIPPING);
+ _lang_Reading = "Reading";
NumArchiveErrors = 0;
ThereAreMessageErrors = false;
@@ -233,6 +234,7 @@ STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 is
case NArchive::NExtract::NAskMode::kExtract: msg = &_lang_Extracting; break;
case NArchive::NExtract::NAskMode::kTest: msg = &_lang_Testing; break;
case NArchive::NExtract::NAskMode::kSkip: msg = &_lang_Skipping; break;
+ case NArchive::NExtract::NAskMode::kReadExternal: msg = &_lang_Reading; break;
// default: s = "Unknown operation";
}
@@ -911,8 +913,10 @@ STDMETHODIMP CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode)
{
COM_TRY_BEGIN
_needUpdateStat = (
- askExtractMode == NArchive::NExtract::NAskMode::kExtract ||
- askExtractMode == NArchive::NExtract::NAskMode::kTest);
+ askExtractMode == NArchive::NExtract::NAskMode::kExtract
+ || askExtractMode == NArchive::NExtract::NAskMode::kTest
+ || askExtractMode == NArchive::NExtract::NAskMode::kReadExternal
+ );
/*
_extractMode = false;
@@ -930,7 +934,7 @@ STDMETHODIMP CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode)
COM_TRY_END
}
-STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, Int32 encrypted)
+STDMETHODIMP CExtractCallbackImp::SetOperationResult8(Int32 opRes, Int32 encrypted, UInt64 size)
{
COM_TRY_BEGIN
if (VirtFileSystem && _newVirtFileWasAdded)
@@ -950,7 +954,7 @@ STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, Int32 encrypt
}
else if (_hashCalc && _needUpdateStat)
{
- _hashCalc->SetSize(_curSize);
+ _hashCalc->SetSize(size); // (_curSize) before 21.04
_hashCalc->Final(_isFolder, _isAltStream, _filePath);
}
return SetOperationResult(opRes, encrypted);
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h
index 297492eb..02578bb4 100644
--- a/CPP/7zip/UI/FileManager/ExtractCallback.h
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.h
@@ -282,6 +282,7 @@ public:
UString _lang_Extracting;
UString _lang_Testing;
UString _lang_Skipping;
+ UString _lang_Reading;
UString _lang_Empty;
bool _totalFilesDefined;
diff --git a/CPP/7zip/UI/FileManager/FM.dsp b/CPP/7zip/UI/FileManager/FM.dsp
index d87beff5..a12d3307 100644
--- a/CPP/7zip/UI/FileManager/FM.dsp
+++ b/CPP/7zip/UI/FileManager/FM.dsp
@@ -1076,6 +1076,14 @@ SOURCE=..\..\..\Common\DynamicBuffer.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\DynLimBuf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\DynLimBuf.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\Exception.h
# End Source File
# Begin Source File
@@ -1419,6 +1427,10 @@ SOURCE=..\Explorer\ContextMenuFlags.h
# End Source File
# Begin Source File
+SOURCE=..\Explorer\MyExplorerCommand.h
+# End Source File
+# Begin Source File
+
SOURCE=..\Explorer\RegistryContextMenu.cpp
# End Source File
# Begin Source File
@@ -1491,6 +1503,18 @@ SOURCE=..\..\IStream.h
SOURCE=..\..\PropID.h
# End Source File
# End Group
+# Begin Group "ArchiveCommon"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ItemNameUtils.h
+# End Source File
+# End Group
# Begin Source File
SOURCE=.\7zFM.exe.manifest
diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.rc b/CPP/7zip/UI/FileManager/ListViewDialog.rc
index 961d224a..4343b755 100644
--- a/CPP/7zip/UI/FileManager/ListViewDialog.rc
+++ b/CPP/7zip/UI/FileManager/ListViewDialog.rc
@@ -1,7 +1,7 @@
#include "ListViewDialogRes.h"
#include "../../GuiCommon.rc"
-#define xc 440
+#define xc 480
#define yc 320
IDD_LISTVIEW DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp
index ac3a7b14..05f24d71 100644
--- a/CPP/7zip/UI/FileManager/MenuPage.cpp
+++ b/CPP/7zip/UI/FileManager/MenuPage.cpp
@@ -63,7 +63,8 @@ static const CContextMenuItem kMenuItems[] =
{ IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressToZipEmail },
#endif
- { IDS_PROP_CHECKSUM, kCRC }
+ { IDS_PROP_CHECKSUM, kCRC },
+ { IDS_PROP_CHECKSUM, kCRC_Cascaded },
};
@@ -188,8 +189,11 @@ bool CMenuPage::OnInit()
UString s = LangString(menuItem.ControlID);
if (menuItem.Flag == kCRC)
s = "CRC SHA";
- if (menuItem.Flag == kOpenAs ||
- menuItem.Flag == kCRC)
+ else if (menuItem.Flag == kCRC_Cascaded)
+ s = "7-Zip > CRC SHA";
+ if (menuItem.Flag == kOpenAs
+ || menuItem.Flag == kCRC
+ || menuItem.Flag == kCRC_Cascaded)
s += " >";
switch (menuItem.ControlID)
diff --git a/CPP/7zip/UI/FileManager/MenuPage.rc b/CPP/7zip/UI/FileManager/MenuPage.rc
index dd32898f..fc211074 100644
--- a/CPP/7zip/UI/FileManager/MenuPage.rc
+++ b/CPP/7zip/UI/FileManager/MenuPage.rc
@@ -2,7 +2,7 @@
#include "../../GuiCommon.rc"
#define xc 240
-#define yc 224
+#define yc 252
IDD_MENU MY_PAGE
#include "MenuPage2.rc"
diff --git a/CPP/7zip/UI/FileManager/MyCom2.h b/CPP/7zip/UI/FileManager/MyCom2.h
index 224a838d..c45c2155 100644
--- a/CPP/7zip/UI/FileManager/MyCom2.h
+++ b/CPP/7zip/UI/FileManager/MyCom2.h
@@ -36,4 +36,12 @@ STDMETHOD_(ULONG, Release)() { InterlockedDecrement((LONG *)&__m_RefCount); if (
MY_QUERYINTERFACE_ENTRY(i3) \
)
+#define MY_UNKNOWN_IMP4_MT(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC_MT2( \
+ i1, \
+ MY_QUERYINTERFACE_ENTRY(i1) \
+ MY_QUERYINTERFACE_ENTRY(i2) \
+ MY_QUERYINTERFACE_ENTRY(i3) \
+ MY_QUERYINTERFACE_ENTRY(i4) \
+ )
+
#endif
diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp
index a133a291..63167d63 100644
--- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp
+++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp
@@ -536,6 +536,31 @@ void CFileMenu::Load(HMENU hMenu, unsigned startPos)
disable = true;
}
}
+
+ if (isHashFolder)
+ {
+ switch (item.wID)
+ {
+ case IDM_OPEN:
+ case IDM_OPEN_INSIDE:
+ case IDM_OPEN_INSIDE_ONE:
+ case IDM_OPEN_INSIDE_PARSER:
+ case IDM_OPEN_OUTSIDE:
+ case IDM_FILE_VIEW:
+ case IDM_FILE_EDIT:
+ // case IDM_RENAME:
+ case IDM_COPY_TO:
+ case IDM_MOVE_TO:
+ // case IDM_DELETE:
+ case IDM_COMMENT:
+ case IDM_CREATE_FOLDER:
+ case IDM_CREATE_FILE:
+ case IDM_LINK:
+ case IDM_DIFF:
+ disable = true;
+ }
+ }
+
if (item.wID == IDM_LINK && numItems != 1)
disable = true;
diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.h b/CPP/7zip/UI/FileManager/MyLoadMenu.h
index 0a38a732..764bf7c7 100644
--- a/CPP/7zip/UI/FileManager/MyLoadMenu.h
+++ b/CPP/7zip/UI/FileManager/MyLoadMenu.h
@@ -14,16 +14,18 @@ struct CFileMenu
{
bool programMenu;
bool readOnly;
+ bool isHashFolder;
bool isFsFolder;
bool allAreFiles;
bool isAltStreamsSupported;
int numItems;
- UString FilePath;
+ FString FilePath;
CFileMenu():
programMenu(false),
readOnly(false),
+ isHashFolder(false),
isFsFolder(false),
allAreFiles(false),
isAltStreamsSupported(true),
diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp
index 6702fa9c..e8c0b947 100644
--- a/CPP/7zip/UI/FileManager/Panel.cpp
+++ b/CPP/7zip/UI/FileManager/Panel.cpp
@@ -797,6 +797,18 @@ bool CPanel::IsArcFolder() const
return GetFolderTypeID().IsPrefixedBy_Ascii_NoCase("7-Zip");
}
+bool CPanel::IsHashFolder() const
+{
+ if (_folder)
+ {
+ NCOM::CPropVariant prop;
+ if (_folder->GetFolderProperty(kpidIsHash, &prop) == S_OK)
+ if (prop.vt == VT_BOOL)
+ return VARIANT_BOOLToBool(prop.boolVal);
+ }
+ return false;
+}
+
UString CPanel::GetFsPath() const
{
if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix() && !IsSuperDrivesPrefix())
diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h
index f39d94e2..d1e4d244 100644
--- a/CPP/7zip/UI/FileManager/Panel.h
+++ b/CPP/7zip/UI/FileManager/Panel.h
@@ -647,6 +647,7 @@ public:
bool IsFSDrivesFolder() const;
bool IsAltStreamsFolder() const;
bool IsArcFolder() const;
+ bool IsHashFolder() const;
/*
c:\Dir
diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp
index e1bd0117..7e1937c9 100644
--- a/CPP/7zip/UI/FileManager/PanelCopy.cpp
+++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp
@@ -126,6 +126,12 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &ind
UStringVector *messages,
bool &usePassword, UString &password)
{
+ if (IsHashFolder())
+ {
+ if (!options.testMode)
+ return E_NOTIMPL;
+ }
+
if (!_folderOperations)
{
UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
@@ -290,6 +296,11 @@ struct CThreadUpdate
HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths,
bool showErrorMessages, UStringVector *messages)
{
+ if (IsHashFolder())
+ {
+ if (moveMode)
+ return E_NOTIMPL;
+ }
// CDisableNotify disableNotify(*this);
HRESULT res;
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
index 68fe7b02..ba54491d 100644
--- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
+++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
@@ -1566,6 +1566,10 @@ tryInternal tryExternal
void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode, bool useEditor, const wchar_t *type)
{
+ // we don't want to change hash data here
+ if (IsHashFolder())
+ return;
+
const UString name = GetItemName(index);
const UString relPath = GetItemRelPath(index);
@@ -1793,6 +1797,8 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo
tpi->UsePassword = usePassword;
tpi->Password = password;
tpi->ReadOnly = IsThereReadOnlyFolder();
+ if (IsHashFolder())
+ tpi->ReadOnly = true;
if (!tpi->FileInfo.Find(tempFilePath))
return;
diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp
index 12f471b3..d2114f1c 100644
--- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp
+++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp
@@ -92,11 +92,16 @@ UString ConvertSizeToString(UInt64 value)
return s;
}
-static inline unsigned GetHex(unsigned v)
+static inline unsigned GetHex_Upper(unsigned v)
{
return (v < 10) ? ('0' + v) : ('A' + (v - 10));
}
+static inline unsigned GetHex_Lower(unsigned v)
+{
+ return (v < 10) ? ('0' + v) : ('a' + (v - 10));
+}
+
/*
static void HexToString(char *dest, const Byte *data, UInt32 size)
{
@@ -350,11 +355,21 @@ LRESULT CPanel::SetItemText(LVITEMW &item)
if (dataSize > limit)
dataSize = limit;
WCHAR *dest = text;
+ const bool needUpper = (dataSize <= 8)
+ && (propID == kpidCRC || propID == kpidChecksum);
for (UInt32 i = 0; i < dataSize; i++)
{
unsigned b = ((const Byte *)data)[i];
- dest[0] = (WCHAR)GetHex((b >> 4) & 0xF);
- dest[1] = (WCHAR)GetHex(b & 0xF);
+ if (needUpper)
+ {
+ dest[0] = (WCHAR)GetHex_Upper((b >> 4) & 0xF);
+ dest[1] = (WCHAR)GetHex_Upper(b & 0xF);
+ }
+ else
+ {
+ dest[0] = (WCHAR)GetHex_Lower((b >> 4) & 0xF);
+ dest[1] = (WCHAR)GetHex_Lower(b & 0xF);
+ }
dest += 2;
}
*dest = 0;
diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp
index 7a88f8f2..99a76cfa 100644
--- a/CPP/7zip/UI/FileManager/PanelMenu.cpp
+++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp
@@ -133,9 +133,14 @@ static void AddPropertyString(PROPID propID, UInt64 val, CListViewDialog &dialog
}
-static inline char GetHex(Byte value)
+static inline unsigned GetHex_Upper(unsigned v)
{
- return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+ return (v < 10) ? ('0' + v) : ('A' + (v - 10));
+}
+
+static inline unsigned GetHex_Lower(unsigned v)
+{
+ return (v < 10) ? ('0' + v) : ('a' + (v - 10));
}
static const Byte kSpecProps[] =
@@ -225,11 +230,21 @@ void CPanel::Properties()
}
else
{
+ const bool needUpper = (dataSize <= 8)
+ && (propID == kpidCRC || propID == kpidChecksum);
for (UInt32 k = 0; k < dataSize; k++)
{
- Byte b = ((const Byte *)data)[k];
- s += GetHex((Byte)((b >> 4) & 0xF));
- s += GetHex((Byte)(b & 0xF));
+ const Byte b = ((const Byte *)data)[k];
+ if (needUpper)
+ {
+ s += (char)GetHex_Upper((b >> 4) & 0xF);
+ s += (char)GetHex_Upper(b & 0xF);
+ }
+ else
+ {
+ s += (char)GetHex_Lower((b >> 4) & 0xF);
+ s += (char)GetHex_Lower(b & 0xF);
+ }
}
}
}
@@ -931,6 +946,7 @@ void CPanel::CreateFileMenu(HMENU menuSpec,
CFileMenu fm;
fm.readOnly = IsThereReadOnlyFolder();
+ fm.isHashFolder = IsHashFolder();
fm.isFsFolder = Is_IO_FS_Folder();
fm.programMenu = programMenu;
fm.allAreFiles = allAreFiles;
@@ -939,7 +955,7 @@ void CPanel::CreateFileMenu(HMENU menuSpec,
fm.isAltStreamsSupported = false;
if (fm.numItems == 1)
- fm.FilePath = GetItemFullPath(operatedIndices[0]);
+ fm.FilePath = us2fs(GetItemFullPath(operatedIndices[0]));
if (_folderAltStreams)
{
diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp
index d3e2e978..6c59ea38 100644
--- a/CPP/7zip/UI/FileManager/PanelOperations.cpp
+++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp
@@ -355,6 +355,9 @@ bool Dlg_CreateFolder(HWND wnd, UString &destName);
void CPanel::CreateFolder()
{
+ if (IsHashFolder())
+ return;
+
if (!CheckBeforeUpdate(IDS_CREATE_FOLDER_ERROR))
return;
@@ -415,6 +418,9 @@ void CPanel::CreateFolder()
void CPanel::CreateFile()
{
+ if (IsHashFolder())
+ return;
+
if (!CheckBeforeUpdate(IDS_CREATE_FILE_ERROR))
return;
@@ -473,6 +479,8 @@ void CPanel::RenameFile()
void CPanel::ChangeComment()
{
+ if (IsHashFolder())
+ return;
if (!CheckBeforeUpdate(IDS_COMMENT))
return;
CDisableTimerProcessing disableTimerProcessing2(*this);
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
index 7b132468..54273d0c 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
@@ -5,7 +5,7 @@
#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
-#include "../../../Windows/Control/Static.h"
+#include "../../../Windows/Clipboard.h"
#include "../../../Windows/ErrorMsg.h"
#include "../GUI/ExtractRes.h"
@@ -239,7 +239,7 @@ void CProgressSync::AddError_Code_Name(DWORD systemError, const wchar_t *name)
CProgressDialog::CProgressDialog():
_timer(0),
CompressingMode(true),
- MainWindow(0)
+ MainWindow(NULL)
{
_isDir = false;
@@ -280,7 +280,7 @@ CProgressDialog::~CProgressDialog()
}
void CProgressDialog::AddToTitle(LPCWSTR s)
{
- if (MainWindow != 0)
+ if (MainWindow)
{
CWindow window(MainWindow);
window.SetText((UString)s + MainTitle);
@@ -357,6 +357,7 @@ bool CProgressDialog::OnInit()
m_ProgressBar.Attach(GetItem(IDC_PROGRESS1));
_messageList.Attach(GetItem(IDL_PROGRESS_MESSAGES));
_messageList.SetUnicodeFormat();
+ _messageList.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
_wasCreated = true;
_dialogCreatedEvent.Set();
@@ -1046,6 +1047,8 @@ bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
}
if (_inCancelMessageBox)
{
+ /* if user is in MessageBox(), we will call OnExternalCloseMessage()
+ later, when MessageBox() will be closed */
_externalCloseMessageWasReceived = true;
break;
}
@@ -1142,13 +1145,16 @@ void CProgressDialog::OnPriorityButton()
void CProgressDialog::AddMessageDirect(LPCWSTR message, bool needNumber)
{
- int itemIndex = _messageList.GetItemCount();
wchar_t sz[16];
sz[0] = 0;
if (needNumber)
ConvertUInt32ToString(_numMessages + 1, sz);
- _messageList.InsertItem(itemIndex, sz);
- _messageList.SetSubItem(itemIndex, 1, message);
+ const unsigned itemIndex = _messageStrings.Size(); // _messageList.GetItemCount();
+ if (_messageList.InsertItem((int)itemIndex, sz) == (int)itemIndex)
+ {
+ _messageList.SetSubItem((int)itemIndex, 1, message);
+ _messageStrings.Add(message);
+ }
}
void CProgressDialog::AddMessage(LPCWSTR message)
@@ -1217,24 +1223,42 @@ bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
End(IDCLOSE);
break;
}
+
+ if (_cancelWasPressed)
+ return true;
- bool paused = Sync.Get_Paused();
+ const bool paused = Sync.Get_Paused();
+
if (!paused)
+ {
OnPauseButton();
+ }
+
_inCancelMessageBox = true;
- int res = ::MessageBoxW(*this, LangString(IDS_PROGRESS_ASK_CANCEL), _title, MB_YESNOCANCEL);
+ const int res = ::MessageBoxW(*this, LangString(IDS_PROGRESS_ASK_CANCEL), _title, MB_YESNOCANCEL);
_inCancelMessageBox = false;
+ if (res == IDYES)
+ _cancelWasPressed = true;
+
if (!paused)
+ {
OnPauseButton();
- if (res == IDCANCEL || res == IDNO)
+ }
+
+ if (_externalCloseMessageWasReceived)
{
- if (_externalCloseMessageWasReceived)
- OnExternalCloseMessage();
+ /* we have received kCloseMessage while we were in MessageBoxW().
+ so we call OnExternalCloseMessage() here.
+ it can show MessageBox and it can close dialog */
+ OnExternalCloseMessage();
return true;
}
- _cancelWasPressed = true;
+ if (!_cancelWasPressed)
+ return true;
+
MessagesDisplayed = true;
+ // we will call Sync.Set_Stopped(true) in OnButtonClicked() : OnCancel()
break;
}
@@ -1270,6 +1294,87 @@ void CProgressDialog::ProcessWasFinished()
}
+bool CProgressDialog::OnNotify(UINT /* controlID */, LPNMHDR header)
+{
+ if (header->hwndFrom != _messageList)
+ return false;
+ switch (header->code)
+ {
+ case LVN_KEYDOWN:
+ {
+ LPNMLVKEYDOWN keyDownInfo = LPNMLVKEYDOWN(header);
+ switch (keyDownInfo->wVKey)
+ {
+ case 'A':
+ {
+ if (IsKeyDown(VK_CONTROL))
+ {
+ _messageList.SelectAll();
+ return true;
+ }
+ break;
+ }
+ case VK_INSERT:
+ case 'C':
+ {
+ if (IsKeyDown(VK_CONTROL))
+ {
+ CopyToClipboard();
+ return true;
+ }
+ break;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+static void ListView_GetSelected(NControl::CListView &listView, CUIntVector &vector)
+{
+ vector.Clear();
+ int index = -1;
+ for (;;)
+ {
+ index = listView.GetNextSelectedItem(index);
+ if (index < 0)
+ break;
+ vector.Add(index);
+ }
+}
+
+
+void CProgressDialog::CopyToClipboard()
+{
+ CUIntVector indexes;
+ ListView_GetSelected(_messageList, indexes);
+ UString s;
+ unsigned numIndexes = indexes.Size();
+ if (numIndexes == 0)
+ numIndexes = _messageList.GetItemCount();
+
+ for (unsigned i = 0; i < numIndexes; i++)
+ {
+ const unsigned index = (i < indexes.Size() ? indexes[i] : i);
+ // s.Add_UInt32(index);
+ // s += ": ";
+ s += _messageStrings[index];
+ {
+ s +=
+ #ifdef _WIN32
+ "\r\n"
+ #else
+ "\n"
+ #endif
+ ;
+ }
+ }
+
+ ClipboardSetText(*this, s);
+}
+
+
static THREAD_FUNC_DECL MyThreadFunction(void *param)
{
CProgressThreadVirt *p = (CProgressThreadVirt *)param;
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h
index c17dd395..d8259d6a 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog2.h
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h
@@ -152,6 +152,7 @@ class CProgressDialog: public NWindows::NControl::CModalDialog
NWindows::NControl::CListView _messageList;
int _numMessages;
+ UStringVector _messageStrings;
#ifdef __ITaskbarList3_INTERFACE_DEFINED__
CMyComPtr<ITaskbarList3> _taskbarList;
@@ -212,6 +213,9 @@ class CProgressDialog: public NWindows::NControl::CModalDialog
virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
virtual void OnCancel();
virtual void OnOK();
+ virtual bool OnNotify(UINT /* controlID */, LPNMHDR header);
+ void CopyToClipboard();
+
NWindows::NSynchronization::CManualResetEvent _createDialogEvent;
NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;
#ifndef _SFX
diff --git a/CPP/7zip/UI/FileManager/VerCtrl.cpp b/CPP/7zip/UI/FileManager/VerCtrl.cpp
index efed8468..7e53d81f 100644
--- a/CPP/7zip/UI/FileManager/VerCtrl.cpp
+++ b/CPP/7zip/UI/FileManager/VerCtrl.cpp
@@ -18,10 +18,10 @@ using namespace NFile;
using namespace NFind;
using namespace NDir;
-static UString ConvertPath_to_Ctrl(const UString &path)
+static FString ConvertPath_to_Ctrl(const FString &path)
{
- UString s = path;
- s.Replace(L':', L'_');
+ FString s = path;
+ s.Replace(FChar(':'), FChar('_'));
return s;
}
@@ -33,11 +33,11 @@ struct CFileDataInfo
CFileDataInfo(): IsOpen (false) {}
UInt64 GetSize() const { return (((UInt64)Info.nFileSizeHigh) << 32) + Info.nFileSizeLow; }
- bool Read(const UString &path);
+ bool Read(const FString &path);
};
-bool CFileDataInfo::Read(const UString &path)
+bool CFileDataInfo::Read(const FString &path)
{
IsOpen = false;
NIO::CInFile file;
@@ -69,7 +69,7 @@ bool CFileDataInfo::Read(const UString &path)
}
-static bool CreateComplexDir_for_File(const UString &path)
+static bool CreateComplexDir_for_File(const FString &path)
{
FString resDirPrefix;
FString resFileName;
@@ -81,7 +81,7 @@ static bool CreateComplexDir_for_File(const UString &path)
static bool ParseNumberString(const FString &s, UInt32 &number)
{
- const wchar_t *end;
+ const FChar *end;
UInt64 result = ConvertStringToUInt64(s, &end);
if (*end != 0 || s.IsEmpty() || result > (UInt32)0x7FFFFFFF)
return false;
@@ -145,7 +145,7 @@ void CApp::VerCtrl(unsigned id)
return;
}
- const UString path = panel.GetItemFullPath(indices[0]);
+ const FString path = us2fs(panel.GetItemFullPath(indices[0]));
UString vercPath;
ReadReg_VerCtrlPath(vercPath);
@@ -161,8 +161,8 @@ void CApp::VerCtrl(unsigned id)
return;
}
- const UString dirPrefix2 = vercPath + ConvertPath_to_Ctrl(dirPrefix);
- const UString path2 = dirPrefix2 + fileName;
+ const FString dirPrefix2 = us2fs(vercPath) + ConvertPath_to_Ctrl(dirPrefix);
+ const FString path2 = dirPrefix2 + fileName;
bool sameTime = false;
bool sameData = false;
@@ -362,6 +362,6 @@ void CApp::VerCtrl(unsigned id)
{
if (!fdi2.IsOpen)
return;
- DiffFiles(path2, path);
+ DiffFiles(fs2us(path2), fs2us(path));
}
}
diff --git a/CPP/7zip/UI/FileManager/makefile b/CPP/7zip/UI/FileManager/makefile
index 4525d846..dd2a2f20 100644
--- a/CPP/7zip/UI/FileManager/makefile
+++ b/CPP/7zip/UI/FileManager/makefile
@@ -5,6 +5,7 @@ CFLAGS = $(CFLAGS) \
!include "FM.mak"
COMMON_OBJS = \
+ $O\DynLimBuf.obj \
$O\IntToString.obj \
$O\Lang.obj \
$O\MyString.obj \
@@ -93,6 +94,10 @@ GUI_OBJS = \
COMPRESS_OBJS = \
$O\CopyCoder.obj \
+AR_COMMON_OBJS = \
+ $O\ItemNameUtils.obj \
+
+
C_OBJS = $(C_OBJS) \
$O\Alloc.obj \
$O\CpuArch.obj \
diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp
index 3298526e..510d1ec3 100644
--- a/CPP/7zip/UI/GUI/CompressDialog.cpp
+++ b/CPP/7zip/UI/GUI/CompressDialog.cpp
@@ -80,8 +80,8 @@ using namespace NDir;
static const unsigned kHistorySize = 20;
-static const UInt32 kNoSolidBlockSize = 0;
-static const UInt32 kSolidBlockSize = 64;
+static const UInt32 kSolidLog_NoSolid = 0;
+static const UInt32 kSolidLog_FullSolid = 64;
static const UInt32 kLzmaMaxDictSize = (UInt32)15 << 28;
@@ -112,7 +112,11 @@ enum EMethodID
kBZip2,
kDeflate,
kDeflate64,
- kPPMdZip
+ kPPMdZip,
+ kSha256,
+ kSha1,
+ kCrc32,
+ kCrc64,
};
static LPCSTR const kMethodsNames[] =
@@ -125,6 +129,10 @@ static LPCSTR const kMethodsNames[] =
, "Deflate"
, "Deflate64"
, "PPMd"
+ , "SHA256"
+ , "SHA1"
+ , "CRC32"
+ , "CRC64"
};
static const EMethodID g_7zMethods[] =
@@ -133,6 +141,9 @@ static const EMethodID g_7zMethods[] =
kLZMA,
kPPMd,
kBZip2
+ , kDeflate
+ , kDeflate64
+ , kCopy
};
static const EMethodID g_7zSfxMethods[] =
@@ -173,12 +184,20 @@ static const EMethodID g_SwfcMethods[] =
// kLZMA
};
+static const EMethodID g_HashMethods[] =
+{
+ kSha256
+ , kSha1
+ // , kCrc32
+ // , kCrc64
+};
+
struct CFormatInfo
{
LPCSTR Name;
UInt32 LevelsMask;
unsigned NumMethods;
- const EMethodID *MathodIDs;
+ const EMethodID *MethodIDs;
bool Filter;
bool Solid;
bool MultiThread;
@@ -194,9 +213,11 @@ static const CFormatInfo g_Formats[] =
{
{
"",
- (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
+ // (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
+ ((UInt32)1 << 10) - 1,
+ // (UInt32)(Int32)-1,
0, 0,
- false, false, false, false, false, false
+ false, false, true, false, false, false
},
{
k7zFormat,
@@ -245,6 +266,12 @@ static const CFormatInfo g_Formats[] =
(1 << 0),
0, 0,
false, false, false, false, false, false
+ },
+ {
+ "Hash",
+ (0 << 0),
+ METHODS_PAIR(g_HashMethods),
+ false, false, false, false, false, false
}
};
@@ -256,23 +283,6 @@ static bool IsMethodSupportedBySfx(int methodID)
return false;
}
-static bool GetMaxRamSizeForProgram(UInt64 &ramSize, UInt64 &size)
-{
- size = (UInt64)(sizeof(size_t)) << 29;
- bool ramSize_Defined = NSystem::GetRamSize(size);
- ramSize = size;
- size = size / 16 * 15;
- const UInt64 kMinSysSize = (1 << 24);
- if (size <= kMinSysSize)
- size = 0;
- else
- size -= kMinSysSize;
- const UInt64 kMinUseSize = (1 << 24);
- if (size < kMinUseSize)
- size = kMinUseSize;
- return ramSize_Defined;
-}
-
static const
// NCompressDialog::NUpdateMode::EEnum
@@ -327,7 +337,31 @@ void CCompressDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2)
b1.Val = b2.Val = val;
}
-
+
+void CCompressDialog::SetMethods(const CObjectVector<CCodecInfoUser> &userCodecs)
+{
+ ExternalMethods.Clear();
+ {
+ FOR_VECTOR (i, userCodecs)
+ {
+ const CCodecInfoUser &c = userCodecs[i];
+ if (!c.EncoderIsAssigned
+ || !c.IsFilter_Assigned
+ || c.IsFilter
+ || c.NumStreams != 1)
+ continue;
+ unsigned k;
+ for (k = 0; k < ARRAY_SIZE(g_7zMethods); k++)
+ if (c.Name.IsEqualTo_Ascii_NoCase(kMethodsNames[g_7zMethods[k]]))
+ break;
+ if (k != ARRAY_SIZE(g_7zMethods))
+ continue;
+ ExternalMethods.Add(c.Name);
+ }
+ }
+}
+
+
bool CCompressDialog::OnInit()
{
#ifdef LANG
@@ -335,6 +369,28 @@ bool CCompressDialog::OnInit()
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
#endif
+ {
+ UInt64 size = (UInt64)(sizeof(size_t)) << 29;
+ _ramSize_Defined = NSystem::GetRamSize(size);
+ // size = 100 << 20; // for debug only;
+ _ramSize = size;
+ const UInt64 kMinUseSize = (1 << 26);
+ if (size < kMinUseSize)
+ size = kMinUseSize;
+
+ _ramUsage_Limit = size / 32 * 30; // it's relaxed limit for user defined settings
+
+ unsigned bits = sizeof(size_t) * 8;
+ if (bits == 32)
+ {
+ const UInt32 limit2 = (UInt32)7 << 28;
+ if (size > limit2)
+ size = limit2;
+ }
+
+ _ramUsage_Auto = size / 32 * 28; // it's same as in auto usage limit in handlers
+ }
+
_password1Control.Attach(GetItem(IDE_COMPRESS_PASSWORD1));
_password2Control.Attach(GetItem(IDE_COMPRESS_PASSWORD2));
_password1Control.SetText(Info.Password);
@@ -400,8 +456,6 @@ bool CCompressDialog::OnInit()
StartDirPrefix = DirPrefix;
SetArchiveName(fileName);
}
- SetLevel();
- SetParams();
for (unsigned i = 0; i < m_RegistryInfo.ArcPaths.Size() && i < kHistorySize; i++)
m_ArchivePath.AddString(m_RegistryInfo.ArcPaths[i]);
@@ -412,8 +466,6 @@ bool CCompressDialog::OnInit()
AddComboItems(m_PathMode, k_PathMode_IDs, ARRAY_SIZE(k_PathMode_IDs),
k_PathMode_Vals, Info.PathMode);
- SetSolidBlockSize();
- SetNumThreads();
TCHAR s[32] = { TEXT('/'), TEXT(' '), 0 };
ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2);
@@ -422,13 +474,10 @@ bool CCompressDialog::OnInit()
CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite);
CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing);
- CheckControlsEnable();
+ FormatChanged();
// OnButtonSFX();
- SetEncryptionMethod();
- SetMemoryUsage();
-
NormalizePosition();
return CModalDialog::OnInit();
@@ -497,7 +546,7 @@ void CCompressDialog::CheckSFXControlsEnable()
bool enable = fi.SFX;
if (enable)
{
- int methodID = GetMethodID();
+ const int methodID = GetMethodID();
enable = (methodID == -1 || IsMethodSupportedBySfx(methodID));
}
if (!enable)
@@ -515,21 +564,41 @@ void CCompressDialog::CheckVolumeEnable()
}
*/
-void CCompressDialog::CheckControlsEnable()
+void CCompressDialog::EnableMultiCombo(unsigned id)
+{
+ NWindows::NControl::CComboBox combo;
+ combo.Attach(GetItem(id));
+ const bool enable = (combo.GetCount() > 1);
+ EnableItem(id, enable);
+}
+
+
+void CCompressDialog::FormatChanged()
{
+ SetLevel();
+ SetSolidBlockSize();
+ SetParams();
+ SetNumThreads();
+
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
Info.SolidIsSpecified = fi.Solid;
- bool multiThreadEnable = fi.MultiThread;
- Info.MultiThreadIsAllowed = multiThreadEnable;
Info.EncryptHeadersIsAllowed = fi.EncryptFileNames;
+ /*
+ const bool multiThreadEnable = fi.MultiThread;
+ Info.MultiThreadIsAllowed = multiThreadEnable;
EnableItem(IDC_COMPRESS_SOLID, fi.Solid);
EnableItem(IDC_COMPRESS_THREADS, multiThreadEnable);
+ const bool methodEnable = (fi.MethodIDs != NULL);
+ EnableItem(IDC_COMPRESS_METHOD, methodEnable);
+ EnableMultiCombo(IDC_COMPRESS_DICTIONARY, methodEnable);
+ EnableItem(IDC_COMPRESS_ORDER, methodEnable);
+ */
CheckSFXControlsEnable();
{
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
+ const CArcInfoEx &ai = Get_ArcInfoEx();
ShowItem_Bool(IDX_COMPRESS_NT_SYM_LINKS, ai.Flags_SymLinks());
ShowItem_Bool(IDX_COMPRESS_NT_HARD_LINKS, ai.Flags_HardLinks());
@@ -557,8 +626,12 @@ void CCompressDialog::CheckControlsEnable()
EnableItem(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames);
ShowItem_Bool(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames);
+
+ SetEncryptionMethod();
+ SetMemoryUsage();
}
+
bool CCompressDialog::IsSFX()
{
CWindow sfxButton = GetItem(IDX_COMPRESS_SFX);
@@ -765,18 +838,16 @@ void CCompressDialog::OnOK()
}
{
- UInt64 ramSize;
- UInt64 maxRamSize;
- const bool maxRamSize_Defined = GetMaxRamSizeForProgram(ramSize, maxRamSize);
UInt64 decompressMem;
const UInt64 memUsage = GetMemoryUsage_DecompMem(decompressMem);
- if (maxRamSize_Defined && memUsage > maxRamSize)
+ if (memUsage != (UInt64)(Int64)-1)
+ if (_ramSize_Defined && memUsage > _ramUsage_Limit)
{
UString s;
UString s2 = LangString(IDT_COMPRESS_MEMORY);
if (s2.IsEmpty())
GetItemText(IDT_COMPRESS_MEMORY, s2);
- SetErrorMessage_MemUsage(s, memUsage, ramSize, maxRamSize, s2);
+ SetErrorMessage_MemUsage(s, memUsage, _ramSize, _ramUsage_Limit, s2);
MessageBoxError(s);
return;
}
@@ -807,7 +878,7 @@ void CCompressDialog::OnOK()
{
// Info.SolidIsSpecified = g_Formats[GetStaticFormatIndex()].Solid;
- UInt32 solidLogSize = GetBlockSizeSpec();
+ const UInt32 solidLogSize = GetBlockSizeSpec();
Info.SolidBlockSize = 0;
if (solidLogSize == (UInt32)(Int32)-1)
Info.SolidIsSpecified = false;
@@ -834,7 +905,7 @@ void CCompressDialog::OnOK()
GetButton_Bools(IDX_COMPRESS_NT_SECUR, Info.NtSecurity, m_RegistryInfo.NtSecurity);
{
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
+ const CArcInfoEx &ai = Get_ArcInfoEx();
if (!ai.Flags_SymLinks()) Info.SymLinks.Val = false;
if (!ai.Flags_HardLinks()) Info.HardLinks.Val = false;
if (!ai.Flags_AltStreams()) Info.AltStreams.Val = false;
@@ -924,28 +995,16 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
case IDC_COMPRESS_FORMAT:
{
- bool isSFX = IsSFX();
+ const bool isSFX = IsSFX();
SaveOptionsInMem();
- m_Solid.ResetContent();
- SetLevel();
- SetSolidBlockSize();
- SetNumThreads();
- SetParams();
- CheckControlsEnable();
+ FormatChanged();
SetArchiveName2(isSFX);
- SetEncryptionMethod();
- SetMemoryUsage();
return true;
}
case IDC_COMPRESS_LEVEL:
{
- {
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
- int index = FindRegistryFormatAlways(ai.Name);
- NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
- fo.ResetForLevelChange();
- }
+ Get_FormatOptions().ResetForLevelChange();
SetMethod();
SetSolidBlockSize();
@@ -957,29 +1016,33 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
case IDC_COMPRESS_METHOD:
{
- SetDictionary();
- SetOrder();
+ MethodChanged();
SetSolidBlockSize();
SetNumThreads();
CheckSFXNameChange();
SetMemoryUsage();
+ if (Get_ArcInfoEx().Flags_HashHandler())
+ SetArchiveName2(false);
return true;
}
case IDC_COMPRESS_DICTIONARY:
{
- UInt32 blockSizeLog = GetBlockSizeSpec();
- if (blockSizeLog != (UInt32)(Int32)-1
- && blockSizeLog != kNoSolidBlockSize
- && blockSizeLog != kSolidBlockSize)
+ /* we want to change the reported threads for Auto line
+ and keep selected NumThreads option
+ So we save selected NumThreads option in memory */
+ SaveOptionsInMem();
+ const UInt32 blockSizeLog = GetBlockSizeSpec();
+ if (// blockSizeLog != (UInt32)(Int32)-1 &&
+ blockSizeLog != kSolidLog_NoSolid
+ && blockSizeLog != kSolidLog_FullSolid)
{
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
- int index = FindRegistryFormatAlways(ai.Name);
- NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
- fo.Reset_BlockLogSize();
- SetSolidBlockSize(true);
+ Get_FormatOptions().Reset_BlockLogSize();
+ // SetSolidBlockSize(true);
}
+ SetSolidBlockSize();
+ SetNumThreads(); // we want to change the reported threads for Auto line only
SetMemoryUsage();
return true;
}
@@ -1005,7 +1068,7 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
void CCompressDialog::CheckSFXNameChange()
{
- bool isSFX = IsSFX();
+ const bool isSFX = IsSFX();
CheckSFXControlsEnable();
if (isSFX != IsSFX())
SetArchiveName2(isSFX);
@@ -1063,7 +1126,18 @@ void CCompressDialog::SetArchiveName(const UString &name)
else
{
fileName += '.';
- fileName += ai.GetMainExt();
+ UString ext = ai.GetMainExt();
+ if (ai.Flags_HashHandler())
+ {
+ UString estimatedName;
+ GetMethodSpec(estimatedName);
+ if (!estimatedName.IsEmpty())
+ {
+ ext = estimatedName;
+ ext.MakeLower_Ascii();
+ }
+ }
+ fileName += ext;
}
m_ArchivePath.SetText(fileName);
}
@@ -1093,7 +1167,7 @@ int CCompressDialog::FindRegistryFormatAlways(const UString &name)
int CCompressDialog::GetStaticFormatIndex()
{
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
+ const CArcInfoEx &ai = Get_ArcInfoEx();
for (unsigned i = 0; i < ARRAY_SIZE(g_Formats); i++)
if (ai.Name.IsEqualTo_Ascii_NoCase(g_Formats[i].Name))
return i;
@@ -1112,11 +1186,11 @@ void CCompressDialog::SetNearestSelectComboBox(NControl::CComboBox &comboBox, UI
comboBox.SetCurSel(0);
}
-void CCompressDialog::SetLevel()
+void CCompressDialog::SetLevel2()
{
m_Level.ResetContent();
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
+ const CArcInfoEx &ai = Get_ArcInfoEx();
UInt32 level = 5;
{
int index = FindRegistryFormat(ai.Name);
@@ -1132,17 +1206,23 @@ void CCompressDialog::SetLevel()
}
}
- for (unsigned i = 0; i <= 9; i++)
+ for (unsigned i = 0; i < sizeof(UInt32) * 8; i++)
{
- if ((fi.LevelsMask & (1 << i)) != 0)
+ const UInt32 mask = (UInt32)1 << i;
+ if ((fi.LevelsMask & mask) != 0)
{
UInt32 langID = g_Levels[i];
- int index = (int)m_Level.AddString(LangString(langID));
+ UString s;
+ s.Add_UInt32(i);
+ s += " - ";
+ s += LangString(langID);
+ int index = (int)m_Level.AddString(s);
m_Level.SetItemData(index, i);
}
+ if (fi.LevelsMask <= mask)
+ break;
}
SetNearestSelectComboBox(m_Level, level);
- SetMethod();
}
@@ -1151,38 +1231,78 @@ static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s)
return cb.AddString((CSysString)s);
}
+// static const char *k_Auto = "- "; // "auto : ";
-void CCompressDialog::SetMethod(int keepMethodId)
+static void Modify_Auto(AString &s)
+{
+ s.Insert(0, "* ");
+ // s += " -";
+}
+
+void CCompressDialog::SetMethod2(int keepMethodId)
{
m_Method.ResetContent();
- UInt32 level = GetLevel();
- if (level == 0)
+ _auto_MethodId = -1;
+ const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
+ const CArcInfoEx &ai = Get_ArcInfoEx();
+ if (GetLevel() == 0 && !ai.Flags_HashHandler())
{
- SetDictionary();
- SetOrder();
+ MethodChanged();
return;
}
- const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
- int index = FindRegistryFormat(ai.Name);
UString defaultMethod;
- if (index >= 0)
{
- const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
- defaultMethod = fo.Method;
+ const int index = FindRegistryFormat(ai.Name);
+ if (index >= 0)
+ {
+ const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
+ defaultMethod = fo.Method;
+ }
}
- bool isSfx = IsSFX();
+ const bool isSfx = IsSFX();
bool weUseSameMethod = false;
+
+ const bool is7z = ai.Name.IsEqualTo_Ascii_NoCase("7z");
- for (unsigned m = 0; m < fi.NumMethods; m++)
+ for (unsigned m = 0;; m++)
{
- EMethodID methodID = fi.MathodIDs[m];
+ int methodID;
+ const char *method;
+ if (m < fi.NumMethods)
+ {
+ methodID = fi.MethodIDs[m];
+ method = kMethodsNames[methodID];
+ if (is7z)
+ if (methodID == kCopy
+ || methodID == kDeflate
+ || methodID == kDeflate64
+ )
+ continue;
+ }
+ else
+ {
+ if (!is7z)
+ break;
+ unsigned extIndex = m - fi.NumMethods;
+ if (extIndex >= ExternalMethods.Size())
+ break;
+ methodID = ARRAY_SIZE(kMethodsNames) + extIndex;
+ method = ExternalMethods[extIndex].Ptr();
+ }
if (isSfx)
if (!IsMethodSupportedBySfx(methodID))
continue;
- const char *method = kMethodsNames[methodID];
- int itemIndex = (int)ComboBox_AddStringAscii(m_Method, method);
- m_Method.SetItemData(itemIndex, methodID);
+
+ AString s (method);
+ int writtenMethodId = methodID;
+ if (m == 0)
+ {
+ _auto_MethodId = methodID;
+ writtenMethodId = -1;
+ Modify_Auto(s);
+ }
+ const int itemIndex = (int)ComboBox_AddStringAscii(m_Method, s);
+ m_Method.SetItemData(itemIndex, writtenMethodId);
if (keepMethodId == methodID)
{
m_Method.SetCurSel(itemIndex);
@@ -1194,29 +1314,26 @@ void CCompressDialog::SetMethod(int keepMethodId)
}
if (!weUseSameMethod)
- {
- SetDictionary();
- SetOrder();
- }
+ MethodChanged();
}
+
+
bool CCompressDialog::IsZipFormat()
{
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
- return ai.Name.IsEqualTo_Ascii_NoCase("zip");
+ return Get_ArcInfoEx().Name.IsEqualTo_Ascii_NoCase("zip");
}
bool CCompressDialog::IsXzFormat()
{
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
- return ai.Name.IsEqualTo_Ascii_NoCase("xz");
+ return Get_ArcInfoEx().Name.IsEqualTo_Ascii_NoCase("xz");
}
void CCompressDialog::SetEncryptionMethod()
{
_encryptionMethod.ResetContent();
_default_encryptionMethod_Index = -1;
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
+ const CArcInfoEx &ai = Get_ArcInfoEx();
if (ai.Name.IsEqualTo_Ascii_NoCase("7z"))
{
ComboBox_AddStringAscii(_encryptionMethod, "AES-256");
@@ -1244,21 +1361,63 @@ void CCompressDialog::SetEncryptionMethod()
}
}
-int CCompressDialog::GetMethodID()
+
+int CCompressDialog::GetMethodID_RAW()
{
if (m_Method.GetCount() <= 0)
return -1;
- return (int)(UInt32)m_Method.GetItemData_of_CurSel();
+ return (int)(Int32)(UInt32)m_Method.GetItemData_of_CurSel();
}
-UString CCompressDialog::GetMethodSpec()
+int CCompressDialog::GetMethodID()
+{
+ int raw = GetMethodID_RAW();
+ if (raw < 0)
+ return _auto_MethodId;
+ return raw;
+}
+
+
+UString CCompressDialog::GetMethodSpec(UString &estimatedName)
{
+ estimatedName.Empty();
+ if (m_Method.GetCount() < 1)
+ return estimatedName;
+ const int methodIdRaw = GetMethodID_RAW();
+ int methodId = methodIdRaw;
+ if (methodIdRaw < 0)
+ methodId = _auto_MethodId;
UString s;
- if (m_Method.GetCount() > 1)
- s = kMethodsNames[GetMethodID()];
+ if (methodId >= 0)
+ {
+ if (methodId < ARRAY_SIZE(kMethodsNames))
+ estimatedName = kMethodsNames[methodId];
+ else
+ estimatedName = ExternalMethods[methodId - ARRAY_SIZE(kMethodsNames)];
+ if (methodIdRaw >= 0)
+ s = estimatedName;
+ }
return s;
}
+
+UString CCompressDialog::GetMethodSpec()
+{
+ UString estimatedName;
+ UString s = GetMethodSpec(estimatedName);
+ return s;
+}
+
+bool CCompressDialog::IsMethodEqualTo(const UString &s)
+{
+ UString estimatedName;
+ const UString shortName = GetMethodSpec(estimatedName);
+ if (s.IsEmpty())
+ return shortName.IsEmpty();
+ return s.IsEqualTo_NoCase(estimatedName);
+}
+
+
UString CCompressDialog::GetEncryptionMethodSpec()
{
UString s;
@@ -1271,14 +1430,16 @@ UString CCompressDialog::GetEncryptionMethodSpec()
return s;
}
+static const size_t k_Auto_Dict = (size_t)0 - 1;
-void CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow)
+
+int CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow)
{
Byte c = 0;
unsigned moveBits = 0;
- if ((sizeShow & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; }
- else if ((sizeShow & 0x3FF) == 0) { moveBits = 10; c = 'K'; }
- TCHAR s[32];
+ if ((sizeShow & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; }
+ else if ((sizeShow & 0x3FF) == 0) { moveBits = 10; c = 'K'; }
+ char s[32];
ConvertUInt64ToString(sizeShow >> moveBits, s);
unsigned pos = MyStringLen(s);
s[pos++] = ' ';
@@ -1286,47 +1447,51 @@ void CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow)
s[pos++] = c;
s[pos++] = 'B';
s[pos++] = 0;
- const int index = (int)m_Dictionary.AddString(s);
+ AString s2 (s);
+ if (sizeReal == k_Auto_Dict)
+ Modify_Auto(s2);
+ const int index = (int)ComboBox_AddStringAscii(m_Dictionary, s2);
m_Dictionary.SetItemData(index, sizeReal);
+ return index;
}
-void CCompressDialog::AddDict(size_t size)
+int CCompressDialog::AddDict(size_t size)
{
- AddDict2(size, size);
+ return AddDict2(size, size);
}
-void CCompressDialog::SetDictionary()
+void CCompressDialog::SetDictionary2()
{
m_Dictionary.ResetContent();
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
- const int index = FindRegistryFormat(ai.Name);
+ // _auto_Dict = (UInt32)1 << 24; // we can use this dictSize to calculate _auto_Solid for unknown method for 7z
+ _auto_Dict = (UInt32)(Int32)-1; // for debug:
+
+ const CArcInfoEx &ai = Get_ArcInfoEx();
UInt32 defaultDict = (UInt32)(Int32)-1;
-
- if (index >= 0)
{
- const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
- if (fo.Method.IsEqualTo_NoCase(GetMethodSpec()))
- defaultDict = fo.Dictionary;
+ const int index = FindRegistryFormat(ai.Name);
+ if (index >= 0)
+ {
+ const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
+ if (IsMethodEqualTo(fo.Method))
+ defaultDict = fo.Dictionary;
+ }
}
const int methodID = GetMethodID();
const UInt32 level = GetLevel2();
if (methodID < 0)
return;
- UInt64 ramSize;
- UInt64 maxRamSize;
- const bool maxRamSize_Defined = GetMaxRamSizeForProgram(ramSize, maxRamSize);
switch (methodID)
{
case kLZMA:
case kLZMA2:
{
- if (defaultDict == (UInt32)(Int32)-1)
{
- defaultDict =
+ _auto_Dict =
( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) :
( level <= 6 ? ((UInt32)1 << (level + 19)) :
( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26)
@@ -1334,12 +1499,13 @@ void CCompressDialog::SetDictionary()
}
// we use threshold 3.75 GiB to switch to kLzmaMaxDictSize.
- if (defaultDict >= ((UInt32)15 << 28))
+ if (defaultDict != (UInt32)(Int32)-1
+ && defaultDict >= ((UInt32)15 << 28))
defaultDict = kLzmaMaxDictSize;
const size_t kLzmaMaxDictSize_Up = (size_t)1 << (20 + sizeof(size_t) / 4 * 6);
- int curSel = 0;
+ int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
for (unsigned i = (16 - 1) * 2; i <= (32 - 1) * 2; i++)
{
@@ -1354,33 +1520,36 @@ void CCompressDialog::SetDictionary()
if (dict_up >= kLzmaMaxDictSize)
dict = kLzmaMaxDictSize; // we reduce dictionary
- AddDict(dict);
+ const int index = AddDict(dict);
// AddDict2(dict, dict_up); // for debug : we show 4 GB
- const UInt64 memUsage = GetMemoryUsageComp_Dict(dict);
- if (dict <= defaultDict && (!maxRamSize_Defined || memUsage <= maxRamSize))
- curSel = m_Dictionary.GetCount() - 1;
+ // const UInt32 numThreads = 2;
+ // const UInt64 memUsage = GetMemoryUsageComp_Threads_Dict(numThreads, dict);
+ if (defaultDict != (UInt32)(Int32)-1)
+ if (dict <= defaultDict || curSel <= 0)
+ // if (!maxRamSize_Defined || memUsage <= maxRamSize)
+ curSel = index;
if (dict_up >= kLzmaMaxDictSize_Up)
break;
}
m_Dictionary.SetCurSel(curSel);
- // SetNearestSelectComboBox(m_Dictionary, defaultDict);
break;
}
case kPPMd:
{
- if (defaultDict == (UInt32)(Int32)-1)
- defaultDict = (UInt32)1 << (level + 19);
+ _auto_Dict = (UInt32)1 << (level + 19);
const UInt32 kPpmd_Default_4g = (UInt32)0 - ((UInt32)1 << 10);
const size_t kPpmd_MaxDictSize_Up = (size_t)1 << (29 + sizeof(size_t) / 8);
- if (defaultDict >= ((UInt32)15 << 28)) // threshold
+ if (defaultDict != (UInt32)(Int32)-1
+ && defaultDict >= ((UInt32)15 << 28)) // threshold
defaultDict = kPpmd_Default_4g;
- int curSel = 0;
+ int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
+
for (unsigned i = (20 - 1) * 2; i <= (32 - 1) * 2; i++)
{
if (i == (20 - 1) * 2 + 1)
@@ -1391,36 +1560,38 @@ void CCompressDialog::SetDictionary()
if (dict_up >= kPpmd_Default_4g)
dict = kPpmd_Default_4g;
- AddDict2(dict, dict_up);
+ const int index = AddDict2(dict, dict_up);
// AddDict2((UInt32)((UInt32)0 - 2), dict_up); // for debug
// AddDict(dict_up); // for debug
- const UInt64 memUsage = GetMemoryUsageComp_Dict(dict);
- if (dict <= defaultDict && (!maxRamSize_Defined || memUsage <= maxRamSize))
- curSel = m_Dictionary.GetCount() - 1;
+ // const UInt64 memUsage = GetMemoryUsageComp_Threads_Dict(1, dict);
+ if (defaultDict != (UInt32)(Int32)-1)
+ if (dict <= defaultDict || curSel <= 0)
+ // if (!maxRamSize_Defined || memUsage <= maxRamSize)
+ curSel = index;
if (dict_up >= kPpmd_MaxDictSize_Up)
break;
}
m_Dictionary.SetCurSel(curSel);
- // SetNearestSelectComboBox(m_Dictionary, defaultDict);
break;
}
case kPPMdZip:
{
- if (defaultDict == (UInt32)(Int32)-1)
- defaultDict = (UInt32)1 << (level + 19);
+ _auto_Dict = (UInt32)1 << (level + 19);
- int curSel = 0;
+ int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
+
for (unsigned i = 20; i <= 28; i++)
{
const UInt32 dict = (UInt32)1 << i;
- AddDict(dict);
- const UInt64 memUsage = GetMemoryUsageComp_Dict(dict);
- if ((dict <= defaultDict && (!maxRamSize_Defined || memUsage <= maxRamSize)))
- curSel = m_Dictionary.GetCount() - 1;
+ const int index = AddDict(dict);
+ // const UInt64 memUsage = GetMemoryUsageComp_Threads_Dict(1, dict);
+ if (defaultDict != (UInt32)(Int32)-1)
+ if (dict <= defaultDict || curSel <= 0)
+ // if (!maxRamSize_Defined || memUsage <= maxRamSize)
+ curSel = index;
}
m_Dictionary.SetCurSel(curSel);
- // SetNearestSelectComboBox(m_Dictionary, defaultDict);
break;
}
@@ -1428,32 +1599,43 @@ void CCompressDialog::SetDictionary()
case kDeflate64:
{
const UInt32 dict = (methodID == kDeflate ? (UInt32)(1 << 15) : (UInt32)(1 << 16));
- AddDict(dict);
+ _auto_Dict = dict;
+ AddDict2(k_Auto_Dict, _auto_Dict);
m_Dictionary.SetCurSel(0);
+ // EnableItem(IDC_COMPRESS_DICTIONARY, false);
break;
}
case kBZip2:
{
- if (defaultDict == (UInt32)(Int32)-1)
{
- if (level >= 5) defaultDict = (900 << 10);
- else if (level >= 3) defaultDict = (500 << 10);
- else defaultDict = (100 << 10);
+ if (level >= 5) _auto_Dict = (900 << 10);
+ else if (level >= 3) _auto_Dict = (500 << 10);
+ else _auto_Dict = (100 << 10);
}
+
+ int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
- int curSel = 0;
for (unsigned i = 1; i <= 9; i++)
{
const UInt32 dict = ((UInt32)i * 100) << 10;
AddDict(dict);
// AddDict2(i * 100000, dict);
- if (i <= defaultDict / 100000)
- curSel = m_Dictionary.GetCount() - 1;
+ if (defaultDict != (UInt32)(Int32)-1)
+ if (i <= defaultDict / 100000 || curSel <= 0)
+ curSel = m_Dictionary.GetCount() - 1;
}
m_Dictionary.SetCurSel(curSel);
break;
}
+
+ case kCopy:
+ {
+ _auto_Dict = 0;
+ AddDict(0);
+ m_Dictionary.SetCurSel(0);
+ break;
+ }
}
}
@@ -1471,6 +1653,9 @@ UInt64 CCompressDialog::GetComboValue_64(NWindows::NControl::CComboBox &c, int d
if (c.GetCount() <= defMax)
return (UInt64)(Int64)-1;
// LRESULT is signed. so we cast it to unsigned size_t at first:
+ LRESULT val = c.GetItemData_of_CurSel();
+ if (val == (LPARAM)(INT_PTR)(-1))
+ return (UInt64)(Int64)-1;
return (UInt64)(size_t)c.GetItemData_of_CurSel();
}
@@ -1482,31 +1667,47 @@ UInt32 CCompressDialog::GetLevel2()
return level;
}
+
int CCompressDialog::AddOrder(UInt32 size)
{
- TCHAR s[32];
+ char s[32];
ConvertUInt32ToString(size, s);
- int index = (int)m_Order.AddString(s);
+ int index = (int)ComboBox_AddStringAscii(m_Order, s);
m_Order.SetItemData(index, size);
return index;
}
-void CCompressDialog::SetOrder()
+int CCompressDialog::AddOrder_Auto()
+{
+ AString s;
+ s.Add_UInt32(_auto_Order);
+ Modify_Auto(s);
+ int index = (int)ComboBox_AddStringAscii(m_Order, s);
+ m_Order.SetItemData(index, (LPARAM)(INT_PTR)(-1));
+ return index;
+}
+
+void CCompressDialog::SetOrder2()
{
m_Order.ResetContent();
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
- int index = FindRegistryFormat(ai.Name);
- UInt32 defaultOrder = (UInt32)(Int32)-1;
- if (index >= 0)
+ _auto_Order = 1;
+
+ const CArcInfoEx &ai = Get_ArcInfoEx();
+ UInt32 defaultOrder = (UInt32)(Int32)-1;
+
{
- const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
- if (fo.Method.IsEqualTo_NoCase(GetMethodSpec()))
- defaultOrder = fo.Order;
+ const int index = FindRegistryFormat(ai.Name);
+ if (index >= 0)
+ {
+ const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
+ if (IsMethodEqualTo(fo.Method))
+ defaultOrder = fo.Order;
+ }
}
- int methodID = GetMethodID();
- UInt32 level = GetLevel2();
+ const int methodID = GetMethodID();
+ const UInt32 level = GetLevel2();
if (methodID < 0)
return;
@@ -1515,81 +1716,91 @@ void CCompressDialog::SetOrder()
case kLZMA:
case kLZMA2:
{
- if (defaultOrder == (UInt32)(Int32)-1)
- defaultOrder = (level >= 7) ? 64 : 32;
- for (unsigned i = 3; i <= 8; i++)
- for (unsigned j = 0; j < 2; j++)
- {
- UInt32 order = ((UInt32)(2 + j) << (i - 1));
- if (order <= 256)
- AddOrder(order);
- }
- AddOrder(273);
- SetNearestSelectComboBox(m_Order, defaultOrder);
+ _auto_Order = (level < 7 ? 32 : 64);
+ int curSel = AddOrder_Auto();
+ for (unsigned i = 2 * 2; i < 8 * 2; i++)
+ {
+ UInt32 order = ((UInt32)(2 + (i & 1)) << (i / 2));
+ if (order > 256)
+ order = 273;
+ const int index = AddOrder(order);
+ if (defaultOrder != (UInt32)(Int32)-1)
+ if (order <= defaultOrder || curSel <= 0)
+ curSel = index;
+ }
+ m_Order.SetCurSel(curSel);
break;
}
-
- case kPPMd:
+
+ case kDeflate:
+ case kDeflate64:
{
- if (defaultOrder == (UInt32)(Int32)-1)
{
- if (level >= 9) defaultOrder = 32;
- else if (level >= 7) defaultOrder = 16;
- else if (level >= 5) defaultOrder = 6;
- else defaultOrder = 4;
+ if (level >= 9) _auto_Order = 128;
+ else if (level >= 7) _auto_Order = 64;
+ else _auto_Order = 32;
+ }
+ int curSel = AddOrder_Auto();
+ for (unsigned i = 2 * 2; i < 8 * 2; i++)
+ {
+ UInt32 order = ((UInt32)(2 + (i & 1)) << (i / 2));
+ if (order > 256)
+ order = (methodID == kDeflate64 ? 257 : 258);
+ const int index = AddOrder(order);
+ if (defaultOrder != (UInt32)(Int32)-1)
+ if (order <= defaultOrder || curSel <= 0)
+ curSel = index;
}
- AddOrder(2);
- AddOrder(3);
-
- for (unsigned i = 2; i < 8; i++)
- for (unsigned j = 0; j < 4; j++)
- {
- UInt32 order = (4 + j) << (i - 2);
- if (order < 32)
- AddOrder(order);
- }
-
- AddOrder(32);
- SetNearestSelectComboBox(m_Order, defaultOrder);
+ m_Order.SetCurSel(curSel);
break;
}
-
- case kDeflate:
- case kDeflate64:
+
+ case kPPMd:
{
- if (defaultOrder == (UInt32)(Int32)-1)
{
- if (level >= 9) defaultOrder = 128;
- else if (level >= 7) defaultOrder = 64;
- else defaultOrder = 32;
+ if (level >= 9) _auto_Order = 32;
+ else if (level >= 7) _auto_Order = 16;
+ else if (level >= 5) _auto_Order = 6;
+ else _auto_Order = 4;
}
- for (unsigned i = 3; i <= 8; i++)
- for (unsigned j = 0; j < 2; j++)
- {
- UInt32 order = ((UInt32)(2 + j) << (i - 1));;
- if (order <= 256)
- AddOrder(order);
- }
-
- AddOrder(methodID == kDeflate64 ? 257 : 258);
- SetNearestSelectComboBox(m_Order, defaultOrder);
+ int curSel = AddOrder_Auto();
+
+ for (unsigned i = 0;; i++)
+ {
+ UInt32 order = i + 2;
+ if (i >= 2)
+ order = (4 + ((i - 2) & 3)) << ((i - 2) / 4);
+ const int index = AddOrder(order);
+ if (defaultOrder != (UInt32)(Int32)-1)
+ if (order <= defaultOrder || curSel <= 0)
+ curSel = index;
+ if (order >= 32)
+ break;
+ }
+ m_Order.SetCurSel(curSel);
break;
}
-
- case kBZip2:
- break;
-
+
case kPPMdZip:
{
- if (defaultOrder == (UInt32)(Int32)-1)
- defaultOrder = level + 3;
+ _auto_Order = level + 3;
+ int curSel = AddOrder_Auto();
for (unsigned i = 2; i <= 16; i++)
- AddOrder(i);
- SetNearestSelectComboBox(m_Order, defaultOrder);
+ {
+ const int index = AddOrder(i);
+ if (defaultOrder != (UInt32)(Int32)-1)
+ if (i <= defaultOrder || curSel <= 0)
+ curSel = index;
+ }
+ m_Order.SetCurSel(curSel);
break;
}
+
+ // case kBZip2:
+ default:
+ break;
}
}
@@ -1620,50 +1831,67 @@ static UInt64 Get_Lzma2_ChunkSize(UInt64 dict)
}
-void CCompressDialog::SetSolidBlockSize(bool useDictionary)
+static void Add_Size(AString &s2, UInt64 val)
+{
+ unsigned moveBits = 0;
+ Byte c = 0;
+ if ((val & 0x3FFFFFFF) == 0) { moveBits = 30; c = 'G'; }
+ else if ((val & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; }
+ else if ((val & 0x3FF) == 0) { moveBits = 10; c = 'K'; }
+ char s[32];
+ ConvertUInt64ToString(val >> moveBits, s);
+ unsigned pos = MyStringLen(s);
+ s[pos++] = ' ';
+ if (moveBits != 0)
+ s[pos++] = c;
+ s[pos++] = 'B';
+ s[pos++] = 0;
+ s2 += s;
+}
+
+
+void CCompressDialog::SetSolidBlockSize2()
{
m_Solid.ResetContent();
+ _auto_Solid = 1 << 20;
+
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
if (!fi.Solid)
return;
- UInt32 level = GetLevel2();
+ const UInt32 level = GetLevel2();
if (level == 0)
return;
- UInt64 dict = GetDictSpec();
+ UInt64 dict = GetDict2();
if (dict == (UInt64)(Int64)-1)
- dict = 1;
+ {
+ dict = 1 << 25; // default dict for unknown methods
+ // return;
+ }
+
UInt32 defaultBlockSize = (UInt32)(Int32)-1;
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
+ const CArcInfoEx &ai = Get_ArcInfoEx();
- if (useDictionary)
+ /*
+ if (usePrevDictionary)
defaultBlockSize = GetBlockSizeSpec();
else
+ */
{
- int index = FindRegistryFormat(ai.Name);
+ const int index = FindRegistryFormat(ai.Name);
if (index >= 0)
{
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
- if (fo.Method.IsEqualTo_NoCase(GetMethodSpec()))
+ if (IsMethodEqualTo(fo.Method))
defaultBlockSize = fo.BlockLogSize;
}
}
- bool is7z = ai.Name.IsEqualTo_Ascii_NoCase("7z");
+ const bool is7z = ai.Name.IsEqualTo_Ascii_NoCase("7z");
- {
- UString s ('-');
- if (is7z)
- LangString(IDS_COMPRESS_NON_SOLID, s);
- int index = (int)m_Solid.AddString(s);
- m_Solid.SetItemData(index, (UInt32)kNoSolidBlockSize);
- if (defaultBlockSize == kNoSolidBlockSize)
- m_Solid.SetCurSel(0);
- }
-
const UInt64 cs = Get_Lzma2_ChunkSize(dict);
// Solid Block Size
@@ -1673,98 +1901,215 @@ void CCompressDialog::SetSolidBlockSize(bool useDictionary)
{
// we use same default block sizes as defined in 7z encoder
UInt64 kMaxSize = (UInt64)1 << 32;
- if (GetMethodID() == kLZMA2)
+ const int methodId = GetMethodID();
+ if (methodId == kLZMA2)
{
blockSize = cs << 6;
kMaxSize = (UInt64)1 << 34;
}
else
- blockSize = (UInt64)dict << 7;
+ {
+ UInt64 dict2 = dict;
+ if (methodId == kBZip2)
+ {
+ dict2 /= 100000;
+ if (dict2 < 1)
+ dict2 = 1;
+ dict2 *= 100000;
+ }
+ blockSize = dict2 << 7;
+ }
const UInt32 kMinSize = (UInt32)1 << 24;
if (blockSize < kMinSize) blockSize = kMinSize;
if (blockSize > kMaxSize) blockSize = kMaxSize;
}
+
+ _auto_Solid = blockSize;
+
+ int curSel;
+ {
+ AString s;
+ Add_Size(s, _auto_Solid);
+ Modify_Auto(s);
+ int index = (int)ComboBox_AddStringAscii(m_Solid, s);
+ m_Solid.SetItemData(index, (UInt32)(Int32)-1);
+ curSel = index;
+ }
+
+ if (is7z)
+ {
+ UString s ('-');
+ // kSolidLog_NoSolid = 0 for xz means default blockSize
+ if (is7z)
+ LangString(IDS_COMPRESS_NON_SOLID, s);
+ const int index = (int)m_Solid.AddString(s);
+ m_Solid.SetItemData(index, (UInt32)kSolidLog_NoSolid);
+ if (defaultBlockSize == kSolidLog_NoSolid)
+ curSel = index;
+ }
for (unsigned i = 20; i <= 36; i++)
{
- if (defaultBlockSize == (UInt32)(Int32)-1 && ((UInt64)1 << i) >= blockSize)
- defaultBlockSize = i;
-
- TCHAR s[32];
- char post;
- ConvertUInt32ToString(1 << (i % 10), s);
- if (i < 20) post = 'K';
- else if (i < 30) post = 'M';
- else post = 'G';
- unsigned pos = (unsigned)lstrlen(s);
- s[pos++] = ' ';
- s[pos++] = post;
- s[pos++] = 'B';
- s[pos] = 0;
- int index = (int)m_Solid.AddString(s);
+ AString s;
+ Add_Size(s, (UInt64)1 << i);
+ const int index = (int)ComboBox_AddStringAscii(m_Solid, s);
m_Solid.SetItemData(index, (UInt32)i);
+ if (defaultBlockSize != (UInt32)(Int32)-1)
+ if (i <= defaultBlockSize || index <= 1)
+ curSel = index;
}
{
- int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID));
- m_Solid.SetItemData(index, kSolidBlockSize);
+ const int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID));
+ m_Solid.SetItemData(index, kSolidLog_FullSolid);
+ if (defaultBlockSize == kSolidLog_FullSolid)
+ curSel = index;
}
-
- if (defaultBlockSize == (UInt32)(Int32)-1)
- defaultBlockSize = kSolidBlockSize;
- if (defaultBlockSize != kNoSolidBlockSize)
- SetNearestSelectComboBox(m_Solid, defaultBlockSize);
+
+ m_Solid.SetCurSel(curSel);
}
-void CCompressDialog::SetNumThreads()
+
+void CCompressDialog::SetNumThreads2()
{
- m_NumThreads.ResetContent();
+ _auto_NumThreads = 1;
+ m_NumThreads.ResetContent();
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
if (!fi.MultiThread)
return;
- UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors();
- // numHardwareThreads = 64;
+ const UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors();
+ // 64; // for debug:
UInt32 defaultValue = numHardwareThreads;
+ bool useAutoThreads = true;
{
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
+ const CArcInfoEx &ai = Get_ArcInfoEx();
int index = FindRegistryFormat(ai.Name);
if (index >= 0)
{
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
- if (fo.Method.IsEqualTo_NoCase(GetMethodSpec()) && fo.NumThreads != (UInt32)(Int32)-1)
+ if (IsMethodEqualTo(fo.Method) && fo.NumThreads != (UInt32)(Int32)-1)
+ {
defaultValue = fo.NumThreads;
+ useAutoThreads = false;
+ }
}
}
- UInt32 numAlgoThreadsMax = 1;
- int methodID = GetMethodID();
+ UInt32 numAlgoThreadsMax = numHardwareThreads * 2;
+ const int methodID = GetMethodID();
switch (methodID)
{
case kLZMA: numAlgoThreadsMax = 2; break;
case kLZMA2: numAlgoThreadsMax = 256; break;
case kBZip2: numAlgoThreadsMax = 32; break;
+ case kCopy:
+ case kPPMd:
+ case kDeflate:
+ case kDeflate64:
+ case kPPMdZip:
+ numAlgoThreadsMax = 1;
}
- if (IsZipFormat())
- numAlgoThreadsMax = 128;
+ const bool isZip = IsZipFormat();
+ if (isZip)
+ {
+ numAlgoThreadsMax =
+ #ifdef _WIN32
+ 64; // _WIN32 supports only 64 threads in one group. So no need for more threads here
+ #else
+ 128;
+ #endif
+ }
+
+ UInt32 autoThreads = numHardwareThreads;
+ if (autoThreads > numAlgoThreadsMax)
+ autoThreads = numAlgoThreadsMax;
+
+ if (autoThreads > 1 && _ramSize_Defined)
+ {
+ if (isZip)
+ {
+ for (; autoThreads > 1; autoThreads--)
+ {
+ const UInt64 dict64 = GetDict2();
+ UInt64 decompressMemory;
+ const UInt64 usage = GetMemoryUsage_Threads_Dict_DecompMem(autoThreads, dict64, decompressMemory);
+ if (usage <= _ramUsage_Auto)
+ break;
+ }
+ }
+ else if (methodID == kLZMA2)
+ {
+ const UInt64 dict64 = GetDict2();
+ const UInt32 numThreads1 = (GetLevel2() >= 5 ? 2 : 1);
+ UInt32 numBlockThreads = autoThreads / numThreads1;
+ for (; numBlockThreads > 1; numBlockThreads--)
+ {
+ autoThreads = numBlockThreads * numThreads1;
+ UInt64 decompressMemory;
+ const UInt64 usage = GetMemoryUsage_Threads_Dict_DecompMem(autoThreads, dict64, decompressMemory);
+ if (usage <= _ramUsage_Auto)
+ break;
+ }
+ autoThreads = numBlockThreads * numThreads1;
+ }
+ }
+
+ _auto_NumThreads = autoThreads;
+
+ int curSel = -1;
+ {
+ AString s;
+ s.Add_UInt32(autoThreads);
+ Modify_Auto(s);
+ int index = (int)ComboBox_AddStringAscii(m_NumThreads, s);
+ m_NumThreads.SetItemData(index, (LPARAM)(INT_PTR)(-1));
+ // m_NumThreads.SetItemData(index, autoThreads);
+ if (useAutoThreads)
+ curSel = index;
+ }
+
+ if (numAlgoThreadsMax != autoThreads || autoThreads != 1)
for (UInt32 i = 1; i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++)
{
- TCHAR s[32];
+ char s[32];
ConvertUInt32ToString(i, s);
- int index = (int)m_NumThreads.AddString(s);
+ int index = (int)ComboBox_AddStringAscii(m_NumThreads, s);
m_NumThreads.SetItemData(index, (UInt32)i);
+ if (!useAutoThreads && i == defaultValue)
+ curSel = index;
}
- SetNearestSelectComboBox(m_NumThreads, defaultValue);
+
+ m_NumThreads.SetCurSel(curSel);
}
+UInt64 CCompressDialog::GetMemoryUsage_DecompMem(UInt64 &decompressMemory)
+{
+ return GetMemoryUsage_Dict_DecompMem(GetDict2(), decompressMemory);
+}
+
+UInt64 CCompressDialog::GetMemoryUsageComp_Threads_Dict(UInt32 numThreads, UInt64 dict64)
+{
+ UInt64 decompressMemory;
+ return GetMemoryUsage_Threads_Dict_DecompMem(numThreads, dict64, decompressMemory);
+}
+
UInt64 CCompressDialog::GetMemoryUsage_Dict_DecompMem(UInt64 dict64, UInt64 &decompressMemory)
{
- decompressMemory = UInt64(Int64(-1));
+ return GetMemoryUsage_Threads_Dict_DecompMem(GetNumThreads2(), dict64, decompressMemory);
+}
+
+UInt64 CCompressDialog::GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads, UInt64 dict64, UInt64 &decompressMemory)
+{
+ decompressMemory = (UInt64)(Int64)-1;
+ if (dict64 == (UInt64)(Int64)-1)
+ return (UInt64)(Int64)-1;
+
UInt32 level = GetLevel2();
if (level == 0)
{
@@ -1776,21 +2121,25 @@ UInt64 CCompressDialog::GetMemoryUsage_Dict_DecompMem(UInt64 dict64, UInt64 &dec
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
if (fi.Filter && level >= 9)
size += (12 << 20) * 2 + (5 << 20);
- UInt32 numThreads = GetNumThreads2();
+ // UInt32 numThreads = GetNumThreads2();
+ UInt32 numMainZipThreads = 1;
+
if (IsZipFormat())
{
UInt32 numSubThreads = 1;
if (GetMethodID() == kLZMA && numThreads > 1 && level >= 5)
numSubThreads = 2;
- UInt32 numMainThreads = numThreads / numSubThreads;
- if (numMainThreads > 1)
- size += (UInt64)numMainThreads << 25;
+ numMainZipThreads = numThreads / numSubThreads;
+ if (numMainZipThreads > 1)
+ size += (UInt64)numMainZipThreads * ((size_t)sizeof(size_t) << 23);
+ else
+ numMainZipThreads = 1;
}
- int methidId = GetMethodID();
+ const int methodId = GetMethodID();
- switch (methidId)
+ switch (methodId)
{
case kLZMA:
case kLZMA2:
@@ -1824,9 +2173,9 @@ UInt64 CCompressDialog::GetMemoryUsage_Dict_DecompMem(UInt64 dict64, UInt64 &dec
UInt32 numBlockThreads = numThreads / numThreads1;
- UInt64 chunkSize = 0;
+ UInt64 chunkSize = 0; // it's solid chunk
- if (methidId != kLZMA && numBlockThreads != 1)
+ if (methodId != kLZMA && numBlockThreads != 1)
{
chunkSize = Get_Lzma2_ChunkSize(dict);
@@ -1835,12 +2184,12 @@ UInt64 CCompressDialog::GetMemoryUsage_Dict_DecompMem(UInt64 dict64, UInt64 &dec
UInt32 blockSizeLog = GetBlockSizeSpec();
if (blockSizeLog != (UInt32)(Int32)-1)
{
- if (blockSizeLog == kSolidBlockSize)
+ if (blockSizeLog == kSolidLog_FullSolid)
{
numBlockThreads = 1;
chunkSize = 0;
}
- else if (blockSizeLog != kNoSolidBlockSize)
+ else if (blockSizeLog != kSolidLog_NoSolid)
chunkSize = (UInt64)1 << blockSizeLog;
}
}
@@ -1859,7 +2208,10 @@ UInt64 CCompressDialog::GetMemoryUsage_Dict_DecompMem(UInt64 dict64, UInt64 &dec
else
{
size += numBlockThreads * (size1 + chunkSize);
- UInt64 numPackChunks = numBlockThreads + (numBlockThreads / 4) + 2;
+ UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1;
+ if (chunkSize < ((UInt32)1 << 26)) numBlockThreads++;
+ if (chunkSize < ((UInt32)1 << 24)) numBlockThreads++;
+ if (chunkSize < ((UInt32)1 << 22)) numBlockThreads++;
size += numPackChunks * chunkSize;
}
@@ -1876,14 +2228,10 @@ UInt64 CCompressDialog::GetMemoryUsage_Dict_DecompMem(UInt64 dict64, UInt64 &dec
case kDeflate:
case kDeflate64:
{
- /*
- UInt32 order = GetOrder();
- if (order == (UInt32)(Int32)-1)
- order = 32;
- */
- if (level >= 7)
- size += (1 << 20);
- size += 3 << 20;
+ UInt64 size1 = 3 << 20;
+ // if (level >= 7)
+ size1 += (1 << 20);
+ size += size1 * numMainZipThreads;
decompressMemory = (2 << 20);
return size;
}
@@ -1905,16 +2253,6 @@ UInt64 CCompressDialog::GetMemoryUsage_Dict_DecompMem(UInt64 dict64, UInt64 &dec
return (UInt64)(Int64)-1;
}
-UInt64 CCompressDialog::GetMemoryUsage_DecompMem(UInt64 &decompressMemory)
-{
- return GetMemoryUsage_Dict_DecompMem(GetDict(), decompressMemory);
-}
-
-UInt64 CCompressDialog::GetMemoryUsageComp_Dict(UInt64 dict64)
-{
- UInt64 decompressMemory;
- return GetMemoryUsage_Dict_DecompMem(dict64, decompressMemory);
-}
void CCompressDialog::PrintMemUsage(UINT res, UInt64 value)
{
@@ -1949,7 +2287,7 @@ void CCompressDialog::SetMemoryUsage()
void CCompressDialog::SetParams()
{
- const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
+ const CArcInfoEx &ai = Get_ArcInfoEx();
m_Params.SetText(TEXT(""));
const int index = FindRegistryFormat(ai.Name);
if (index >= 0)
@@ -1961,10 +2299,11 @@ void CCompressDialog::SetParams()
void CCompressDialog::SaveOptionsInMem()
{
- const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex];
- const int index = FindRegistryFormatAlways(ai.Name);
m_Params.GetText(Info.Options);
Info.Options.Trim();
+
+ const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex];
+ const int index = FindRegistryFormatAlways(ai.Name);
NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
fo.Options = Info.Options;
fo.Level = GetLevelSpec();
diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h
index 234e0239..d8091b04 100644
--- a/CPP/7zip/UI/GUI/CompressDialog.h
+++ b/CPP/7zip/UI/GUI/CompressDialog.h
@@ -34,7 +34,7 @@ namespace NCompressDialog
NWildcard::ECensorPathMode PathMode;
bool SolidIsSpecified;
- bool MultiThreadIsAllowed;
+ // bool MultiThreadIsAllowed;
UInt64 SolidBlockSize;
UInt32 NumThreads;
@@ -80,6 +80,8 @@ namespace NCompressDialog
FormatIndex(-1)
{
Level = Order = (UInt32)(Int32)-1;
+ NumThreads = (UInt32)(Int32)-1;
+ SolidIsSpecified = false;
Dict64 = (UInt64)(Int64)(-1);
OrderMode = false;
Method.Empty();
@@ -100,16 +102,23 @@ class CCompressDialog: public NWindows::NControl::CModalDialog
NWindows::NControl::CComboBox m_Order;
NWindows::NControl::CComboBox m_Solid;
NWindows::NControl::CComboBox m_NumThreads;
+ NWindows::NControl::CComboBox m_Volume;
+
+ NWindows::NControl::CDialogChildControl m_Params;
NWindows::NControl::CComboBox m_UpdateMode;
NWindows::NControl::CComboBox m_PathMode;
- NWindows::NControl::CComboBox m_Volume;
- NWindows::NControl::CDialogChildControl m_Params;
-
NWindows::NControl::CEdit _password1Control;
NWindows::NControl::CEdit _password2Control;
NWindows::NControl::CComboBox _encryptionMethod;
+
+ int _auto_MethodId;
+ UInt32 _auto_Dict; // (UInt32)(Int32)-1 means unknown
+ UInt32 _auto_Order;
+ UInt64 _auto_Solid;
+ UInt32 _auto_NumThreads;
+
int _default_encryptionMethod_Index;
NCompression::CInfo m_RegistryInfo;
@@ -118,13 +127,30 @@ class CCompressDialog: public NWindows::NControl::CModalDialog
UString DirPrefix;
UString StartDirPrefix;
+ bool _ramSize_Defined;
+ UInt64 _ramSize;
+ UInt64 _ramUsage_Auto;
+ UInt64 _ramUsage_Limit;
+
+
void CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2);
void GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2);
void SetArchiveName(const UString &name);
int FindRegistryFormat(const UString &name);
int FindRegistryFormatAlways(const UString &name);
+
+ const CArcInfoEx &Get_ArcInfoEx()
+ {
+ return (*ArcFormats)[GetFormatIndex()];
+ }
+ NCompression::CFormatOptions &Get_FormatOptions()
+ {
+ const CArcInfoEx &ai = Get_ArcInfoEx();
+ return m_RegistryInfo.Formats[ FindRegistryFormatAlways(ai.Name) ];
+ }
+
void CheckSFXNameChange();
void SetArchiveName2(bool prevWasSFX);
@@ -132,11 +158,35 @@ class CCompressDialog: public NWindows::NControl::CModalDialog
void SetNearestSelectComboBox(NWindows::NControl::CComboBox &comboBox, UInt32 value);
- void SetLevel();
+ void SetLevel2();
+ void SetLevel()
+ {
+ SetLevel2();
+ EnableMultiCombo(IDC_COMPRESS_LEVEL);
+ SetMethod();
+ }
+
+ void SetMethod2(int keepMethodId);
+ void SetMethod(int keepMethodId = -1)
+ {
+ SetMethod2(keepMethodId);
+ EnableMultiCombo(IDC_COMPRESS_METHOD);
+ }
+
+ void MethodChanged()
+ {
+ SetDictionary2();
+ EnableMultiCombo(IDC_COMPRESS_DICTIONARY);
+ SetOrder2();
+ EnableMultiCombo(IDC_COMPRESS_ORDER);
+ }
- void SetMethod(int keepMethodId = -1);
+ int GetMethodID_RAW();
int GetMethodID();
+
+ UString GetMethodSpec(UString &estimatedName);
UString GetMethodSpec();
+ bool IsMethodEqualTo(const UString &s);
UString GetEncryptionMethodSpec();
bool IsZipFormat();
@@ -144,10 +194,10 @@ class CCompressDialog: public NWindows::NControl::CModalDialog
void SetEncryptionMethod();
- void AddDict2(size_t sizeReal, size_t sizeShow);
- void AddDict(size_t size);
-
- void SetDictionary();
+ int AddDict2(size_t sizeReal, size_t sizeShow);
+ int AddDict(size_t size);
+
+ void SetDictionary2();
UInt32 GetComboValue(NWindows::NControl::CComboBox &c, int defMax = 0);
UInt64 GetComboValue_64(NWindows::NControl::CComboBox &c, int defMax = 0);
@@ -155,24 +205,60 @@ class CCompressDialog: public NWindows::NControl::CModalDialog
UInt32 GetLevel() { return GetComboValue(m_Level); }
UInt32 GetLevelSpec() { return GetComboValue(m_Level, 1); }
UInt32 GetLevel2();
- UInt64 GetDict() { return GetComboValue_64(m_Dictionary); }
+
UInt64 GetDictSpec() { return GetComboValue_64(m_Dictionary, 1); }
- UInt32 GetOrder() { return GetComboValue(m_Order); }
+ UInt64 GetDict2()
+ {
+ UInt64 num = GetDictSpec();
+ if (num == (UInt64)(Int64)-1)
+ {
+ if (_auto_Dict == (UInt32)(Int32)-1)
+ return (UInt64)(Int64)-1; // unknown
+ num = _auto_Dict;
+ }
+ return num;
+ }
+
+ // UInt32 GetOrder() { return GetComboValue(m_Order); }
UInt32 GetOrderSpec() { return GetComboValue(m_Order, 1); }
UInt32 GetNumThreadsSpec() { return GetComboValue(m_NumThreads, 1); }
- UInt32 GetNumThreads2() { UInt32 num = GetNumThreadsSpec(); if (num == UInt32(-1)) num = 1; return num; }
+
+ UInt32 GetNumThreads2()
+ {
+ UInt32 num = GetNumThreadsSpec();
+ if (num == (UInt32)(Int32)-1)
+ num = _auto_NumThreads;
+ return num;
+ }
+
UInt32 GetBlockSizeSpec() { return GetComboValue(m_Solid, 1); }
int AddOrder(UInt32 size);
- void SetOrder();
+ int AddOrder_Auto();
+
+ void SetOrder2();
+
bool GetOrderMode();
- void SetSolidBlockSize(bool useDictionary = false);
- void SetNumThreads();
+ void SetSolidBlockSize2();
+ void SetSolidBlockSize(/* bool useDictionary = false */)
+ {
+ SetSolidBlockSize2();
+ EnableMultiCombo(IDC_COMPRESS_SOLID);
+ }
+
+ void SetNumThreads2();
+ void SetNumThreads()
+ {
+ SetNumThreads2();
+ EnableMultiCombo(IDC_COMPRESS_THREADS);
+ }
+
UInt64 GetMemoryUsage_Dict_DecompMem(UInt64 dict, UInt64 &decompressMemory);
+ UInt64 GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads, UInt64 dict, UInt64 &decompressMemory);
UInt64 GetMemoryUsage_DecompMem(UInt64 &decompressMemory);
- UInt64 GetMemoryUsageComp_Dict(UInt64 dict64);
+ UInt64 GetMemoryUsageComp_Threads_Dict(UInt32 numThreads, UInt64 dict64);
void PrintMemUsage(UINT res, UInt64 value);
void SetMemoryUsage();
@@ -186,9 +272,32 @@ class CCompressDialog: public NWindows::NControl::CModalDialog
bool SetArcPathFields(const UString &path, UString &name, bool always);
bool GetFinalPath_Smart(UString &resPath);
+ void CheckSFXControlsEnable();
+ // void CheckVolumeEnable();
+ void EnableMultiCombo(unsigned id);
+ void FormatChanged();
+
+ void OnButtonSetArchive();
+ bool IsSFX();
+ void OnButtonSFX();
+
+ virtual bool OnInit();
+ virtual bool OnCommand(int code, int itemID, LPARAM lParam);
+ virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
+ virtual void OnOK();
+ virtual void OnHelp();
+
+ void MessageBoxError(LPCWSTR message)
+ {
+ MessageBoxW(*this, message, L"7-Zip", MB_ICONERROR);
+ }
+
public:
- CObjectVector<CArcInfoEx> *ArcFormats;
+ const CObjectVector<CArcInfoEx> *ArcFormats;
CUIntVector ArcIndices; // can not be empty, must contain Info.FormatIndex, if Info.FormatIndex >= 0
+ AStringVector ExternalMethods;
+
+ void SetMethods(const CObjectVector<CCodecInfoUser> &userCodecs);
NCompressDialog::CInfo Info;
UString OriginalFileName; // for bzip2, gzip2
@@ -201,28 +310,6 @@ public:
}
CCompressDialog(): CurrentDirWasChanged(false) {};
-
- void MessageBoxError(LPCWSTR message)
- {
- MessageBoxW(*this, message, L"7-Zip", MB_ICONERROR);
- }
-
-protected:
-
- void CheckSFXControlsEnable();
- // void CheckVolumeEnable();
- void CheckControlsEnable();
-
- void OnButtonSetArchive();
- bool IsSFX();
- void OnButtonSFX();
-
- virtual bool OnInit();
- virtual bool OnCommand(int code, int itemID, LPARAM lParam);
- virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
- virtual void OnOK();
- virtual void OnHelp();
-
};
#endif
diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp
index 1e37efb8..59403ee9 100644
--- a/CPP/7zip/UI/GUI/ExtractGUI.cpp
+++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp
@@ -64,6 +64,12 @@ class CThreadExtracting: public CProgressThreadVirt
{
HRESULT ProcessVirt();
public:
+ /*
+ #ifdef EXTERNAL_CODECS
+ const CExternalCodecs *externalCodecs;
+ #endif
+ */
+
CCodecs *codecs;
CExtractCallbackImp *ExtractCallbackSpec;
const CObjectVector<COpenType> *FormatIndices;
@@ -105,7 +111,13 @@ HRESULT CThreadExtracting::ProcessVirt()
*/
#endif
- HRESULT res = Extract(codecs,
+ HRESULT res = Extract(
+ /*
+ #ifdef EXTERNAL_CODECS
+ externalCodecs,
+ #endif
+ */
+ codecs,
*FormatIndices, *ExcludedFormatIndices,
*ArchivePaths, *ArchivePathsFull,
*WildcardCensor, *Options, ExtractCallbackSpec, ExtractCallback,
@@ -154,6 +166,7 @@ HRESULT CThreadExtracting::ProcessVirt()
HRESULT ExtractGUI(
+ // DECL_EXTERNAL_CODECS_LOC_VARS
CCodecs *codecs,
const CObjectVector<COpenType> &formatIndices,
const CIntVector &excludedFormatIndices,
@@ -172,6 +185,11 @@ HRESULT ExtractGUI(
messageWasDisplayed = false;
CThreadExtracting extracter;
+ /*
+ #ifdef EXTERNAL_CODECS
+ extracter.externalCodecs = __externalCodecs;
+ #endif
+ */
extracter.codecs = codecs;
extracter.FormatIndices = &formatIndices;
extracter.ExcludedFormatIndices = &excludedFormatIndices;
diff --git a/CPP/7zip/UI/GUI/ExtractGUI.h b/CPP/7zip/UI/GUI/ExtractGUI.h
index d55b30de..3b412590 100644
--- a/CPP/7zip/UI/GUI/ExtractGUI.h
+++ b/CPP/7zip/UI/GUI/ExtractGUI.h
@@ -20,6 +20,7 @@
*/
HRESULT ExtractGUI(
+ // DECL_EXTERNAL_CODECS_LOC_VARS
CCodecs *codecs,
const CObjectVector<COpenType> &formatIndices,
const CIntVector &excludedFormatIndices,
diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp
index 37567019..32a48e74 100644
--- a/CPP/7zip/UI/GUI/GUI.cpp
+++ b/CPP/7zip/UI/GUI/GUI.cpp
@@ -34,6 +34,10 @@
using namespace NWindows;
+#ifdef EXTERNAL_CODECS
+const CExternalCodecs *g_ExternalCodecs_Ptr;
+#endif
+
extern
HINSTANCE g_hInstance;
HINSTANCE g_hInstance;
@@ -134,18 +138,22 @@ static int Main2()
codecs->CaseSensitiveChange = options.CaseSensitiveChange;
codecs->CaseSensitive = options.CaseSensitive;
ThrowException_if_Error(codecs->Load());
-
+ Codecs_AddHashArcHandler(codecs);
+
#ifdef EXTERNAL_CODECS
{
+ g_ExternalCodecs_Ptr = &__externalCodecs;
UString s;
codecs->GetCodecsErrorMessage(s);
if (!s.IsEmpty())
+ {
MessageBoxW(0, s, L"7-Zip", MB_ICONERROR);
+ }
+
}
#endif
-
- bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
+ const bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
if (codecs->Formats.Size() == 0 &&
(isExtractGroupCommand
@@ -170,7 +178,7 @@ static int Main2()
return NExitCode::kFatalError;
}
- CIntVector excludedFormatIndices;
+ CIntVector excludedFormats;
FOR_VECTOR (k, options.ExcludedArcTypes)
{
CIntVector tempIndices;
@@ -180,12 +188,13 @@ static int Main2()
ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE);
return NExitCode::kFatalError;
}
- excludedFormatIndices.AddToUniqueSorted(tempIndices[0]);
- // excludedFormatIndices.Sort();
+ excludedFormats.AddToUniqueSorted(tempIndices[0]);
+ // excludedFormats.Sort();
}
#ifdef EXTERNAL_CODECS
if (isExtractGroupCommand
+ || options.Command.IsFromUpdateGroup()
|| options.Command.CommandType == NCommandType::kHash
|| options.Command.CommandType == NCommandType::kBenchmark)
ThrowException_if_Error(__externalCodecs.Load());
@@ -270,8 +279,10 @@ static int Main2()
ecs->MultiArcMode = (ArchivePathsSorted.Size() > 1);
- HRESULT result = ExtractGUI(codecs,
- formatIndices, excludedFormatIndices,
+ HRESULT result = ExtractGUI(
+ // EXTERNAL_CODECS_VARS_L
+ codecs,
+ formatIndices, excludedFormats,
ArchivePathsSorted,
ArchivePathsFullSorted,
options.Censor.Pairs.Front().Head,
diff --git a/CPP/7zip/UI/GUI/GUI.dsp b/CPP/7zip/UI/GUI/GUI.dsp
index 7e65f481..53a2c92f 100644
--- a/CPP/7zip/UI/GUI/GUI.dsp
+++ b/CPP/7zip/UI/GUI/GUI.dsp
@@ -872,6 +872,14 @@ SOURCE=..\..\..\Common\CRC.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\DynLimBuf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\DynLimBuf.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\IntToString.cpp
# End Source File
# Begin Source File
@@ -1188,6 +1196,14 @@ SOURCE=..\..\..\Windows\Window.h
# PROP Default_Filter ""
# Begin Source File
+SOURCE=..\..\Archive\Common\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ItemNameUtils.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/UI/GUI/HashGUI.cpp b/CPP/7zip/UI/GUI/HashGUI.cpp
index 37cd65e9..219135fb 100644
--- a/CPP/7zip/UI/GUI/HashGUI.cpp
+++ b/CPP/7zip/UI/GUI/HashGUI.cpp
@@ -174,10 +174,12 @@ HRESULT CHashCallbackGUI::SetOperationResult(UInt64 /* fileSize */, const CHashB
return CheckBreak();
}
+static const unsigned k_DigestStringSize = k_HashCalc_DigestSize_Max * 2 + k_HashCalc_ExtraSize * 2 + 16;
+
static void AddHashString(CProperty &s, const CHasherState &h, unsigned digestIndex)
{
- char temp[k_HashCalc_DigestSize_Max * 2 + 4];
- AddHashHexToString(temp, h.Digests[digestIndex], h.DigestSize);
+ char temp[k_DigestStringSize];
+ h.WriteToString(digestIndex, temp);
s.Value = temp;
}
diff --git a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp
index 33852e3b..1f272cd9 100644
--- a/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp
+++ b/CPP/7zip/UI/GUI/UpdateCallbackGUI.cpp
@@ -156,7 +156,7 @@ HRESULT CUpdateCallbackGUI::ReportExtractResult(Int32 opRes, Int32 isEncrypted,
return S_OK;
}
-HRESULT CUpdateCallbackGUI::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir)
+HRESULT CUpdateCallbackGUI::ReportUpdateOperation(UInt32 op, const wchar_t *name, bool isDir)
{
return SetOperation_Base(op, name, isDir);
}
diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp
index 28f19d25..1bdc9ffe 100644
--- a/CPP/7zip/UI/GUI/UpdateGUI.cpp
+++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp
@@ -146,7 +146,8 @@ static void SetOutProperties(
bool orderMode,
UInt32 order,
bool solidIsSpecified, UInt64 solidBlockSize,
- bool multiThreadIsAllowed, UInt32 numThreads,
+ // bool multiThreadIsAllowed,
+ UInt32 numThreads,
const UString &encryptionMethod,
bool encryptHeadersIsAllowed, bool encryptHeaders,
bool /* sfxMode */)
@@ -182,7 +183,9 @@ static void SetOutProperties(
AddProp(properties, "he", encryptHeaders);
if (solidIsSpecified)
AddProp(properties, "s", GetNumInBytesString(solidBlockSize));
- if (multiThreadIsAllowed)
+ if (
+ // multiThreadIsAllowed &&
+ numThreads != (UInt32)(Int32)-1)
AddProp(properties, "mt", numThreads);
}
@@ -287,6 +290,11 @@ static HRESULT ShowDialog(
CCompressDialog dialog;
NCompressDialog::CInfo &di = dialog.Info;
dialog.ArcFormats = &codecs->Formats;
+ {
+ CObjectVector<CCodecInfoUser> userCodecs;
+ codecs->Get_CodecsInfoUser_Vector(userCodecs);
+ dialog.SetMethods(userCodecs);
+ }
if (options.MethodMode.Type_Defined)
di.FormatIndex = options.MethodMode.Type.FormatIndex;
@@ -299,9 +307,13 @@ static HRESULT ShowDialog(
if (!oneFile && ai.Flags_KeepName())
continue;
if ((int)i != di.FormatIndex)
+ {
+ if (ai.Flags_HashHandler())
+ continue;
if (ai.Name.IsEqualTo_Ascii_NoCase("swfc"))
if (!oneFile || name.Len() < 4 || !StringsAreEqualNoCase_Ascii(name.RightPtr(4), ".swf"))
continue;
+ }
dialog.ArcIndices.Add(i);
}
if (dialog.ArcIndices.IsEmpty())
@@ -392,7 +404,8 @@ static HRESULT ShowDialog(
di.Dict64,
di.OrderMode, di.Order,
di.SolidIsSpecified, di.SolidBlockSize,
- di.MultiThreadIsAllowed, di.NumThreads,
+ // di.MultiThreadIsAllowed,
+ di.NumThreads,
di.EncryptionMethod,
di.EncryptHeadersIsAllowed, di.EncryptHeaders,
di.SFXMode);
@@ -464,6 +477,13 @@ HRESULT UpdateGUI(
tu.UpdateCallbackGUI->Init();
UString title = LangString(IDS_PROGRESS_COMPRESSING);
+ if (!formatIndices.IsEmpty())
+ {
+ const int fin = formatIndices[0].FormatIndex;
+ if (fin >= 0)
+ if (codecs->Formats[fin].Flags_HashHandler())
+ title = LangString(IDS_CHECKSUM_CALCULATING);
+ }
/*
if (hwndParent != 0)
diff --git a/CPP/7zip/UI/GUI/makefile b/CPP/7zip/UI/GUI/makefile
index 255c4f24..123410c1 100644
--- a/CPP/7zip/UI/GUI/makefile
+++ b/CPP/7zip/UI/GUI/makefile
@@ -24,6 +24,7 @@ GUI_OBJS = \
COMMON_OBJS = \
$O\CommandLineParser.obj \
$O\CRC.obj \
+ $O\DynLimBuf.obj \
$O\IntToString.obj \
$O\Lang.obj \
$O\ListFileUtils.obj \
@@ -102,6 +103,7 @@ UI_COMMON_OBJS = \
$O\ZipRegistry.obj \
AR_COMMON_OBJS = \
+ $O\ItemNameUtils.obj \
$O\OutStreamWithCRC.obj \
FM_OBJS = \