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
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
parentd789d4137d8a7c16696c5bc1b13f24bb887eb7ea (diff)
21.0421.04
-rw-r--r--Asm/x86/7zAsm.asm4
-rw-r--r--Asm/x86/LzFindOpt.asm4
-rw-r--r--C/7zVersion.h6
-rw-r--r--C/7zip_gcc_c.mak2
-rw-r--r--C/LzFind.c8
-rw-r--r--C/Util/7zipInstall/7zipInstall.c5
-rw-r--r--C/Util/Lzma/LzmaUtil.c7
-rw-r--r--C/Util/Lzma/LzmaUtil.dsp4
-rw-r--r--C/Util/Lzma/makefile2
-rw-r--r--C/Util/Lzma/makefile.gcc2
-rw-r--r--C/Util/LzmaLib/makefile1
-rw-r--r--C/XzDec.c5
-rw-r--r--C/XzIn.c5
-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
-rw-r--r--CPP/Common/CksumReg.cpp60
-rw-r--r--CPP/Common/MyCom.h4
-rw-r--r--CPP/Common/MyString.cpp11
-rw-r--r--CPP/Common/MyString.h1
-rw-r--r--CPP/Common/MyTypes.h6
-rw-r--r--CPP/Common/Wildcard.h22
-rw-r--r--CPP/Windows/ErrorMsg.cpp4
-rw-r--r--CPP/Windows/FileDir.cpp55
-rw-r--r--CPP/Windows/FileFind.cpp44
-rw-r--r--CPP/Windows/FileFind.h30
-rw-r--r--CPP/Windows/FileIO.cpp19
-rw-r--r--CPP/Windows/FileIO.h11
-rw-r--r--CPP/Windows/FileName.cpp30
-rw-r--r--CPP/Windows/System.cpp7
-rw-r--r--CPP/Windows/SystemInfo.cpp24
-rw-r--r--DOC/7zip.wxs2
-rw-r--r--DOC/readme.txt2
-rw-r--r--DOC/src-history.txt15
152 files changed, 6037 insertions, 934 deletions
diff --git a/Asm/x86/7zAsm.asm b/Asm/x86/7zAsm.asm
index 34c278cb..8b2c92e0 100644
--- a/Asm/x86/7zAsm.asm
+++ b/Asm/x86/7zAsm.asm
@@ -1,5 +1,5 @@
; 7zAsm.asm -- ASM macros
-; 2021-07-13 : Igor Pavlov : Public domain
+; 2021-08-29 : Igor Pavlov : Public domain
ifdef RAX
x64 equ 1
@@ -27,6 +27,8 @@ else
endif
endif
+OPTION PROLOGUE:NONE
+OPTION EPILOGUE:NONE
MY_ASM_START macro
ifdef x64
diff --git a/Asm/x86/LzFindOpt.asm b/Asm/x86/LzFindOpt.asm
index bc3a6fe7..42e10bda 100644
--- a/Asm/x86/LzFindOpt.asm
+++ b/Asm/x86/LzFindOpt.asm
@@ -1,5 +1,5 @@
; LzFindOpt.asm -- ASM version of GetMatchesSpecN_2() function
-; 2021-07-13: Igor Pavlov : Public domain
+; 2021-07-21: Igor Pavlov : Public domain
;
ifndef x64
@@ -475,7 +475,7 @@ long_loop:
je long_footer
cmp delta_x, [hash]
jne long_footer
- movzx t0_x, BYTE PTR [diff + cur]
+ movzx t0_x, BYTE PTR [diff + 1 * cur]
cmp [cur], t0_L
jne long_footer
cmp d, d_lim
diff --git a/C/7zVersion.h b/C/7zVersion.h
index e7fff57d..5fc7c9c5 100644
--- a/C/7zVersion.h
+++ b/C/7zVersion.h
@@ -1,7 +1,7 @@
#define MY_VER_MAJOR 21
-#define MY_VER_MINOR 03
+#define MY_VER_MINOR 04
#define MY_VER_BUILD 0
-#define MY_VERSION_NUMBERS "21.03 beta"
+#define MY_VERSION_NUMBERS "21.04 beta"
#define MY_VERSION MY_VERSION_NUMBERS
#ifdef MY_CPU_NAME
@@ -10,7 +10,7 @@
#define MY_VERSION_CPU MY_VERSION
#endif
-#define MY_DATE "2021-07-20"
+#define MY_DATE "2021-11-02"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"
diff --git a/C/7zip_gcc_c.mak b/C/7zip_gcc_c.mak
index e98d6761..09e66d57 100644
--- a/C/7zip_gcc_c.mak
+++ b/C/7zip_gcc_c.mak
@@ -174,6 +174,8 @@ $O/LzFind.o: ../../../C/LzFind.c
# ifdef MT_FILES
$O/LzFindMt.o: ../../../C/LzFindMt.c
$(CC) $(CFLAGS) $<
+$O/LzFindOpt.o: ../../../C/LzFindOpt.c
+ $(CC) $(CFLAGS) $<
$O/Threads.o: ../../../C/Threads.c
$(CC) $(CFLAGS) $<
diff --git a/C/LzFind.c b/C/LzFind.c
index 3b32eae8..bf157a0b 100644
--- a/C/LzFind.c
+++ b/C/LzFind.c
@@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms
-2021-07-12 : Igor Pavlov : Public domain */
+2021-09-03 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -1592,7 +1592,7 @@ void LzFindPrepare()
{
if (CPU_IsSupported_NEON())
{
- #pragma message ("=== LzFind NEON")
+ // #pragma message ("=== LzFind NEON")
_PRF(printf("\n=== LzFind NEON\n"));
f = LzFind_SaturSub_128;
}
@@ -1601,14 +1601,14 @@ void LzFindPrepare()
#else // MY_CPU_ARM_OR_ARM64
if (CPU_IsSupported_SSE41())
{
- #pragma message ("=== LzFind SSE41")
+ // #pragma message ("=== LzFind SSE41")
_PRF(printf("\n=== LzFind SSE41\n"));
f = LzFind_SaturSub_128;
#ifdef USE_AVX2
if (CPU_IsSupported_AVX2())
{
- #pragma message ("=== LzFind AVX2")
+ // #pragma message ("=== LzFind AVX2")
_PRF(printf("\n=== LzFind AVX2\n"));
f = LzFind_SaturSub_256;
}
diff --git a/C/Util/7zipInstall/7zipInstall.c b/C/Util/7zipInstall/7zipInstall.c
index 7aa11de7..00d0f41a 100644
--- a/C/Util/7zipInstall/7zipInstall.c
+++ b/C/Util/7zipInstall/7zipInstall.c
@@ -1,5 +1,5 @@
/* 7zipInstall.c - 7-Zip Installer
-2021-02-23 : Igor Pavlov : Public domain */
+2021-09-02 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -926,6 +926,9 @@ static void WriteShellEx()
wcscpy(destPath + 1, path);
CatAscii(destPath, "Uninstall.exe\"");
MyRegistry_SetString(destKey, L"UninstallString", destPath);
+
+ CatAscii(destPath, " /S");
+ MyRegistry_SetString(destKey, L"QuietUninstallString", destPath);
MyRegistry_SetDWORD(destKey, L"NoModify", 1);
MyRegistry_SetDWORD(destKey, L"NoRepair", 1);
diff --git a/C/Util/Lzma/LzmaUtil.c b/C/Util/Lzma/LzmaUtil.c
index e613b9c2..62a59079 100644
--- a/C/Util/Lzma/LzmaUtil.c
+++ b/C/Util/Lzma/LzmaUtil.c
@@ -1,5 +1,5 @@
/* LzmaUtil.c -- Test application for LZMA compression
-2021-02-15 : Igor Pavlov : Public domain */
+2021-11-01 : Igor Pavlov : Public domain */
#include "../../Precomp.h"
@@ -12,6 +12,7 @@
#include "../../Alloc.h"
#include "../../7zFile.h"
#include "../../7zVersion.h"
+#include "../../LzFind.h"
#include "../../LzmaDec.h"
#include "../../LzmaEnc.h"
@@ -195,6 +196,8 @@ static int main2(int numArgs, const char *args[], char *rs)
int encodeMode;
BoolInt useOutFile = False;
+ LzFindPrepare();
+
FileSeqInStream_CreateVTable(&inStream);
File_Construct(&inStream.file);
inStream.wres = 0;
@@ -276,7 +279,7 @@ static int main2(int numArgs, const char *args[], char *rs)
int MY_CDECL main(int numArgs, const char *args[])
{
- char rs[800] = { 0 };
+ char rs[1000] = { 0 };
int res = main2(numArgs, args, rs);
fputs(rs, stdout);
return res;
diff --git a/C/Util/Lzma/LzmaUtil.dsp b/C/Util/Lzma/LzmaUtil.dsp
index f060a267..4e38e4a6 100644
--- a/C/Util/Lzma/LzmaUtil.dsp
+++ b/C/Util/Lzma/LzmaUtil.dsp
@@ -134,6 +134,10 @@ SOURCE=..\..\LzFindMt.h
# End Source File
# Begin Source File
+SOURCE=..\..\LzFindOpt.c
+# End Source File
+# Begin Source File
+
SOURCE=..\..\LzHash.h
# End Source File
# Begin Source File
diff --git a/C/Util/Lzma/makefile b/C/Util/Lzma/makefile
index 47953227..7813bdb0 100644
--- a/C/Util/Lzma/makefile
+++ b/C/Util/Lzma/makefile
@@ -8,8 +8,10 @@ LIB_OBJS = \
C_OBJS = \
$O\Alloc.obj \
+ $O\CpuArch.obj \
$O\LzFind.obj \
$O\LzFindMt.obj \
+ $O\LzFindOpt.obj \
$O\LzmaDec.obj \
$O\LzmaEnc.obj \
$O\7zFile.obj \
diff --git a/C/Util/Lzma/makefile.gcc b/C/Util/Lzma/makefile.gcc
index f9d59e3e..2acb0b80 100644
--- a/C/Util/Lzma/makefile.gcc
+++ b/C/Util/Lzma/makefile.gcc
@@ -8,8 +8,10 @@ OBJS = \
$O/7zFile.o \
$O/7zStream.o \
$O/Alloc.o \
+ $O/CpuArch.o \
$O/LzFind.o \
$O/LzFindMt.o \
+ $O/LzFindOpt.o \
$O/LzmaDec.o \
$O/LzmaEnc.o \
$O/LzmaUtil.o \
diff --git a/C/Util/LzmaLib/makefile b/C/Util/LzmaLib/makefile
index eb6ade33..b36f1de0 100644
--- a/C/Util/LzmaLib/makefile
+++ b/C/Util/LzmaLib/makefile
@@ -11,6 +11,7 @@ LIB_OBJS = \
C_OBJS = \
$O\Alloc.obj \
+ $O\CpuArch.obj \
$O\LzFind.obj \
$O\LzFindMt.obj \
$O\LzFindOpt.obj \
diff --git a/C/XzDec.c b/C/XzDec.c
index 3db9b3f2..3f96a37f 100644
--- a/C/XzDec.c
+++ b/C/XzDec.c
@@ -1,5 +1,5 @@
/* XzDec.c -- Xz Decode
-2021-04-01 : Igor Pavlov : Public domain */
+2021-09-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -773,7 +773,8 @@ static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
{ unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
- if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
+ if (s == 0) return SZ_ERROR_ARCHIVE; \
+ pos += s; }
static BoolInt XzBlock_AreSupportedFilters(const CXzBlock *p)
diff --git a/C/XzIn.c b/C/XzIn.c
index bb6dbb99..84f868ec 100644
--- a/C/XzIn.c
+++ b/C/XzIn.c
@@ -1,5 +1,5 @@
/* XzIn.c - Xz input
-2021-04-01 : Igor Pavlov : Public domain */
+2021-09-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -26,7 +26,8 @@ SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream)
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
{ unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
- if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
+ if (s == 0) return SZ_ERROR_ARCHIVE; \
+ pos += s; }
SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, BoolInt *isIndex, UInt32 *headerSizeRes)
{
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 = \
diff --git a/CPP/Common/CksumReg.cpp b/CPP/Common/CksumReg.cpp
new file mode 100644
index 00000000..29d9f82e
--- /dev/null
+++ b/CPP/Common/CksumReg.cpp
@@ -0,0 +1,60 @@
+// CksumReg.cpp
+
+#include "StdAfx.h"
+
+#include "../../C/CpuArch.h"
+
+#include "../Common/MyCom.h"
+
+#include "../7zip/Common/RegisterCodec.h"
+
+#include "../7zip/Compress/BZip2Crc.h"
+
+class CCksumHasher:
+ public IHasher,
+ public CMyUnknownImp
+{
+ CBZip2Crc _crc;
+ UInt64 _size;
+ Byte mtDummy[1 << 7];
+
+public:
+ CCksumHasher()
+ {
+ _crc.Init(0);
+ _size = 0;
+ }
+
+ MY_UNKNOWN_IMP1(IHasher)
+ INTERFACE_IHasher(;)
+};
+
+STDMETHODIMP_(void) CCksumHasher::Init() throw()
+{
+ _crc.Init(0);
+ _size = 0;
+}
+
+STDMETHODIMP_(void) CCksumHasher::Update(const void *data, UInt32 size) throw()
+{
+ _size += size;
+ CBZip2Crc crc = _crc;
+ for (UInt32 i = 0; i < size; i++)
+ crc.UpdateByte(((const Byte *)data)[i]);
+ _crc = crc;
+}
+
+STDMETHODIMP_(void) CCksumHasher::Final(Byte *digest) throw()
+{
+ UInt64 size = _size;
+ CBZip2Crc crc = _crc;
+ while (size)
+ {
+ crc.UpdateByte((Byte)size);
+ size >>= 8;
+ }
+ const UInt32 val = crc.GetDigest();
+ SetUi32(digest, val);
+}
+
+REGISTER_HASHER(CCksumHasher, 0x203, "CKSUM", 4)
diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h
index 524f6efb..ce2f0dd1 100644
--- a/CPP/Common/MyCom.h
+++ b/CPP/Common/MyCom.h
@@ -230,8 +230,8 @@ public:
#define MY_ADDREF_RELEASE \
STDMETHOD_(ULONG, AddRef)() throw() { return ++__m_RefCount; } \
-STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \
- return __m_RefCount; delete this; return 0; }
+STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) return __m_RefCount; \
+ delete this; return 0; }
#define MY_UNKNOWN_IMP_SPEC(i) \
MY_QUERYINTERFACE_BEGIN \
diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp
index 821c9b37..cef70839 100644
--- a/CPP/Common/MyString.cpp
+++ b/CPP/Common/MyString.cpp
@@ -322,6 +322,17 @@ bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw()
}
}
+bool IsString1PrefixedByString2_NoCase_Ascii(const char *s1, const char *s2) throw()
+{
+ for (;;)
+ {
+ char c2 = *s2++; if (c2 == 0) return true;
+ char c1 = *s1++;
+ if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
+ return false;
+ }
+}
+
bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) throw()
{
for (;;)
diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h
index c242d923..539cb2d4 100644
--- a/CPP/Common/MyString.h
+++ b/CPP/Common/MyString.h
@@ -198,6 +198,7 @@ bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw();
bool IsString1PrefixedByString2(const char *s1, const char *s2) throw();
bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw();
bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw();
+bool IsString1PrefixedByString2_NoCase_Ascii(const char *s1, const char *s2) throw();
bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *u, const char *a) throw();
bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw();
diff --git a/CPP/Common/MyTypes.h b/CPP/Common/MyTypes.h
index 2b1acce2..71b8e7fa 100644
--- a/CPP/Common/MyTypes.h
+++ b/CPP/Common/MyTypes.h
@@ -25,6 +25,12 @@ struct CBoolPair
Val = true;
Def = true;
}
+
+ void SetVal_as_Defined(bool val)
+ {
+ Val = val;
+ Def = true;
+ }
};
#define CLASS_NO_COPY(cls) \
diff --git a/CPP/Common/Wildcard.h b/CPP/Common/Wildcard.h
index 32b1521f..fb0f1fed 100644
--- a/CPP/Common/Wildcard.h
+++ b/CPP/Common/Wildcard.h
@@ -59,8 +59,18 @@ class CCensorNode MY_UNCOPYABLE
bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const;
void AddItemSimple(bool include, CItem &item);
public:
- CCensorNode(): Parent(NULL) { };
- CCensorNode(const UString &name, CCensorNode *parent): Parent(parent), Name(name) { };
+ // bool ExcludeDirItems;
+
+ CCensorNode():
+ Parent(NULL)
+ // , ExcludeDirItems(false)
+ {};
+
+ CCensorNode(const UString &name, CCensorNode *parent):
+ Parent(parent)
+ // , ExcludeDirItems(false)
+ , Name(name)
+ {}
UString Name; // WIN32 doesn't support wildcards in file names
CObjectVector<CCensorNode> SubNodes;
@@ -151,6 +161,14 @@ class CCensor MY_UNCOPYABLE
public:
CObjectVector<CPair> Pairs;
+ bool ExcludeDirItems;
+ bool ExcludeFileItems;
+
+ CCensor():
+ ExcludeDirItems(false),
+ ExcludeFileItems(false)
+ {}
+
CObjectVector<NWildcard::CCensorPath> CensorPaths;
bool AllAreRelative() const
diff --git a/CPP/Windows/ErrorMsg.cpp b/CPP/Windows/ErrorMsg.cpp
index 63fd7922..f6343a5c 100644
--- a/CPP/Windows/ErrorMsg.cpp
+++ b/CPP/Windows/ErrorMsg.cpp
@@ -77,8 +77,8 @@ static bool MyFormatMessage(DWORD errorCode, UString &message)
break;
}
- /* strerror() for unknow errors still shows message "Unknown error -12345678")
- So we must trasfer error codes before strerror() */
+ /* strerror() for unknown errors still shows message "Unknown error -12345678")
+ So we must transfer error codes before strerror() */
if (!s)
{
if ((errorCode & 0xFFFF0000) == (UInt32)((MY__FACILITY__WRes << 16) | 0x80000000))
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp
index c06e7f37..8193f61f 100644
--- a/CPP/Windows/FileDir.cpp
+++ b/CPP/Windows/FileDir.cpp
@@ -5,6 +5,7 @@
#ifndef _WIN32
#include <stdio.h>
+#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <unistd.h>
@@ -887,17 +888,39 @@ bool GetCurrentDir(FString &path)
char s[MY__PATH_MAX + 1];
char *res = getcwd(s, MY__PATH_MAX);
- if (!res)
+ if (res)
{
- // if (errno != ERANGE)
- return false;
+ path = fas2fs(s);
+ return true;
+ }
+ {
+ // if (errno != ERANGE) return false;
+ #if defined(__GLIBC__) || defined(__APPLE__)
+ /* As an extension to the POSIX.1-2001 standard, glibc's getcwd()
+ allocates the buffer dynamically using malloc(3) if buf is NULL. */
+ res = getcwd(NULL, 0);
+ if (res)
+ {
+ path = fas2fs(res);
+ ::free(res);
+ return true;
+ }
+ #endif
+ return false;
}
- path = fas2fs(s);
- return true;
}
-static void FILETME_To_timespec(const FILETIME *ft, timespec &ts)
+
+// #undef UTIME_OMIT // to debug
+
+#ifndef UTIME_OMIT
+ /* we can define UTIME_OMIT for debian and another systems.
+ Is it OK to define UTIME_OMIT to -2 here, if UTIME_OMIT is not defined? */
+ // #define UTIME_OMIT -2
+#endif
+
+static bool FILETME_To_timespec(const FILETIME *ft, timespec &ts)
{
if (ft)
{
@@ -909,14 +932,20 @@ static void FILETME_To_timespec(const FILETIME *ft, timespec &ts)
ts.tv_sec = sec2;
const UInt64 winTime = (((UInt64)ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
ts.tv_nsec = (long)((winTime % 10000000) * 100);
- return;
+ return true;
}
}
// else
{
ts.tv_sec = 0;
- // ts.tv_nsec = UTIME_NOW; // set to the current time
- ts.tv_nsec = UTIME_OMIT; // keep old timesptamp
+ ts.tv_nsec =
+ #ifdef UTIME_OMIT
+ UTIME_OMIT; // keep old timesptamp
+ #else
+ // UTIME_NOW; // set to the current time
+ 0;
+ #endif
+ return false;
}
}
@@ -968,8 +997,12 @@ bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const
struct timespec times[2];
UNUSED_VAR(cTime)
- FILETME_To_timespec(aTime, times[0]);
- FILETME_To_timespec(mTime, times[1]);
+ bool needChange;
+ needChange = FILETME_To_timespec(aTime, times[0]);
+ needChange |= FILETME_To_timespec(mTime, times[1]);
+
+ if (!needChange)
+ return true;
const int flags = 0; // follow link
// = AT_SYMLINK_NOFOLLOW; // don't follow link
diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp
index 8ef0f7b6..591f8df0 100644
--- a/CPP/Windows/FileFind.cpp
+++ b/CPP/Windows/FileFind.cpp
@@ -1001,7 +1001,17 @@ void CFileInfo::SetFrom_stat(const struct stat &st)
// NTime::UnixTimeToFileTime(st.st_mtime, MTime);
// NTime::UnixTimeToFileTime(st.st_atime, ATime);
#ifdef __APPLE__
+ // #ifdef _DARWIN_FEATURE_64_BIT_INODE
+ /*
+ here we can use birthtime instead of st_ctimespec.
+ but we use st_ctimespec for compatibility with previous versions and p7zip.
+ st_birthtimespec in OSX
+ st_birthtim : at FreeBSD, NetBSD
+ */
+ // timespec_To_FILETIME(st.st_birthtimespec, CTime);
+ // #else
timespec_To_FILETIME(st.st_ctimespec, CTime);
+ // #endif
timespec_To_FILETIME(st.st_mtimespec, MTime);
timespec_To_FILETIME(st.st_atimespec, ATime);
#else
@@ -1093,15 +1103,18 @@ void CEnumerator::SetDirPrefix(const FString &dirPrefix)
bool CDirEntry::IsDots() const throw()
{
- if (
- #if !defined(_AIX)
- !IsDir() ||
- #endif
- Name.IsEmpty())
- return false;
- if (Name[0] != '.')
+ /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN)
+ we can call fstatat() for that case, but we use only (Name) check here */
+
+ #if !defined(_AIX)
+ if (Type != DT_DIR && Type != DT_UNKNOWN)
return false;
- return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.');
+ #endif
+
+ return Name.Len() != 0
+ && Name.Len() <= 2
+ && Name[0] == '.'
+ && (Name.Len() == 1 || Name[1] == '.');
}
@@ -1135,6 +1148,19 @@ bool CEnumerator::NextAny(CDirEntry &fi, bool &found)
#if !defined(_AIX)
fi.Type = de->d_type;
+ /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN)
+ we can set (Type) from fstatat() in that case.
+ But (Type) is not too important. So we don't set it here with slow fstatat() */
+ /*
+ // fi.Type = DT_UNKNOWN; // for debug
+ if (fi.Type == DT_UNKNOWN)
+ {
+ struct stat st;
+ if (fstatat(dirfd(_dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) == 0)
+ if (S_ISDIR(st.st_mode))
+ fi.Type = DT_DIR;
+ }
+ */
#endif
/*
@@ -1191,7 +1217,7 @@ bool CEnumerator::Next(CDirEntry &fileInfo, bool &found)
}
*/
-bool CEnumerator::Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink)
+bool CEnumerator::Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const
{
// printf("\nCEnumerator::Fill_FileInfo()\n");
struct stat st;
diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h
index 009e84e7..8f28ee33 100644
--- a/CPP/Windows/FileFind.h
+++ b/CPP/Windows/FileFind.h
@@ -103,6 +103,15 @@ public:
return S_ISLNK(mod);
}
#endif
+
+ bool IsOsSymLink() const
+ {
+ #ifdef _WIN32
+ return HasReparsePoint();
+ #else
+ return IsPosixLink();
+ #endif
+ }
};
struct CFileInfo: public CFileInfoBase
@@ -223,13 +232,15 @@ struct CDirEntry
#endif
FString Name;
+ /*
#if !defined(_AIX)
bool IsDir() const
{
- // DT_DIR is
+ // (Type == DT_UNKNOWN) on some systems
return Type == DT_DIR;
}
#endif
+ */
bool IsDots() const throw();
};
@@ -246,7 +257,22 @@ public:
void SetDirPrefix(const FString &dirPrefix);
bool Next(CDirEntry &fileInfo, bool &found);
- bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink);
+ bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const;
+ bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const
+ {
+ #if !defined(_AIX)
+ if (de.Type == DT_DIR)
+ return true;
+ if (de.Type != DT_UNKNOWN)
+ return false;
+ #endif
+ CFileInfo fileInfo;
+ if (Fill_FileInfo(de, fileInfo, followLink))
+ {
+ return fileInfo.IsDir();
+ }
+ return false; // change it
+ }
};
/*
diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp
index b6f2f26e..84aad042 100644
--- a/CPP/Windows/FileIO.cpp
+++ b/CPP/Windows/FileIO.cpp
@@ -498,7 +498,24 @@ bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) throw
data = (const void *)((const unsigned char *)data + processedLoc);
size -= processedLoc;
}
- while (size > 0);
+ while (size != 0);
+ return true;
+}
+
+bool COutFile::WriteFull(const void *data, size_t size) throw()
+{
+ do
+ {
+ UInt32 processedLoc = 0;
+ const UInt32 sizeCur = (size > kChunkSizeMax ? kChunkSizeMax : (UInt32)size);
+ if (!WritePart(data, sizeCur, processedLoc))
+ return false;
+ if (processedLoc == 0)
+ return (size == 0);
+ data = (const void *)((const unsigned char *)data + processedLoc);
+ size -= processedLoc;
+ }
+ while (size != 0);
return true;
}
diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h
index 276e595e..85cae631 100644
--- a/CPP/Windows/FileIO.h
+++ b/CPP/Windows/FileIO.h
@@ -244,6 +244,7 @@ public:
bool SetMTime(const FILETIME *mTime) throw();
bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw();
bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw();
+ bool WriteFull(const void *data, size_t size) throw();
bool SetEndOfFile() throw();
bool SetLength(UInt64 length) throw();
};
@@ -315,6 +316,16 @@ public:
bool Create(const char *name, bool createAlways);
bool Open(const char *name, DWORD creationDisposition);
ssize_t write_full(const void *data, size_t size, size_t &processed) throw();
+
+ bool WriteFull(const void *data, size_t size) throw()
+ {
+ size_t processed;
+ ssize_t res = write_full(data, size, processed);
+ if (res == -1)
+ return false;
+ return processed == size;
+ }
+
bool SetLength(UInt64 length) throw();
bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw();
bool SetMTime(const FILETIME *mTime) throw();
diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp
index 4ee94575..d61ff7e1 100644
--- a/CPP/Windows/FileName.cpp
+++ b/CPP/Windows/FileName.cpp
@@ -6,6 +6,7 @@
#include <limits.h>
#include <unistd.h>
#include "../Common/StringConvert.h"
+#include "FileDir.h"
#endif
#include "FileName.h"
@@ -65,6 +66,19 @@ void NormalizeDirPathPrefix(UString &dirPath)
}
#ifdef _WIN32
+
+#ifndef USE_UNICODE_FSTRING
+#ifdef WIN_LONG_PATH
+static void NormalizeDirSeparators(UString &s)
+{
+ const unsigned len = s.Len();
+ for (unsigned i = 0; i < len; i++)
+ if (s[i] == '/')
+ s.ReplaceOneCharAtPos(i, WCHAR_PATH_SEPARATOR);
+}
+#endif
+#endif
+
void NormalizeDirSeparators(FString &s)
{
const unsigned len = s.Len();
@@ -72,6 +86,7 @@ void NormalizeDirSeparators(FString &s)
if (s[i] == '/')
s.ReplaceOneCharAtPos(i, FCHAR_PATH_SEPARATOR);
}
+
#endif
@@ -391,16 +406,9 @@ static bool GetCurDir(UString &path)
#else
- #define MY__PATH_MAX PATH_MAX
- // #define MY__PATH_MAX 1024
-
- char s[MY__PATH_MAX + 1];
- char *res = getcwd(s, MY__PATH_MAX);
- if (!res)
- {
- // if (errno != ERANGE)
- return false;
- }
+ FString s;
+ if (!NDir::GetCurrentDir(s))
+ return false;
path = GetUnicodeString(s);
return true;
@@ -721,7 +729,7 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
true false * use Super path
true true true don't use any path, we already used mainPath
true true false use main path as Super Path, we don't try mainMath
- That case is possible now if GetCurDir returns unknow
+ That case is possible now if GetCurDir returns unknown
type of path (not drive and not network)
We can change that code if we want to try mainPath, if GetSuperPathBase returns error,
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp
index 099407ec..3a14b77d 100644
--- a/CPP/Windows/System.cpp
+++ b/CPP/Windows/System.cpp
@@ -202,9 +202,12 @@ bool GetRamSize(UInt64 &size)
size = val;
#elif defined(_AIX)
-
// fixme
-
+ #elif defined(__gnu_hurd__)
+ // fixme
+ #elif defined(__FreeBSD_kernel__) && defined(__GLIBC__)
+ // GNU/kFreeBSD Debian
+ // fixme
#else
struct sysinfo info;
diff --git a/CPP/Windows/SystemInfo.cpp b/CPP/Windows/SystemInfo.cpp
index 9346afd5..82145d9c 100644
--- a/CPP/Windows/SystemInfo.cpp
+++ b/CPP/Windows/SystemInfo.cpp
@@ -20,6 +20,22 @@
#include <sys/auxv.h>
+// #undef AT_HWCAP // to debug
+// #undef AT_HWCAP2 // to debug
+
+/* the following patch for some debian systems.
+ Is it OK to define AT_HWCAP and AT_HWCAP2 here with these constant numbers? */
+
+#if defined(__FreeBSD_kernel__) && defined(__GLIBC__)
+ #ifndef AT_HWCAP
+ #define AT_HWCAP 16
+ #endif
+ #ifndef AT_HWCAP2
+ #define AT_HWCAP2 26
+ #endif
+#endif
+
+
#ifdef MY_CPU_ARM_OR_ARM64
#include <asm/hwcap.h>
#endif
@@ -75,7 +91,7 @@ static bool ReadFile_to_Buffer(CFSTR fileName, CByteBuffer &buf)
#endif
-#ifndef __APPLE__
+#if defined(_WIN32) || defined(AT_HWCAP) || defined(AT_HWCAP2)
static void PrintHex(AString &s, UInt64 v)
{
char temp[32];
@@ -657,6 +673,7 @@ void AddCpuFeatures(AString &s)
#endif
+ #ifdef AT_HWCAP
s.Add_OptSpaced("hwcap:");
{
unsigned long h = getauxval(AT_HWCAP);
@@ -671,7 +688,9 @@ void AddCpuFeatures(AString &s)
if (h & HWCAP_NEON) s += ":NEON";
#endif
}
-
+ #endif // AT_HWCAP
+
+ #ifdef AT_HWCAP2
{
unsigned long h = getauxval(AT_HWCAP2);
#ifndef MY_CPU_ARM
@@ -688,6 +707,7 @@ void AddCpuFeatures(AString &s)
#endif
}
}
+ #endif // AT_HWCAP2
#endif // _AIX
#endif // _WIN32
}
diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs
index c18e7068..f636287b 100644
--- a/DOC/7zip.wxs
+++ b/DOC/7zip.wxs
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<?define VerMajor = "21" ?>
-<?define VerMinor = "03" ?>
+<?define VerMinor = "04" ?>
<?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>
diff --git a/DOC/readme.txt b/DOC/readme.txt
index d5e16452..c9896c89 100644
--- a/DOC/readme.txt
+++ b/DOC/readme.txt
@@ -1,4 +1,4 @@
-7-Zip 21.03 Sources
+7-Zip 21.04 Sources
-------------------
7-Zip is a file archiver for Windows.
diff --git a/DOC/src-history.txt b/DOC/src-history.txt
index b802c69a..3e7c9dfc 100644
--- a/DOC/src-history.txt
+++ b/DOC/src-history.txt
@@ -1,6 +1,21 @@
HISTORY of the 7-Zip source code
--------------------------------
+21.04 beta 2021-11-02
+-------------------------
+- 7-Zip now reduces the number of working CPU threads for compression,
+ if RAM size is not enough for compression with big LZMA2 dictionary.
+- 7-Zip now can create and check "file.sha256" and "file.sha1" text files
+ that contain the list of file names and SHA-1 / SHA-256 checksums in format
+ compatible with sha1sum/sha256sum programs.
+
+
+21.03 beta 2021-07-20
+-------------------------
+- The maximum dictionary size for LZMA/LZMA2 compressing was increased to 4 GB (3840 MiB).
+- Minor speed optimizations in LZMA/LZMA2 compressing.
+
+
21.02 alpha 2021-05-06
-------------------------
- 7-Zip now writes additional field for filename in UTF-8 encoding to zip archives.