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

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/CPP/7zip
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip')
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.cpp6
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.h1
-rw-r--r--CPP/7zip/Archive/7z/7zHandlerOut.cpp24
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.cpp14
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.h4
-rw-r--r--CPP/7zip/Archive/7z/makefile8
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer.cpp19
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer.h32
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2MT.cpp254
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2MT.h77
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2ST.cpp562
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2ST.h129
-rw-r--r--CPP/7zip/Archive/Common/CoderMixerMT.cpp99
-rw-r--r--CPP/7zip/Archive/Common/CoderMixerMT.h70
-rw-r--r--CPP/7zip/Archive/Common/FindSignature.cpp2
-rw-r--r--CPP/7zip/Archive/Common/FindSignature.h4
-rw-r--r--CPP/7zip/Archive/DllExports2.cpp2
-rw-r--r--CPP/7zip/Archive/Nsis/NsisIn.h2
-rw-r--r--CPP/7zip/Archive/Rar/Rar5Handler.cpp2683
-rw-r--r--CPP/7zip/Archive/Rar/Rar5Handler.h410
-rw-r--r--CPP/7zip/Archive/Rar/RarHandler.cpp417
-rw-r--r--CPP/7zip/Archive/Rar/RarVol.h129
-rw-r--r--CPP/7zip/Archive/Tar/TarHandlerOut.cpp24
-rw-r--r--CPP/7zip/Archive/Tar/TarUpdate.cpp24
-rw-r--r--CPP/7zip/Archive/Tar/TarUpdate.h7
-rw-r--r--CPP/7zip/Archive/XarHandler.cpp9
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandlerOut.cpp4
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.cpp48
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.cpp3
-rw-r--r--CPP/7zip/Bundles/Fm/FM.dsp8
-rw-r--r--CPP/7zip/Bundles/Format7zF/Arc.mak5
-rw-r--r--CPP/7zip/Bundles/Format7zF/Format7z.dsp70
-rw-r--r--CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp2
-rw-r--r--CPP/7zip/Bundles/SFXCon/SfxCon.cpp2
-rw-r--r--CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp2
-rw-r--r--CPP/7zip/Bundles/SFXWin/SfxWin.cpp2
-rw-r--r--CPP/7zip/Common/FilterCoder.h2
-rw-r--r--CPP/7zip/Common/LimitedStreams.cpp2
-rw-r--r--CPP/7zip/Common/PropId.cpp5
-rw-r--r--CPP/7zip/Common/UniqBlocks.cpp2
-rw-r--r--CPP/7zip/Compress/Codec.def2
-rw-r--r--CPP/7zip/Compress/DeflateEncoder.cpp8
-rw-r--r--CPP/7zip/Compress/HuffmanDecoder.h19
-rw-r--r--CPP/7zip/Compress/Rar1Decoder.cpp2
-rw-r--r--CPP/7zip/Compress/Rar2Decoder.cpp2
-rw-r--r--CPP/7zip/Compress/Rar3Decoder.cpp22
-rw-r--r--CPP/7zip/Compress/Rar3Decoder.h1
-rw-r--r--CPP/7zip/Compress/Rar3Vm.cpp105
-rw-r--r--CPP/7zip/Compress/Rar3Vm.h34
-rw-r--r--CPP/7zip/Compress/Rar5Decoder.cpp960
-rw-r--r--CPP/7zip/Compress/Rar5Decoder.h335
-rw-r--r--CPP/7zip/Compress/RarCodecsRegister.cpp3
-rw-r--r--CPP/7zip/Crypto/HmacSha256.cpp62
-rw-r--r--CPP/7zip/Crypto/HmacSha256.h27
-rw-r--r--CPP/7zip/Crypto/Rar20Crypto.cpp62
-rw-r--r--CPP/7zip/Crypto/Rar20Crypto.h16
-rw-r--r--CPP/7zip/Crypto/Rar5Aes.cpp257
-rw-r--r--CPP/7zip/Crypto/Rar5Aes.h84
-rw-r--r--CPP/7zip/Crypto/RarAes.cpp22
-rw-r--r--CPP/7zip/Crypto/RarAes.h19
-rw-r--r--CPP/7zip/Guid.txt1
-rw-r--r--CPP/7zip/IProgress.h1
-rw-r--r--CPP/7zip/IStream.h2
-rw-r--r--CPP/7zip/PropID.h1
-rw-r--r--CPP/7zip/UI/Agent/AgentOut.cpp15
-rw-r--r--CPP/7zip/UI/Client7z/Client7z.cpp2
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.cpp165
-rw-r--r--CPP/7zip/UI/Common/ArchiveExtractCallback.h9
-rw-r--r--CPP/7zip/UI/Common/ArchiveOpenCallback.h19
-rw-r--r--CPP/7zip/UI/Common/Bench.cpp3
-rw-r--r--CPP/7zip/UI/Common/LoadCodecs.cpp4
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.cpp84
-rw-r--r--CPP/7zip/UI/Common/UpdateAction.h2
-rw-r--r--CPP/7zip/UI/Common/UpdateCallback.cpp2
-rw-r--r--CPP/7zip/UI/Console/ConsoleClose.cpp4
-rw-r--r--CPP/7zip/UI/Console/List.cpp1
-rw-r--r--CPP/7zip/UI/Console/Main.cpp164
-rw-r--r--CPP/7zip/UI/Explorer/ContextMenu.h4
-rw-r--r--CPP/7zip/UI/Explorer/DllExportsExplorer.cpp4
-rw-r--r--CPP/7zip/UI/Far/Far.cpp29
-rw-r--r--CPP/7zip/UI/Far/Messages.h2
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog.cpp8
-rw-r--r--CPP/7zip/UI/FileManager/ClassDefs.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/FM.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/FSFolderCopy.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.cpp40
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.h1
-rw-r--r--CPP/7zip/UI/FileManager/Panel.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/Panel.h4
-rw-r--r--CPP/7zip/UI/FileManager/PanelFolderChange.cpp10
-rw-r--r--CPP/7zip/UI/FileManager/PanelItemOpen.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/PanelOperations.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/PanelSelect.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog.h2
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/PropertyName.rc1
-rw-r--r--CPP/7zip/UI/FileManager/PropertyNameRes.h1
-rw-r--r--CPP/7zip/UI/FileManager/RootFolder.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/StdAfx.h8
-rw-r--r--CPP/7zip/UI/FileManager/SysIconUtils.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/SysIconUtils.h4
-rw-r--r--CPP/7zip/UI/FileManager/SystemPage.cpp4
-rw-r--r--CPP/7zip/UI/GUI/BenchmarkDialog.cpp2
-rw-r--r--CPP/7zip/UI/GUI/GUI.cpp4
-rw-r--r--CPP/7zip/UI/GUI/StdAfx.h6
106 files changed, 6006 insertions, 1848 deletions
diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
index d1a810cb..bfe1b24e 100644
--- a/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -301,6 +301,12 @@ HRESULT CDecoder::Decode(
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
+ #ifndef _SFX
+ // we don't support RAR codecs here
+ if ((coderInfo.MethodID >> 8) == 0x403)
+ return E_NOTIMPL;
+ #endif
+
CCreatedCoder cod;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
index 8a078e19..eb7791bc 100644
--- a/CPP/7zip/Archive/7z/7zHandler.h
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -44,6 +44,7 @@ public:
UInt64 _numSolidBytes;
bool _numSolidBytesDefined;
bool _solidExtension;
+ bool _useTypeSorting;
bool _compressHeaders;
bool _encryptHeadersSpecified;
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index 5cab6a82..7ece4c68 100644
--- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -508,14 +508,19 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (ui.NewData)
{
- NCOM::CPropVariant prop;
- RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
- if (prop.vt != VT_UI8)
- return E_INVALIDARG;
- ui.Size = (UInt64)prop.uhVal.QuadPart;
- if (ui.Size != 0 && ui.IsAnti)
- return E_INVALIDARG;
+ ui.Size = 0;
+ if (!ui.IsDir)
+ {
+ NCOM::CPropVariant prop;
+ RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
+ if (prop.vt != VT_UI8)
+ return E_INVALIDARG;
+ ui.Size = (UInt64)prop.uhVal.QuadPart;
+ if (ui.Size != 0 && ui.IsAnti)
+ return E_INVALIDARG;
+ }
}
+
updateItems.Add(ui);
}
@@ -613,6 +618,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.NumSolidFiles = _numSolidFiles;
options.NumSolidBytes = _numSolidBytes;
options.SolidExtension = _solidExtension;
+ options.UseTypeSorting = _useTypeSorting;
+
options.RemoveSfxBlock = _removeSfxBlock;
// options.VolumeMode = _volumeMode;
@@ -701,6 +708,7 @@ void COutHandler::InitProps()
// _volumeMode = false;
InitSolid();
+ _useTypeSorting = false;
}
HRESULT COutHandler::SetSolidFromString(const UString &s)
@@ -821,6 +829,8 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
+ if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
+
// if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
}
return CMultiMethodProps::SetProperty(name, value);
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index e7c9ecc6..345cd627 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -554,11 +554,11 @@ static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param
}
static const char *g_Exts =
- " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo"
+ " 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo"
" zip jar ear war msi"
" 3gp avi mov mpeg mpg mpe wmv"
" aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav"
- " swf "
+ " swf"
" chm hxi hxs"
" gif jpeg jpg jp2 png tiff bmp ico psd psp"
" awg ps eps cgm dxf svg vrml wmf emf ai md"
@@ -569,9 +569,9 @@ static const char *g_Exts =
" vmdk dsk nvram vmem vmsd vmsn vmss vmtm"
" inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def"
" f77 f f90 f95"
- " asm sql manifest dep "
- " mak clw csproj vcproj sln dsp dsw "
- " class "
+ " asm sql manifest dep"
+ " mak clw csproj vcproj sln dsp dsw"
+ " class"
" bat cmd"
" xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"
" awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs"
@@ -580,7 +580,7 @@ static const char *g_Exts =
" abw afp cwk lwp wpd wps wpt wrf wri"
" abf afm bdf fon mgf otf pcf pfa snf ttf"
" dbf mdb nsf ntf wdb db fdb gdb"
- " exe dll ocx vbx sfx sys tlb awx com obj lib out o so "
+ " exe dll ocx vbx sfx sys tlb awx com obj lib out o so"
" pdb pch idb ncb opt";
static unsigned GetExtIndex(const char *ext)
@@ -2251,7 +2251,7 @@ HRESULT Update(
continue;
CRecordVector<CRefItem> refItems;
refItems.ClearAndSetSize(numFiles);
- bool sortByType = (numSolidFiles > 1);
+ bool sortByType = (options.UseTypeSorting && numSolidFiles > 1);
for (i = 0; i < numFiles; i++)
refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);
CSortParam sortParam;
diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h
index 3986af43..a7abf779 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.h
+++ b/CPP/7zip/Archive/7z/7zUpdate.h
@@ -97,6 +97,9 @@ struct CUpdateOptions
UInt64 NumSolidFiles;
UInt64 NumSolidBytes;
bool SolidExtension;
+
+ bool UseTypeSorting;
+
bool RemoveSfxBlock;
bool MultiThreadMixer;
@@ -109,6 +112,7 @@ struct CUpdateOptions
NumSolidFiles((UInt64)(Int64)(-1)),
NumSolidBytes((UInt64)(Int64)(-1)),
SolidExtension(false),
+ UseTypeSorting(true),
RemoveSfxBlock(false),
MultiThreadMixer(true)
{}
diff --git a/CPP/7zip/Archive/7z/makefile b/CPP/7zip/Archive/7z/makefile
index 19982112..49818371 100644
--- a/CPP/7zip/Archive/7z/makefile
+++ b/CPP/7zip/Archive/7z/makefile
@@ -1,5 +1,5 @@
PROG = 7z.dll
-DEF_FILE = ../../Archive/Archive2.def
+DEF_FILE = ../Archive.def
CFLAGS = $(CFLAGS) \
-DEXTERNAL_CODECS \
@@ -60,9 +60,11 @@ WIN_OBJS = \
$O\StreamUtils.obj \
$O\VirtThread.obj \
+COMPRESS_OBJS = \
+ $O\CopyCoder.obj \
+
AR_COMMON_OBJS = \
$O\CoderMixer2.obj \
- $O\CoderMixer2MT.obj \
$O\CrossThreadProgress.obj \
$O\HandlerOut.obj \
$O\InStreamWithCRC.obj \
@@ -76,4 +78,6 @@ C_OBJS = \
$O\CpuArch.obj \
$O\Threads.obj \
+!include "../../Crc.mak"
+
!include "../../7zip.mak"
diff --git a/CPP/7zip/Archive/Common/CoderMixer.cpp b/CPP/7zip/Archive/Common/CoderMixer.cpp
deleted file mode 100644
index a19f0457..00000000
--- a/CPP/7zip/Archive/Common/CoderMixer.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// CoderMixer.cpp
-
-#include "StdAfx.h"
-
-#include "CoderMixer.h"
-
-namespace NCoderMixer {
-
-void CCoderInfo::SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize)
-{
- InSizeAssigned = (inSize != 0);
- if (InSizeAssigned)
- InSizeValue = *inSize;
- OutSizeAssigned = (outSize != 0);
- if (OutSizeAssigned)
- OutSizeValue = *outSize;
-}
-
-}
diff --git a/CPP/7zip/Archive/Common/CoderMixer.h b/CPP/7zip/Archive/Common/CoderMixer.h
deleted file mode 100644
index 6379dd80..00000000
--- a/CPP/7zip/Archive/Common/CoderMixer.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// CoderMixer.h
-
-#ifndef __CODER_MIXER_H
-#define __CODER_MIXER_H
-
-#include "../../../Common/MyCom.h"
-#include "../../ICoder.h"
-
-namespace NCoderMixer {
-
-struct CCoderInfo
-{
- CMyComPtr<ICompressCoder> Coder;
- CMyComPtr<ISequentialInStream> InStream;
- CMyComPtr<ISequentialOutStream> OutStream;
- CMyComPtr<ICompressProgressInfo> Progress;
-
- UInt64 InSizeValue;
- UInt64 OutSizeValue;
- bool InSizeAssigned;
- bool OutSizeAssigned;
-
- void ReInit()
- {
- InSizeAssigned = OutSizeAssigned = false;
- }
-
- void SetCoderInfo(const UInt64 *inSize, const UInt64 *outSize);
-};
-
-}
-#endif
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
deleted file mode 100644
index c0139862..00000000
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-// CoderMixer2MT.cpp
-
-#include "StdAfx.h"
-
-#include "CoderMixer2MT.h"
-
-namespace NCoderMixer2 {
-
-void CCoderMT::Execute() { Code(NULL); }
-
-void CCoderMT::Code(ICompressProgressInfo *progress)
-{
- unsigned numInStreams = EncodeMode ? 1 : NumStreams;
- unsigned numOutStreams = EncodeMode ? NumStreams : 1;
-
- InStreamPointers.ClearAndReserve(numInStreams);
- OutStreamPointers.ClearAndReserve(numOutStreams);
-
- unsigned i;
-
- for (i = 0; i < numInStreams; i++)
- InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
-
- for (i = 0; i < numOutStreams; i++)
- OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
-
- // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
- /*
- if (UnpackSizePointer)
- UnpackSizePointer = &UnpackSize;
- for (i = 0; i < NumStreams; i++)
- if (PackSizePointers[i])
- PackSizePointers[i] = &PackSizes[i];
- */
-
- if (Coder)
- Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
- EncodeMode ? UnpackSizePointer : PackSizePointers[0],
- EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
- progress);
- else
- Result = Coder2->Code(
- &InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams,
- &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams,
- progress);
-
- InStreamPointers.Clear();
- OutStreamPointers.Clear();
-
- for (i = 0; i < InStreams.Size(); i++)
- InStreams[i].Release();
- for (i = 0; i < OutStreams.Size(); i++)
- OutStreams[i].Release();
-}
-
-HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
-{
- CMixer::SetBindInfo(bindInfo);
-
- _streamBinders.Clear();
- FOR_VECTOR (i, _bi.Bonds)
- {
- RINOK(_streamBinders.AddNew().CreateEvents());
- }
- return S_OK;
-}
-
-void CMixerMT::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter)
-{
- const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
- CCoderMT &c2 = _coders.AddNew();
- c2.NumStreams = c.NumStreams;
- c2.EncodeMode = EncodeMode;
- c2.Coder = coder;
- c2.Coder2 = coder2;
- IsFilter_Vector.Add(isFilter);
-}
-
-CCoder &CMixerMT::GetCoder(unsigned index)
-{
- return _coders[index];
-}
-
-void CMixerMT::ReInit()
-{
- FOR_VECTOR (i, _streamBinders)
- _streamBinders[i].ReInit();
-}
-
-void CMixerMT::SelectMainCoder(bool useFirst)
-{
- unsigned ci = _bi.UnpackCoder;
-
- if (!useFirst)
- for (;;)
- {
- if (_coders[ci].NumStreams != 1)
- break;
- if (!IsFilter_Vector[ci])
- break;
-
- UInt32 st = _bi.Coder_to_Stream[ci];
- if (_bi.IsStream_in_PackStreams(st))
- break;
- int bond = _bi.FindBond_for_PackStream(st);
- if (bond < 0)
- throw 20150213;
- ci = _bi.Bonds[bond].UnpackIndex;
- }
-
- MainCoderIndex = ci;
-}
-
-HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
-{
- unsigned i;
-
- for (i = 0; i < _coders.Size(); i++)
- {
- CCoderMT &coderInfo = _coders[i];
- const CCoderStreamsInfo &csi = _bi.Coders[i];
-
- UInt32 j;
-
- unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
- unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
-
- coderInfo.InStreams.Clear();
- for (j = 0; j < numInStreams; j++)
- coderInfo.InStreams.AddNew();
-
- coderInfo.OutStreams.Clear();
- for (j = 0; j < numOutStreams; j++)
- coderInfo.OutStreams.AddNew();
- }
-
- for (i = 0; i < _bi.Bonds.Size(); i++)
- {
- const CBond &bond = _bi.Bonds[i];
-
- UInt32 inCoderIndex, inCoderStreamIndex;
- UInt32 outCoderIndex, outCoderStreamIndex;
-
- {
- UInt32 coderIndex, coderStreamIndex;
- _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
-
- inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
- outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
-
- inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
- outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
- }
-
- _streamBinders[i].CreateStreams(
- &_coders[inCoderIndex].InStreams[inCoderStreamIndex],
- &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
-
- CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
- _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
- _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
- if (inSetSize && outSetSize)
- {
- const UInt32 kBufSize = 1 << 19;
- inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
- outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
- }
- }
-
- {
- CCoderMT &cod = _coders[_bi.UnpackCoder];
- if (EncodeMode)
- cod.InStreams[0] = inStreams[0];
- else
- cod.OutStreams[0] = outStreams[0];
- }
-
- for (i = 0; i < _bi.PackStreams.Size(); i++)
- {
- UInt32 coderIndex, coderStreamIndex;
- _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
- CCoderMT &cod = _coders[coderIndex];
- if (EncodeMode)
- cod.OutStreams[coderStreamIndex] = outStreams[i];
- else
- cod.InStreams[coderStreamIndex] = inStreams[i];
- }
-
- return S_OK;
-}
-
-HRESULT CMixerMT::ReturnIfError(HRESULT code)
-{
- FOR_VECTOR (i, _coders)
- if (_coders[i].Result == code)
- return code;
- return S_OK;
-}
-
-HRESULT CMixerMT::Code(
- ISequentialInStream * const *inStreams,
- ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress)
-{
- Init(inStreams, outStreams);
-
- unsigned i;
- for (i = 0; i < _coders.Size(); i++)
- if (i != MainCoderIndex)
- {
- RINOK(_coders[i].Create());
- }
-
- for (i = 0; i < _coders.Size(); i++)
- if (i != MainCoderIndex)
- _coders[i].Start();
-
- _coders[MainCoderIndex].Code(progress);
-
- for (i = 0; i < _coders.Size(); i++)
- if (i != MainCoderIndex)
- _coders[i].WaitExecuteFinish();
-
- RINOK(ReturnIfError(E_ABORT));
- RINOK(ReturnIfError(E_OUTOFMEMORY));
-
- for (i = 0; i < _coders.Size(); i++)
- {
- HRESULT result = _coders[i].Result;
- if (result != S_OK
- && result != k_My_HRESULT_WritingWasCut
- && result != S_FALSE
- && result != E_FAIL)
- return result;
- }
-
- RINOK(ReturnIfError(S_FALSE));
-
- for (i = 0; i < _coders.Size(); i++)
- {
- HRESULT result = _coders[i].Result;
- if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
- return result;
- }
-
- return S_OK;
-}
-
-UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
-{
- return _streamBinders[bondIndex].ProcessedSize;
-}
-
-}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h
deleted file mode 100644
index 41bb3e1c..00000000
--- a/CPP/7zip/Archive/Common/CoderMixer2MT.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// CoderMixer2MT.h
-
-#ifndef __CODER_MIXER2_MT_H
-#define __CODER_MIXER2_MT_H
-
-#include "../../../Common/MyCom.h"
-
-#include "../../Common/StreamBinder.h"
-#include "../../Common/VirtThread.h"
-
-#include "CoderMixer2.h"
-
-namespace NCoderMixer2 {
-
-class CCoderMT: public CCoder, public CVirtThread
-{
- CLASS_NO_COPY(CCoderMT)
- CRecordVector<ISequentialInStream*> InStreamPointers;
- CRecordVector<ISequentialOutStream*> OutStreamPointers;
-
-private:
- void Execute();
-public:
- bool EncodeMode;
- HRESULT Result;
- CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
- CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
-
- CCoderMT(): EncodeMode(false) {}
- ~CCoderMT() { CVirtThread::WaitThreadFinish(); }
-
- void Code(ICompressProgressInfo *progress);
-};
-
-
-
-class CMixerMT:
- public IUnknown,
- public CMixer,
- public CMyUnknownImp
-{
- CObjectVector<CStreamBinder> _streamBinders;
-
- HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
- HRESULT ReturnIfError(HRESULT code);
-
-public:
- CObjectVector<CCoderMT> _coders;
-
- MY_UNKNOWN_IMP
-
- virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
-
- virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter);
-
- virtual CCoder &GetCoder(unsigned index);
-
- virtual void SelectMainCoder(bool useFirst);
-
- virtual void ReInit();
-
- virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
- { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
-
- virtual HRESULT Code(
- ISequentialInStream * const *inStreams,
- ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress);
-
- virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
-
- CMixerMT(bool encodeMode): CMixer(encodeMode) {}
-};
-
-}
-
-#endif
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
deleted file mode 100644
index 127c1ed4..00000000
--- a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
+++ /dev/null
@@ -1,562 +0,0 @@
-// CoderMixer2ST.cpp
-
-#include "StdAfx.h"
-
-#include "CoderMixer2ST.h"
-
-STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize)
-{
- UInt32 realProcessed = 0;
- HRESULT result = S_OK;
- if (_stream)
- result = _stream->Read(data, size, &realProcessed);
- _size += realProcessed;
- if (size != 0 && realProcessed == 0)
- _wasFinished = true;
- if (processedSize)
- *processedSize = realProcessed;
- return result;
-}
-
-
-
-STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize)
-{
- HRESULT result = S_OK;
- if (_stream)
- result = _stream->Write(data, size, &size);
- _size += size;
- if (processedSize)
- *processedSize = size;
- return result;
-}
-
-STDMETHODIMP COutStreamCalcSize::Flush()
-{
- HRESULT result = S_OK;
- if (_stream)
- {
- CMyComPtr<IOutStreamFlush> outStreamFlush;
- _stream.QueryInterface(IID_IOutStreamFlush, &outStreamFlush);
- if (outStreamFlush)
- result = outStreamFlush->Flush();;
- }
- return result;
-}
-
-
-
-namespace NCoderMixer2 {
-
-CMixerST::CMixerST(bool encodeMode):
- CMixer(encodeMode)
- {}
-
-CMixerST::~CMixerST() {}
-
-void CMixerST::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter)
-{
- IsFilter_Vector.Add(isFilter);
- const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
- CCoderST &c2 = _coders.AddNew();
- c2.NumStreams = c.NumStreams;
- c2.Coder = coder;
- c2.Coder2 = coder2;
-
- /*
- if (isFilter)
- {
- c2.CanRead = true;
- c2.CanWrite = true;
- }
- else
- */
- {
- IUnknown *unk = (coder ? (IUnknown *)coder : (IUnknown *)coder2);
- {
- CMyComPtr<ISequentialInStream> s;
- unk->QueryInterface(IID_ISequentialInStream, (void**)&s);
- c2.CanRead = (s != NULL);
- }
- {
- CMyComPtr<ISequentialOutStream> s;
- unk->QueryInterface(IID_ISequentialOutStream, (void**)&s);
- c2.CanWrite = (s != NULL);
- }
- }
-}
-
-CCoder &CMixerST::GetCoder(unsigned index)
-{
- return _coders[index];
-}
-
-void CMixerST::ReInit() {}
-
-HRESULT CMixerST::GetInStream2(
- ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
- UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
-{
- UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
-
- if (EncodeMode)
- {
- _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
- if (coderStreamIndex != 0)
- return E_NOTIMPL;
- }
-
- const CCoder &coder = _coders[coderIndex];
-
- CMyComPtr<ISequentialInStream> seqInStream;
- coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
- if (!seqInStream)
- return E_NOTIMPL;
-
- UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
- UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
-
- bool isSet = false;
-
- if (numInStreams == 1)
- {
- CMyComPtr<ICompressSetInStream> setStream;
- coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
- if (setStream)
- {
- CMyComPtr<ISequentialInStream> seqInStream2;
- RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2));
- RINOK(setStream->SetInStream(seqInStream2));
- isSet = true;
- }
- }
-
- if (!isSet && numInStreams != 0)
- {
- CMyComPtr<ICompressSetInStream2> setStream2;
- coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
- if (!setStream2)
- return E_NOTIMPL;
-
- for (UInt32 i = 0; i < numInStreams; i++)
- {
- CMyComPtr<ISequentialInStream> seqInStream2;
- RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2));
- RINOK(setStream2->SetInStream2(i, seqInStream2));
- }
- }
-
- *inStreamRes = seqInStream.Detach();
- return S_OK;
-}
-
-
-HRESULT CMixerST::GetInStream(
- ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
- UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
-{
- CMyComPtr<ISequentialInStream> seqInStream;
-
- {
- int index = -1;
- if (EncodeMode)
- {
- if (_bi.UnpackCoder == inStreamIndex)
- index = 0;
- }
- else
- index = _bi.FindStream_in_PackStreams(inStreamIndex);
-
- if (index >= 0)
- {
- seqInStream = inStreams[index];
- *inStreamRes = seqInStream.Detach();
- return S_OK;
- }
- }
-
- int bond = FindBond_for_Stream(
- true, // forInputStream
- inStreamIndex);
- if (bond < 0)
- return E_INVALIDARG;
-
- RINOK(GetInStream2(inStreams, /* inSizes, */
- _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream));
-
- while (_binderStreams.Size() <= (unsigned)bond)
- _binderStreams.AddNew();
- CStBinderStream &bs = _binderStreams[bond];
-
- if (bs.StreamRef || bs.InStreamSpec)
- return E_NOTIMPL;
-
- CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
- bs.StreamRef = spec;
- bs.InStreamSpec = spec;
-
- spec->SetStream(seqInStream);
- spec->Init();
-
- seqInStream = bs.InStreamSpec;
-
- *inStreamRes = seqInStream.Detach();
- return S_OK;
-}
-
-
-HRESULT CMixerST::GetOutStream(
- ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
- UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
-{
- CMyComPtr<ISequentialOutStream> seqOutStream;
-
- {
- int index = -1;
- if (!EncodeMode)
- {
- if (_bi.UnpackCoder == outStreamIndex)
- index = 0;
- }
- else
- index = _bi.FindStream_in_PackStreams(outStreamIndex);
-
- if (index >= 0)
- {
- seqOutStream = outStreams[index];
- *outStreamRes = seqOutStream.Detach();
- return S_OK;
- }
- }
-
- int bond = FindBond_for_Stream(
- false, // forInputStream
- outStreamIndex);
- if (bond < 0)
- return E_INVALIDARG;
-
- UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
-
- UInt32 coderIndex = inStreamIndex;
- UInt32 coderStreamIndex = 0;
-
- if (!EncodeMode)
- _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
-
- CCoder &coder = _coders[coderIndex];
-
- /*
- if (!coder.Coder)
- return E_NOTIMPL;
- */
-
- coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
- if (!seqOutStream)
- return E_NOTIMPL;
-
- UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
- UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
-
- bool isSet = false;
-
- if (numOutStreams == 1)
- {
- CMyComPtr<ICompressSetOutStream> setOutStream;
- coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
- if (setOutStream)
- {
- CMyComPtr<ISequentialOutStream> seqOutStream2;
- RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2));
- RINOK(setOutStream->SetOutStream(seqOutStream2));
- isSet = true;
- }
- }
-
- if (!isSet && numOutStreams != 0)
- {
- // return E_NOTIMPL;
- // /*
- CMyComPtr<ICompressSetOutStream2> setStream2;
- coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
- if (!setStream2)
- return E_NOTIMPL;
- for (UInt32 i = 0; i < numOutStreams; i++)
- {
- CMyComPtr<ISequentialOutStream> seqOutStream2;
- RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2));
- RINOK(setStream2->SetOutStream2(i, seqOutStream2));
- }
- // */
- }
-
- while (_binderStreams.Size() <= (unsigned)bond)
- _binderStreams.AddNew();
- CStBinderStream &bs = _binderStreams[bond];
-
- if (bs.StreamRef || bs.OutStreamSpec)
- return E_NOTIMPL;
-
- COutStreamCalcSize *spec = new COutStreamCalcSize;
- bs.StreamRef = (ISequentialOutStream *)spec;
- bs.OutStreamSpec = spec;
-
- spec->SetStream(seqOutStream);
- spec->Init();
-
- seqOutStream = bs.OutStreamSpec;
-
- *outStreamRes = seqOutStream.Detach();
- return S_OK;
-}
-
-
-static HRESULT GetError(HRESULT res, HRESULT res2)
-{
- if (res == res2)
- return res;
- if (res == S_OK)
- return res2;
- if (res == k_My_HRESULT_WritingWasCut)
- {
- if (res2 != S_OK)
- return res2;
- }
- return res;
-}
-
-
-HRESULT CMixerST::FlushStream(UInt32 streamIndex)
-{
- {
- int index = -1;
- if (!EncodeMode)
- {
- if (_bi.UnpackCoder == streamIndex)
- index = 0;
- }
- else
- index = _bi.FindStream_in_PackStreams(streamIndex);
-
- if (index >= 0)
- return S_OK;
- }
-
- int bond = FindBond_for_Stream(
- false, // forInputStream
- streamIndex);
- if (bond < 0)
- return E_INVALIDARG;
-
- UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
-
- UInt32 coderIndex = inStreamIndex;
- UInt32 coderStreamIndex = 0;
- if (!EncodeMode)
- _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
-
- CCoder &coder = _coders[coderIndex];
- CMyComPtr<IOutStreamFlush> flush;
- coder.QueryInterface(IID_IOutStreamFlush, (void **)&flush);
- HRESULT res = S_OK;
- if (flush)
- {
- res = flush->Flush();
- }
- return GetError(res, FlushCoder(coderIndex));
-}
-
-
-HRESULT CMixerST::FlushCoder(UInt32 coderIndex)
-{
- CCoder &coder = _coders[coderIndex];
-
- UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
- UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
-
- HRESULT res = S_OK;
- for (unsigned i = 0; i < numOutStreams; i++)
- res = GetError(res, FlushStream(startIndex + i));
- return res;
-}
-
-
-void CMixerST::SelectMainCoder(bool useFirst)
-{
- unsigned ci = _bi.UnpackCoder;
-
- int firstNonFilter = -1;
- int firstAllowed = ci;
-
- for (;;)
- {
- const CCoderST &coder = _coders[ci];
- // break;
-
- if (ci != _bi.UnpackCoder)
- if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
- {
- firstAllowed = ci;
- firstNonFilter = -2;
- }
-
- if (coder.NumStreams != 1)
- break;
-
- UInt32 st = _bi.Coder_to_Stream[ci];
- if (_bi.IsStream_in_PackStreams(st))
- break;
- int bond = _bi.FindBond_for_PackStream(st);
- if (bond < 0)
- throw 20150213;
-
- if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
- break;
-
- if (firstNonFilter == -1 && !IsFilter_Vector[ci])
- firstNonFilter = ci;
-
- ci = _bi.Bonds[bond].UnpackIndex;
- }
-
- ci = firstNonFilter;
- if (firstNonFilter < 0 || useFirst)
- ci = firstAllowed;
- MainCoderIndex = ci;
-}
-
-
-HRESULT CMixerST::Code(
- ISequentialInStream * const *inStreams,
- ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress)
-{
- _binderStreams.Clear();
- unsigned ci = MainCoderIndex;
-
- const CCoder &mainCoder = _coders[MainCoderIndex];
-
- CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
- CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
-
- UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams;
- UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
-
- UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci];
- UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
-
- UInt32 i;
-
- for (i = 0; i < numInStreams; i++)
- {
- CMyComPtr<ISequentialInStream> seqInStream;
- RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream));
- seqInStreams.Add(seqInStream);
- }
-
- for (i = 0; i < numOutStreams; i++)
- {
- CMyComPtr<ISequentialOutStream> seqOutStream;
- RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream));
- seqOutStreams.Add(seqOutStream);
- }
-
- CRecordVector< ISequentialInStream * > seqInStreamsSpec;
- CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
-
- for (i = 0; i < numInStreams; i++)
- seqInStreamsSpec.Add(seqInStreams[i]);
- for (i = 0; i < numOutStreams; i++)
- seqOutStreamsSpec.Add(seqOutStreams[i]);
-
- for (i = 0; i < _coders.Size(); i++)
- {
- if (i == ci)
- continue;
-
- CCoder &coder = _coders[i];
-
- CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
- coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
- if (setOutStreamSize)
- {
- RINOK(setOutStreamSize->SetOutStreamSize(
- EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer));
- }
- }
-
- const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front();
- const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer;
-
- HRESULT res;
- if (mainCoder.Coder)
- {
- res = mainCoder.Coder->Code(
- seqInStreamsSpec[0], seqOutStreamsSpec[0],
- isSizes2[0], outSizes2[0],
- progress);
- }
- else
- {
- res = mainCoder.Coder2->Code(
- &seqInStreamsSpec.Front(), isSizes2, numInStreams,
- &seqOutStreamsSpec.Front(), outSizes2, numOutStreams,
- progress);
- }
-
- if (res == k_My_HRESULT_WritingWasCut)
- res = S_OK;
-
- if (res == S_OK || res == S_FALSE)
- {
- res = GetError(res, FlushCoder(ci));
- }
-
- for (i = 0; i < _binderStreams.Size(); i++)
- {
- const CStBinderStream &bs = _binderStreams[i];
- if (bs.InStreamSpec)
- bs.InStreamSpec->ReleaseStream();
- else
- bs.OutStreamSpec->ReleaseStream();
- }
-
- if (res == k_My_HRESULT_WritingWasCut)
- res = S_OK;
- return res;
-}
-
-
-HRESULT CMixerST::GetMainUnpackStream(
- ISequentialInStream * const *inStreams,
- ISequentialInStream **inStreamRes)
-{
- CMyComPtr<ISequentialInStream> seqInStream;
-
- RINOK(GetInStream2(inStreams, /* inSizes, */
- _bi.UnpackCoder, &seqInStream))
-
- FOR_VECTOR (i, _coders)
- {
- CCoder &coder = _coders[i];
- CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
- coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
- if (setOutStreamSize)
- {
- RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer));
- }
- }
-
- *inStreamRes = seqInStream.Detach();
- return S_OK;
-}
-
-
-UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
-{
- const CStBinderStream &bs = _binderStreams[bondIndex];
- if (bs.InStreamSpec)
- return bs.InStreamSpec->GetSize();
- return bs.OutStreamSpec->GetSize();
-}
-
-}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h
deleted file mode 100644
index f2f7c4cb..00000000
--- a/CPP/7zip/Archive/Common/CoderMixer2ST.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// CoderMixer2ST.h
-
-#ifndef __CODER_MIXER2_ST_H
-#define __CODER_MIXER2_ST_H
-
-#include "../../../Common/MyCom.h"
-
-#include "../../ICoder.h"
-
-#include "CoderMixer2.h"
-
-class CSequentialInStreamCalcSize:
- public ISequentialInStream,
- public CMyUnknownImp
-{
-public:
- MY_UNKNOWN_IMP1(ISequentialInStream)
-
- STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
-private:
- CMyComPtr<ISequentialInStream> _stream;
- UInt64 _size;
- bool _wasFinished;
-public:
- void SetStream(ISequentialInStream *stream) { _stream = stream; }
- void Init()
- {
- _size = 0;
- _wasFinished = false;
- }
- void ReleaseStream() { _stream.Release(); }
- UInt64 GetSize() const { return _size; }
- bool WasFinished() const { return _wasFinished; }
-};
-
-
-class COutStreamCalcSize:
- public ISequentialOutStream,
- public IOutStreamFlush,
- public CMyUnknownImp
-{
- CMyComPtr<ISequentialOutStream> _stream;
- UInt64 _size;
-public:
- MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFlush)
-
- STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
- STDMETHOD(Flush)();
-
- void SetStream(ISequentialOutStream *stream) { _stream = stream; }
- void ReleaseStream() { _stream.Release(); }
- void Init() { _size = 0; }
- UInt64 GetSize() const { return _size; }
-};
-
-
-
-namespace NCoderMixer2 {
-
-struct CCoderST: public CCoder
-{
- bool CanRead;
- bool CanWrite;
-
- CCoderST(): CanRead(false), CanWrite(false) {}
-};
-
-
-struct CStBinderStream
-{
- CSequentialInStreamCalcSize *InStreamSpec;
- COutStreamCalcSize *OutStreamSpec;
- CMyComPtr<IUnknown> StreamRef;
-
- CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
-};
-
-
-class CMixerST:
- public IUnknown,
- public CMixer,
- public CMyUnknownImp
-{
- HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
- UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
- HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
- UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
- HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
- UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
-
- HRESULT FlushStream(UInt32 streamIndex);
- HRESULT FlushCoder(UInt32 coderIndex);
-
-public:
- CObjectVector<CCoderST> _coders;
-
- CObjectVector<CStBinderStream> _binderStreams;
-
- MY_UNKNOWN_IMP
-
- CMixerST(bool encodeMode);
- ~CMixerST();
-
- virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter);
-
- virtual CCoder &GetCoder(unsigned index);
-
- virtual void SelectMainCoder(bool useFirst);
-
- virtual void ReInit();
-
- virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
- { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
-
- virtual HRESULT Code(
- ISequentialInStream * const *inStreams,
- ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress);
-
- virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
-
- HRESULT GetMainUnpackStream(
- ISequentialInStream * const *inStreams,
- ISequentialInStream **inStreamRes);
-};
-
-}
-
-#endif
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.cpp b/CPP/7zip/Archive/Common/CoderMixerMT.cpp
deleted file mode 100644
index 96ea76a3..00000000
--- a/CPP/7zip/Archive/Common/CoderMixerMT.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-// CoderMixerMT.cpp
-
-#include "StdAfx.h"
-
-#include "CoderMixerMT.h"
-
-namespace NCoderMixer {
-
-void CCoder::Execute() { Code(NULL); }
-
-void CCoder::Code(ICompressProgressInfo *progress)
-{
- Result = Coder->Code(InStream, OutStream,
- InSizeAssigned ? &InSizeValue : NULL,
- OutSizeAssigned ? &OutSizeValue : NULL,
- progress);
- InStream.Release();
- OutStream.Release();
-}
-
-void CCoderMixerMT::AddCoder(ICompressCoder *coder)
-{
- _coders.Add(CCoder());
- _coders.Back().Coder = coder;
-}
-
-void CCoderMixerMT::ReInit()
-{
- for(int i = 0; i < _coders.Size(); i++)
- _coders[i].ReInit();
-}
-
-HRESULT CCoderMixerMT::ReturnIfError(HRESULT code)
-{
- for (int i = 0; i < _coders.Size(); i++)
- if (_coders[i].Result == code)
- return code;
- return S_OK;
-}
-
-STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream,
- ISequentialOutStream *outStream,
- const UInt64 * /* inSize */, const UInt64 * /* outSize */,
- ICompressProgressInfo *progress)
-{
- _coders.Front().InStream = inStream;
- int i;
- _coders.Back().OutStream = outStream;
-
- for (i = 0; i < _coders.Size(); i++)
- if (i != _progressCoderIndex)
- {
- RINOK(_coders[i].Create());
- }
-
- _streamBinders.Clear();
- for (i = 0; i + 1 < _coders.Size(); i++)
- {
- _streamBinders.Add(CStreamBinder());
- CStreamBinder &sb = _streamBinders[i];
- RINOK(sb.CreateEvents());
- sb.CreateStreams(&_coders[i + 1].InStream, &_coders[i].OutStream);
- }
-
- for(i = 0; i < _streamBinders.Size(); i++)
- _streamBinders[i].ReInit();
-
- for (i = 0; i < _coders.Size(); i++)
- if (i != _progressCoderIndex)
- _coders[i].Start();
-
- _coders[_progressCoderIndex].Code(progress);
-
- for (i = 0; i < _coders.Size(); i++)
- if (i != _progressCoderIndex)
- _coders[i].WaitExecuteFinish();
-
- RINOK(ReturnIfError(E_ABORT));
- RINOK(ReturnIfError(E_OUTOFMEMORY));
-
- for (i = 0; i < _coders.Size(); i++)
- {
- HRESULT result = _coders[i].Result;
- if (result != S_OK && result != E_FAIL && result != S_FALSE)
- return result;
- }
-
- RINOK(ReturnIfError(S_FALSE));
-
- for (i = 0; i < _coders.Size(); i++)
- {
- HRESULT result = _coders[i].Result;
- if (result != S_OK)
- return result;
- }
- return S_OK;
-}
-
-}
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h
deleted file mode 100644
index d2891b26..00000000
--- a/CPP/7zip/Archive/Common/CoderMixerMT.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// CoderMixerMT.h
-
-#ifndef __CODER_MIXER_MT_H
-#define __CODER_MIXER_MT_H
-
-#include "../../../Common/MyVector.h"
-#include "../../../Common/MyCom.h"
-#include "../../ICoder.h"
-#include "../../Common/StreamBinder.h"
-#include "../../Common/VirtThread.h"
-#include "CoderMixer.h"
-
-namespace NCoderMixer {
-
-struct CCoder: public CCoderInfo, public CVirtThread
-{
- HRESULT Result;
-
- virtual void Execute();
- void Code(ICompressProgressInfo *progress);
- virtual ~CCoder() { CVirtThread::WaitThreadFinish(); }
-};
-
-/*
- for each coder
- AddCoder()
- SetProgressIndex(UInt32 coderIndex);
-
- for each file
- {
- ReInit()
- for each coder
- SetCoderInfo
- Code
- }
-*/
-
-
-class CCoderMixerMT:
- public ICompressCoder,
- public CMyUnknownImp
-{
- CObjectVector<CStreamBinder> _streamBinders;
- int _progressCoderIndex;
-
- HRESULT ReturnIfError(HRESULT code);
-public:
- CObjectVector<CCoder> _coders;
- MY_UNKNOWN_IMP
-
- STDMETHOD(Code)(ISequentialInStream *inStream,
- ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize,
- ICompressProgressInfo *progress);
-
- void AddCoder(ICompressCoder *coder);
- void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; }
-
- void ReInit();
- void SetCoderInfo(UInt32 coderIndex, const UInt64 *inSize, const UInt64 *outSize)
- { _coders[coderIndex].SetCoderInfo(inSize, outSize); }
-
- /*
- UInt64 GetWriteProcessedSize(UInt32 binderIndex) const
- { return _streamBinders[binderIndex].ProcessedSize; }
- */
-};
-
-}
-#endif
diff --git a/CPP/7zip/Archive/Common/FindSignature.cpp b/CPP/7zip/Archive/Common/FindSignature.cpp
index e9a0f032..fc952fa8 100644
--- a/CPP/7zip/Archive/Common/FindSignature.cpp
+++ b/CPP/7zip/Archive/Common/FindSignature.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include <string.h>
+
#include "../../../Common/MyBuffer.h"
#include "../../Common/StreamUtils.h"
diff --git a/CPP/7zip/Archive/Common/FindSignature.h b/CPP/7zip/Archive/Common/FindSignature.h
index e15af573..c359b9ed 100644
--- a/CPP/7zip/Archive/Common/FindSignature.h
+++ b/CPP/7zip/Archive/Common/FindSignature.h
@@ -1,7 +1,7 @@
// FindSignature.h
-#ifndef __FINDSIGNATURE_H
-#define __FINDSIGNATURE_H
+#ifndef __FIND_SIGNATURE_H
+#define __FIND_SIGNATURE_H
#include "../../IStream.h"
diff --git a/CPP/7zip/Archive/DllExports2.cpp b/CPP/7zip/Archive/DllExports2.cpp
index 2b196abe..979b4bf9 100644
--- a/CPP/7zip/Archive/DllExports2.cpp
+++ b/CPP/7zip/Archive/DllExports2.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../Common/MyWindows.h"
+
#include "../../Common/MyInitGuid.h"
#if defined(_7ZIP_LARGE_PAGES)
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h
index 2bab5299..498784b8 100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.h
+++ b/CPP/7zip/Archive/Nsis/NsisIn.h
@@ -16,7 +16,7 @@
/* If NSIS_SCRIPT is defined, it will decompile NSIS script to [NSIS].nsi file.
The code is much larger in that case. */
-#define NSIS_SCRIPT
+// #define NSIS_SCRIPT
namespace NArchive {
namespace NNsis {
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp
new file mode 100644
index 00000000..72fe4f68
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp
@@ -0,0 +1,2683 @@
+// Rar5Handler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/7zCrc.h"
+#include "../../../../C/CpuArch.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/UTFConvert.h"
+
+#include "../../../Windows/PropVariantUtils.h"
+#include "../../../Windows/TimeUtils.h"
+
+#include "../../IPassword.h"
+
+#include "../../Common/FilterCoder.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/RegisterArc.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../../Common/RegisterCodec.h"
+
+#include "../../Compress/CopyCoder.h"
+
+#include "../../Crypto/Rar5Aes.h"
+
+#include "../Common/FindSignature.h"
+#include "../Common/ItemNameUtils.h"
+
+#include "RarVol.h"
+#include "Rar5Handler.h"
+
+using namespace NWindows;
+
+#define Get32(p) GetUi32(p)
+
+namespace NArchive {
+
+namespace NRar {
+
+HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize);
+
+}
+
+namespace NRar5 {
+
+static const unsigned kMarkerSize = 8;
+
+#define SIGNATURE { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0 }
+
+static const Byte kMarker[kMarkerSize] = SIGNATURE;
+
+static const size_t kCommentSize_Max = (size_t)1 << 16;
+
+static const char * const kHostOS[] =
+{
+ "Windows"
+ , "Unix"
+};
+
+static const CUInt32PCharPair k_ArcFlags[] =
+{
+ { 0, "Volume" },
+ { 1, "VolumeField" },
+ { 2, "Solid" },
+ { 3, "Recovery" },
+ { 4, "Lock" }
+};
+
+
+
+template <unsigned alignMask>
+struct CAlignedBuffer
+{
+ Byte *_buf;
+ Byte *_bufBase;
+ size_t _size;
+
+ CAlignedBuffer(): _buf(NULL), _bufBase(NULL), _size(0) {}
+ ~CAlignedBuffer() { ::MyFree(_bufBase); }
+public:
+ operator Byte *() { return _buf; }
+ operator const Byte *() const { return _buf; }
+
+ void AllocAtLeast(size_t size)
+ {
+ if (_buf && _size >= size)
+ return;
+ ::MyFree(_bufBase);
+ _buf = NULL;
+ _size = 0;
+ _bufBase = (Byte *)::MyAlloc(size + alignMask);
+
+ if (_bufBase)
+ {
+ _size = size;
+ // _buf = (Byte *)(((uintptr_t)_bufBase + alignMask) & ~(uintptr_t)alignMask);
+ _buf = (Byte *)(((ptrdiff_t)_bufBase + alignMask) & ~(ptrdiff_t)alignMask);
+ }
+ }
+};
+
+static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val)
+{
+ *val = 0;
+
+ for (unsigned i = 0; i < maxSize;)
+ {
+ Byte b = p[i];
+ if (i < 10)
+ *val |= (UInt64)(b & 0x7F) << (7 * i++);
+ if ((b & 0x80) == 0)
+ return i;
+ }
+ return 0;
+}
+
+
+int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const
+{
+ recordDataSize = 0;
+ size_t offset = 0;
+
+ for (;;)
+ {
+ size_t rem = Extra.Size() - offset;
+ if (rem == 0)
+ return -1;
+
+ {
+ UInt64 size;
+ unsigned num = ReadVarInt(Extra + offset, rem, &size);
+ if (num == 0)
+ return -1;
+ offset += num;
+ rem -= num;
+ if (size > rem)
+ return -1;
+ rem = (size_t)size;
+ }
+ {
+ UInt64 type2;
+ unsigned num = ReadVarInt(Extra + offset, rem, &type2);
+ if (num == 0)
+ return -1;
+ offset += num;
+ rem -= num;
+
+ // There was BUG in RAR 5.21- : it stored (size-1) instead of (size)
+ // for Subdata record in Service header.
+ // That record always was last in bad archives, so we can fix that case.
+ if (type2 == NExtraRecordType::kSubdata
+ && RecordType == NHeaderType::kService
+ && rem + 1 == Extra.Size() - offset)
+ rem++;
+
+ if (type2 == type)
+ {
+ recordDataSize = (unsigned)rem;
+ return (int)offset;
+ }
+
+ offset += rem;
+ }
+ }
+}
+
+
+bool CCryptoInfo::Parse(const Byte *p, size_t size)
+{
+ unsigned num = ReadVarInt(p, size, &Algo);
+ if (num == 0) return false; p += num; size -= num;
+
+ num = ReadVarInt(p, size, &Flags);
+ if (num == 0) return false; p += num; size -= num;
+
+ if (size != 1 + 16 + 16 + (unsigned)(IsThereCheck() ? 12 : 0))
+ return false;
+
+ Cnt = p[0];
+
+ return true;
+}
+
+
+bool CItem::FindExtra_Version(UInt64 &version) const
+{
+ unsigned size;
+ int offset = FindExtra(NExtraRecordType::kVersion, size);
+ if (offset < 0)
+ return false;
+ const Byte *p = Extra + (unsigned)offset;
+
+ UInt64 Flags;
+ unsigned num = ReadVarInt(p, size, &Flags);
+ if (num == 0) return false; p += num; size -= num;
+
+ num = ReadVarInt(p, size, &version);
+ if (num == 0) return false; p += num; size -= num;
+
+ return size == 0;
+}
+
+bool CItem::FindExtra_Link(CLinkInfo &link) const
+{
+ unsigned size;
+ int offset = FindExtra(NExtraRecordType::kLink, size);
+ if (offset < 0)
+ return false;
+ const Byte *p = Extra + (unsigned)offset;
+
+ unsigned num = ReadVarInt(p, size, &link.Type);
+ if (num == 0) return false; p += num; size -= num;
+
+ num = ReadVarInt(p, size, &link.Flags);
+ if (num == 0) return false; p += num; size -= num;
+
+ UInt64 len;
+ num = ReadVarInt(p, size, &len);
+ if (num == 0) return false; p += num; size -= num;
+
+ if (size != len)
+ return false;
+
+ link.NameLen = (unsigned)len;
+ link.NameOffset = (unsigned)(p - Extra);
+ return true;
+}
+
+bool CItem::Is_CopyLink() const
+{
+ CLinkInfo link;
+ return FindExtra_Link(link) && link.Type == NLinkType::kFileCopy;
+}
+
+void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const
+{
+ CLinkInfo link;
+ if (!FindExtra_Link(link))
+ return;
+
+ if (link.Type != linkType)
+ {
+ if (linkType != NLinkType::kUnixSymLink)
+ return;
+ switch ((unsigned)link.Type)
+ {
+ case NLinkType::kUnixSymLink:
+ case NLinkType::kWinSymLink:
+ case NLinkType::kWinJunction:
+ break;
+ default: return;
+ }
+ }
+
+ AString s;
+ s.SetFrom_CalcLen((const char *)(Extra + link.NameOffset), link.NameLen);
+
+ UString unicode;
+ if (ConvertUTF8ToUnicode(s, unicode))
+ prop = NItemName::GetOSName(unicode);
+}
+
+bool CItem::GetAltStreamName(AString &name) const
+{
+ name.Empty();
+ unsigned size;
+ int offset = FindExtra(NExtraRecordType::kSubdata, size);
+ if (offset < 0)
+ return false;
+ name.SetFrom_CalcLen((const char *)(Extra + (unsigned)offset), size);
+ return true;
+}
+
+
+class CHash
+{
+ bool _calcCRC;
+ UInt32 _crc;
+ int _blakeOffset;
+ CBlake2sp _blake;
+public:
+
+ void Init_NoCalc()
+ {
+ _calcCRC = false;
+ _crc = CRC_INIT_VAL;
+ _blakeOffset = -1;
+ }
+
+ void Init(const CItem &item);
+ void Update(const void *data, size_t size);
+ UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
+
+ bool Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoderSpec);
+};
+
+void CHash::Init(const CItem &item)
+{
+ _crc = CRC_INIT_VAL;
+ _calcCRC = item.Has_CRC();
+
+ _blakeOffset = item.FindExtra_Blake();
+ if (_blakeOffset >= 0)
+ Blake2sp_Init(&_blake);
+}
+
+void CHash::Update(const void *data, size_t size)
+{
+ if (_calcCRC)
+ _crc = CrcUpdate(_crc, data, size);
+ if (_blakeOffset >= 0)
+ Blake2sp_Update(&_blake, (const Byte *)data, size);
+}
+
+bool CHash::Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoderSpec)
+{
+ if (_calcCRC)
+ {
+ UInt32 crc = GetCRC();
+ if (cryptoDecoderSpec)
+ crc = cryptoDecoderSpec->Hmac_Convert_Crc32(crc);
+ if (crc != item.CRC)
+ return false;
+ }
+
+ if (_blakeOffset >= 0)
+ {
+ Byte digest[BLAKE2S_DIGEST_SIZE];
+ Blake2sp_Final(&_blake, digest);
+ if (cryptoDecoderSpec)
+ cryptoDecoderSpec->Hmac_Convert_32Bytes(digest);
+ if (memcmp(digest, &item.Extra[(unsigned)_blakeOffset], BLAKE2S_DIGEST_SIZE) != 0)
+ return false;
+ }
+
+ return true;
+}
+
+
+class COutStreamWithHash:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ ISequentialOutStream *_stream;
+ UInt64 _pos;
+ UInt64 _size;
+ bool _size_Defined;
+ Byte *_destBuf;
+public:
+ CHash _hash;
+
+ COutStreamWithHash(): _destBuf(NULL) {}
+
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void Init(const CItem &item, Byte *destBuf)
+ {
+ _size_Defined = false;
+ _size = 0;
+ _destBuf = NULL;
+ if (!item.Is_UnknownSize())
+ {
+ _size_Defined = true;
+ _size = item.Size;
+ _destBuf = destBuf;
+ }
+ _pos = 0;
+ _hash.Init(item);
+ }
+ UInt64 GetPos() const { return _pos; }
+};
+
+
+STDMETHODIMP COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ HRESULT result = S_OK;
+ if (_size_Defined)
+ {
+ UInt64 rem = _size - _pos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+ if (_stream)
+ result = _stream->Write(data, size, &size);
+ if (_destBuf)
+ memcpy(_destBuf + (size_t)_pos, data, size);
+ _hash.Update(data, size);
+ _pos += size;
+ if (processedSize)
+ *processedSize = size;
+ return result;
+}
+
+
+
+
+
+class CInArchive
+{
+ CAlignedBuffer<AES_BLOCK_SIZE - 1> _buf;
+ size_t _bufSize;
+ size_t _bufPos;
+ ISequentialInStream *_stream;
+
+ NCrypto::NRar5::CDecoder *m_CryptoDecoderSpec;
+ CMyComPtr<ICompressFilter> m_CryptoDecoder;
+
+
+
+ HRESULT ReadStream_Check(void *data, size_t size);
+
+public:
+ bool m_CryptoMode;
+
+ bool WrongPassword;
+ bool IsArc;
+ bool UnexpectedEnd;
+
+ UInt64 StreamStartPosition;
+ UInt64 Position;
+
+ bool ReadVar(UInt64 &val);
+
+ struct CHeader
+ {
+ UInt64 Type;
+ UInt64 Flags;
+ size_t ExtraSize;
+ UInt64 DataSize;
+ };
+
+ HRESULT ReadBlockHeader(CHeader &h);
+ bool ReadFileHeader(const CHeader &header, CItem &item);
+ void AddToSeekValue(UInt64 addValue)
+ {
+ Position += addValue;
+ }
+
+ HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, ICryptoGetTextPassword *getTextPassword,
+ CInArcInfo &info);
+};
+
+
+static HRESULT MySetPassword(ICryptoGetTextPassword *getTextPassword, NCrypto::NRar5::CDecoder *cryptoDecoderSpec)
+{
+ CMyComBSTR password;
+ RINOK(getTextPassword->CryptoGetTextPassword(&password));
+ AString utf8;
+ const unsigned kPasswordLen_MAX = 127;
+ UString unicode = (LPCOLESTR)password;
+ if (unicode.Len() > kPasswordLen_MAX)
+ unicode.DeleteFrom(kPasswordLen_MAX);
+ ConvertUnicodeToUTF8(unicode, utf8);
+ cryptoDecoderSpec->SetPassword((const Byte *)(const char *)utf8, utf8.Len());
+ return S_OK;
+}
+
+
+bool CInArchive::ReadVar(UInt64 &val)
+{
+ unsigned offset = ReadVarInt(_buf + _bufPos, _bufSize - _bufPos, &val);
+ _bufPos += offset;
+ return (offset != 0);
+}
+
+
+HRESULT CInArchive::ReadStream_Check(void *data, size_t size)
+{
+ size_t size2 = size;
+ RINOK(ReadStream(_stream, data, &size2));
+ if (size2 == size)
+ return S_OK;
+ UnexpectedEnd = true;
+ return S_FALSE;
+}
+
+
+HRESULT CInArchive::ReadBlockHeader(CHeader &h)
+{
+ h.Type = 0;
+ h.Flags = 0;
+ h.ExtraSize = 0;
+ h.DataSize = 0;
+
+ const unsigned kStartSize = 4 + 3;
+ const unsigned kBufSize = AES_BLOCK_SIZE + AES_BLOCK_SIZE; // must be >= kStartSize;
+ Byte buf[kBufSize];
+ unsigned filled;
+
+ if (m_CryptoMode)
+ {
+ RINOK(ReadStream_Check(buf, kBufSize));
+ memcpy(m_CryptoDecoderSpec->_iv, buf, AES_BLOCK_SIZE);
+ RINOK(m_CryptoDecoderSpec->Init());
+
+ _buf.AllocAtLeast(1 << 12);
+ if (!(Byte *)_buf)
+ return E_OUTOFMEMORY;
+
+ memcpy(_buf, buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+ if (m_CryptoDecoderSpec->Filter(_buf, AES_BLOCK_SIZE) != AES_BLOCK_SIZE)
+ return E_FAIL;
+ memcpy(buf, _buf, AES_BLOCK_SIZE);
+ filled = AES_BLOCK_SIZE;
+ }
+ else
+ {
+ RINOK(ReadStream_Check(buf, kStartSize));
+ filled = kStartSize;
+ }
+
+ UInt64 val;
+ unsigned offset = ReadVarInt(buf + 4, 3, &val);
+ if (offset == 0)
+ return S_FALSE;
+ {
+ size_t size = (size_t)val;
+ _bufPos = (4 + offset);
+ _bufSize = _bufPos + size;
+ if (size < 2)
+ return S_FALSE;
+ }
+
+ size_t allocSize = _bufSize;
+ if (m_CryptoMode)
+ allocSize = (allocSize + AES_BLOCK_SIZE - 1) & ~(size_t)(AES_BLOCK_SIZE - 1);
+ _buf.AllocAtLeast(allocSize);
+ if (!(Byte *)_buf)
+ return E_OUTOFMEMORY;
+
+ memcpy(_buf, buf, filled);
+
+ size_t rem = allocSize - filled;
+ AddToSeekValue(allocSize + (m_CryptoMode ? AES_BLOCK_SIZE : 0));
+ RINOK(ReadStream_Check(_buf + filled, rem));
+ if (m_CryptoMode)
+ {
+ if (m_CryptoDecoderSpec->Filter(_buf + filled, (UInt32)rem) != rem)
+ return E_FAIL;
+ }
+
+ if (CrcCalc(_buf + 4, _bufSize - 4) != Get32(buf))
+ return S_FALSE;
+
+ if (!ReadVar(h.Type)) return S_FALSE;
+ if (!ReadVar(h.Flags)) return S_FALSE;
+
+ if (h.Flags & NHeaderFlags::kExtra)
+ {
+ UInt64 extraSize;
+ if (!ReadVar(extraSize))
+ return S_FALSE;
+ if (extraSize > _bufSize)
+ return S_FALSE;
+ h.ExtraSize = (size_t)extraSize;
+ }
+
+ if (h.Flags & NHeaderFlags::kData)
+ {
+ if (!ReadVar(h.DataSize))
+ return S_FALSE;
+ }
+
+ return S_OK;
+}
+
+
+/*
+int CInArcInfo::FindExtra(unsigned type, unsigned &recordDataSize) const
+{
+ recordDataSize = 0;
+ size_t offset = 0;
+
+ for (;;)
+ {
+ size_t rem = Extra.Size() - offset;
+ if (rem == 0)
+ return -1;
+
+ {
+ UInt64 size;
+ unsigned num = ReadVarInt(Extra + offset, rem, &size);
+ if (num == 0)
+ return -1;
+ offset += num;
+ rem -= num;
+ if (size > rem)
+ return -1;
+ rem = (size_t)size;
+ }
+ {
+ UInt64 type2;
+ unsigned num = ReadVarInt(Extra + offset, rem, &type2);
+ if (num == 0)
+ return -1;
+ offset += num;
+ rem -= num;
+
+ if (type2 == type)
+ {
+ recordDataSize = (unsigned)rem;
+ return (int)offset;
+ }
+
+ offset += rem;
+ }
+ }
+}
+
+
+bool CInArcInfo::FindExtra_Locator(CLocator &locator) const
+{
+ locator.Flags = 0;
+ locator.QuickOpen = 0;
+ locator.Recovery = 0;
+
+ unsigned size;
+ int offset = FindExtra(kArcExtraRecordType_Locator, size);
+ if (offset < 0)
+ return false;
+ const Byte *p = Extra + (unsigned)offset;
+
+ unsigned num;
+
+ num = ReadVarInt(p, size, &locator.Flags);
+ if (num == 0) return false; p += num; size -= num;
+
+ if (locator.Is_QuickOpen())
+ {
+ num = ReadVarInt(p, size, &locator.QuickOpen);
+ if (num == 0) return false; p += num; size -= num;
+ }
+
+ if (locator.Is_Recovery())
+ {
+ num = ReadVarInt(p, size, &locator.Recovery);
+ if (num == 0) return false; p += num; size -= num;
+ }
+
+ return true;
+}
+*/
+
+
+HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit, ICryptoGetTextPassword *getTextPassword,
+ CInArcInfo &info)
+{
+ m_CryptoMode = false;
+
+ WrongPassword = false;
+ IsArc = false;
+ UnexpectedEnd = false;
+
+ Position = StreamStartPosition;
+
+ UInt64 arcStartPos = StreamStartPosition;
+ {
+ Byte marker[kMarkerSize];
+ RINOK(ReadStream_FALSE(stream, marker, kMarkerSize));
+ if (memcmp(marker, kMarker, kMarkerSize) == 0)
+ Position += kMarkerSize;
+ else
+ {
+ if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)
+ return S_FALSE;
+ RINOK(stream->Seek(StreamStartPosition, STREAM_SEEK_SET, NULL));
+ RINOK(FindSignatureInStream(stream, kMarker, kMarkerSize,
+ searchHeaderSizeLimit, arcStartPos));
+ arcStartPos += StreamStartPosition;
+ Position = arcStartPos + kMarkerSize;
+ RINOK(stream->Seek(Position, STREAM_SEEK_SET, NULL));
+ }
+ }
+
+ info.StartPos = arcStartPos;
+ _stream = stream;
+
+ CHeader h;
+ RINOK(ReadBlockHeader(h));
+ info.IsEncrypted = false;
+
+ if (h.Type == NHeaderType::kArcEncrypt)
+ {
+ info.IsEncrypted = true;
+ IsArc = true;
+ if (!getTextPassword)
+ return E_NOTIMPL;
+
+ m_CryptoMode = true;
+
+ if (!m_CryptoDecoder)
+ {
+ m_CryptoDecoderSpec = new NCrypto::NRar5::CDecoder;
+ m_CryptoDecoder = m_CryptoDecoderSpec;
+ }
+
+ RINOK(m_CryptoDecoderSpec->SetDecoderProps(
+ _buf + _bufPos, (unsigned)(_bufSize - _bufPos), false, false));
+
+ RINOK(MySetPassword(getTextPassword, m_CryptoDecoderSpec));
+
+ if (!m_CryptoDecoderSpec->CalcKey_and_CheckPassword())
+ {
+ WrongPassword = True;
+ return S_FALSE;
+ }
+
+ RINOK(ReadBlockHeader(h));
+ }
+
+ if (h.Type != NHeaderType::kArc)
+ return S_FALSE;
+
+ IsArc = true;
+ info.VolNumber = 0;
+
+ if (!ReadVar(info.Flags))
+ return S_FALSE;
+
+ if (info.Flags & NArcFlags::kVolNumber)
+ if (!ReadVar(info.VolNumber))
+ return S_FALSE;
+
+ if (h.ExtraSize != 0)
+ {
+ if (_bufSize - _bufPos < h.ExtraSize)
+ return S_FALSE;
+ /*
+ info.Extra.Alloc(h.ExtraSize);
+ memcpy(info.Extra, _buf + _bufPos, h.ExtraSize);
+ */
+ _bufPos += h.ExtraSize;
+
+ /*
+ CInArcInfo::CLocator locator;
+ if (info.FindExtra_Locator(locator))
+ locator.Flags = locator.Flags;
+ */
+ }
+
+ if (_bufPos != _bufSize)
+ return S_FALSE;
+
+ return S_OK;
+}
+
+
+bool CInArchive::ReadFileHeader(const CHeader &header, CItem &item)
+{
+ item.UnixMTime = 0;
+ item.CRC = 0;
+ item.Flags = 0;
+
+ item.CommonFlags = (UInt32)header.Flags;
+ item.PackSize = header.DataSize;
+
+ UInt64 flags64;
+ if (!ReadVar(flags64)) return false;
+ item.Flags = (UInt32)flags64;
+
+ if (!ReadVar(item.Size)) return false;
+
+ {
+ UInt64 attrib;
+ if (!ReadVar(attrib)) return false;
+ item.Attrib = (UInt32)attrib;
+ }
+
+ if (item.Has_UnixMTime())
+ {
+ if (_bufSize - _bufPos < 4)
+ return false;
+ item.UnixMTime = Get32(_buf + _bufPos);
+ _bufPos += 4;
+ }
+
+ if (item.Has_CRC())
+ {
+ if (_bufSize - _bufPos < 4)
+ return false;
+ item.CRC = Get32(_buf + _bufPos);
+ _bufPos += 4;
+ }
+
+ {
+ UInt64 method;
+ if (!ReadVar(method)) return false;
+ item.Method = (UInt32)method;
+ }
+
+ if (!ReadVar(item.HostOS)) return false;
+
+ {
+ UInt64 len;
+ if (!ReadVar(len)) return false;
+ if (len > _bufSize - _bufPos)
+ return false;
+ item.Name.SetFrom_CalcLen((const char *)(_buf + _bufPos), (unsigned)len);
+ _bufPos += (unsigned)len;
+ }
+
+ item.Extra.Free();
+ size_t extraSize = header.ExtraSize;
+ if (extraSize != 0)
+ {
+ if (_bufSize - _bufPos < extraSize)
+ return false;
+ item.Extra.Alloc(extraSize);
+ memcpy(item.Extra, _buf + _bufPos, extraSize);
+ _bufPos += extraSize;
+ }
+
+
+ return (_bufPos == _bufSize);
+}
+
+
+
+struct CLinkFile
+{
+ unsigned Index;
+ unsigned NumLinks;
+ CByteBuffer Data;
+ HRESULT Res;
+ bool crcOK;
+
+ CLinkFile(): Index(0), NumLinks(0), Res(S_OK), crcOK(true) {}
+};
+
+
+struct CUnpacker
+{
+ NCompress::CCopyCoder *copyCoderSpec;
+ CMyComPtr<ICompressCoder> copyCoder;
+
+ CMyComPtr<ICompressCoder> LzCoders[2];
+ bool NeedClearSolid[2];
+
+ CFilterCoder *filterStreamSpec;
+ CMyComPtr<ISequentialInStream> filterStream;
+
+ NCrypto::NRar5::CDecoder *cryptoDecoderSpec;
+ CMyComPtr<ICompressFilter> cryptoDecoder;
+
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+
+ COutStreamWithHash *outStreamSpec;
+ CMyComPtr<ISequentialOutStream> outStream;
+
+ CByteBuffer _tempBuf;
+
+ CLinkFile *linkFile;
+
+ CUnpacker(): linkFile(NULL) { NeedClearSolid[0] = NeedClearSolid[1] = true; }
+
+ HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool isSolid, bool &wrongPassword);
+
+ HRESULT Code(const CItem &item, const CItem &lastItem, UInt64 packSize,
+ ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress,
+ bool &isCrcOK);
+
+ HRESULT DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, UInt64 packSize, ISequentialInStream *inStream, CByteBuffer &buffer);
+};
+
+
+static const unsigned kLzMethodMax = 5;
+
+HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool isSolid, bool &wrongPassword)
+{
+ wrongPassword = false;
+
+ if (item.GetAlgoVersion() != 0)
+ return E_NOTIMPL;
+
+ if (!outStream)
+ {
+ outStreamSpec = new COutStreamWithHash;
+ outStream = outStreamSpec;
+ }
+
+ unsigned method = item.GetMethod();
+
+ if (method == 0)
+ {
+ if (!copyCoder)
+ {
+ copyCoderSpec = new NCompress::CCopyCoder;
+ copyCoder = copyCoderSpec;
+ }
+ }
+ else
+ {
+ if (method > kLzMethodMax)
+ return E_NOTIMPL;
+
+ /*
+ if (item.IsSplitBefore())
+ return S_FALSE;
+ */
+
+ int lzIndex = item.IsService() ? 1 : 0;
+ CMyComPtr<ICompressCoder> &lzCoder = LzCoders[lzIndex];
+
+ if (!lzCoder)
+ {
+ const UInt32 methodID = 0x40305;
+ RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS methodID, false, lzCoder));
+ if (!lzCoder)
+ return E_NOTIMPL;
+ }
+
+ CMyComPtr<ICompressSetDecoderProperties2> csdp;
+ RINOK(lzCoder.QueryInterface(IID_ICompressSetDecoderProperties2, &csdp));
+
+ Byte props[2] = { (Byte)(item.GetDictSize()), (Byte)(isSolid ? 1 : 0) };
+ RINOK(csdp->SetDecoderProperties2(props, 2));
+ }
+
+ unsigned cryptoSize = 0;
+ int cryptoOffset = item.FindExtra(NExtraRecordType::kCrypto, cryptoSize);
+
+ if (cryptoOffset >= 0)
+ {
+ if (!filterStream)
+ {
+ filterStreamSpec = new CFilterCoder(false);
+ filterStream = filterStreamSpec;
+ }
+
+ if (!cryptoDecoder)
+ {
+ cryptoDecoderSpec = new NCrypto::NRar5::CDecoder;
+ cryptoDecoder = cryptoDecoderSpec;
+ }
+
+ RINOK(cryptoDecoderSpec->SetDecoderProps(item.Extra + (unsigned)cryptoOffset, cryptoSize, true, item.IsService()));
+
+ if (!getTextPassword)
+ {
+ wrongPassword = True;
+ return E_NOTIMPL;
+ }
+
+ RINOK(MySetPassword(getTextPassword, cryptoDecoderSpec));
+
+ if (!cryptoDecoderSpec->CalcKey_and_CheckPassword())
+ wrongPassword = True;
+ }
+
+ return S_OK;
+}
+
+
+HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSize,
+ ISequentialInStream *volsInStream, ISequentialOutStream *realOutStream, ICompressProgressInfo *progress,
+ bool &isCrcOK)
+{
+ isCrcOK = true;
+
+ unsigned method = item.GetMethod();
+ if (method > kLzMethodMax)
+ return E_NOTIMPL;
+
+ if (linkFile && !lastItem.Is_UnknownSize())
+ {
+ size_t dataSize = (size_t)lastItem.Size;
+ if (dataSize != lastItem.Size)
+ return E_NOTIMPL;
+ linkFile->Data.Alloc(dataSize);
+ }
+
+ bool isCryptoMode = false;
+ ISequentialInStream *inStream;
+
+ if (item.IsEncrypted())
+ {
+ filterStreamSpec->Filter = cryptoDecoder;
+ filterStreamSpec->SetInStream(volsInStream);
+ filterStreamSpec->SetOutStreamSize(NULL);
+ inStream = filterStream;
+ isCryptoMode = true;
+ }
+ else
+ inStream = volsInStream;
+
+ ICompressCoder *commonCoder = (method == 0) ? copyCoder : LzCoders[item.IsService() ? 1 : 0];
+
+ outStreamSpec->SetStream(realOutStream);
+ outStreamSpec->Init(lastItem, (linkFile ? (Byte *)linkFile->Data : NULL));
+
+ NeedClearSolid[item.IsService() ? 1 : 0] = false;
+
+ HRESULT res = S_OK;
+ if (packSize != 0 || lastItem.Is_UnknownSize() || lastItem.Size != 0)
+ {
+ res = commonCoder->Code(inStream, outStream, &packSize,
+ lastItem.Is_UnknownSize() ? NULL : &lastItem.Size, progress);
+ }
+ else
+ {
+ res = res;
+ }
+
+ if (isCryptoMode)
+ filterStreamSpec->ReleaseInStream();
+
+ UInt64 processedSize = outStreamSpec->GetPos();
+ if (res == S_OK && !lastItem.Is_UnknownSize() && processedSize != lastItem.Size)
+ res = S_FALSE;
+
+ // if (res == S_OK)
+ {
+ unsigned cryptoSize = 0;
+ int cryptoOffset = lastItem.FindExtra(NExtraRecordType::kCrypto, cryptoSize);
+ NCrypto::NRar5::CDecoder *crypto = NULL;
+
+ if (cryptoOffset >= 0)
+ {
+ CCryptoInfo cryptoInfo;
+ if (cryptoInfo.Parse(lastItem.Extra + (unsigned)cryptoOffset, cryptoSize))
+ if (cryptoInfo.UseMAC())
+ crypto = cryptoDecoderSpec;
+ }
+
+ isCrcOK = outStreamSpec->_hash.Check(lastItem, crypto);
+ }
+
+ if (linkFile)
+ {
+ linkFile->Res = res;
+ linkFile->crcOK = isCrcOK;
+ if (!lastItem.Is_UnknownSize() && processedSize != lastItem.Size)
+ linkFile->Data.ChangeSize_KeepData((size_t)processedSize, (size_t)processedSize);
+ }
+
+ return res;
+}
+
+
+HRESULT CUnpacker::DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, UInt64 packSize, ISequentialInStream *inStream, CByteBuffer &buffer)
+{
+ CBufPtrSeqOutStream *outSpec = new CBufPtrSeqOutStream;
+ CMyComPtr<ISequentialOutStream> out = outSpec;
+ _tempBuf.AllocAtLeast((size_t)item.Size);
+ outSpec->Init(_tempBuf, (size_t)item.Size);
+
+ bool wrongPassword;
+
+ if (item.IsSolid())
+ return E_NOTIMPL;
+
+ HRESULT res = Create(EXTERNAL_CODECS_LOC_VARS item, item.IsSolid(), wrongPassword);
+
+ if (res == S_OK)
+ {
+ if (wrongPassword)
+ return S_FALSE;
+
+ CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> limitedStream(limitedStreamSpec);
+ limitedStreamSpec->SetStream(inStream);
+ limitedStreamSpec->Init(packSize);
+
+ bool crcOK = true;
+ res = Code(item, item, packSize, limitedStream, out, NULL, crcOK);
+ if (res == S_OK)
+ {
+ if (!crcOK || outSpec->GetPos() != item.Size)
+ res = S_FALSE;
+ else
+ buffer.CopyFrom(_tempBuf, (size_t)item.Size);
+ }
+ }
+
+ return res;
+}
+
+
+struct CTempBuf
+{
+ CByteBuffer _buf;
+ size_t _offset;
+ bool _isOK;
+
+ void Clear()
+ {
+ _offset = 0;
+ _isOK = true;
+ }
+
+ CTempBuf() { Clear(); }
+
+ HRESULT Decode(DECL_EXTERNAL_CODECS_LOC_VARS
+ const CItem &item,
+ ISequentialInStream *inStream, CUnpacker &unpacker, CByteBuffer &destBuf);
+};
+
+
+HRESULT CTempBuf::Decode(DECL_EXTERNAL_CODECS_LOC_VARS
+ const CItem &item,
+ ISequentialInStream *inStream,
+ CUnpacker &unpacker,
+ CByteBuffer &destBuf)
+{
+ const size_t kPackSize_Max = (1 << 24);
+ if (item.Size > (1 << 24)
+ || item.Size == 0
+ || item.PackSize >= kPackSize_Max)
+ {
+ Clear();
+ return S_OK;
+ }
+
+ if (item.IsSplit() /* && _isOK */)
+ {
+ size_t packSize = (size_t)item.PackSize;
+ if (packSize > kPackSize_Max - _offset)
+ return S_OK;
+ size_t newSize = _offset + packSize;
+ if (newSize > _buf.Size())
+ _buf.ChangeSize_KeepData(newSize, _offset);
+
+ Byte *data = (Byte *)_buf + _offset;
+ RINOK(ReadStream_FALSE(inStream, data, packSize));
+
+ _offset += packSize;
+
+ if (item.IsSplitAfter())
+ {
+ CHash hash;
+ hash.Init(item);
+ hash.Update(data, packSize);
+ _isOK = hash.Check(item, NULL); // RAR5 doesn't use HMAC for packed part
+ }
+ }
+
+ if (_isOK)
+ {
+ if (!item.IsSplitAfter())
+ {
+ if (_offset == 0)
+ {
+ RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_LOC_VARS
+ item, item.PackSize, inStream, destBuf));
+ }
+ else
+ {
+ CBufInStream *bufInStreamSpec = new CBufInStream;
+ CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec;
+ bufInStreamSpec->Init(_buf, _offset);
+ RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_LOC_VARS
+ item, _offset, bufInStream, destBuf));
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+static const Byte kProps[] =
+{
+ kpidPath,
+ kpidIsDir,
+ kpidSize,
+ kpidPackSize,
+ kpidMTime,
+ kpidCTime,
+ kpidATime,
+ kpidAttrib,
+
+ kpidIsAltStream,
+ kpidEncrypted,
+ kpidSolid,
+ kpidSplitBefore,
+ kpidSplitAfter,
+ kpidCRC,
+ kpidHostOS,
+ kpidMethod,
+
+ kpidSymLink,
+ kpidHardLink,
+ kpidCopyLink,
+};
+
+
+static const Byte kArcProps[] =
+{
+ kpidTotalPhySize,
+ kpidCharacts,
+ kpidSolid,
+ kpidNumBlocks,
+ kpidEncrypted,
+ kpidIsVolume,
+ kpidVolumeIndex,
+ kpidNumVolumes,
+ kpidComment
+};
+
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+
+UInt64 CHandler::GetPackSize(unsigned refIndex) const
+{
+ UInt64 size = 0;
+ unsigned index = _refs[refIndex].Item;
+ for (;;)
+ {
+ const CItem &item = _items[index];
+ size += item.PackSize;
+ if (item.NextItem < 0)
+ return size;
+ index = item.NextItem;
+ }
+}
+
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+
+ NCOM::CPropVariant prop;
+
+ const CInArcInfo *arcInfo = NULL;
+ if (!_arcs.IsEmpty())
+ arcInfo = &_arcs[0].Info;
+
+ switch (propID)
+ {
+ case kpidVolumeIndex: if (arcInfo && arcInfo->IsVolume()) prop = arcInfo->GetVolIndex(); break;
+ case kpidSolid: if (arcInfo) prop = arcInfo->IsSolid(); break;
+ case kpidCharacts:
+ {
+ if (!_arcs.IsEmpty())
+ {
+ FLAGS_TO_PROP(k_ArcFlags, (UInt32)arcInfo->Flags, prop);
+ }
+ break;
+ }
+ case kpidEncrypted: if (arcInfo) prop = arcInfo->IsEncrypted; break; // it's for encrypted names.
+ case kpidIsVolume: if (arcInfo) prop = arcInfo->IsVolume(); break;
+ case kpidNumVolumes: prop = (UInt32)_arcs.Size(); break;
+ case kpidOffset: if (arcInfo && arcInfo->StartPos != 0) prop = arcInfo->StartPos; break;
+
+ case kpidTotalPhySize:
+ {
+ if (_arcs.Size() > 1)
+ {
+ UInt64 sum = 0;
+ FOR_VECTOR (v, _arcs)
+ sum += _arcs[v].Info.GetPhySize();
+ prop = sum;
+ }
+ break;
+ }
+
+ case kpidPhySize:
+ {
+ if (arcInfo)
+ prop = arcInfo->GetPhySize();
+ break;
+ }
+
+ case kpidComment:
+ {
+ // if (!_arcs.IsEmpty())
+ {
+ // const CArc &arc = _arcs[0];
+ const CByteBuffer &cmt = _comment;
+ if (cmt.Size() != 0 && cmt.Size() < (1 << 16))
+ {
+ AString s;
+ s.SetFrom_CalcLen((const char *)(const Byte *)cmt, (unsigned)cmt.Size());
+ UString unicode;
+ if (ConvertUTF8ToUnicode(s, unicode))
+ prop = unicode;
+ }
+ }
+ break;
+ }
+
+ case kpidNumBlocks:
+ {
+ UInt32 numBlocks = 0;
+ FOR_VECTOR (i, _refs)
+ if (!_items[_refs[i].Item].IsSolid())
+ numBlocks++;
+ prop = (UInt32)numBlocks;
+ break;
+ }
+
+ case kpidErrorFlags:
+ {
+ UInt32 v = _errorFlags;
+ if (!_isArc)
+ v |= kpv_ErrorFlags_IsNotArc;
+ prop = v;
+ break;
+ }
+
+ /*
+ case kpidWarningFlags:
+ {
+ if (_warningFlags != 0)
+ prop = _warningFlags;
+ break;
+ }
+ */
+
+ case kpidExtension:
+ if (_arcs.Size() == 1)
+ {
+ if (arcInfo->IsVolume())
+ {
+ char sz[32];
+ ConvertUInt64ToString(arcInfo->GetVolIndex() + 1, sz);
+ unsigned len = MyStringLen(sz);
+ AString s = "part";
+ for (; len < 2; len++)
+ s += '0';
+ s += sz;
+ s += ".rar";
+ prop = s;
+ }
+ }
+ break;
+
+ case kpidIsAltStream: prop = true; break;
+ }
+
+ prop.Detach(value);
+ return S_OK;
+
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _refs.Size();
+ return S_OK;
+}
+
+
+static const Byte kRawProps[] =
+{
+ kpidChecksum,
+ kpidNtSecure
+};
+
+
+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::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType)
+{
+ *parentType = NParentType::kDir;
+ *parent = (UInt32)(Int32)-1;
+
+ if (index >= _refs.Size())
+ return S_OK;
+
+ const CRefItem &ref = _refs[index];
+ const CItem &item = _items[ref.Item];
+
+ if (item.Is_STM() && ref.Parent >= 0)
+ {
+ *parent = (UInt32)ref.Parent;
+ *parentType = NParentType::kAltStream;
+ }
+
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
+{
+ *data = NULL;
+ *dataSize = 0;
+ *propType = 0;
+
+ if (index >= _refs.Size())
+ return E_INVALIDARG;
+
+ const CItem &item = _items[_refs[index].Item];
+
+ if (propID == kpidNtSecure)
+ {
+ if (item.ACL >= 0)
+ {
+ const CByteBuffer &buf = _acls[item.ACL];
+ *dataSize = (UInt32)buf.Size();
+ *propType = NPropDataType::kRaw;
+ *data = (const Byte *)buf;
+ }
+ return S_OK;
+ }
+
+ if (propID == kpidChecksum)
+ {
+ int hashRecOffset = item.FindExtra_Blake();
+ if (hashRecOffset >= 0)
+ {
+ *dataSize = BLAKE2S_DIGEST_SIZE;
+ *propType = NPropDataType::kRaw;
+ *data = &item.Extra[hashRecOffset];
+ }
+ return S_OK;
+ }
+
+ return S_OK;
+}
+
+
+static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CPropVariant &prop)
+{
+ unsigned size;
+ int offset = item.FindExtra(NExtraRecordType::kTime, size);
+ if (offset < 0)
+ return;
+
+ const Byte *p = item.Extra + (unsigned)offset;
+ UInt64 flags;
+ {
+ unsigned num = ReadVarInt(p, size, &flags);
+ if (num == 0)
+ return;
+ p += num;
+ size -= num;
+ }
+
+ if ((flags & (NTimeRecord::NFlags::kMTime << stampIndex)) == 0)
+ return;
+
+ unsigned numStamps = 0;
+ unsigned i;
+ for (i = 0; i < 3; i++)
+ if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0)
+ numStamps++;
+ unsigned stampSizeLog = ((flags & NTimeRecord::NFlags::kUnixTime) != 0) ? 2 : 3;
+
+ if ((numStamps << stampSizeLog) != size)
+ return;
+
+ numStamps = 0;
+ for (i = 0; i < stampIndex; i++)
+ if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0)
+ numStamps++;
+
+ p += (numStamps << stampSizeLog);
+
+ FILETIME ft;
+ if ((flags & NTimeRecord::NFlags::kUnixTime) != 0)
+ NWindows::NTime::UnixTimeToFileTime(Get32(p), ft);
+ else
+ {
+ ft.dwLowDateTime = Get32(p);
+ ft.dwHighDateTime = Get32(p + 4);
+ }
+
+ prop = ft;
+}
+
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+
+ NCOM::CPropVariant prop;
+ const CRefItem &ref = _refs[index];
+ const CItem &item = _items[ref.Item];
+ const CItem &lastItem = _items[ref.Last];
+
+ switch (propID)
+ {
+ case kpidPath:
+ {
+ UString unicodeName;
+
+ if (item.Is_STM())
+ {
+ AString s;
+ if (ref.Parent >= 0)
+ {
+ CItem &mainItem = _items[_refs[ref.Parent].Item];
+ s = mainItem.Name;
+ }
+
+ AString name;
+ item.GetAltStreamName(name);
+ if (name[0] != ':')
+ s += ':';
+ s += name;
+ if (!ConvertUTF8ToUnicode(s, unicodeName))
+ break;
+ }
+ else
+ {
+ if (!ConvertUTF8ToUnicode(item.Name, unicodeName))
+ break;
+ if (item.Version_Defined)
+ {
+ wchar_t temp[32];
+ // temp[0] = ';';
+ // ConvertUInt64ToString(item.Version, temp + 1);
+ // unicodeName += temp;
+ ConvertUInt64ToString(item.Version, temp);
+ UString s2 = L"[VER]" WSTRING_PATH_SEPARATOR;
+ s2 += temp;
+ s2.Add_PathSepar();
+ unicodeName.Insert(0, s2);
+ }
+ }
+
+ NItemName::ConvertToOSName2(unicodeName);
+ prop = unicodeName;
+
+ break;
+ }
+
+ case kpidIsDir: prop = item.IsDir(); break;
+ case kpidSize: if (!lastItem.Is_UnknownSize()) prop = lastItem.Size; break;
+ case kpidPackSize: prop = GetPackSize(index); break;
+
+ case kpidMTime:
+ {
+ TimeRecordToProp(item, NTimeRecord::k_Index_MTime, prop);
+ if (prop.vt == VT_EMPTY && item.Has_UnixMTime())
+ {
+ FILETIME ft;
+ NWindows::NTime::UnixTimeToFileTime(item.UnixMTime, ft);
+ prop = ft;
+ }
+ if (prop.vt == VT_EMPTY && ref.Parent >= 0)
+ {
+ const CItem &baseItem = _items[_refs[ref.Parent].Item];
+ TimeRecordToProp(baseItem, NTimeRecord::k_Index_MTime, prop);
+ if (prop.vt == VT_EMPTY && baseItem.Has_UnixMTime())
+ {
+ FILETIME ft;
+ NWindows::NTime::UnixTimeToFileTime(baseItem.UnixMTime, ft);
+ prop = ft;
+ }
+ }
+ break;
+ }
+ case kpidCTime: TimeRecordToProp(item, NTimeRecord::k_Index_CTime, prop); break;
+ case kpidATime: TimeRecordToProp(item, NTimeRecord::k_Index_ATime, prop); break;
+
+ case kpidName:
+ {
+ if (item.Is_STM())
+ {
+ AString name;
+ item.GetAltStreamName(name);
+ if (name[0] == ':')
+ {
+ name.DeleteFrontal(1);
+ UString unicodeName;
+ if (ConvertUTF8ToUnicode(name, unicodeName))
+ prop = unicodeName;
+ }
+ }
+ break;
+ }
+
+ case kpidIsAltStream: prop = item.Is_STM(); break;
+
+ case kpidSymLink: item.Link_to_Prop(NLinkType::kUnixSymLink, prop); break;
+ case kpidHardLink: item.Link_to_Prop(NLinkType::kHardLink, prop); break;
+ case kpidCopyLink: item.Link_to_Prop(NLinkType::kFileCopy, prop); break;
+
+ case kpidAttrib: prop = item.GetWinAttrib(); break;
+ case kpidEncrypted: prop = item.IsEncrypted(); break;
+ case kpidSolid: prop = item.IsSolid(); break;
+
+ case kpidSplitBefore: prop = item.IsSplitBefore(); break;
+ case kpidSplitAfter: prop = lastItem.IsSplitAfter(); break;
+ case kpidCRC:
+ {
+ const CItem *item2 = (lastItem.IsSplitAfter() ? &item : &lastItem);
+ if (item2->Has_CRC())
+ prop = item2->CRC;
+ break;
+ }
+
+ case kpidMethod:
+ {
+ char temp[64];
+ unsigned algo = item.GetAlgoVersion();
+ char *s = temp;
+ if (algo != 0)
+ {
+ ConvertUInt32ToString(algo, s);
+ s += MyStringLen(s);
+ *s++ = ':';
+ }
+ unsigned m = item.GetMethod();
+ {
+ s[0] = 'm';
+ s[1] = (char)(m + '0');
+ s[2] = 0;
+ if (!item.IsDir())
+ {
+ s[2] = ':';
+ ConvertUInt32ToString(item.GetDictSize() + 17, s + 3);
+ }
+ }
+
+ unsigned cryptoSize = 0;
+ int cryptoOffset = item.FindExtra(NExtraRecordType::kCrypto, cryptoSize);
+ if (cryptoOffset >= 0)
+ {
+ s = temp + strlen(temp);
+ *s++ = ' ';
+ strcpy(s, "AES:");
+ CCryptoInfo cryptoInfo;
+ if (cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize))
+ {
+ s += strlen(s);
+ ConvertUInt32ToString(cryptoInfo.Cnt, s);
+ s += strlen(s);
+ *s++ = ':';
+ ConvertUInt64ToString(cryptoInfo.Flags, s);
+ }
+ }
+
+ prop = temp;
+ break;
+ }
+
+ case kpidHostOS:
+ if (item.HostOS < ARRAY_SIZE(kHostOS))
+ prop = kHostOS[(size_t)item.HostOS];
+ else
+ prop = (UInt64)item.HostOS;
+ break;
+ }
+
+ prop.Detach(value);
+ return S_OK;
+
+ COM_TRY_END
+}
+
+
+
+// ---------- Copy Links ----------
+
+static int CompareItemsPaths(const CHandler &handler, unsigned p1, unsigned p2, const AString *name1)
+{
+ const CItem &item1 = handler._items[handler._refs[p1].Item];
+ const CItem &item2 = handler._items[handler._refs[p2].Item];
+
+ if (item1.Version_Defined)
+ {
+ if (!item2.Version_Defined)
+ return -1;
+ int res = MyCompare(item1.Version, item2.Version);
+ if (res != 0)
+ return res;
+ }
+ else if (item2.Version_Defined)
+ return 1;
+
+ if (!name1)
+ name1 = &item1.Name;
+ return strcmp(*name1, item2.Name);
+}
+
+static int CompareItemsPaths2(const CHandler &handler, unsigned p1, unsigned p2, const AString *name1)
+{
+ int res = CompareItemsPaths(handler, p1, p2, name1);
+ if (res != 0)
+ return res;
+ return MyCompare(p1, p2);
+}
+
+static int CompareItemsPaths_Sort(const unsigned *p1, const unsigned *p2, void *param)
+{
+ return CompareItemsPaths2(*(const CHandler *)param, *p1, *p2, NULL);
+}
+
+static int FindLink(const CHandler &handler, const CUIntVector &sorted,
+ const AString &s, unsigned index)
+{
+ unsigned left = 0, right = sorted.Size();
+ for (;;)
+ {
+ if (left == right)
+ {
+ if (left > 0)
+ {
+ unsigned refIndex = sorted[left - 1];
+ if (CompareItemsPaths(handler, index, refIndex, &s) == 0)
+ return refIndex;
+ }
+ if (right < sorted.Size())
+ {
+ unsigned refIndex = sorted[right];
+ if (CompareItemsPaths(handler, index, refIndex, &s) == 0)
+ return refIndex;
+ }
+ return -1;
+ }
+
+ unsigned mid = (left + right) / 2;
+ unsigned refIndex = sorted[mid];
+ int compare = CompareItemsPaths2(handler, index, refIndex, &s);
+ if (compare == 0)
+ return refIndex;
+ if (compare < 0)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+}
+
+void CHandler::FillLinks()
+{
+ unsigned i;
+
+ for (i = 0; i < _refs.Size(); i++)
+ {
+ const CItem &item = _items[_refs[i].Item];
+ if (!item.IsDir() && !item.IsService() && item.NeedUse_as_CopyLink())
+ break;
+ }
+
+ if (i == _refs.Size())
+ return;
+
+ CUIntVector sorted;
+ for (i = 0; i < _refs.Size(); i++)
+ {
+ const CItem &item = _items[_refs[i].Item];
+ if (!item.IsDir() && !item.IsService())
+ sorted.Add(i);
+ }
+
+ if (sorted.IsEmpty())
+ return;
+
+ sorted.Sort(CompareItemsPaths_Sort, (void *)this);
+
+ AString link;
+
+ for (i = 0; i < _refs.Size(); i++)
+ {
+ CRefItem &ref = _refs[i];
+ const CItem &item = _items[ref.Item];
+ if (item.IsDir() || item.IsService() || item.PackSize != 0)
+ continue;
+ CItem::CLinkInfo linkInfo;
+ if (!item.FindExtra_Link(linkInfo) || linkInfo.Type != NLinkType::kFileCopy)
+ continue;
+ link.SetFrom_CalcLen((const char *)(item.Extra + linkInfo.NameOffset), linkInfo.NameLen);
+ int linkIndex = FindLink(*this, sorted, link, i);
+ if (linkIndex < 0)
+ continue;
+ if ((unsigned)linkIndex >= i)
+ continue; // we don't support forward links that can lead to loops
+ const CRefItem &linkRef = _refs[linkIndex];
+ const CItem &linkItem = _items[linkRef.Item];
+ if (linkItem.Size == item.Size)
+ {
+ if (linkRef.Link >= 0)
+ ref.Link = linkRef.Link;
+ else if (!linkItem.NeedUse_as_CopyLink())
+ ref.Link = linkIndex;
+ }
+ }
+}
+
+
+
+HRESULT CHandler::Open2(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openCallback)
+{
+ CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+
+ NRar::CVolumeName seqName;
+
+ UInt64 totalBytes = 0;
+ UInt64 curBytes = 0;
+
+ if (openCallback)
+ {
+ openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
+ openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
+ }
+
+ CTempBuf tempBuf;
+
+ CUnpacker unpacker;
+ unpacker.getTextPassword = getTextPassword;
+
+ int prevSplitFile = -1;
+ int prevMainFile = -1;
+
+ CInArchive arch;
+
+ for (;;)
+ {
+ CMyComPtr<IInStream> inStream;
+
+ if (_arcs.IsEmpty())
+ inStream = stream;
+ else
+ {
+ if (!openVolumeCallback)
+ break;
+
+ if (_arcs.Size() == 1)
+ {
+ UString baseName;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
+ if (prop.vt != VT_BSTR)
+ break;
+ baseName = prop.bstrVal;
+ }
+ if (!seqName.InitName(baseName))
+ break;
+ }
+
+ HRESULT result = openVolumeCallback->GetStream(seqName.GetNextName(), &inStream);
+ if (result == S_FALSE)
+ break;
+ if (result != S_OK)
+ return result;
+ if (!inStream)
+ break;
+ }
+
+ UInt64 endPos = 0;
+ RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &arch.StreamStartPosition));
+ RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));
+ RINOK(inStream->Seek(arch.StreamStartPosition, STREAM_SEEK_SET, NULL));
+
+ if (openCallback)
+ {
+ totalBytes += endPos;
+ RINOK(openCallback->SetTotal(NULL, &totalBytes));
+ }
+
+ CInArcInfo arcInfoOpen;
+ HRESULT res = arch.Open(inStream, maxCheckStartPosition, getTextPassword, arcInfoOpen);
+ if (arch.IsArc && arch.UnexpectedEnd)
+ _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
+ if (_arcs.IsEmpty())
+ {
+ _isArc = arch.IsArc;
+ }
+
+ if (res != S_OK)
+ {
+ if (res != S_FALSE)
+ return res;
+ if (_arcs.IsEmpty())
+ return res;
+ break;
+ }
+
+ CArc &arc = _arcs.AddNew();
+ CInArcInfo &arcInfo = arc.Info;
+ arcInfo = arcInfoOpen;
+ arc.Stream = inStream;
+
+ CItem item;
+
+ for (;;)
+ {
+ item.Clear();
+
+ arcInfo.EndPos = arch.Position;
+
+ if (arch.Position > endPos)
+ {
+ _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
+ break;
+ }
+
+ RINOK(inStream->Seek(arch.Position, STREAM_SEEK_SET, NULL));
+
+ {
+ CInArchive::CHeader h;
+ HRESULT res = arch.ReadBlockHeader(h);
+ if (res != S_OK)
+ {
+ if (res != S_FALSE)
+ return res;
+ if (arch.UnexpectedEnd)
+ {
+ _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;
+ if (arcInfo.EndPos < arch.Position)
+ arcInfo.EndPos = arch.Position;
+ if (arcInfo.EndPos < endPos)
+ arcInfo.EndPos = endPos;
+ }
+ else
+ _errorFlags |= kpv_ErrorFlags_HeadersError;
+ break;
+ }
+
+ if (h.Type == NHeaderType::kEndOfArc)
+ {
+ arcInfo.EndPos = arch.Position;
+ arcInfo.EndOfArchive_was_Read = true;
+ if (!arch.ReadVar(arcInfo.EndFlags))
+ _errorFlags |= kpv_ErrorFlags_HeadersError;
+ if (arcInfo.IsVolume())
+ {
+ // for multivolume archives RAR can add ZERO bytes at the end for alignment.
+ // We must skip these bytes to prevent phySize warning.
+ RINOK(inStream->Seek(arcInfo.EndPos, STREAM_SEEK_SET, NULL));
+ bool areThereNonZeros;
+ UInt64 numZeros;
+ const UInt64 maxSize = 1 << 12;
+ RINOK(NRar::ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize));
+ if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize)
+ arcInfo.EndPos += numZeros;
+ }
+ break;
+ }
+
+ if (h.Type != NHeaderType::kFile &&
+ h.Type != NHeaderType::kService)
+ {
+ _errorFlags |= kpv_ErrorFlags_UnsupportedFeature;
+ break;
+ }
+
+ item.RecordType = (Byte)h.Type;
+
+ if (!arch.ReadFileHeader(h, item))
+ {
+ _errorFlags |= kpv_ErrorFlags_HeadersError;
+ break;
+ }
+
+ // item.MainPartSize = (UInt32)(Position - item.Position);
+ item.DataPos = arch.Position;
+ }
+
+ bool isOk_packSize = true;
+ {
+ arcInfo.EndPos = arch.Position;
+ if (arch.Position + item.PackSize < arch.Position)
+ {
+ isOk_packSize = false;
+ _errorFlags |= kpv_ErrorFlags_HeadersError;
+ if (arcInfo.EndPos < endPos)
+ arcInfo.EndPos = endPos;
+ }
+ else
+ {
+ arch.AddToSeekValue(item.PackSize); // Position points to next header;
+ arcInfo.EndPos = arch.Position;
+ }
+ }
+
+ bool needAdd = true;
+
+ {
+ if (_comment.Size() == 0
+ && item.Is_CMT()
+ && item.PackSize < kCommentSize_Max
+ && item.PackSize == item.Size
+ && item.PackSize != 0
+ && item.GetMethod() == 0
+ && !item.IsSplit())
+ {
+ RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_VARS item, item.PackSize, inStream, _comment));
+ needAdd = false;
+ }
+ }
+
+ if (needAdd)
+ {
+ CRefItem ref;
+ ref.Item = _items.Size();
+ ref.Last = ref.Item;
+ ref.Parent = -1;
+ ref.Link = -1;
+
+ if (item.IsService())
+ {
+ if (item.Is_STM())
+ {
+ if (prevMainFile >= 0)
+ ref.Parent = prevMainFile;
+ }
+ else
+ {
+ needAdd = false;
+ if (item.Is_ACL() && (!item.IsEncrypted() || arch.m_CryptoMode))
+ {
+ if (prevMainFile >= 0 && item.Size < (1 << 24) && item.Size != 0)
+ {
+ CItem &mainItem = _items[_refs[prevMainFile].Item];
+
+ if (mainItem.ACL < 0)
+ {
+ CByteBuffer acl;
+ HRESULT res = tempBuf.Decode(EXTERNAL_CODECS_VARS item, inStream, unpacker, acl);
+ if (!item.IsSplitAfter())
+ tempBuf.Clear();
+ if (res != S_OK)
+ {
+ tempBuf.Clear();
+ if (res != S_FALSE && res != E_NOTIMPL)
+ return res;
+ }
+ // RINOK();
+
+ if (res == S_OK && acl.Size() != 0)
+ {
+ if (_acls.IsEmpty() || acl != _acls.Back())
+ _acls.Add(acl);
+ mainItem.ACL = _acls.Size() - 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (needAdd)
+ {
+ if (item.IsSplitBefore())
+ {
+ if (prevSplitFile >= 0)
+ {
+ CRefItem &ref = _refs[prevSplitFile];
+ CItem &prevItem = _items[ref.Last];
+ if (item.IsNextForItem(prevItem))
+ {
+ ref.Last = _items.Size();
+ prevItem.NextItem = ref.Last;
+ needAdd = false;
+ }
+ }
+ }
+ }
+
+ if (needAdd)
+ {
+ if (item.IsSplitAfter())
+ prevSplitFile = _refs.Size();
+ if (!item.IsService())
+ prevMainFile = _refs.Size();
+ _refs.Add(ref);
+ }
+ }
+
+ {
+ UInt64 version;
+ if (item.FindExtra_Version(version))
+ {
+ item.Version_Defined = true;
+ item.Version = version;
+ }
+ }
+
+ item.VolIndex = _arcs.Size() - 1;
+ _items.Add(item);
+
+ if (openCallback && (_items.Size() & 0xFF) == 0)
+ {
+ UInt64 numFiles = _items.Size();
+ UInt64 numBytes = curBytes + item.DataPos;
+ RINOK(openCallback->SetCompleted(&numFiles, &numBytes));
+ }
+
+ if (!isOk_packSize)
+ break;
+ }
+
+ curBytes += endPos;
+ if (!arcInfo.IsVolume())
+ break;
+ if (arcInfo.EndOfArchive_was_Read
+ && !arcInfo.AreMoreVolumes())
+ break;
+ }
+
+ FillLinks();
+
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openCallback)
+{
+ COM_TRY_BEGIN
+ Close();
+ return Open2(stream, maxCheckStartPosition, openCallback);
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ COM_TRY_BEGIN
+ _errorFlags = 0;
+ // _warningFlags = 0;
+ _isArc = false;
+ _refs.Clear();
+ _items.Clear();
+ _arcs.Clear();
+ _acls.Clear();
+ _comment.Free();
+ return S_OK;
+ COM_TRY_END
+}
+
+
+class CVolsInStream:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ UInt64 _rem;
+ ISequentialInStream *_stream;
+ const CObjectVector<CArc> *_arcs;
+ const CObjectVector<CItem> *_items;
+ int _itemIndex;
+public:
+ bool CrcIsOK;
+private:
+ CHash _hash;
+public:
+ MY_UNKNOWN_IMP
+ void Init(const CObjectVector<CArc> *arcs,
+ const CObjectVector<CItem> *items,
+ unsigned itemIndex)
+ {
+ _arcs = arcs;
+ _items = items;
+ _itemIndex = itemIndex;
+ _stream = NULL;
+ CrcIsOK = true;
+ }
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ UInt32 realProcessedSize = 0;
+
+ while (size != 0)
+ {
+ if (!_stream)
+ {
+ if (_itemIndex < 0)
+ break;
+ const CItem &item = (*_items)[_itemIndex];
+ IInStream *s = (*_arcs)[item.VolIndex].Stream;
+ RINOK(s->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
+ _stream = s;
+ if (CrcIsOK && item.IsSplitAfter())
+ _hash.Init(item);
+ else
+ _hash.Init_NoCalc();
+ _rem = item.PackSize;
+ }
+ {
+ UInt32 cur = size;
+ if (cur > _rem)
+ cur = (UInt32)_rem;
+ UInt32 num = cur;
+ HRESULT res = _stream->Read(data, cur, &cur);
+ _hash.Update(data, cur);
+ realProcessedSize += cur;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ data = (Byte *)data + cur;
+ size -= cur;
+ _rem -= cur;
+ if (_rem == 0)
+ {
+ const CItem &item = (*_items)[_itemIndex];
+ _itemIndex = item.NextItem;
+ if (!_hash.Check(item, NULL)) // RAR doesn't use MAC here
+ CrcIsOK = false;
+ _stream = NULL;
+ }
+ if (res != S_OK)
+ return res;
+ if (realProcessedSize != 0)
+ return S_OK;
+ if (cur == 0 && num != 0)
+ return S_OK;
+ }
+ }
+
+ return S_OK;
+}
+
+
+static int FindLinkBuf(CObjectVector<CLinkFile> &linkFiles, unsigned index)
+{
+ unsigned left = 0, right = linkFiles.Size();
+ for (;;)
+ {
+ if (left == right)
+ return -1;
+ unsigned mid = (left + right) / 2;
+ unsigned linkIndex = linkFiles[mid].Index;
+ if (index == linkIndex)
+ return mid;
+ if (index < linkIndex)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+}
+
+
+static inline int DecoderRes_to_OpRes(HRESULT res, bool crcOK)
+{
+ if (res == E_NOTIMPL)
+ return NExtract::NOperationResult::kUnsupportedMethod;
+ // if (res == S_FALSE)
+ if (res != S_OK)
+ return NExtract::NOperationResult::kDataError;
+ return crcOK ?
+ NExtract::NOperationResult::kOK :
+ NExtract::NOperationResult::kCRCError;
+}
+
+
+static HRESULT CopyData_with_Progress(const Byte *data, size_t size,
+ ISequentialOutStream *outStream, ICompressProgressInfo *progress)
+{
+ size_t pos = 0;
+
+ while (pos < size)
+ {
+ const UInt32 kStepSize = ((UInt32)1 << 24);
+ UInt32 cur32;
+ {
+ size_t cur = size - pos;
+ if (cur > kStepSize)
+ cur = kStepSize;
+ cur32 = (UInt32)cur;
+ }
+ RINOK(outStream->Write(data + pos, cur32, &cur32));
+ if (cur32 == 0)
+ return E_FAIL;
+ pos += cur32;
+ if (progress)
+ {
+ UInt64 pos64 = pos;
+ RINOK(progress->SetRatioInfo(&pos64, &pos64));
+ }
+ }
+
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+
+ bool allFilesMode = (numItems == (UInt32)(Int32)-1);
+ if (allFilesMode)
+ numItems = _refs.Size();
+ if (numItems == 0)
+ return S_OK;
+
+ CByteArr extractStatuses(_refs.Size());
+ memset(extractStatuses, 0, _refs.Size());
+
+ // we don't want to use temp buffer for big link files.
+ const size_t k_CopyLinkFile_MaxSize = (size_t)1 << (28 + sizeof(size_t) / 2);
+
+ const Byte kStatus_Extract = 1 << 0;
+ const Byte kStatus_Skip = 1 << 1;
+ const Byte kStatus_Link = 1 << 2;
+
+ CObjectVector<CLinkFile> linkFiles;
+
+ {
+ UInt64 total = 0;
+ bool thereAreLinks = false;
+
+ {
+ unsigned solidLimit = 0;
+ for (UInt32 t = 0; t < numItems; t++)
+ {
+ unsigned index = allFilesMode ? t : indices[t];
+ const CRefItem &ref = _refs[index];
+ const CItem &item = _items[ref.Item];
+
+ extractStatuses[index] |= kStatus_Extract;
+ total += item.Size;
+
+ if (ref.Link >= 0)
+ {
+ if (!testMode)
+ {
+ if ((unsigned)ref.Link < index)
+ {
+ const CItem &linkItem = _items[_refs[(unsigned)ref.Link].Item];
+ if (linkItem.IsSolid() && linkItem.Size <= k_CopyLinkFile_MaxSize)
+ {
+ if (extractStatuses[(unsigned)ref.Link] == 0)
+ total += linkItem.Size;
+ extractStatuses[(unsigned)ref.Link] |= kStatus_Link;
+ thereAreLinks = true;
+ }
+ }
+ }
+ continue;
+ }
+
+ if (item.IsService())
+ continue;
+
+ if (item.IsSolid())
+ {
+ unsigned j = index;
+
+ while (j > solidLimit)
+ {
+ j--;
+ const CItem &item2 = _items[_refs[j].Item];
+ if (!item2.IsService())
+ {
+ if (extractStatuses[j] == 0)
+ total += item2.Size;
+ extractStatuses[j] |= kStatus_Skip;
+ if (!item2.IsSolid())
+ break;
+ }
+ }
+ }
+
+ solidLimit = index + 1;
+ }
+ }
+
+ if (thereAreLinks)
+ {
+ unsigned solidLimit = 0;
+
+ FOR_VECTOR(i, _refs)
+ {
+ if ((extractStatuses[i] & kStatus_Link) == 0)
+ continue;
+ const CItem &item = _items[_refs[i].Item];
+ /*
+ if (item.IsService())
+ continue;
+ */
+
+ CLinkFile &linkFile = linkFiles.AddNew();
+ linkFile.Index = i;
+
+ if (item.IsSolid())
+ {
+ unsigned j = i;
+
+ while (j > solidLimit)
+ {
+ j--;
+ const CItem &item2 = _items[_refs[j].Item];
+ if (!item2.IsService())
+ {
+ if (extractStatuses[j] != 0)
+ break;
+ extractStatuses[j] = kStatus_Skip;
+ total += item2.Size;
+ if (!item2.IsSolid())
+ break;
+ }
+ }
+ }
+
+ solidLimit = i + 1;
+ }
+
+ for (UInt32 t = 0; t < numItems; t++)
+ {
+ unsigned index = allFilesMode ? t : indices[t];
+ const CRefItem &ref = _refs[index];
+
+ int linkIndex = ref.Link;
+ if (linkIndex < 0 || (unsigned)linkIndex >= index)
+ continue;
+ const CItem &linkItem = _items[_refs[(unsigned)linkIndex].Item];
+ if (!linkItem.IsSolid() || linkItem.Size > k_CopyLinkFile_MaxSize)
+ continue;
+ int bufIndex = FindLinkBuf(linkFiles, linkIndex);
+ if (bufIndex < 0)
+ return E_FAIL;
+ linkFiles[bufIndex].NumLinks++;
+ }
+ }
+
+ RINOK(extractCallback->SetTotal(total));
+ }
+
+
+ UInt64 totalUnpacked = 0;
+ UInt64 totalPacked = 0;
+ UInt64 curUnpackSize = 0;
+ UInt64 curPackSize = 0;
+
+ CUnpacker unpacker;
+
+ CVolsInStream *volsInStreamSpec = new CVolsInStream;
+ CMyComPtr<ISequentialInStream> volsInStream = volsInStreamSpec;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+
+ // bool needClearSolid = true;
+
+ FOR_VECTOR(i, _refs)
+ {
+ if (extractStatuses[i] == 0)
+ continue;
+
+ totalUnpacked += curUnpackSize;
+ totalPacked += curPackSize;
+ lps->InSize = totalPacked;
+ lps->OutSize = totalUnpacked;
+ RINOK(lps->SetCur());
+
+ CMyComPtr<ISequentialOutStream> realOutStream;
+
+ Int32 askMode =
+ ((extractStatuses[i] & kStatus_Extract) != 0) ? (testMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract) :
+ NExtract::NAskMode::kSkip;
+
+ unpacker.linkFile = NULL;
+
+ if (((extractStatuses[i] & kStatus_Link) != 0))
+ {
+ int bufIndex = FindLinkBuf(linkFiles, i);
+ if (bufIndex < 0)
+ return E_FAIL;
+ unpacker.linkFile = &linkFiles[bufIndex];
+ }
+
+ UInt32 index = i;
+
+ const CRefItem *ref = &_refs[index];
+ const CItem *item = &_items[ref->Item];
+
+ curUnpackSize = item->Size;
+ curPackSize = GetPackSize(index);
+
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ bool isSolid;
+ {
+ bool &needClearSolid = unpacker.NeedClearSolid[item->IsService() ? 1 : 0];
+ isSolid = (item->IsSolid() && !needClearSolid);
+ if (item->IsService())
+ isSolid = false;
+ needClearSolid = !item->IsSolid();
+ }
+
+ if (item->IsDir())
+ {
+ RINOK(extractCallback->PrepareOperation(askMode));
+ RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ int index2 = ref->Link;
+
+ int bufIndex = -1;
+
+ if (index2 >= 0)
+ {
+ const CRefItem &ref2 = _refs[index2];
+ const CItem &item2 = _items[ref2.Item];
+ if (!item2.IsSolid())
+ {
+ item = &item2;
+ ref = &ref2;
+ curUnpackSize = item->Size;
+ curPackSize = GetPackSize(index2);
+ }
+ else if ((unsigned)index2 < index)
+ bufIndex = FindLinkBuf(linkFiles, index2);
+ }
+
+ if (!realOutStream)
+ {
+ if (testMode)
+ {
+ if (item->Is_CopyLink() && item->PackSize == 0)
+ {
+ RINOK(extractCallback->PrepareOperation(askMode));
+ RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+ continue;
+ }
+ }
+ else
+ {
+ if (item->IsService())
+ continue;
+
+ bool needDecode = false;
+
+ for (unsigned n = i + 1; n < _refs.Size(); n++)
+ {
+ const CItem &nextItem = _items[_refs[n].Item];
+ if (nextItem.IsService())
+ continue;
+ if (!nextItem.IsSolid())
+ break;
+ if (extractStatuses[i] != 0)
+ {
+ needDecode = true;
+ break;
+ }
+ }
+
+ if (!needDecode)
+ continue;
+
+ askMode = NExtract::NAskMode::kSkip;
+ }
+ }
+
+ RINOK(extractCallback->PrepareOperation(askMode));
+
+ if (bufIndex >= 0)
+ {
+ CLinkFile &linkFile = linkFiles[bufIndex];
+ if (linkFile.NumLinks == 0)
+ return E_FAIL;
+ if (realOutStream)
+ {
+ RINOK(CopyData_with_Progress(linkFile.Data, linkFile.Data.Size(), realOutStream, progress));
+ }
+ if (--linkFile.NumLinks == 0)
+ linkFile.Data.Free();
+ RINOK(extractCallback->SetOperationResult(DecoderRes_to_OpRes(linkFile.Res, linkFile.crcOK)));
+ continue;
+ }
+
+ if (item->Is_CopyLink() && item->PackSize == 0)
+ {
+ RINOK(extractCallback->SetOperationResult(
+ realOutStream ?
+ NExtract::NOperationResult::kUnsupportedMethod:
+ NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ volsInStreamSpec->Init(&_arcs, &_items, ref->Item);
+
+ UInt64 packSize = curPackSize;
+
+ if (item->IsEncrypted())
+ if (!unpacker.getTextPassword)
+ extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&unpacker.getTextPassword);
+
+ bool wrongPassword;
+ HRESULT result = unpacker.Create(EXTERNAL_CODECS_VARS *item, isSolid, wrongPassword);
+
+ if (wrongPassword)
+ {
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kWrongPassword));
+ continue;
+ }
+
+ bool crcOK = true;
+ if (result == S_OK)
+ result = unpacker.Code(*item, _items[ref->Last], packSize, volsInStream, realOutStream, progress, crcOK);
+ realOutStream.Release();
+ if (!volsInStreamSpec->CrcIsOK)
+ crcOK = false;
+
+ int opRes = crcOK ?
+ NExtract::NOperationResult::kOK:
+ NExtract::NOperationResult::kCRCError;
+
+ if (result != S_OK)
+ {
+ if (result == S_FALSE)
+ opRes = NExtract::NOperationResult::kDataError;
+ else if (result == E_NOTIMPL)
+ opRes = NExtract::NOperationResult::kUnsupportedMethod;
+ else
+ return result;
+ }
+
+ RINOK(extractCallback->SetOperationResult(opRes));
+ }
+
+ {
+ FOR_VECTOR(i, linkFiles)
+ if (linkFiles[i].NumLinks != 0)
+ return E_FAIL;
+ }
+
+ return S_OK;
+
+ COM_TRY_END
+}
+
+
+IMPL_ISetCompressCodecsInfo
+
+REGISTER_ARC_I(
+ "Rar5", "rar r00", 0, 0xCC,
+ kMarker,
+ 0,
+ NArcInfoFlags::kFindSignature,
+ NULL)
+
+}}
+
+
+class CBlake2spHasher:
+ public IHasher,
+ public CMyUnknownImp
+{
+ CBlake2sp _blake;
+ Byte mtDummy[1 << 7];
+
+public:
+ CBlake2spHasher() { Init(); }
+
+ MY_UNKNOWN_IMP
+ INTERFACE_IHasher(;)
+};
+
+STDMETHODIMP_(void) CBlake2spHasher::Init() throw()
+{
+ Blake2sp_Init(&_blake);
+}
+
+STDMETHODIMP_(void) CBlake2spHasher::Update(const void *data, UInt32 size) throw()
+{
+ Blake2sp_Update(&_blake, (const Byte *)data, size);
+}
+
+STDMETHODIMP_(void) CBlake2spHasher::Final(Byte *digest) throw()
+{
+ Blake2sp_Final(&_blake, digest);
+}
+
+REGISTER_HASHER(CBlake2spHasher, 0x202, "BLAKE2sp", BLAKE2S_DIGEST_SIZE)
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.h b/CPP/7zip/Archive/Rar/Rar5Handler.h
new file mode 100644
index 00000000..5eaf0075
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/Rar5Handler.h
@@ -0,0 +1,410 @@
+// Rar5Handler.h
+
+#ifndef __RAR5_HANDLER_H
+#define __RAR5_HANDLER_H
+
+#include "../../../../C/Blake2.h"
+
+#include "../../../Common/MyBuffer.h"
+
+#include "../../../Windows/PropVariant.h"
+
+#include "../../Common/CreateCoder.h"
+
+#include "../IArchive.h"
+
+namespace NArchive {
+namespace NRar5 {
+
+namespace NHeaderFlags
+{
+ const unsigned kExtra = 1 << 0;
+ const unsigned kData = 1 << 1;
+ // const unsigned kUnknown = 1 << 2;
+ const unsigned kPrevVol = 1 << 3;
+ const unsigned kNextVol = 1 << 4;
+ // const unsigned kIsChild = 1 << 5;
+ // const unsigned kPreserveChild = 1 << 6;
+}
+
+namespace NHeaderType
+{
+ enum
+ {
+ kArc = 1,
+ kFile,
+ kService,
+ kArcEncrypt,
+ kEndOfArc
+ };
+}
+
+namespace NArcFlags
+{
+ const unsigned kVol = 1 << 0;
+ const unsigned kVolNumber = 1 << 1;
+ const unsigned kSolid = 1 << 2;
+ // const unsigned kRecovery = 1 << 3;
+ // const unsigned kLocked = 1 << 4;
+}
+
+const unsigned kArcExtraRecordType_Locator = 1;
+
+namespace NLocatorFlags
+{
+ const unsigned kQuickOpen = 1 << 0;
+ const unsigned kRecovery = 1 << 1;
+}
+
+namespace NFileFlags
+{
+ const unsigned kIsDir = 1 << 0;
+ const unsigned kUnixTime = 1 << 1;
+ const unsigned kCrc32 = 1 << 2;
+ const unsigned kUnknownSize = 1 << 3;
+}
+
+namespace NMethodFlags
+{
+ // const unsigned kVersionMask = 0x3F;
+ const unsigned kSolid = 1 << 6;
+}
+
+namespace NArcEndFlags
+{
+ const unsigned kMoreVols = 1 << 0;
+}
+
+enum EHostOS
+{
+ kHost_Windows = 0,
+ kHost_Unix
+};
+
+
+
+// ---------- Extra ----------
+
+namespace NExtraRecordType
+{
+ enum
+ {
+ kCrypto = 1,
+ kHash,
+ kTime,
+ kVersion,
+ kLink,
+ kUnixOwner,
+ kSubdata
+ };
+}
+
+// const unsigned kCryptoAlgo_AES = 0;
+
+namespace NCryptoFlags
+{
+ const unsigned kPswCheck = 1 << 0;
+ const unsigned kUseMAC = 1 << 1;
+}
+
+struct CCryptoInfo
+{
+ UInt64 Algo;
+ UInt64 Flags;
+ Byte Cnt;
+
+ bool UseMAC() const { return (Flags & NCryptoFlags::kUseMAC) != 0; }
+ bool IsThereCheck() const { return (Flags & NCryptoFlags::kPswCheck) != 0; }
+ bool Parse(const Byte *p, size_t size);
+};
+
+const unsigned kHashID_Blake2sp = 0;
+
+namespace NTimeRecord
+{
+ enum
+ {
+ k_Index_MTime = 0,
+ k_Index_CTime,
+ k_Index_ATime
+ };
+
+ namespace NFlags
+ {
+ const unsigned kUnixTime = 1 << 0;
+ const unsigned kMTime = 1 << 1;
+ // const unsigned kCTime = 1 << 2;
+ // const unsigned kATime = 1 << 3;
+ }
+}
+
+namespace NLinkType
+{
+ enum
+ {
+ kUnixSymLink = 1,
+ kWinSymLink,
+ kWinJunction,
+ kHardLink,
+ kFileCopy
+ };
+}
+
+namespace NLinkFlags
+{
+ const unsigned kTargetIsDir = 1 << 0;
+}
+
+
+struct CItem
+{
+ UInt32 CommonFlags;
+ UInt32 Flags;
+
+ Byte RecordType;
+ bool Version_Defined;
+
+ int ACL;
+
+ AString Name;
+
+ int VolIndex;
+ int NextItem;
+
+ UInt32 UnixMTime;
+ UInt32 CRC;
+ UInt32 Attrib;
+ UInt32 Method;
+
+ CByteBuffer Extra;
+
+ UInt64 Size;
+ UInt64 PackSize;
+ UInt64 HostOS;
+
+ UInt64 DataPos;
+ UInt64 Version;
+
+ CItem() { Clear(); }
+
+ void Clear()
+ {
+ CommonFlags = 0;
+ Flags = 0;
+
+ VolIndex = 0;
+ NextItem = -1;
+
+ Version_Defined = false;
+ Version = 0;
+
+ Name.Empty();
+ Extra.Free();
+ ACL = -1;
+ }
+
+ bool IsSplitBefore() const { return (CommonFlags & NHeaderFlags::kPrevVol) != 0; }
+ bool IsSplitAfter() const { return (CommonFlags & NHeaderFlags::kNextVol) != 0; }
+ bool IsSplit() const { return (CommonFlags & (NHeaderFlags::kPrevVol | NHeaderFlags::kNextVol)) != 0; }
+
+ bool IsDir() const { return (Flags & NFileFlags::kIsDir) != 0; }
+ bool Has_UnixMTime() const { return (Flags & NFileFlags::kUnixTime) != 0; }
+ bool Has_CRC() const { return (Flags & NFileFlags::kCrc32) != 0; }
+ bool Is_UnknownSize() const { return (Flags & NFileFlags::kUnknownSize) != 0; }
+
+ bool IsNextForItem(const CItem &prev) const
+ {
+ return !IsDir() && !prev.IsDir() && IsSplitBefore() && prev.IsSplitAfter() && (Name == prev.Name);
+ // && false;
+ }
+
+ bool IsSolid() const { return ((UInt32)Method & NMethodFlags::kSolid) != 0; }
+ unsigned GetAlgoVersion() const { return (unsigned)Method & 0x3F; }
+ unsigned GetMethod() const { return ((unsigned)Method >> 7) & 0x7; }
+ UInt32 GetDictSize() const { return (((UInt32)Method >> 10) & 0xF); }
+
+ bool IsService() const { return RecordType == NHeaderType::kService; }
+
+ bool Is_STM() const { return IsService() && Name == "STM"; }
+ bool Is_CMT() const { return IsService() && Name == "CMT"; }
+ bool Is_ACL() const { return IsService() && Name == "ACL"; }
+ // bool Is_QO() const { return IsService() && Name == "QO"; }
+
+ int FindExtra(unsigned type, unsigned &recordDataSize) const;
+
+ bool IsEncrypted() const
+ {
+ unsigned size;
+ return FindExtra(NExtraRecordType::kCrypto, size) >= 0;
+ }
+
+ int FindExtra_Blake() const
+ {
+ unsigned size = 0;
+ int offset = FindExtra(NExtraRecordType::kHash, size);
+ if (offset >= 0
+ && size == BLAKE2S_DIGEST_SIZE + 1
+ && Extra[(unsigned)offset] == kHashID_Blake2sp)
+ return offset + 1;
+ return -1;
+ }
+
+ bool FindExtra_Version(UInt64 &version) const;
+
+ struct CLinkInfo
+ {
+ UInt64 Type;
+ UInt64 Flags;
+ unsigned NameOffset;
+ unsigned NameLen;
+ };
+
+ bool FindExtra_Link(CLinkInfo &link) const;
+ void Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const;
+ bool Is_CopyLink() const;
+
+ bool NeedUse_as_CopyLink() const { return PackSize == 0 && Is_CopyLink(); }
+
+ bool GetAltStreamName(AString &name) const;
+
+ UInt32 GetWinAttrib() const
+ {
+ UInt32 a;
+ switch (HostOS)
+ {
+ case kHost_Windows: a = Attrib; break;
+ case kHost_Unix: a = (Attrib << 16); break;
+ default: a = 0;
+ }
+ // if (IsDir()) a |= FILE_ATTRIBUTE_DIRECTORY;
+ return a;
+ }
+
+ UInt64 GetDataPosition() const { return DataPos; }
+};
+
+
+struct CInArcInfo
+{
+ UInt64 Flags;
+ UInt64 VolNumber;
+ UInt64 StartPos;
+ UInt64 EndPos;
+
+ UInt64 EndFlags;
+ bool EndOfArchive_was_Read;
+
+ bool IsEncrypted;
+
+ // CByteBuffer Extra;
+
+ /*
+ struct CLocator
+ {
+ UInt64 Flags;
+ UInt64 QuickOpen;
+ UInt64 Recovery;
+
+ bool Is_QuickOpen() const { return (Flags & NLocatorFlags::kQuickOpen) != 0; }
+ bool Is_Recovery() const { return (Flags & NLocatorFlags::kRecovery) != 0; }
+ };
+
+ int FindExtra(unsigned type, unsigned &recordDataSize) const;
+ bool FindExtra_Locator(CLocator &locator) const;
+ */
+
+ CInArcInfo():
+ Flags(0),
+ VolNumber(0),
+ StartPos(0),
+ EndPos(0),
+ EndFlags(0),
+ EndOfArchive_was_Read(false),
+ IsEncrypted(false)
+ {}
+
+ /*
+ void Clear()
+ {
+ Flags = 0;
+ VolNumber = 0;
+ StartPos = 0;
+ EndPos = 0;
+ EndFlags = 0;
+ EndOfArchive_was_Read = false;
+ Extra.Free();
+ }
+ */
+
+ UInt64 GetPhySize() const { return EndPos - StartPos; }
+
+ bool AreMoreVolumes() const { return (EndFlags & NArcEndFlags::kMoreVols) != 0; }
+
+ bool IsVolume() const { return (Flags & NArcFlags::kVol) != 0; }
+ bool IsSolid() const { return (Flags & NArcFlags::kSolid) != 0; }
+ bool Is_VolNumber_Defined() const { return (Flags & NArcFlags::kVolNumber) != 0; }
+
+ UInt64 GetVolIndex() const { return Is_VolNumber_Defined() ? VolNumber : 0; }
+};
+
+
+struct CRefItem
+{
+ unsigned Item;
+ unsigned Last;
+ int Parent;
+ int Link;
+};
+
+
+struct CArc
+{
+ CMyComPtr<IInStream> Stream;
+ CInArcInfo Info;
+};
+
+
+class CHandler:
+ public IInArchive,
+ public IArchiveGetRawProps,
+ PUBLIC_ISetCompressCodecsInfo
+ public CMyUnknownImp
+{
+public:
+ CRecordVector<CRefItem> _refs;
+ CObjectVector<CItem> _items;
+private:
+ CObjectVector<CArc> _arcs;
+ CObjectVector<CByteBuffer> _acls;
+
+ UInt32 _errorFlags;
+ // UInt32 _warningFlags;
+ bool _isArc;
+ CByteBuffer _comment;
+
+ DECL_EXTERNAL_CODECS_VARS
+
+ UInt64 GetPackSize(unsigned refIndex) const;
+
+ void FillLinks();
+
+ HRESULT Open2(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openCallback);
+
+public:
+ MY_QUERYINTERFACE_BEGIN2(IInArchive)
+ MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
+ QUERY_ENTRY_ISetCompressCodecsInfo
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ INTERFACE_IInArchive(;)
+ INTERFACE_IArchiveGetRawProps(;)
+
+ DECL_ISetCompressCodecsInfo
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp
index 516e5d7f..d6d894f4 100644
--- a/CPP/7zip/Archive/Rar/RarHandler.cpp
+++ b/CPP/7zip/Archive/Rar/RarHandler.cpp
@@ -30,6 +30,7 @@
#include "../Common/ItemNameUtils.h"
#include "../Common/OutStreamWithCRC.h"
+#include "RarVol.h"
#include "RarHandler.h"
using namespace NWindows;
@@ -44,6 +45,8 @@ namespace NRar {
static const Byte kMarker[NHeader::kMarkerSize] = SIGNATURE;
+const unsigned kPasswordLen_MAX = 127;
+
bool CItem::IgnoreItem() const
{
switch (HostOS)
@@ -131,7 +134,7 @@ class CInArchive
CByteBuffer _comment;
CByteBuffer m_FileHeaderData;
NHeader::NBlock::CBlock m_BlockHeader;
- NCrypto::NRar29::CDecoder *m_RarAESSpec;
+ NCrypto::NRar3::CDecoder *m_RarAESSpec;
CMyComPtr<ICompressFilter> m_RarAES;
CBuffer<Byte> m_DecryptedData;
Byte *m_DecryptedDataAligned;
@@ -362,6 +365,7 @@ static int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime)
_ttt_ .DosTime = Get32(p); p += 4; size -= 4; \
READ_TIME(_mask_, _ttt_); } \
+
bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
{
const Byte *pStart = p;
@@ -500,7 +504,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
}
if (!m_RarAES)
{
- m_RarAESSpec = new NCrypto::NRar29::CDecoder;
+ m_RarAESSpec = new NCrypto::NRar3::CDecoder;
m_RarAES = m_RarAESSpec;
}
m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld());
@@ -518,7 +522,10 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
unsigned len = 0;
if (password)
len = MyStringLen(password);
- CByteBuffer buffer(len * 2);
+ if (len > kPasswordLen_MAX)
+ len = kPasswordLen_MAX;
+
+ CByteArr buffer(len * 2);
for (unsigned i = 0; i < len; i++)
{
wchar_t c = password[i];
@@ -526,7 +533,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
}
- RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
+ m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2);
const UInt32 kDecryptedBufferSize = (1 << 12);
if (m_DecryptedData.Size() == 0)
@@ -990,121 +997,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END
}
-static bool IsDigit(wchar_t c)
-{
- return c >= L'0' && c <= L'9';
-}
-class CVolumeName
-{
- bool _first;
- bool _newStyle;
- UString _unchangedPart;
- UString _changedPart;
- UString _afterPart;
-public:
- CVolumeName(): _newStyle(true) {};
-
- bool InitName(const UString &name, bool newStyle)
- {
- _first = true;
- _newStyle = newStyle;
- int dotPos = name.ReverseFind_Dot();
- UString basePart = name;
-
- if (dotPos >= 0)
- {
- UString ext = name.Ptr(dotPos + 1);
- if (ext.IsEqualTo_Ascii_NoCase("rar"))
- {
- _afterPart = name.Ptr(dotPos);
- basePart = name.Left(dotPos);
- }
- else if (ext.IsEqualTo_Ascii_NoCase("exe"))
- {
- _afterPart.SetFromAscii(".rar");
- basePart = name.Left(dotPos);
- }
- else if (!_newStyle)
- {
- if (ext.IsEqualTo_Ascii_NoCase("000") ||
- ext.IsEqualTo_Ascii_NoCase("001") ||
- ext.IsEqualTo_Ascii_NoCase("r00") ||
- ext.IsEqualTo_Ascii_NoCase("r01"))
- {
- _afterPart.Empty();
- _first = false;
- _changedPart = ext;
- _unchangedPart = name.Left(dotPos + 1);
- return true;
- }
- }
- }
-
- if (!_newStyle)
- {
- _afterPart.Empty();
- _unchangedPart = basePart;
- _unchangedPart += L'.';
- _changedPart.SetFromAscii("r00");
- return true;
- }
-
- if (basePart.IsEmpty())
- return false;
- unsigned i = basePart.Len();
-
- do
- if (!IsDigit(basePart[i - 1]))
- break;
- while (--i);
-
- _unchangedPart = basePart.Left(i);
- _changedPart = basePart.Ptr(i);
- return true;
- }
-
- /*
- void MakeBeforeFirstName()
- {
- unsigned len = _changedPart.Len();
- _changedPart.Empty();
- for (unsigned i = 0; i < len; i++)
- _changedPart += L'0';
- }
- */
-
- UString GetNextName()
- {
- if (_newStyle || !_first)
- {
- unsigned i = _changedPart.Len();
- for (;;)
- {
- wchar_t c = _changedPart[--i];
- if (c == L'9')
- {
- c = L'0';
- _changedPart.ReplaceOneCharAtPos(i, c);
- if (i == 0)
- {
- _changedPart.InsertAtFront(L'1');
- break;
- }
- continue;
- }
- c++;
- _changedPart.ReplaceOneCharAtPos(i, c);
- break;
- }
- }
-
- _first = false;
- return _unchangedPart + _changedPart + _afterPart;
- }
-};
-
-static HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
+HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)
{
areThereNonZeros = false;
numZeros = 0;
@@ -1136,7 +1030,6 @@ HRESULT CHandler::Open2(IInStream *stream,
{
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
- CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openCallback;
CVolumeName seqName;
@@ -1145,8 +1038,8 @@ HRESULT CHandler::Open2(IInStream *stream,
if (openCallback)
{
- openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
- openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
+ openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
+ openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
}
CInArchive archive;
@@ -1363,108 +1256,91 @@ struct CMethodItem
};
-class CFolderInStream:
+class CVolsInStream:
public ISequentialInStream,
public CMyUnknownImp
{
-public:
- MY_UNKNOWN_IMP
-
- STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
-
-private:
- const CObjectVector<CArc> *_archives;
+ UInt64 _rem;
+ ISequentialInStream *_stream;
+ const CObjectVector<CArc> *_arcs;
const CObjectVector<CItem> *_items;
CRefItem _refItem;
unsigned _curIndex;
UInt32 _crc;
- bool _fileIsOpen;
- CMyComPtr<ISequentialInStream> _stream;
+ bool _calcCrc;
- HRESULT OpenStream();
- HRESULT CloseStream();
public:
- void Init(const CObjectVector<CArc> *archives,
- const CObjectVector<CItem> *items,
- const CRefItem &refItem);
-
- CRecordVector<UInt32> CRCs;
-};
-
-
-ISequentialInStream* CArc::CreateLimitedStream(UInt64 offset, UInt64 size) const
-{
- CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
- CMyComPtr<ISequentialInStream> inStream(streamSpec);
- Stream->Seek(offset, STREAM_SEEK_SET, NULL);
- streamSpec->SetStream(Stream);
- streamSpec->Init(size);
- return inStream.Detach();
-}
-
-void CFolderInStream::Init(
- const CObjectVector<CArc> *archives,
- const CObjectVector<CItem> *items,
- const CRefItem &refItem)
-{
- _archives = archives;
- _items = items;
- _refItem = refItem;
- _curIndex = 0;
- CRCs.Clear();
- _fileIsOpen = false;
-}
+ MY_UNKNOWN_IMP
-HRESULT CFolderInStream::OpenStream()
-{
- while (_curIndex < _refItem.NumItems)
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ void Init(const CObjectVector<CArc> *arcs,
+ const CObjectVector<CItem> *items,
+ const CRefItem &refItem)
{
- const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
- _stream.Attach((*_archives)[_refItem.VolumeIndex + _curIndex].
- CreateLimitedStream(item.GetDataPosition(), item.PackSize));
- _curIndex++;
- _fileIsOpen = true;
- _crc = CRC_INIT_VAL;
- return S_OK;
+ _arcs = arcs;
+ _items = items;
+ _refItem = refItem;
+ _curIndex = 0;
+ _stream = NULL;
+ CrcIsOK = true;
}
- return S_OK;
-}
-HRESULT CFolderInStream::CloseStream()
-{
- CRCs.Add(CRC_GET_DIGEST(_crc));
- _stream.Release();
- _fileIsOpen = false;
- return S_OK;
-}
+ bool CrcIsOK;
+};
-STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+
+STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
+ if (processedSize)
+ *processedSize = 0;
UInt32 realProcessedSize = 0;
- while ((_curIndex < _refItem.NumItems || _fileIsOpen) && size > 0)
+
+ while (size != 0)
{
- if (_fileIsOpen)
+ if (!_stream)
{
- UInt32 localProcessedSize;
- RINOK(_stream->Read(
- ((Byte *)data) + realProcessedSize, size, &localProcessedSize));
- _crc = CrcUpdate(_crc, ((Byte *)data) + realProcessedSize, localProcessedSize);
- if (localProcessedSize == 0)
- {
- RINOK(CloseStream());
- continue;
- }
- realProcessedSize += localProcessedSize;
- size -= localProcessedSize;
- break;
+ if (_curIndex >= _refItem.NumItems)
+ break;
+ const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
+ IInStream *s = (*_arcs)[_refItem.VolumeIndex + _curIndex].Stream;
+ RINOK(s->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
+ _stream = s;
+ _calcCrc = (CrcIsOK && item.IsSplitAfter());
+ _crc = CRC_INIT_VAL;
+ _rem = item.PackSize;
}
- else
{
- RINOK(OpenStream());
+ UInt32 cur = size;
+ if (cur > _rem)
+ cur = (UInt32)_rem;
+ UInt32 num = cur;
+ HRESULT res = _stream->Read(data, cur, &cur);
+ if (_calcCrc)
+ _crc = CrcUpdate(_crc, data, cur);
+ realProcessedSize += cur;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ data = (Byte *)data + cur;
+ size -= cur;
+ _rem -= cur;
+ if (_rem == 0)
+ {
+ const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
+ _curIndex++;
+ if (_calcCrc && CRC_GET_DIGEST(_crc) != item.FileCRC)
+ CrcIsOK = false;
+ _stream = NULL;
+ }
+ if (res != S_OK)
+ return res;
+ if (realProcessedSize != 0)
+ return S_OK;
+ if (cur == 0 && num != 0)
+ return S_OK;
}
}
- if (processedSize != 0)
- *processedSize = realProcessedSize;
+
return S_OK;
}
@@ -1526,13 +1402,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CFilterCoder *filterStreamSpec = new CFilterCoder(false);
CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
- NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;
+ NCrypto::NRar2::CDecoder *rar20CryptoDecoderSpec = NULL;
CMyComPtr<ICompressFilter> rar20CryptoDecoder;
- NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL;
- CMyComPtr<ICompressFilter> rar29CryptoDecoder;
+ NCrypto::NRar3::CDecoder *rar3CryptoDecoderSpec = NULL;
+ CMyComPtr<ICompressFilter> rar3CryptoDecoder;
- CFolderInStream *folderInStreamSpec = NULL;
- CMyComPtr<ISequentialInStream> folderInStream;
+ CVolsInStream *volsInStreamSpec = NULL;
+ CMyComPtr<ISequentialInStream> volsInStream;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
@@ -1602,26 +1478,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStreamSpec->Init();
realOutStream.Release();
- /*
- for (unsigned partIndex = 0; partIndex < 1; partIndex++)
- {
- CMyComPtr<ISequentialInStream> inStream;
-
- // item redefinition
- const CItem &item = _items[refItem.ItemIndex + partIndex];
-
- CInArchive &archive = _arcs[refItem.VolumeIndex + partIndex];
-
- inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(),
- item.PackSize));
- */
- if (!folderInStream)
+ if (!volsInStream)
{
- folderInStreamSpec = new CFolderInStream;
- folderInStream = folderInStreamSpec;
+ volsInStreamSpec = new CVolsInStream;
+ volsInStream = volsInStreamSpec;
}
- folderInStreamSpec->Init(&_arcs, &_items, refItem);
+ volsInStreamSpec->Init(&_arcs, &_items, refItem);
UInt64 packSize = currentPackSize;
@@ -1632,29 +1495,29 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (item.IsEncrypted())
{
- CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
+ // CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
if (item.UnPackVersion >= 29)
{
- if (!rar29CryptoDecoder)
+ if (!rar3CryptoDecoder)
{
- rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;
- rar29CryptoDecoder = rar29CryptoDecoderSpec;
+ rar3CryptoDecoderSpec = new NCrypto::NRar3::CDecoder;
+ rar3CryptoDecoder = rar3CryptoDecoderSpec;
}
- rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
+ rar3CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
/*
CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
- RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
+ RINOK(rar3CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
&cryptoProperties));
*/
- RINOK(rar29CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
- filterStreamSpec->Filter = rar29CryptoDecoder;
+ RINOK(rar3CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
+ filterStreamSpec->Filter = rar3CryptoDecoder;
}
else if (item.UnPackVersion >= 20)
{
if (!rar20CryptoDecoder)
{
- rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;
+ rar20CryptoDecoderSpec = new NCrypto::NRar2::CDecoder;
rar20CryptoDecoder = rar20CryptoDecoderSpec;
}
filterStreamSpec->Filter = rar20CryptoDecoder;
@@ -1666,49 +1529,66 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
continue;
}
- RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
+ // RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
if (!getTextPassword)
extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
- if (getTextPassword)
+
+ if (!getTextPassword)
+ {
+ outStream.Release();
+ RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
+ continue;
+ }
+
+ // if (getTextPassword)
{
CMyComBSTR password;
RINOK(getTextPassword->CryptoGetTextPassword(&password));
+
if (item.UnPackVersion >= 29)
{
- UString unicodePassword;
unsigned len = 0;
if (password)
len = MyStringLen(password);
- CByteBuffer buffer(len * 2);
+ if (len > kPasswordLen_MAX)
+ len = kPasswordLen_MAX;
+ CByteArr buffer(len * 2);
for (unsigned i = 0; i < len; i++)
{
wchar_t c = password[i];
((Byte *)buffer)[i * 2] = (Byte)c;
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
}
- RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
+ rar3CryptoDecoderSpec->SetPassword((const Byte *)buffer, len * 2);
}
else
{
AString oemPassword;
if (password)
- oemPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);
- RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len()));
+ {
+ UString unicode = (LPCOLESTR)password;
+ if (unicode.Len() > kPasswordLen_MAX)
+ unicode.DeleteFrom(kPasswordLen_MAX);
+ oemPassword = UnicodeStringToMultiByte(unicode, CP_OEMCP);
+ }
+ rar20CryptoDecoderSpec->SetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len());
}
}
+ /*
else
{
- RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
+ RINOK(cryptoSetPassword->CryptoSetPassword(NULL, 0));
}
+ */
- filterStreamSpec->SetInStream(folderInStream);
+ filterStreamSpec->SetInStream(volsInStream);
filterStreamSpec->SetOutStreamSize(NULL);
inStream = filterStream;
}
else
{
- inStream = folderInStream;
+ inStream = volsInStream;
}
CMyComPtr<ICompressCoder> commonCoder;
@@ -1766,7 +1646,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);
if (solidStart)
{
- isSolid = false;
+ isSolid = 0;
solidStart = false;
}
@@ -1786,46 +1666,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (item.IsEncrypted())
filterStreamSpec->ReleaseInStream();
- if (result == S_FALSE)
- {
- outStream.Release();
- RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));
- continue;
- }
- if (result != S_OK)
- return result;
+
+ const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
+ int opRes = (volsInStreamSpec->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ?
+ NExtract::NOperationResult::kOK:
+ NExtract::NOperationResult::kCRCError;
+ outStream.Release();
- /*
- if (refItem.NumItems == 1 &&
- !item.IsSplitBefore() && !item.IsSplitAfter())
- */
- {
- const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
- bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC;
- outStream.Release();
- RINOK(extractCallback->SetOperationResult(crcOK ?
- NExtract::NOperationResult::kOK:
- NExtract::NOperationResult::kCRCError));
- }
- /*
- else
+ if (result != S_OK)
{
- bool crcOK = true;
- for (unsigned partIndex = 0; partIndex < refItem.NumItems; partIndex++)
- {
- const CItem &item = _items[refItem.ItemIndex + partIndex];
- if (item.FileCRC != folderInStreamSpec->CRCs[partIndex])
- {
- crcOK = false;
- break;
- }
- }
- RINOK(extractCallback->SetOperationResult(crcOK ?
- NExtract::NOperationResult::kOK:
- NExtract::NOperationResult::kCRCError));
+ if (result == S_FALSE)
+ opRes = NExtract::NOperationResult::kDataError;
+ else if (result == E_NOTIMPL)
+ opRes = NExtract::NOperationResult::kUnsupportedMethod;
+ else
+ return result;
}
- */
+ RINOK(extractCallback->SetOperationResult(opRes));
}
+
return S_OK;
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/Rar/RarVol.h b/CPP/7zip/Archive/Rar/RarVol.h
new file mode 100644
index 00000000..d0f91de6
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/RarVol.h
@@ -0,0 +1,129 @@
+// RarVol.h
+
+#ifndef __ARCHIVE_RAR_VOL_H
+#define __ARCHIVE_RAR_VOL_H
+
+#include "../../../Common/StringConvert.h"
+
+#include "RarHeader.h"
+
+namespace NArchive {
+namespace NRar {
+
+inline bool IsDigit(wchar_t c)
+{
+ return c >= L'0' && c <= L'9';
+}
+
+class CVolumeName
+{
+ bool _first;
+ bool _newStyle;
+ UString _unchangedPart;
+ UString _changedPart;
+ UString _afterPart;
+public:
+ CVolumeName(): _newStyle(true) {};
+
+ bool InitName(const UString &name, bool newStyle = true)
+ {
+ _first = true;
+ _newStyle = newStyle;
+ int dotPos = name.ReverseFind_Dot();
+ UString basePart = name;
+
+ if (dotPos >= 0)
+ {
+ UString ext = name.Ptr(dotPos + 1);
+ if (ext.IsEqualTo_Ascii_NoCase("rar"))
+ {
+ _afterPart = name.Ptr(dotPos);
+ basePart = name.Left(dotPos);
+ }
+ else if (ext.IsEqualTo_Ascii_NoCase("exe"))
+ {
+ _afterPart.SetFromAscii(".rar");
+ basePart = name.Left(dotPos);
+ }
+ else if (!_newStyle)
+ {
+ if (ext.IsEqualTo_Ascii_NoCase("000") ||
+ ext.IsEqualTo_Ascii_NoCase("001") ||
+ ext.IsEqualTo_Ascii_NoCase("r00") ||
+ ext.IsEqualTo_Ascii_NoCase("r01"))
+ {
+ _afterPart.Empty();
+ _first = false;
+ _changedPart = ext;
+ _unchangedPart = name.Left(dotPos + 1);
+ return true;
+ }
+ }
+ }
+
+ if (!_newStyle)
+ {
+ _afterPart.Empty();
+ _unchangedPart = basePart;
+ _unchangedPart += L'.';
+ _changedPart.SetFromAscii("r00");
+ return true;
+ }
+
+ if (basePart.IsEmpty())
+ return false;
+ unsigned i = basePart.Len();
+
+ do
+ if (!IsDigit(basePart[i - 1]))
+ break;
+ while (--i);
+
+ _unchangedPart = basePart.Left(i);
+ _changedPart = basePart.Ptr(i);
+ return true;
+ }
+
+ /*
+ void MakeBeforeFirstName()
+ {
+ unsigned len = _changedPart.Len();
+ _changedPart.Empty();
+ for (unsigned i = 0; i < len; i++)
+ _changedPart += L'0';
+ }
+ */
+
+ UString GetNextName()
+ {
+ if (_newStyle || !_first)
+ {
+ unsigned i = _changedPart.Len();
+ for (;;)
+ {
+ wchar_t c = _changedPart[--i];
+ if (c == L'9')
+ {
+ c = L'0';
+ _changedPart.ReplaceOneCharAtPos(i, c);
+ if (i == 0)
+ {
+ _changedPart.InsertAtFront(L'1');
+ break;
+ }
+ continue;
+ }
+ c++;
+ _changedPart.ReplaceOneCharAtPos(i, c);
+ break;
+ }
+ }
+
+ _first = false;
+ return _unchangedPart + _changedPart + _afterPart;
+ }
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
index ae005ac5..8dd99869 100644
--- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
@@ -29,11 +29,13 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(index, propId, &prop));
+
if (prop.vt == VT_BSTR)
{
UString s = prop.bstrVal;
if (convertSlash)
s = NItemName::MakeLegalName(s);
+
if (codePage == CP_UTF8)
{
ConvertUnicodeToUTF8(s, res);
@@ -44,9 +46,11 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
}
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
+
return S_OK;
}
+
// sort old files with original order.
static int CompareUpdateItems(void *const *p1, void *const *p2, void *)
@@ -57,33 +61,39 @@ static int CompareUpdateItems(void *const *p1, void *const *p2, void *)
{
if (u2.NewProps)
return -1;
- return MyCompare(u1.IndexInArchive, u2.IndexInArchive);
+ return MyCompare(u1.IndexInArc, u2.IndexInArc);
}
if (!u2.NewProps)
return 1;
return MyCompare(u1.IndexInClient, u2.IndexInClient);
}
+
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *callback)
{
COM_TRY_BEGIN
+
if ((_stream && (_error != k_ErrorType_OK /* || _isSparse */)) || _seqStream)
return E_NOTIMPL;
CObjectVector<CUpdateItem> updateItems;
UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage);
+
for (UInt32 i = 0; i < numItems; i++)
{
CUpdateItem ui;
Int32 newData;
Int32 newProps;
- UInt32 indexInArchive;
+ UInt32 indexInArc;
+
if (!callback)
return E_FAIL;
- RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
+
+ RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc));
+
ui.NewProps = IntToBool(newProps);
ui.NewData = IntToBool(newData);
- ui.IndexInArchive = indexInArchive;
+ ui.IndexInArc = indexInArc;
ui.IndexInClient = i;
if (IntToBool(newProps))
@@ -109,6 +119,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
else
ui.Mode = prop.ulVal;
}
+
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidMTime, &prop));
@@ -119,6 +130,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
else
ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime);
}
+
RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, true));
if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/')
ui.Name += '/';
@@ -139,14 +151,18 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_INVALIDARG;
*/
}
+
updateItems.Add(ui);
}
+
if (_thereIsPaxExtendedHeader)
{
// we restore original order of files, if there is pax header block
updateItems.Sort(CompareUpdateItems, NULL);
}
+
return UpdateArchive(_stream, outStream, _items, updateItems, codePage, callback);
+
COM_TRY_END
}
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp
index 3adbdee9..0cdb30d1 100644
--- a/CPP/7zip/Archive/Tar/TarUpdate.cpp
+++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp
@@ -43,7 +43,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
if (ui.NewData)
complexity += ui.Size;
else
- complexity += inputItems[ui.IndexInArchive].GetFullSize();
+ complexity += inputItems[ui.IndexInArc].GetFullSize();
}
RINOK(updateCallback->SetTotal(complexity));
@@ -68,12 +68,14 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
const CUpdateItem &ui = updateItems[i];
CItem item;
+
if (ui.NewProps)
{
item.Mode = ui.Mode;
item.Name = ui.Name;
item.User = ui.User;
item.Group = ui.Group;
+
if (ui.IsDir)
{
item.LinkFlag = NFileHeader::NLinkFlag::kDirectory;
@@ -84,6 +86,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
item.LinkFlag = NFileHeader::NLinkFlag::kNormal;
item.PackSize = ui.Size;
}
+
item.MTime = ui.MTime;
item.DeviceMajorDefined = false;
item.DeviceMinorDefined = false;
@@ -92,7 +95,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
memcpy(item.Magic, NFileHeader::NMagic::kUsTar_00, 8);
}
else
- item = inputItems[ui.IndexInArchive];
+ item = inputItems[ui.IndexInArc];
AString symLink;
if (ui.NewData || ui.NewProps)
@@ -116,6 +119,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
CMyComPtr<ISequentialInStream> fileInStream;
bool needWrite = true;
+
if (!symLink.IsEmpty())
{
item.PackSize = 0;
@@ -124,6 +128,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
else
{
HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);
+
if (res == S_FALSE)
needWrite = false;
else
@@ -141,10 +146,17 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
if (getProps->GetProps(&size2, NULL, NULL, &mTime, NULL) == S_OK)
{
item.PackSize = size2;
+ item.Size = size2;
item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);;
}
}
}
+ else
+ {
+ item.PackSize = 0;
+ item.Size = 0;
+ }
+
{
AString hardLink;
RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, true));
@@ -183,13 +195,15 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
RINOK(outArchive.FillDataResidual(item.PackSize));
}
}
+
complexity += item.PackSize;
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
else
{
- const CItemEx &existItem = inputItems[ui.IndexInArchive];
+ const CItemEx &existItem = inputItems[ui.IndexInArc];
UInt64 size;
+
if (ui.NewProps)
{
// memcpy(item.Magic, NFileHeader::NMagic::kEmpty, 8);
@@ -225,12 +239,13 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL));
size = existItem.GetFullSize();
}
+
streamSpec->Init(size);
if (opCallback)
{
RINOK(opCallback->ReportOperation(
- NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArchive,
+ NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArc,
NUpdateNotifyOp::kReplicate))
}
@@ -242,6 +257,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
complexity += size;
}
}
+
lps->InSize = lps->OutSize = complexity;
RINOK(lps->SetCur());
return outArchive.WriteFinishHeader();
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h
index c2393416..b758635f 100644
--- a/CPP/7zip/Archive/Tar/TarUpdate.h
+++ b/CPP/7zip/Archive/Tar/TarUpdate.h
@@ -4,6 +4,7 @@
#define __TAR_UPDATE_H
#include "../IArchive.h"
+
#include "TarItem.h"
namespace NArchive {
@@ -11,10 +12,10 @@ namespace NTar {
struct CUpdateItem
{
- int IndexInArchive;
+ int IndexInArc;
int IndexInClient;
- Int64 MTime;
UInt64 Size;
+ Int64 MTime;
UInt32 Mode;
bool NewData;
bool NewProps;
@@ -22,6 +23,8 @@ struct CUpdateItem
AString Name;
AString User;
AString Group;
+
+ CUpdateItem(): Size(0), IsDir(false) {}
};
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp
index 7e89bf48..5ef3bdf9 100644
--- a/CPP/7zip/Archive/XarHandler.cpp
+++ b/CPP/7zip/Archive/XarHandler.cpp
@@ -358,15 +358,24 @@ HRESULT CHandler::Open2(IInStream *stream)
return S_FALSE;
UInt64 totalPackSize = 0;
+ unsigned numMainFiles = 0;
+
FOR_VECTOR(i, _files)
{
const CFile &file = _files[i];
file.UpdateTotalPackSize(totalPackSize);
if (file.Name == "Payload")
+ {
_mainSubfile = i;
+ numMainFiles++;
+ }
if (file.Name == "PackageInfo")
_is_pkg = true;
}
+
+ if (numMainFiles > 1)
+ _mainSubfile = -1;
+
_phySize = _dataStartPos + totalPackSize;
return S_OK;
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index f1c8b227..aa06c4f8 100644
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -207,7 +207,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
if (IntToBool(newData))
{
- UInt64 size;
+ UInt64 size = 0;
+ if (!ui.IsDir)
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidSize, &prop));
@@ -219,6 +220,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
largestSizeDefined = true;
}
ui.Size = size;
+
// ui.Size -= ui.Size / 2;
}
updateItems.Add(ui);
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
index 6f495305..3c466424 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.cpp
+++ b/CPP/7zip/Archive/Zip/ZipIn.cpp
@@ -591,6 +591,29 @@ static bool FlagsAreSame(const CItem &i1, const CItem &i2)
return ((i1.Flags & mask) == (i2.Flags & mask));
}
+// #ifdef _WIN32
+static bool AreEqualPaths_IgnoreSlashes(const char *s1, const char *s2)
+{
+ for (;;)
+ {
+ char c1 = *s1++;
+ char c2 = *s2++;
+ if (c1 == c2)
+ {
+ if (c1 == 0)
+ return true;
+ }
+ else
+ {
+ if (c1 == '\\') c1 = '/';
+ if (c2 == '\\') c2 = '/';
+ if (c1 != c2)
+ return false;
+ }
+ }
+}
+// #endif
+
static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
{
if (!FlagsAreSame(cdItem, localItem))
@@ -611,7 +634,30 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
return false;
*/
if (cdItem.Name != localItem.Name)
- return false;
+ {
+ // #ifdef _WIN32
+ // some xap files use backslash in central dir items.
+ // we can ignore such errors in windows, where all slashes are converted to backslashes
+ unsigned hostOs = cdItem.GetHostOS();
+
+ if (hostOs == NFileHeader::NHostOS::kFAT ||
+ hostOs == NFileHeader::NHostOS::kNTFS)
+ {
+ if (!AreEqualPaths_IgnoreSlashes(cdItem.Name, localItem.Name))
+ {
+ // pkzip 2.50 uses DOS encoding in central dir and WIN encoding in local header.
+ // so we ignore that error
+ if (hostOs != NFileHeader::NHostOS::kFAT
+ || cdItem.MadeByVersion.Version != 25)
+ return false;
+ }
+ }
+ /*
+ else
+ #endif
+ return false;
+ */
+ }
return true;
}
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index 9a9526cc..7d03056c 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -103,7 +103,8 @@ static void SetFileHeader(
item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;
item.Method = kMethodForDirectory;
item.PackSize = 0;
- item.Crc = 0; // test it
+ item.Size = 0;
+ item.Crc = 0;
}
}
diff --git a/CPP/7zip/Bundles/Fm/FM.dsp b/CPP/7zip/Bundles/Fm/FM.dsp
index dfb0bb47..057da977 100644
--- a/CPP/7zip/Bundles/Fm/FM.dsp
+++ b/CPP/7zip/Bundles/Fm/FM.dsp
@@ -332,14 +332,6 @@ SOURCE=..\..\Archive\7z\7zUpdate.h
# PROP Default_Filter ""
# Begin Source File
-SOURCE=..\..\Archive\Common\CoderMixer.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\Archive\Common\CoderMixer.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\Archive\Common\CoderMixer2.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak
index c2f415cf..a1221c61 100644
--- a/CPP/7zip/Bundles/Format7zF/Arc.mak
+++ b/CPP/7zip/Bundles/Format7zF/Arc.mak
@@ -141,6 +141,7 @@ NSIS_OBJS = \
RAR_OBJS = \
$O\RarHandler.obj \
+ $O\Rar5Handler.obj \
TAR_OBJS = \
$O\TarHandler.obj \
@@ -212,6 +213,7 @@ COMPRESS_OBJS = \
$O\Rar2Decoder.obj \
$O\Rar3Decoder.obj \
$O\Rar3Vm.obj \
+ $O\Rar5Decoder.obj \
$O\RarCodecsRegister.obj \
$O\ShrinkDecoder.obj \
$O\ZlibDecoder.obj \
@@ -222,11 +224,13 @@ CRYPTO_OBJS = \
$O\7zAes.obj \
$O\7zAesRegister.obj \
$O\HmacSha1.obj \
+ $O\HmacSha256.obj \
$O\MyAes.obj \
$O\MyAesReg.obj \
$O\Pbkdf2HmacSha1.obj \
$O\RandGen.obj \
$O\Rar20Crypto.obj \
+ $O\Rar5Aes.obj \
$O\RarAes.obj \
$O\WzAes.obj \
$O\ZipCrypto.obj \
@@ -239,6 +243,7 @@ C_OBJS = \
$O\Alloc.obj \
$O\Bcj2.obj \
$O\Bcj2Enc.obj \
+ $O\Blake2s.obj \
$O\Bra.obj \
$O\Bra86.obj \
$O\BraIA64.obj \
diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
index 82df284c..169d9f0e 100644
--- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp
+++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
@@ -243,6 +243,10 @@ SOURCE=..\..\..\Common\CrcReg.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\Defs.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\DynamicBuffer.h
# End Source File
# Begin Source File
@@ -452,6 +456,24 @@ SOURCE=..\..\Compress\Rar3Vm.h
# End Source File
# Begin Source File
+SOURCE=..\..\Compress\Rar5Decoder.cpp
+
+!IF "$(CFG)" == "7z - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "7z - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Rar5Decoder.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Compress\RarCodecsRegister.cpp
# End Source File
# End Group
@@ -821,6 +843,14 @@ SOURCE=..\..\Crypto\HmacSha1.h
# End Source File
# Begin Source File
+SOURCE=..\..\Crypto\HmacSha256.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\HmacSha256.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Crypto\MyAes.cpp
# End Source File
# Begin Source File
@@ -887,6 +917,14 @@ SOURCE=..\..\Crypto\Rar20Crypto.h
# End Source File
# Begin Source File
+SOURCE=..\..\Crypto\Rar5Aes.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\Rar5Aes.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Crypto\RarAes.cpp
# End Source File
# Begin Source File
@@ -1319,6 +1357,26 @@ SOURCE=..\..\..\..\C\Bcj2Enc.c
# End Source File
# Begin Source File
+SOURCE=..\..\..\..\C\Blake2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Blake2s.c
+
+!IF "$(CFG)" == "7z - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "7z - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\..\C\Bra.c
!IF "$(CFG)" == "7z - Win32 Release"
@@ -1874,6 +1932,14 @@ SOURCE=..\..\Archive\7z\7zUpdateItem.h
# PROP Default_Filter ""
# Begin Source File
+SOURCE=..\..\Archive\Rar\Rar5Handler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Rar\Rar5Handler.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Archive\Rar\RarHandler.cpp
# End Source File
# Begin Source File
@@ -1888,6 +1954,10 @@ SOURCE=..\..\Archive\Rar\RarHeader.h
SOURCE=..\..\Archive\Rar\RarItem.h
# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Rar\RarVol.h
+# End Source File
# End Group
# Begin Group "Cab"
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
index 5b64b524..0e8586e9 100644
--- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
+++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp
@@ -12,7 +12,7 @@
#define MY_SET_BINARY_MODE(file)
#endif
-// #include "../../../Common/MyWindows.h"
+#include "../../../Common/MyWindows.h"
#include "../../../Common/MyInitGuid.h"
#include "../../../../C/7zVersion.h"
diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
index 01089c5e..781f810c 100644
--- a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
+++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/CommandLineParser.h"
diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
index 611ef651..cd2584fd 100644
--- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
+++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/CommandLineParser.h"
diff --git a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
index ee57d445..c301ecf8 100644
--- a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
+++ b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include <Shlwapi.h>
#include "../../../Common/MyInitGuid.h"
diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h
index cde33c88..224ff2ca 100644
--- a/CPP/7zip/Common/FilterCoder.h
+++ b/CPP/7zip/Common/FilterCoder.h
@@ -19,7 +19,7 @@
struct CAlignedMidBuffer
{
- #ifndef _WIN32
+ #ifdef _WIN32
Byte *_buf;
diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp
index 2ea718e7..77665ae1 100644
--- a/CPP/7zip/Common/LimitedStreams.cpp
+++ b/CPP/7zip/Common/LimitedStreams.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include <string.h>
+
#include "LimitedStreams.h"
#include "../../Common/Defs.h"
diff --git a/CPP/7zip/Common/PropId.cpp b/CPP/7zip/Common/PropId.cpp
index 2ce6fd85..11d20d55 100644
--- a/CPP/7zip/Common/PropId.cpp
+++ b/CPP/7zip/Common/PropId.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../Common/MyWindows.h"
+
#include "../PropID.h"
// VARTYPE
@@ -101,5 +103,6 @@ const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =
VT_UI8,
VT_UI8,
VT_BOOL,
- VT_BSTR // kpidOutName
+ VT_BSTR,
+ VT_BSTR
};
diff --git a/CPP/7zip/Common/UniqBlocks.cpp b/CPP/7zip/Common/UniqBlocks.cpp
index a2cacdde..8f754e17 100644
--- a/CPP/7zip/Common/UniqBlocks.cpp
+++ b/CPP/7zip/Common/UniqBlocks.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include <string.h>
+
#include "UniqBlocks.h"
unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size)
diff --git a/CPP/7zip/Compress/Codec.def b/CPP/7zip/Compress/Codec.def
index ebf73a3b..f55b2d57 100644
--- a/CPP/7zip/Compress/Codec.def
+++ b/CPP/7zip/Compress/Codec.def
@@ -2,3 +2,5 @@ EXPORTS
CreateObject PRIVATE
GetNumberOfMethods PRIVATE
GetMethodProperty PRIVATE
+ CreateDecoder PRIVATE
+ CreateEncoder PRIVATE
diff --git a/CPP/7zip/Compress/DeflateEncoder.cpp b/CPP/7zip/Compress/DeflateEncoder.cpp
index eb012e8d..94d0092b 100644
--- a/CPP/7zip/Compress/DeflateEncoder.cpp
+++ b/CPP/7zip/Compress/DeflateEncoder.cpp
@@ -130,14 +130,14 @@ CCoder::CCoder(bool deflate64Mode):
m_Values(0),
m_Tables(0)
{
- {
- CEncProps props;
- SetProps(&props);
- }
m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32;
m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32;
m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32;
m_LenDirectBits = deflate64Mode ? kLenDirectBits64 : kLenDirectBits32;
+ {
+ CEncProps props;
+ SetProps(&props);
+ }
MatchFinder_Construct(&_lzInWindow);
}
diff --git a/CPP/7zip/Compress/HuffmanDecoder.h b/CPP/7zip/Compress/HuffmanDecoder.h
index 6faf8005..65e0f93c 100644
--- a/CPP/7zip/Compress/HuffmanDecoder.h
+++ b/CPP/7zip/Compress/HuffmanDecoder.h
@@ -22,11 +22,13 @@ public:
bool SetCodeLengths(const Byte *lens)
{
- unsigned lenCounts[kNumBitsMax + 1];
+ UInt32 lenCounts[kNumBitsMax + 1];
UInt32 tmpPositions[kNumBitsMax + 1];
+
unsigned i;
for (i = 1; i <= kNumBitsMax; i++)
lenCounts[i] = 0;
+
UInt32 symbol;
for (symbol = 0; symbol < m_NumSymbols; symbol++)
@@ -42,7 +44,7 @@ public:
m_Positions[0] = m_Limits[0] = 0;
UInt32 startPos = 0;
UInt32 index = 0;
- const UInt32 kMaxValue = (1 << kNumBitsMax);
+ const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax;
for (i = 1; i <= kNumBitsMax; i++)
{
@@ -74,14 +76,15 @@ public:
UInt32 DecodeSymbol(TBitDecoder *bitStream)
{
unsigned numBits;
- UInt32 value = bitStream->GetValue(kNumBitsMax);
- if (value < m_Limits[kNumTableBits])
- numBits = m_Lengths[value >> (kNumBitsMax - kNumTableBits)];
+ UInt32 val = bitStream->GetValue(kNumBitsMax);
+
+ if (val < m_Limits[kNumTableBits])
+ numBits = m_Lengths[val >> (kNumBitsMax - kNumTableBits)];
else
- for (numBits = kNumTableBits + 1; value >= m_Limits[numBits]; numBits++);
+ for (numBits = kNumTableBits + 1; val >= m_Limits[numBits]; numBits++);
+
bitStream->MovePos(numBits);
- UInt32 index = m_Positions[numBits] +
- ((value - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits));
+ UInt32 index = m_Positions[numBits] + ((val - m_Limits[numBits - 1]) >> (kNumBitsMax - numBits));
if (index >= m_NumSymbols)
// throw CDecoderException(); // test it
return 0xFFFFFFFF;
diff --git a/CPP/7zip/Compress/Rar1Decoder.cpp b/CPP/7zip/Compress/Rar1Decoder.cpp
index 12de7e19..1aaedcc1 100644
--- a/CPP/7zip/Compress/Rar1Decoder.cpp
+++ b/CPP/7zip/Compress/Rar1Decoder.cpp
@@ -486,7 +486,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
if (size < 1)
return E_INVALIDARG;
- m_IsSolid = (data[0] != 0);
+ m_IsSolid = ((data[0] & 1) != 0);
return S_OK;
}
diff --git a/CPP/7zip/Compress/Rar2Decoder.cpp b/CPP/7zip/Compress/Rar2Decoder.cpp
index 6f42d2e6..5082ded3 100644
--- a/CPP/7zip/Compress/Rar2Decoder.cpp
+++ b/CPP/7zip/Compress/Rar2Decoder.cpp
@@ -394,7 +394,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
if (size < 1)
return E_INVALIDARG;
- m_IsSolid = (data[0] != 0);
+ m_IsSolid = ((data[0] & 1) != 0);
return S_OK;
}
diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp
index f0553c85..81eb8285 100644
--- a/CPP/7zip/Compress/Rar3Decoder.cpp
+++ b/CPP/7zip/Compress/Rar3Decoder.cpp
@@ -140,6 +140,8 @@ void CDecoder::ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef)
NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize);
NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32));
CFilter *filter = _filters[tempFilter->FilterIndex];
+ if (!filter->IsSupported)
+ _unsupportedFilter = true;
_vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData);
delete tempFilter;
_tempFilters[tempFilterIndex] = 0;
@@ -226,12 +228,15 @@ void CDecoder::InitFilters()
_filters.Clear();
}
+static const unsigned MAX_UNPACK_FILTERS = 8192;
+
bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
{
CMemBitDecoder inp;
inp.Init(_vmData, codeSize);
UInt32 filterIndex;
+
if (firstByte & 0x80)
{
filterIndex = inp.ReadEncodedUInt32();
@@ -242,6 +247,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
}
else
filterIndex = _lastFilter;
+
if (filterIndex > (UInt32)_filters.Size())
return false;
_lastFilter = filterIndex;
@@ -251,7 +257,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
if (newFilter)
{
// check if too many filters
- if (filterIndex > 1024)
+ if (filterIndex > MAX_UNPACK_FILTERS)
return false;
filter = new CFilter;
_filters.Add(filter);
@@ -301,6 +307,8 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
if (initMask & (1 << i))
tempFilter->InitR[i] = inp.ReadEncodedUInt32();
}
+
+ bool isOK = true;
if (newFilter)
{
UInt32 vmCodeSize = inp.ReadEncodedUInt32();
@@ -308,7 +316,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
return false;
for (UInt32 i = 0; i < vmCodeSize; i++)
_vmCode[i] = (Byte)inp.ReadBits(8);
- filter->PrepareProgram(_vmCode, vmCodeSize);
+ isOK = filter->PrepareProgram(_vmCode, vmCodeSize);
}
Byte *globalData = &tempFilter->GlobalData[0];
@@ -331,7 +339,8 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
for (UInt32 i = 0; i < dataSize; i++)
dest[i] = (Byte)inp.ReadBits(8);
}
- return true;
+
+ return isOK;
}
bool CDecoder::ReadVmCodeLZ()
@@ -796,6 +805,7 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
{
_writtenFileSize = 0;
+ _unsupportedFilter = false;
if (!m_IsSolid)
{
_lzSize = 0;
@@ -843,6 +853,10 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));
if (_writtenFileSize < _unpackSize)
return S_FALSE;
+
+ if (_unsupportedFilter)
+ return E_NOTIMPL;
+
return S_OK;
}
@@ -892,7 +906,7 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
if (size < 1)
return E_INVALIDARG;
- m_IsSolid = (data[0] != 0);
+ m_IsSolid = ((data[0] & 1) != 0);
return S_OK;
}
diff --git a/CPP/7zip/Compress/Rar3Decoder.h b/CPP/7zip/Compress/Rar3Decoder.h
index 77379858..d8dfd11a 100644
--- a/CPP/7zip/Compress/Rar3Decoder.h
+++ b/CPP/7zip/Compress/Rar3Decoder.h
@@ -194,6 +194,7 @@ class CDecoder:
bool m_IsSolid;
bool _lzMode;
+ bool _unsupportedFilter;
UInt32 PrevAlignBits;
UInt32 PrevAlignCount;
diff --git a/CPP/7zip/Compress/Rar3Vm.cpp b/CPP/7zip/Compress/Rar3Vm.cpp
index 3cbfb0e1..5dca9eab 100644
--- a/CPP/7zip/Compress/Rar3Vm.cpp
+++ b/CPP/7zip/Compress/Rar3Vm.cpp
@@ -12,6 +12,8 @@ Note:
#include "StdAfx.h"
+#include <stdlib.h>
+
#include "../../../C/7zCrc.h"
#include "../../../C/Alloc.h"
@@ -55,6 +57,8 @@ namespace NVm {
static const UInt32 kStackRegIndex = kNumRegs - 1;
+#ifdef RARVM_VM_ENABLE
+
static const UInt32 FLAG_C = 1;
static const UInt32 FLAG_Z = 2;
static const UInt32 FLAG_S = 0x80000000;
@@ -113,11 +117,14 @@ static const Byte kCmdFlags[]=
/* CMD_PRINT */ CF_OP0
};
+#endif
+
+
CVm::CVm(): Mem(NULL) {}
bool CVm::Create()
{
- if (Mem == NULL)
+ if (!Mem)
Mem = (Byte *)::MyAlloc(kSpaceSize + 4);
return (Mem != NULL);
}
@@ -145,12 +152,14 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
memcpy(Mem + kGlobalOffset + globalSize, &prg->StaticData[0], staticSize);
bool res = true;
+
#ifdef RARVM_STANDARD_FILTERS
if (prg->StandardFilterIndex >= 0)
ExecuteStandardFilter(prg->StandardFilterIndex);
else
#endif
{
+ #ifdef RARVM_VM_ENABLE
res = ExecuteCode(prg);
if (!res)
{
@@ -158,7 +167,11 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
prg->Commands.Add(CCommand());
prg->Commands.Back().OpCode = CMD_RET;
}
+ #else
+ res = false;
+ #endif
}
+
UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask;
UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask;
if (newBlockPos + newBlockSize >= kSpaceSize)
@@ -175,9 +188,11 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
outGlobalData.ClearAndSetSize(dataSize);
memcpy(&outGlobalData[0], Mem + kGlobalOffset, dataSize);
}
+
return res;
}
+#ifdef RARVM_VM_ENABLE
#define SET_IP(IP) \
if ((IP) >= numCommands) return true; \
@@ -191,7 +206,7 @@ bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
UInt32 CVm::GetOperand32(const COperand *op) const
{
- switch(op->Type)
+ switch (op->Type)
{
case OP_TYPE_REG: return R[op->Data];
case OP_TYPE_REGMEM: return GetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask]);
@@ -201,7 +216,7 @@ UInt32 CVm::GetOperand32(const COperand *op) const
void CVm::SetOperand32(const COperand *op, UInt32 val)
{
- switch(op->Type)
+ switch (op->Type)
{
case OP_TYPE_REG: R[op->Data] = val; return;
case OP_TYPE_REGMEM: SetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask], val); return;
@@ -210,7 +225,7 @@ void CVm::SetOperand32(const COperand *op, UInt32 val)
Byte CVm::GetOperand8(const COperand *op) const
{
- switch(op->Type)
+ switch (op->Type)
{
case OP_TYPE_REG: return (Byte)R[op->Data];
case OP_TYPE_REGMEM: return Mem[(op->Base + R[op->Data]) & kSpaceMask];;
@@ -220,7 +235,7 @@ Byte CVm::GetOperand8(const COperand *op) const
void CVm::SetOperand8(const COperand *op, Byte val)
{
- switch(op->Type)
+ switch (op->Type)
{
case OP_TYPE_REG: R[op->Data] = (R[op->Data] & 0xFFFFFF00) | val; return;
case OP_TYPE_REGMEM: Mem[(op->Base + R[op->Data]) & kSpaceMask] = val; return;
@@ -253,10 +268,8 @@ bool CVm::ExecuteCode(const CProgram *prg)
for (;;)
{
- switch(cmd->OpCode)
+ switch (cmd->OpCode)
{
- #ifndef RARVM_NO_VM
-
case CMD_MOV:
SetOperand32(&cmd->Op1, GetOperand32(&cmd->Op2));
break;
@@ -619,8 +632,6 @@ bool CVm::ExecuteCode(const CProgram *prg)
}
break;
- #endif
-
case CMD_RET:
{
if (R[kStackRegIndex] >= kSpaceSize)
@@ -638,7 +649,6 @@ bool CVm::ExecuteCode(const CProgram *prg)
}
}
-
//////////////////////////////////////////////////////
// Read program
@@ -682,25 +692,31 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
inp.Init(code, codeSize);
StaticData.Clear();
+
if (inp.ReadBit())
{
UInt32 dataSize = inp.ReadEncodedUInt32() + 1;
for (UInt32 i = 0; inp.Avail() && i < dataSize; i++)
StaticData.Add((Byte)inp.ReadBits(8));
}
+
while (inp.Avail())
{
Commands.Add(CCommand());
CCommand *cmd = &Commands.Back();
+
if (inp.ReadBit() == 0)
cmd->OpCode = (ECommand)inp.ReadBits(3);
else
cmd->OpCode = (ECommand)(8 + inp.ReadBits(5));
+
if (kCmdFlags[(unsigned)cmd->OpCode] & CF_BYTEMODE)
cmd->ByteMode = (inp.ReadBit()) ? true : false;
else
cmd->ByteMode = 0;
+
int opNum = (kCmdFlags[(unsigned)cmd->OpCode] & CF_OPMASK);
+
if (opNum > 0)
{
DecodeArg(inp, cmd->Op1, cmd->ByteMode);
@@ -727,6 +743,7 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
}
}
}
+
if (cmd->ByteMode)
{
switch (cmd->OpCode)
@@ -751,6 +768,9 @@ void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
}
}
+#endif
+
+
#ifdef RARVM_STANDARD_FILTERS
enum EStandardFilter
@@ -760,8 +780,8 @@ enum EStandardFilter
SF_ITANIUM,
SF_RGB,
SF_AUDIO,
- SF_DELTA,
- SF_UPCASE
+ SF_DELTA
+ // SF_UPCASE
};
static const struct CStandardFilterSignature
@@ -777,8 +797,8 @@ kStdFilters[]=
{ 120, 0x3769893f, SF_ITANIUM },
{ 29, 0x0e06077d, SF_DELTA },
{ 149, 0x1c2c5dc8, SF_RGB },
- { 216, 0xbc85e701, SF_AUDIO },
- { 40, 0x46b9c560, SF_UPCASE }
+ { 216, 0xbc85e701, SF_AUDIO }
+ // { 40, 0x46b9c560, SF_UPCASE }
};
static int FindStandardFilter(const Byte *code, UInt32 codeSize)
@@ -795,28 +815,48 @@ static int FindStandardFilter(const Byte *code, UInt32 codeSize)
#endif
-void CProgram::PrepareProgram(const Byte *code, UInt32 codeSize)
+
+bool CProgram::PrepareProgram(const Byte *code, UInt32 codeSize)
{
- Byte xorSum = 0;
- for (UInt32 i = 1; i < codeSize; i++)
- xorSum ^= code[i];
+ IsSupported = false;
+ #ifdef RARVM_VM_ENABLE
Commands.Clear();
+ #endif
+
#ifdef RARVM_STANDARD_FILTERS
StandardFilterIndex = -1;
#endif
- if (xorSum == code[0] && codeSize > 0)
+ bool isOK = false;
+
+ Byte xorSum = 0;
+ for (UInt32 i = 0; i < codeSize; i++)
+ xorSum ^= code[i];
+
+ if (xorSum == 0 && codeSize != 0)
{
+ IsSupported = true;
+ isOK = true;
#ifdef RARVM_STANDARD_FILTERS
StandardFilterIndex = FindStandardFilter(code, codeSize);
if (StandardFilterIndex >= 0)
- return;
+ return true;
#endif
+
+ #ifdef RARVM_VM_ENABLE
ReadProgram(code + 1, codeSize - 1);
+ #else
+ IsSupported = false;
+ #endif
}
+
+ #ifdef RARVM_VM_ENABLE
Commands.Add(CCommand());
Commands.Back().OpCode = CMD_RET;
+ #endif
+
+ return isOK;
}
void CVm::SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize)
@@ -833,12 +873,11 @@ static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9)
return;
dataSize -= 4;
const UInt32 kFileSize = 0x1000000;
- Byte cmpByte2 = (Byte)(e9 ? 0xE9 : 0xE8);
+ Byte cmpMask = (Byte)(e9 ? 0xFE : 0xFF);
for (UInt32 curPos = 0; curPos < dataSize;)
{
- Byte curByte = *(data++);
curPos++;
- if (curByte == 0xE8 || curByte == cmpByte2)
+ if (((*data++) & cmpMask) == 0xE8)
{
UInt32 offset = curPos + fileOffset;
UInt32 addr = (Int32)GetValue32(data);
@@ -852,9 +891,9 @@ static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9)
}
}
-static inline UInt32 ItaniumGetOpType(const Byte *data, int bitPos)
+static inline UInt32 ItaniumGetOpType(const Byte *data, unsigned bitPos)
{
- return (data[(unsigned int)bitPos >> 3] >> (bitPos & 7)) & 0xF;
+ return (data[bitPos >> 3] >> (bitPos & 7)) & 0xF;
}
static const Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};
@@ -870,20 +909,20 @@ static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset)
{
Byte cmdMask = kCmdMasks[b];
if (cmdMask != 0)
- for (int i = 0; i < 3; i++)
+ for (unsigned i = 0; i < 3; i++)
if (cmdMask & (1 << i))
{
- int startPos = i * 41 + 18;
+ unsigned startPos = i * 41 + 18;
if (ItaniumGetOpType(data, startPos + 24) == 5)
{
const UInt32 kMask = 0xFFFFF;
- Byte *p = data + ((unsigned int)startPos >> 3);
+ Byte *p = data + (startPos >> 3);
UInt32 bitField = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16);
- int inBit = (startPos & 7);
+ unsigned inBit = (startPos & 7);
UInt32 offset = (bitField >> inBit) & kMask;
UInt32 andMask = ~(kMask << inBit);
bitField = ((offset - fileOffset) & kMask) << inBit;
- for (int j = 0; j < 3; j++)
+ for (unsigned j = 0; j < 3; j++)
{
p[j] &= andMask;
p[j] |= bitField;
@@ -1016,6 +1055,7 @@ static void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels)
}
}
+/*
static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
{
UInt32 srcPos = 0, destPos = dataSize;
@@ -1028,6 +1068,7 @@ static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
}
return destPos - dataSize;
}
+*/
void CVm::ExecuteStandardFilter(unsigned filterIndex)
{
@@ -1068,6 +1109,7 @@ void CVm::ExecuteStandardFilter(unsigned filterIndex)
SetBlockPos(dataSize);
AudioDecode(Mem, dataSize, R[0]);
break;
+ /*
case SF_UPCASE:
if (dataSize >= kGlobalOffset / 2)
break;
@@ -1075,6 +1117,7 @@ void CVm::ExecuteStandardFilter(unsigned filterIndex)
SetBlockSize(destSize);
SetBlockPos(dataSize);
break;
+ */
}
}
diff --git a/CPP/7zip/Compress/Rar3Vm.h b/CPP/7zip/Compress/Rar3Vm.h
index 23f4abab..4272c93e 100644
--- a/CPP/7zip/Compress/Rar3Vm.h
+++ b/CPP/7zip/Compress/Rar3Vm.h
@@ -7,10 +7,10 @@
#include "../../../C/CpuArch.h"
-#include "../../Common/MyTypes.h"
#include "../../Common/MyVector.h"
#define RARVM_STANDARD_FILTERS
+// #define RARVM_VM_ENABLE
namespace NCompress {
namespace NRar3 {
@@ -39,12 +39,12 @@ namespace NVm {
inline UInt32 GetValue32(const void *addr) { return GetUi32(addr); }
inline void SetValue32(void *addr, UInt32 value) { SetUi32(addr, value); }
-const int kNumRegBits = 3;
+const unsigned kNumRegBits = 3;
const UInt32 kNumRegs = 1 << kNumRegBits;
const UInt32 kNumGpRegs = kNumRegs - 1;
const UInt32 kSpaceSize = 0x40000;
-const UInt32 kSpaceMask = kSpaceSize -1;
+const UInt32 kSpaceMask = kSpaceSize - 1;
const UInt32 kGlobalOffset = 0x3C000;
const UInt32 kGlobalSize = 0x2000;
const UInt32 kFixedGlobalSize = 64;
@@ -57,6 +57,9 @@ namespace NGlobalOffset
const UInt32 kGlobalMemOutSize = 0x30;
}
+
+#ifdef RARVM_VM_ENABLE
+
enum ECommand
{
CMD_MOV, CMD_CMP, CMD_ADD, CMD_SUB, CMD_JZ, CMD_JNZ, CMD_INC, CMD_DEC,
@@ -89,27 +92,36 @@ struct CCommand
COperand Op1, Op2;
};
+#endif
+
+
struct CBlockRef
{
UInt32 Offset;
UInt32 Size;
};
+
class CProgram
{
+ #ifdef RARVM_VM_ENABLE
+ void ReadProgram(const Byte *code, UInt32 codeSize);
public:
CRecordVector<CCommand> Commands;
+ #endif
+
+public:
#ifdef RARVM_STANDARD_FILTERS
int StandardFilterIndex;
#endif
+
+ bool IsSupported;
CRecordVector<Byte> StaticData;
-private:
- void ReadProgram(const Byte *code, UInt32 codeSize);
-public:
- void PrepareProgram(const Byte *code, UInt32 codeSize);
+ bool PrepareProgram(const Byte *code, UInt32 codeSize);
};
+
struct CProgramInitState
{
UInt32 InitR[kNumGpRegs];
@@ -122,6 +134,7 @@ struct CProgramInitState
}
};
+
class CVm
{
static UInt32 GetValue(bool byteMode, const void *addr)
@@ -146,15 +159,18 @@ class CVm
void SetBlockPos(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockPos], v); }
public:
static void SetValue(void *addr, UInt32 value) { SetValue(false, addr, value); }
+
private:
+
+ #ifdef RARVM_VM_ENABLE
UInt32 GetOperand32(const COperand *op) const;
void SetOperand32(const COperand *op, UInt32 val);
Byte GetOperand8(const COperand *op) const;
void SetOperand8(const COperand *op, Byte val);
UInt32 GetOperand(bool byteMode, const COperand *op) const;
void SetOperand(bool byteMode, const COperand *op, UInt32 val);
-
bool ExecuteCode(const CProgram *prg);
+ #endif
#ifdef RARVM_STANDARD_FILTERS
void ExecuteStandardFilter(unsigned filterIndex);
@@ -163,6 +179,7 @@ private:
Byte *Mem;
UInt32 R[kNumRegs + 1]; // R[kNumRegs] = 0 always (speed optimization)
UInt32 Flags;
+
public:
CVm();
~CVm();
@@ -171,7 +188,6 @@ public:
bool Execute(CProgram *prg, const CProgramInitState *initState,
CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData);
const Byte *GetDataPointer(UInt32 offset) const { return Mem + offset; }
-
};
#endif
diff --git a/CPP/7zip/Compress/Rar5Decoder.cpp b/CPP/7zip/Compress/Rar5Decoder.cpp
new file mode 100644
index 00000000..9e3ff3e4
--- /dev/null
+++ b/CPP/7zip/Compress/Rar5Decoder.cpp
@@ -0,0 +1,960 @@
+// Rar5Decoder.cpp
+// According to unRAR license, this code may not be used to develop
+// a program that creates RAR archives
+
+#include "StdAfx.h"
+
+// #include <stdio.h>
+
+#include "../Common/StreamUtils.h"
+
+#include "Rar5Decoder.h"
+
+namespace NCompress {
+namespace NRar5 {
+
+static const size_t kInputBufSize = 1 << 20;
+
+void CBitDecoder::Prepare2() throw()
+{
+ const unsigned kSize = 16;
+ if (_buf > _bufLim)
+ return;
+
+ size_t rem = _bufLim - _buf;
+ if (rem != 0)
+ memcpy(_bufBase, _buf, rem);
+
+ _bufLim = _bufBase + rem;
+ _processedSize += (_buf - _bufBase);
+ _buf = _bufBase;
+
+ if (!_wasFinished)
+ {
+ UInt32 processed = (UInt32)(kInputBufSize - rem);
+ _hres = _stream->Read(_bufLim, (UInt32)processed, &processed);
+ _bufLim += processed;
+ _wasFinished = (processed == 0);
+ if (_hres != S_OK)
+ {
+ _wasFinished = true;
+ // throw CInBufferException(result);
+ }
+ }
+
+ rem = _bufLim - _buf;
+ _bufCheck = _buf;
+ if (rem < kSize)
+ memset(_bufLim, 0xFF, kSize - rem);
+ else
+ _bufCheck = _bufLim - kSize;
+
+ SetCheck2();
+}
+
+
+enum FilterType
+{
+ FILTER_DELTA = 0,
+ FILTER_E8,
+ FILTER_E8E9,
+ FILTER_ARM
+};
+
+static const size_t kWriteStep = (size_t)1 << 22;
+
+CDecoder::CDecoder():
+ _window(NULL),
+ _winPos(0),
+ _winSizeAllocated(0),
+ _lzSize(0),
+ _lzEnd(0),
+ _writtenFileSize(0),
+ _dictSizeLog(0),
+ _isSolid(false),
+ _wasInit(false),
+ _inputBuf(NULL)
+{
+}
+
+CDecoder::~CDecoder()
+{
+ ::MidFree(_window);
+ ::MidFree(_inputBuf);
+}
+
+HRESULT CDecoder::WriteData(const Byte *data, size_t size)
+{
+ HRESULT res = S_OK;
+ if (!_unpackSize_Defined || _writtenFileSize < _unpackSize)
+ {
+ size_t cur = size;
+ if (_unpackSize_Defined)
+ {
+ UInt64 rem = _unpackSize - _writtenFileSize;
+ if (cur > rem)
+ cur = (size_t)rem;
+ }
+ res = WriteStream(_outStream, data, cur);
+ if (res != S_OK)
+ _writeError = true;
+ }
+ _writtenFileSize += size;
+ return res;
+}
+
+HRESULT CDecoder::ExecuteFilter(const CFilter &f)
+{
+ bool useDest = false;
+
+ Byte *data = _filterSrc;
+ UInt32 dataSize = f.Size;
+
+ // printf("\nType = %d offset = %9d size = %5d", f.Type, (unsigned)(f.Start - _lzFileStart), dataSize);
+
+ switch (f.Type)
+ {
+ case FILTER_E8:
+ case FILTER_E8E9:
+ {
+ // printf(" FILTER_E8");
+ if (dataSize > 4)
+ {
+ dataSize -= 4;
+ UInt32 fileOffset = (UInt32)(f.Start - _lzFileStart);
+
+ const UInt32 kFileSize = (UInt32)1 << 24;
+ Byte cmpMask = (Byte)(f.Type == FILTER_E8 ? 0xFF : 0xFE);
+
+ for (UInt32 curPos = 0; curPos < dataSize;)
+ {
+ curPos++;
+ if (((*data++) & cmpMask) == 0xE8)
+ {
+ UInt32 offset = (curPos + fileOffset) & (kFileSize - 1);
+ UInt32 addr = GetUi32(data);
+
+ if (addr < kFileSize)
+ {
+ SetUi32(data, addr - offset);
+ }
+ else if (addr > ((UInt32)0xFFFFFFFF - offset)) // (addr > ~(offset))
+ {
+ SetUi32(data, addr + kFileSize);
+ }
+
+ data += 4;
+ curPos += 4;
+ }
+ }
+ }
+ break;
+ }
+
+ case FILTER_ARM:
+ {
+ if (dataSize >= 4)
+ {
+ dataSize -= 4;
+ UInt32 fileOffset = (UInt32)(f.Start - _lzFileStart);
+
+ for (UInt32 curPos = 0; curPos <= dataSize; curPos += 4)
+ {
+ Byte *d = data + curPos;
+ if (d[3] == 0xEB)
+ {
+ UInt32 offset = d[0] | ((UInt32)d[1] << 8) | ((UInt32)d[2] << 16);
+ offset -= (fileOffset + curPos) >> 2;
+ d[0] = (Byte)offset;
+ d[1] = (Byte)(offset >> 8);
+ d[2] = (Byte)(offset >> 16);
+ }
+ }
+ }
+ break;
+ }
+
+ case FILTER_DELTA:
+ {
+ // printf(" channels = %d", f.Channels);
+ _filterDst.AllocAtLeast(dataSize);
+ if (!_filterDst.IsAllocated())
+ return E_OUTOFMEMORY;
+
+ Byte *dest = _filterDst;
+ UInt32 numChannels = f.Channels;
+
+ for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)
+ {
+ Byte prevByte = 0;
+ for (UInt32 destPos = curChannel; destPos < dataSize; destPos += numChannels)
+ dest[destPos] = (prevByte = (Byte)(prevByte - *data++));
+ }
+ useDest = true;
+ break;
+ }
+
+ default:
+ _unsupportedFilter = true;
+ }
+
+ return WriteData(useDest ?
+ (const Byte *)_filterDst :
+ (const Byte *)_filterSrc,
+ f.Size);
+}
+
+
+HRESULT CDecoder::WriteBuf()
+{
+ DeleteUnusedFilters();
+
+ for (unsigned i = 0; i < _filters.Size();)
+ {
+ const CFilter &f = _filters[i];
+
+ UInt64 blockStart = f.Start;
+
+ size_t lzAvail = (size_t)(_lzSize - _lzWritten);
+ if (lzAvail == 0)
+ break;
+
+ if (blockStart > _lzWritten)
+ {
+ UInt64 rem = blockStart - _lzWritten;
+ size_t size = lzAvail;
+ if (size > rem)
+ size = (size_t)rem;
+ if (size != 0)
+ {
+ RINOK(WriteData(_window + _winPos - lzAvail, size));
+ _lzWritten += size;
+ }
+ continue;
+ }
+
+ UInt32 blockSize = f.Size;
+ size_t offset = (size_t)(_lzWritten - blockStart);
+ if (offset == 0)
+ {
+ _filterSrc.AllocAtLeast(blockSize);
+ if (!_filterSrc.IsAllocated())
+ return E_OUTOFMEMORY;
+ }
+
+ size_t blockRem = (size_t)blockSize - offset;
+ size_t size = lzAvail;
+ if (size > blockRem)
+ size = blockRem;
+ memcpy(_filterSrc + offset, _window + _winPos - lzAvail, size);
+ _lzWritten += size;
+ offset += size;
+ if (offset != blockSize)
+ return S_OK;
+
+ _numUnusedFilters = ++i;
+ RINOK(ExecuteFilter(f));
+ }
+
+ DeleteUnusedFilters();
+
+ if (!_filters.IsEmpty())
+ return S_OK;
+
+ size_t lzAvail = (size_t)(_lzSize - _lzWritten);
+ RINOK(WriteData(_window + _winPos - lzAvail, lzAvail));
+ _lzWritten += lzAvail;
+ return S_OK;
+}
+
+
+static UInt32 ReadUInt32(CBitDecoder &bi)
+{
+ unsigned numBytes = bi.ReadBits9fix(2) + 1;
+ UInt32 v = 0;
+ for (unsigned i = 0; i < numBytes; i++)
+ v += ((UInt32)bi.ReadBits9fix(8) << (i * 8));
+ return v;
+}
+
+
+static const unsigned MAX_UNPACK_FILTERS = 8192;
+
+HRESULT CDecoder::AddFilter(CBitDecoder &_bitStream)
+{
+ DeleteUnusedFilters();
+
+ if (_filters.Size() >= MAX_UNPACK_FILTERS)
+ {
+ RINOK(WriteBuf());
+ DeleteUnusedFilters();
+ if (_filters.Size() >= MAX_UNPACK_FILTERS)
+ {
+ _unsupportedFilter = true;
+ InitFilters();
+ }
+ }
+
+ _bitStream.Prepare();
+
+ CFilter f;
+ UInt32 blockStart = ReadUInt32(_bitStream);
+ f.Size = ReadUInt32(_bitStream);
+
+ // if (f.Size > ((UInt32)1 << 16)) _unsupportedFilter = true;
+
+ f.Type = (Byte)_bitStream.ReadBits9fix(3);
+ if (f.Type == FILTER_DELTA)
+ f.Channels = (Byte)(_bitStream.ReadBits9fix(5) + 1);
+ f.Start = _lzSize + blockStart;
+
+ if (f.Start < _filterEnd)
+ _unsupportedFilter = true;
+ else
+ {
+ _filterEnd = f.Start + f.Size;
+ if (f.Size != 0)
+ _filters.Add(f);
+ }
+
+ return S_OK;
+}
+
+
+#define RIF(x) { if (!(x)) return S_FALSE; }
+
+HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream)
+{
+ if (_progress)
+ {
+ UInt64 packSize = _bitStream.GetProcessedSize();
+ RINOK(_progress->SetRatioInfo(&packSize, &_writtenFileSize));
+ }
+
+ _bitStream.AlignToByte();
+ _bitStream.Prepare();
+
+ unsigned flags = _bitStream.ReadByteInAligned();
+ unsigned checkSum = _bitStream.ReadByteInAligned();
+ checkSum ^= flags;
+
+ UInt32 blockSize;
+ {
+ unsigned num = (flags >> 3) & 3;
+ if (num == 3)
+ return S_FALSE;
+ blockSize = _bitStream.ReadByteInAligned();
+ if (num > 0)
+ {
+ blockSize += (UInt32)_bitStream.ReadByteInAligned() << 8;
+ if (num > 1)
+ blockSize += (UInt32)_bitStream.ReadByteInAligned() << 16;
+ }
+ }
+
+ checkSum ^= blockSize ^ (blockSize >> 8) ^ (blockSize >> 16);
+ if ((Byte)checkSum != 0x5A)
+ return S_FALSE;
+
+ unsigned blockSizeBits7 = (flags & 7) + 1;
+
+ if (blockSize == 0 && blockSizeBits7 != 8)
+ return S_FALSE;
+
+ blockSize += (blockSizeBits7 >> 3);
+ blockSize--;
+
+ _bitStream._blockEndBits7 = (Byte)(blockSizeBits7 & 7);
+ _bitStream._blockEnd = _bitStream.GetProcessedSize_Round() + blockSize;
+
+ _bitStream.SetCheck2();
+
+ _isLastBlock = ((flags & 0x40) != 0);
+
+ if ((flags & 0x80) == 0)
+ {
+ if (!_tableWasFilled && blockSize != 0)
+ return S_FALSE;
+ return S_OK;
+ }
+
+ _tableWasFilled = false;
+
+ {
+ Byte lens2[kLevelTableSize];
+
+ for (unsigned i = 0; i < kLevelTableSize;)
+ {
+ _bitStream.Prepare();
+ unsigned len = (unsigned)_bitStream.ReadBits9fix(4);
+ if (len == 15)
+ {
+ unsigned num = (unsigned)_bitStream.ReadBits9fix(4);
+ if (num != 0)
+ {
+ num += 2;
+ num += i;
+ if (num > kLevelTableSize)
+ num = kLevelTableSize;
+ do
+ lens2[i++] = 0;
+ while (i < num);
+ continue;
+ }
+ }
+ lens2[i++] = (Byte)len;
+ }
+
+ if (_bitStream.IsBlockOverRead())
+ return S_FALSE;
+
+ RIF(m_LevelDecoder.SetCodeLengths(lens2));
+ }
+
+ Byte lens[kTablesSizesSum];
+ unsigned i = 0;
+
+ while (i < kTablesSizesSum)
+ {
+ if (_bitStream._buf >= _bitStream._bufCheck2)
+ {
+ if (_bitStream._buf >= _bitStream._bufCheck)
+ _bitStream.Prepare();
+ if (_bitStream.IsBlockOverRead())
+ return S_FALSE;
+ }
+
+ UInt32 sym = m_LevelDecoder.DecodeSymbol(&_bitStream);
+
+ if (sym < 16)
+ lens[i++] = (Byte)sym;
+ else if (sym > kLevelTableSize)
+ return S_FALSE;
+ else
+ {
+ sym -= 16;
+ unsigned sh = ((sym & 1) << 2);
+ unsigned num = (unsigned)_bitStream.ReadBits9(3 + sh) + 3 + (sh << 1);
+
+ num += i;
+ if (num > kTablesSizesSum)
+ num = kTablesSizesSum;
+
+ if (sym < 2)
+ {
+ if (i == 0)
+ {
+ // return S_FALSE;
+ continue; // original unRAR
+ }
+ Byte v = lens[i - 1];
+ do
+ lens[i++] = v;
+ while (i < num);
+ }
+ else
+ {
+ do
+ lens[i++] = 0;
+ while (i < num);
+ }
+ }
+ }
+
+ if (_bitStream.IsBlockOverRead())
+ return S_FALSE;
+ if (_bitStream.InputEofError())
+ return S_FALSE;
+
+ RIF(m_MainDecoder.SetCodeLengths(&lens[0]));
+ RIF(m_DistDecoder.SetCodeLengths(&lens[kMainTableSize]));
+ RIF(m_AlignDecoder.SetCodeLengths(&lens[kMainTableSize + kDistTableSize]));
+ RIF(m_LenDecoder.SetCodeLengths(&lens[kMainTableSize + kDistTableSize + kAlignTableSize]));
+
+ _useAlignBits = false;
+ // _useAlignBits = true;
+ for (i = 0; i < kAlignTableSize; i++)
+ if (lens[kMainTableSize + kDistTableSize + i] != kNumAlignBits)
+ {
+ _useAlignBits = true;
+ break;
+ }
+
+ _tableWasFilled = true;
+ return S_OK;
+}
+
+
+static inline unsigned SlotToLen(CBitDecoder &_bitStream, unsigned slot)
+{
+ if (slot < 8)
+ return slot + 2;
+ unsigned numBits = (slot >> 2) - 1;
+ return 2 + ((4 | (slot & 3)) << numBits) + _bitStream.ReadBits9(numBits);
+}
+
+
+static const UInt32 kSymbolRep = 258;
+// static const unsigned kMaxMatchLen = 0x1001 + 3;
+
+HRESULT CDecoder::DecodeLZ()
+{
+ CBitDecoder _bitStream;
+ _bitStream._stream = _inStream;
+ _bitStream._bufBase = _inputBuf;
+ _bitStream.Init();
+
+ UInt32 rep0 = _reps[0];
+
+ UInt32 remLen = 0;
+
+ size_t limit;
+ {
+ size_t rem = _winSize - _winPos;
+ if (rem > kWriteStep)
+ rem = kWriteStep;
+ limit = _winPos + rem;
+ }
+
+ for (;;)
+ {
+ if (_winPos >= limit)
+ {
+ RINOK(WriteBuf());
+ if (_unpackSize_Defined && _writtenFileSize > _unpackSize)
+ break; // return S_FALSE;
+
+ {
+ size_t rem = _winSize - _winPos;
+
+ if (rem == 0)
+ {
+ _winPos = 0;
+ rem = _winSize;
+ }
+ if (rem > kWriteStep)
+ rem = kWriteStep;
+ limit = _winPos + rem;
+ }
+
+ if (remLen != 0)
+ {
+ size_t winPos = _winPos;
+ size_t winMask = _winMask;
+ size_t pos = (winPos - (size_t)rep0 - 1) & winMask;
+
+ Byte *win = _window;
+ do
+ {
+ if (winPos >= limit)
+ break;
+ win[winPos] = win[pos];
+ winPos++;
+ pos = (pos + 1) & winMask;
+ }
+ while (--remLen != 0);
+
+ _lzSize += winPos - _winPos;
+ _winPos = winPos;
+ continue;
+ }
+ }
+
+ if (_bitStream._buf >= _bitStream._bufCheck2)
+ {
+ if (_bitStream.InputEofError())
+ break; // return S_FALSE;
+ if (_bitStream._buf >= _bitStream._bufCheck)
+ _bitStream.Prepare2();
+
+ UInt64 processed = _bitStream.GetProcessedSize_Round();
+ if (processed >= _bitStream._blockEnd)
+ {
+ if (processed > _bitStream._blockEnd)
+ break; // return S_FALSE;
+ {
+ unsigned bits7 = _bitStream.GetProcessedBits7();
+ if (bits7 > _bitStream._blockEndBits7)
+ break; // return S_FALSE;
+ if (bits7 == _bitStream._blockEndBits7)
+ {
+ if (_isLastBlock)
+ {
+ _reps[0] = rep0;
+
+ if (_bitStream.InputEofError())
+ break;
+
+ /*
+ // packSize can be 15 bytes larger for encrypted archive
+ if (_packSize_Defined && _packSize < _bitStream.GetProcessedSize())
+ break;
+ */
+
+ return _bitStream._hres;
+ // break;
+ }
+ RINOK(ReadTables(_bitStream));
+ continue;
+ }
+ }
+ }
+ }
+
+ UInt32 sym = m_MainDecoder.DecodeSymbol(&_bitStream);
+
+ if (sym < 256)
+ {
+ size_t winPos = _winPos;
+ _window[winPos] = (Byte)sym;
+ _winPos = winPos + 1;
+ _lzSize++;
+ continue;
+ }
+
+ UInt32 len;
+
+ if (sym < kSymbolRep + kNumReps)
+ {
+ if (sym >= kSymbolRep)
+ {
+ if (sym != kSymbolRep)
+ {
+ UInt32 dist;
+ if (sym == kSymbolRep + 1)
+ dist = _reps[1];
+ else
+ {
+ if (sym == kSymbolRep + 2)
+ dist = _reps[2];
+ else
+ {
+ dist = _reps[3];
+ _reps[3] = _reps[2];
+ }
+ _reps[2] = _reps[1];
+ }
+ _reps[1] = rep0;
+ rep0 = dist;
+ }
+
+ UInt32 sym = m_LenDecoder.DecodeSymbol(&_bitStream);
+ if (sym >= kLenTableSize)
+ break; // return S_FALSE;
+ len = SlotToLen(_bitStream, sym);
+ }
+ else
+ {
+ if (sym == 256)
+ {
+ RINOK(AddFilter(_bitStream));
+ continue;
+ }
+ else // if (sym == 257)
+ {
+ len = _lastLen;
+ // if (len = 0), we ignore that symbol, like original unRAR code, but it can mean error in stream.
+ // if (len == 0) return S_FALSE;
+ if (len == 0)
+ continue;
+ }
+ }
+ }
+ else if (sym >= kMainTableSize)
+ break; // return S_FALSE;
+ else
+ {
+ _reps[3] = _reps[2];
+ _reps[2] = _reps[1];
+ _reps[1] = rep0;
+ len = SlotToLen(_bitStream, sym - (kSymbolRep + kNumReps));
+
+ rep0 = m_DistDecoder.DecodeSymbol(&_bitStream);
+
+ if (rep0 >= 4)
+ {
+ if (rep0 >= _numCorrectDistSymbols)
+ break; // return S_FALSE;
+ unsigned numBits = (rep0 >> 1) - 1;
+ rep0 = (2 | (rep0 & 1)) << numBits;
+
+ if (numBits < kNumAlignBits)
+ rep0 += _bitStream.ReadBits9(numBits);
+ else
+ {
+ len += (numBits >= 7);
+ len += (numBits >= 12);
+ len += (numBits >= 17);
+
+ if (_useAlignBits)
+ {
+ // if (numBits > kNumAlignBits)
+ rep0 += (_bitStream.ReadBits32(numBits - kNumAlignBits) << kNumAlignBits);
+ UInt32 a = m_AlignDecoder.DecodeSymbol(&_bitStream);
+ if (a >= kAlignTableSize)
+ break; // return S_FALSE;
+ rep0 += a;
+ }
+ else
+ rep0 += _bitStream.ReadBits32(numBits);
+ }
+ }
+ }
+
+ _lastLen = len;
+
+ if (rep0 >= _lzSize)
+ _lzError = true;
+
+ {
+ UInt32 lenCur = len;
+ size_t winPos = _winPos;
+ size_t pos = (winPos - (size_t)rep0 - 1) & _winMask;
+ {
+ size_t rem = limit - winPos;
+ // size_t rem = _winSize - winPos;
+
+ if (lenCur > rem)
+ {
+ lenCur = (UInt32)rem;
+ remLen = len - lenCur;
+ }
+ }
+
+ Byte *win = _window;
+ _lzSize += lenCur;
+ _winPos = winPos + lenCur;
+ if (_winSize - pos >= lenCur)
+ {
+ const Byte *src = win + pos;
+ Byte *dest = win + winPos;
+ do
+ *dest++ = *src++;
+ while (--lenCur != 0);
+ }
+ else
+ {
+ do
+ {
+ win[winPos] = win[pos];
+ winPos++;
+ pos = (pos + 1) & _winMask;
+ }
+ while (--lenCur != 0);
+ }
+ }
+ }
+
+ if (_bitStream._hres != S_OK)
+ return _bitStream._hres;
+
+ return S_FALSE;
+}
+
+
+HRESULT CDecoder::CodeReal()
+{
+ _unsupportedFilter = false;
+ _lzError = false;
+ _writeError = false;
+
+ if (!_isSolid || !_wasInit)
+ {
+ size_t clearSize = _winSize;
+ if (_lzSize < _winSize)
+ clearSize = (size_t)_lzSize;
+ memset(_window, 0, clearSize);
+
+ _wasInit = true;
+ _lzSize = 0;
+ _lzWritten = 0;
+ _winPos = 0;
+
+ for (unsigned i = 0; i < kNumReps; i++)
+ _reps[i] = (UInt32)0 - 1;
+
+ _lastLen = 0;
+ _tableWasFilled = false;
+ }
+
+ _isLastBlock = false;
+
+ InitFilters();
+
+ _filterEnd = 0;
+ _writtenFileSize = 0;
+
+ _lzFileStart = _lzSize;
+ _lzWritten = _lzSize;
+
+ HRESULT res = DecodeLZ();
+
+ HRESULT res2 = S_OK;
+ if (!_writeError && res != E_OUTOFMEMORY)
+ res2 = WriteBuf();
+
+ /*
+ if (res == S_OK)
+ if (InputEofError())
+ res = S_FALSE;
+ */
+
+ if (res == S_OK)
+ res = res2;
+
+ if (res == S_OK && _unpackSize_Defined && _writtenFileSize != _unpackSize)
+ return S_FALSE;
+ return res;
+}
+
+
+// Original unRAR claims that maximum possible filter block size is (1 << 16) now,
+// and (1 << 17) is minimum win size required to support filter.
+// Original unRAR uses (1 << 18) for "extra safety and possible filter area size expansion"
+// We can use any win size.
+
+static const unsigned kWinSize_Log_Min = 17;
+
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+ try
+ {
+ if (_dictSizeLog >= sizeof(size_t) * 8)
+ return E_NOTIMPL;
+
+ if (!_isSolid)
+ _lzEnd = 0;
+ else
+ {
+ if (_lzSize < _lzEnd)
+ {
+ if (_window)
+ {
+ UInt64 rem = _lzEnd - _lzSize;
+ if (rem >= _winSize)
+ memset(_window, 0, _winSize);
+ else
+ {
+ size_t pos = (size_t)_lzSize & _winSize;
+ size_t rem2 = _winSize - pos;
+ if (rem2 > rem)
+ rem2 = (size_t)rem;
+ memset(_window + pos, 0, rem2);
+ rem -= rem2;
+ memset(_window, 0, (size_t)rem);
+ }
+ }
+ _lzEnd &= ((((UInt64)1) << 33) - 1);
+ _lzSize = _lzEnd;
+ _winPos = (size_t)(_lzSize & _winSize);
+ }
+ _lzEnd = _lzSize;
+ }
+
+ size_t newSize;
+ {
+ unsigned newSizeLog = _dictSizeLog;
+ if (newSizeLog < kWinSize_Log_Min)
+ newSizeLog = kWinSize_Log_Min;
+ newSize = (size_t)1 << newSizeLog;
+ _numCorrectDistSymbols = newSizeLog * 2;
+ }
+
+ if (!_window || _winSize != newSize)
+ {
+ if (!_isSolid && newSize > _winSizeAllocated)
+ {
+ ::MidFree(_window);
+ _window = NULL;
+ _winSizeAllocated = 0;
+ }
+
+ Byte *win = _window;
+ if (!_window || newSize > _winSizeAllocated)
+ {
+ win = (Byte *)::MidAlloc(newSize);
+ if (!win)
+ return E_OUTOFMEMORY;
+ _winSizeAllocated = newSize;
+ memset(win, 0, newSize);
+ }
+
+ if (_isSolid && _window)
+ {
+ // original unRAR claims:
+ // "Archiving code guarantees that win size does not grow in the same solid stream",
+ // but the original unRAR decoder still supports such grow case.
+
+ Byte *winOld = _window;
+ size_t oldSize = _winSize;
+ size_t newMask = newSize - 1;
+ size_t oldMask = _winSize - 1;
+ size_t winPos = _winPos;
+ for (size_t i = 1; i < oldSize; i++) // i < oldSize) ?
+ win[(winPos - i) & newMask] = winOld[(winPos - i) & oldMask];
+ ::MidFree(_window);
+ }
+
+ _window = win;
+ _winSize = newSize;
+ }
+
+ _winMask = _winSize - 1;
+
+ if (!_inputBuf)
+ {
+ _inputBuf = (Byte *)::MidAlloc(kInputBufSize);
+ if (!_inputBuf)
+ return E_OUTOFMEMORY;
+ }
+
+ _inStream = inStream;
+ _outStream = outStream;
+
+ /*
+ _packSize = 0;
+ _packSize_Defined = (inSize != NULL);
+ if (_packSize_Defined)
+ _packSize = *inSize;
+ */
+
+ _unpackSize = 0;
+ _unpackSize_Defined = (outSize != NULL);
+ if (_unpackSize_Defined)
+ _unpackSize = *outSize;
+
+ if ((Int64)_unpackSize >= 0)
+ _lzEnd += _unpackSize;
+ else
+ _lzEnd = 0;
+
+ _progress = progress;
+
+ HRESULT res = CodeReal();
+
+ if (res != S_OK)
+ return res;
+ if (_lzError)
+ return S_FALSE;
+ if (_unsupportedFilter)
+ return E_NOTIMPL;
+ return S_OK;
+ }
+ // catch(const CInBufferException &e) { return e.ErrorCode; }
+ // catch(...) { return S_FALSE; }
+ catch(...) { return E_OUTOFMEMORY; }
+ // CNewException is possible here. But probably CNewException is caused
+ // by error in data stream.
+}
+
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
+{
+ if (size != 2)
+ return E_NOTIMPL;
+ _dictSizeLog = (Byte)((data[0] & 0xF) + 17);
+ _isSolid = ((data[1] & 1) != 0);
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Compress/Rar5Decoder.h b/CPP/7zip/Compress/Rar5Decoder.h
new file mode 100644
index 00000000..b0a4dd12
--- /dev/null
+++ b/CPP/7zip/Compress/Rar5Decoder.h
@@ -0,0 +1,335 @@
+// Rar5Decoder.h
+// According to unRAR license, this code may not be used to develop
+// a program that creates RAR archives
+
+#ifndef __COMPRESS_RAR5_DECODER_H
+#define __COMPRESS_RAR5_DECODER_H
+
+#include "../../../C/Alloc.h"
+#include "../../../C/CpuArch.h"
+
+#include "../../Common/MyBuffer.h"
+#include "../../Common/MyCom.h"
+#include "../../Common/MyException.h"
+#include "../../Common/MyVector.h"
+
+#include "../ICoder.h"
+
+#include "HuffmanDecoder.h"
+
+namespace NCompress {
+namespace NRar5 {
+
+class CMidBuffer
+{
+ Byte *_data;
+ size_t _size;
+
+ CLASS_NO_COPY(CMidBuffer)
+
+public:
+ CMidBuffer(): _data(NULL), _size(0) {};
+ ~CMidBuffer() { ::MidFree(_data); }
+
+ bool IsAllocated() const { return _data != NULL; }
+ operator Byte *() { return _data; }
+ operator const Byte *() const { return _data; }
+ size_t Size() const { return _size; }
+
+ void AllocAtLeast(size_t size)
+ {
+ if (size > _size)
+ {
+ const size_t kMinSize = (1 << 16);
+ if (size < kMinSize)
+ size = kMinSize;
+ ::MidFree(_data);
+ _data = (Byte *)::MidAlloc(size);
+ _size = size;
+ }
+ }
+};
+
+/*
+struct CInBufferException: public CSystemException
+{
+ CInBufferException(HRESULT errorCode): CSystemException(errorCode) {}
+};
+*/
+
+class CBitDecoder
+{
+public:
+ const Byte *_buf;
+ unsigned _bitPos;
+ bool _wasFinished;
+ Byte _blockEndBits7;
+ const Byte *_bufCheck2;
+ const Byte *_bufCheck;
+ Byte *_bufLim;
+ Byte *_bufBase;
+
+ UInt64 _processedSize;
+ UInt64 _blockEnd;
+
+ ISequentialInStream *_stream;
+ HRESULT _hres;
+
+ void SetCheck2()
+ {
+ _bufCheck2 = _bufCheck;
+ if (_bufCheck > _buf)
+ {
+ UInt64 processed = GetProcessedSize_Round();
+ if (_blockEnd < processed)
+ _bufCheck2 = _buf;
+ else
+ {
+ UInt64 delta = _blockEnd - processed;
+ if ((size_t)(_bufCheck - _buf) > delta)
+ _bufCheck2 = _buf + (size_t)delta;
+ }
+ }
+ }
+
+ bool IsBlockOverRead() const
+ {
+ UInt64 v = GetProcessedSize_Round();
+ if (v < _blockEnd)
+ return false;
+ if (v > _blockEnd)
+ return true;
+ return _bitPos > _blockEndBits7;
+ }
+
+ /*
+ CBitDecoder() throw():
+ _buf(0),
+ _bufLim(0),
+ _bufBase(0),
+ _stream(0),
+ _processedSize(0),
+ _wasFinished(false)
+ {}
+ */
+
+ void Init() throw()
+ {
+ _blockEnd = 0;
+ _blockEndBits7 = 0;
+
+ _bitPos = 0;
+ _processedSize = 0;
+ _buf = _bufBase;
+ _bufLim = _bufBase;
+ _bufCheck = _buf;
+ _bufCheck2 = _buf;
+ _wasFinished = false;
+ }
+
+ void Prepare2() throw();
+
+ void Prepare() throw()
+ {
+ if (_buf >= _bufCheck)
+ Prepare2();
+ }
+
+ bool ExtraBitsWereRead() const
+ {
+ return _buf >= _bufLim && (_buf > _bufLim || _bitPos != 0);
+ }
+
+ bool InputEofError() const { return ExtraBitsWereRead(); }
+
+ unsigned GetProcessedBits7() const { return _bitPos; }
+ UInt64 GetProcessedSize_Round() const { return _processedSize + (_buf - _bufBase); }
+ UInt64 GetProcessedSize() const { return _processedSize + (_buf - _bufBase) + ((_bitPos + 7) >> 3); }
+
+ void AlignToByte()
+ {
+ _buf += (_bitPos + 7) >> 3;
+ _bitPos = 0;
+ }
+
+ Byte ReadByteInAligned()
+ {
+ return *_buf++;
+ }
+
+ UInt32 GetValue(unsigned numBits)
+ {
+ UInt32 v = ((UInt32)_buf[0] << 16) | ((UInt32)_buf[1] << 8) | (UInt32)_buf[2];
+ v >>= (24 - numBits - _bitPos);
+ return v & ((1 << numBits) - 1);
+ }
+
+ void MovePos(unsigned numBits)
+ {
+ _bitPos += numBits;
+ _buf += (_bitPos >> 3);
+ _bitPos &= 7;
+ }
+
+ UInt32 ReadBits9(unsigned numBits)
+ {
+ const Byte *buf = _buf;
+ UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1];
+ v &= ((UInt32)0xFFFF >> _bitPos);
+ numBits += _bitPos;
+ v >>= (16 - numBits);
+ _buf = buf + (numBits >> 3);
+ _bitPos = numBits & 7;
+ return v;
+ }
+
+ UInt32 ReadBits9fix(unsigned numBits)
+ {
+ const Byte *buf = _buf;
+ UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1];
+ UInt32 mask = ((1 << numBits) - 1);
+ numBits += _bitPos;
+ v >>= (16 - numBits);
+ _buf = buf + (numBits >> 3);
+ _bitPos = numBits & 7;
+ return v & mask;
+ }
+
+ UInt32 ReadBits32(unsigned numBits)
+ {
+ UInt32 mask = ((1 << numBits) - 1);
+ numBits += _bitPos;
+ const Byte *buf = _buf;
+ UInt32 v = GetBe32(buf);
+ if (numBits > 32)
+ {
+ v <<= (numBits - 32);
+ v |= (UInt32)buf[4] >> (40 - numBits);
+ }
+ else
+ v >>= (32 - numBits);
+ _buf = buf + (numBits >> 3);
+ _bitPos = numBits & 7;
+ return v & mask;
+ }
+};
+
+
+struct CFilter
+{
+ Byte Type;
+ Byte Channels;
+ UInt32 Size;
+ UInt64 Start;
+};
+
+
+const unsigned kNumReps = 4;
+const unsigned kLenTableSize = 11 * 4;
+const unsigned kMainTableSize = 256 + 1 + 1 + kNumReps + kLenTableSize;
+const unsigned kDistTableSize = 64;
+const unsigned kNumAlignBits = 4;
+const unsigned kAlignTableSize = (1 << kNumAlignBits);
+const unsigned kLevelTableSize = 20;
+const unsigned kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;
+
+const unsigned kNumHuffmanBits = 15;
+
+class CDecoder:
+ public ICompressCoder,
+ public ICompressSetDecoderProperties2,
+ public CMyUnknownImp
+{
+ bool _useAlignBits;
+ bool _isLastBlock;
+ bool _unpackSize_Defined;
+ // bool _packSize_Defined;
+
+ bool _unsupportedFilter;
+ bool _lzError;
+ bool _writeError;
+
+ // CBitDecoder _bitStream;
+ Byte *_window;
+ size_t _winPos;
+ size_t _winSize;
+ size_t _winMask;
+
+ UInt64 _lzSize;
+
+ unsigned _numCorrectDistSymbols;
+ unsigned _numUnusedFilters;
+
+ UInt64 _lzWritten;
+ UInt64 _lzFileStart;
+ UInt64 _unpackSize;
+ // UInt64 _packSize;
+ UInt64 _lzEnd;
+ UInt64 _writtenFileSize;
+ size_t _winSizeAllocated;
+
+ Byte _dictSizeLog;
+ bool _tableWasFilled;
+ bool _isSolid;
+ bool _wasInit;
+
+ UInt32 _reps[kNumReps];
+ UInt32 _lastLen;
+
+ UInt64 _filterEnd;
+ CMidBuffer _filterSrc;
+ CMidBuffer _filterDst;
+
+ CRecordVector<CFilter> _filters;
+
+ ISequentialInStream *_inStream;
+ ISequentialOutStream *_outStream;
+ ICompressProgressInfo *_progress;
+ Byte *_inputBuf;
+
+ NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;
+ NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder;
+ NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder;
+ NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder;
+ NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
+
+
+ void InitFilters()
+ {
+ _numUnusedFilters = 0;
+ _filters.Clear();
+ }
+
+ void DeleteUnusedFilters()
+ {
+ if (_numUnusedFilters != 0)
+ {
+ _filters.DeleteFrontal(_numUnusedFilters);
+ _numUnusedFilters = 0;
+ }
+ }
+
+ HRESULT WriteData(const Byte *data, size_t size);
+ HRESULT ExecuteFilter(const CFilter &f);
+ HRESULT WriteBuf();
+ HRESULT AddFilter(CBitDecoder &_bitStream);
+
+ HRESULT ReadTables(CBitDecoder &_bitStream);
+ HRESULT DecodeLZ();
+ HRESULT CodeReal();
+
+public:
+ CDecoder();
+ ~CDecoder();
+
+ MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
+
+ STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+
+ STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Compress/RarCodecsRegister.cpp b/CPP/7zip/Compress/RarCodecsRegister.cpp
index 66fcc9a9..2f3a1138 100644
--- a/CPP/7zip/Compress/RarCodecsRegister.cpp
+++ b/CPP/7zip/Compress/RarCodecsRegister.cpp
@@ -7,12 +7,14 @@
#include "Rar1Decoder.h"
#include "Rar2Decoder.h"
#include "Rar3Decoder.h"
+#include "Rar5Decoder.h"
#define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NCompress::NRar ## x::CDecoder())
CREATE_CODEC(1)
CREATE_CODEC(2)
CREATE_CODEC(3)
+CREATE_CODEC(5)
#define RAR_CODEC(x, name) { CreateCodec ## x, NULL, 0x40300 + x, "Rar" name, 1, false }
@@ -21,6 +23,7 @@ REGISTER_CODECS_VAR
RAR_CODEC(1, "1"),
RAR_CODEC(2, "2"),
RAR_CODEC(3, "3"),
+ RAR_CODEC(5, "5"),
};
REGISTER_CODECS(Rar)
diff --git a/CPP/7zip/Crypto/HmacSha256.cpp b/CPP/7zip/Crypto/HmacSha256.cpp
new file mode 100644
index 00000000..2e1efb48
--- /dev/null
+++ b/CPP/7zip/Crypto/HmacSha256.cpp
@@ -0,0 +1,62 @@
+// HmacSha256.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "HmacSha256.h"
+
+namespace NCrypto {
+namespace NSha256 {
+
+static const unsigned kBlockSize = 64;
+
+void CHmac::SetKey(const Byte *key, size_t keySize)
+{
+ Byte temp[kBlockSize];
+ size_t i;
+
+ for (i = 0; i < kBlockSize; i++)
+ temp[i] = 0;
+
+ if (keySize > kBlockSize)
+ {
+ Sha256_Init(&_sha);
+ Sha256_Update(&_sha, key, keySize);
+ Sha256_Final(&_sha, temp);
+ }
+ else
+ for (i = 0; i < keySize; i++)
+ temp[i] = key[i];
+
+ for (i = 0; i < kBlockSize; i++)
+ temp[i] ^= 0x36;
+
+ Sha256_Init(&_sha);
+ Sha256_Update(&_sha, temp, kBlockSize);
+
+ for (i = 0; i < kBlockSize; i++)
+ temp[i] ^= 0x36 ^ 0x5C;
+
+ Sha256_Init(&_sha2);
+ Sha256_Update(&_sha2, temp, kBlockSize);
+}
+
+void CHmac::Final(Byte *mac)
+{
+ Sha256_Final(&_sha, mac);
+ Sha256_Update(&_sha2, mac, SHA256_DIGEST_SIZE);
+ Sha256_Final(&_sha2, mac);
+}
+
+/*
+void CHmac::Final(Byte *mac, size_t macSize)
+{
+ Byte digest[SHA256_DIGEST_SIZE];
+ Final(digest);
+ for (size_t i = 0; i < macSize; i++)
+ mac[i] = digest[i];
+}
+*/
+
+}}
diff --git a/CPP/7zip/Crypto/HmacSha256.h b/CPP/7zip/Crypto/HmacSha256.h
new file mode 100644
index 00000000..233424a0
--- /dev/null
+++ b/CPP/7zip/Crypto/HmacSha256.h
@@ -0,0 +1,27 @@
+// HmacSha256.h
+// Implements HMAC-SHA-256 (RFC2104, FIPS-198)
+
+#ifndef __CRYPTO_HMAC_SHA256_H
+#define __CRYPTO_HMAC_SHA256_H
+
+#include "../../../C/Sha256.h"
+
+namespace NCrypto {
+namespace NSha256 {
+
+const unsigned kDigestSize = SHA256_DIGEST_SIZE;
+
+class CHmac
+{
+ CSha256 _sha;
+ CSha256 _sha2;
+public:
+ void SetKey(const Byte *key, size_t keySize);
+ void Update(const Byte *data, size_t dataSize) { Sha256_Update(&_sha, data, dataSize); }
+ void Final(Byte *mac);
+ // void Final(Byte *mac, size_t macSize);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Crypto/Rar20Crypto.cpp b/CPP/7zip/Crypto/Rar20Crypto.cpp
index 1523151d..346d969e 100644
--- a/CPP/7zip/Crypto/Rar20Crypto.cpp
+++ b/CPP/7zip/Crypto/Rar20Crypto.cpp
@@ -9,7 +9,7 @@
#include "Rar20Crypto.h"
namespace NCrypto {
-namespace NRar20 {
+namespace NRar2 {
static const unsigned kNumRounds = 32;
@@ -39,44 +39,48 @@ void CData::UpdateKeys(const Byte *data)
Keys[j] ^= g_CrcTable[data[i + j]];
}
-static void Swap(Byte *b1, Byte *b2)
+static inline void Swap(Byte &b1, Byte &b2)
{
- Byte b = *b1;
- *b1 = *b2;
- *b2 = b;
+ Byte b = b1;
+ b1 = b2;
+ b2 = b;
}
-void CData::SetPassword(const Byte *data, UInt32 size)
+void CData::SetPassword(const Byte *data, unsigned size)
{
Keys[0] = 0xD3A3B879L;
Keys[1] = 0x3F6D12F7L;
Keys[2] = 0x7515A235L;
Keys[3] = 0xA4E7F123L;
- Byte psw[256];
- if (size >= sizeof(psw))
- size = sizeof(psw) - 1;
+ Byte psw[128];
memset(psw, 0, sizeof(psw));
if (size != 0)
+ {
+ if (size >= sizeof(psw))
+ size = sizeof(psw) - 1;
memcpy(psw, data, size);
+ }
+
memcpy(SubstTable, g_InitSubstTable, sizeof(SubstTable));
- for (UInt32 j = 0; j < 256; j++)
- for (UInt32 i = 0; i < size; i += 2)
+ for (unsigned j = 0; j < 256; j++)
+ for (unsigned i = 0; i < size; i += 2)
{
- UInt32 n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF];
- UInt32 n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];
- for (UInt32 k = 1; (n1 & 0xFF) != n2; n1++, k++)
- Swap(&SubstTable[n1 & 0xFF], &SubstTable[(n1 + i + k) & 0xFF]);
+ unsigned n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];
+ unsigned n2 = (Byte)g_CrcTable[(psw[i + 1] + j) & 0xFF];
+ for (unsigned k = 1; (n1 & 0xFF) != n2; n1++, k++)
+ Swap(SubstTable[n1 & 0xFF], SubstTable[(n1 + i + k) & 0xFF]);
}
- for (UInt32 i = 0; i < size; i += 16)
- EncryptBlock(&psw[i]);
+
+ for (unsigned i = 0; i < size; i += 16)
+ EncryptBlock(psw + i);
}
void CData::CryptBlock(Byte *buf, bool encrypt)
{
Byte inBuf[16];
- UInt32 A, B, C, D, T, TA, TB;
+ UInt32 A, B, C, D;
A = GetUi32(buf + 0) ^ Keys[0];
B = GetUi32(buf + 4) ^ Keys[1];
@@ -89,14 +93,10 @@ void CData::CryptBlock(Byte *buf, bool encrypt)
for (unsigned i = 0; i < kNumRounds; i++)
{
UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3];
- T = ((C + rotlFixed(D, 11)) ^ key);
- TA = A ^ SubstLong(T);
- T = ((D ^ rotlFixed(C, 17)) + key);
- TB = B ^ SubstLong(T);
- A = C;
- B = D;
- C = TA;
- D = TB;
+ UInt32 TA = A ^ SubstLong((C + rotlFixed(D, 11)) ^ key);
+ UInt32 TB = B ^ SubstLong((D ^ rotlFixed(C, 17)) + key);
+ A = C; C = TA;
+ B = D; D = TB;
}
SetUi32(buf + 0, C ^ Keys[0]);
@@ -107,12 +107,6 @@ void CData::CryptBlock(Byte *buf, bool encrypt)
UpdateKeys(encrypt ? buf : inBuf);
}
-STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
-{
- _cipher.SetPassword(data, size);
- return S_OK;
-}
-
STDMETHODIMP CDecoder::Init()
{
return S_OK;
@@ -126,10 +120,10 @@ STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
return 0;
if (size < kBlockSize)
return kBlockSize;
- UInt32 i;
size -= kBlockSize;
+ UInt32 i;
for (i = 0; i <= size; i += kBlockSize)
- _cipher.DecryptBlock(data + i);
+ DecryptBlock(data + i);
return i;
}
diff --git a/CPP/7zip/Crypto/Rar20Crypto.h b/CPP/7zip/Crypto/Rar20Crypto.h
index b0445932..b3033700 100644
--- a/CPP/7zip/Crypto/Rar20Crypto.h
+++ b/CPP/7zip/Crypto/Rar20Crypto.h
@@ -6,13 +6,12 @@
#include "../../Common/MyCom.h"
#include "../ICoder.h"
-#include "../IPassword.h"
namespace NCrypto {
-namespace NRar20 {
+namespace NRar2 {
/* ICompressFilter::Init() does nothing for this filter.
- Call CryptoSetPassword() to initialize filter. */
+ Call SetPassword() to initialize filter. */
class CData
{
@@ -31,22 +30,17 @@ class CData
public:
void EncryptBlock(Byte *buf) { CryptBlock(buf, true); }
void DecryptBlock(Byte *buf) { CryptBlock(buf, false); }
- void SetPassword(const Byte *password, UInt32 passwordLen);
+ void SetPassword(const Byte *password, unsigned passwordLen);
};
class CDecoder:
public ICompressFilter,
- public ICryptoSetPassword,
public CMyUnknownImp,
public CData
{
- CData _cipher;
public:
- MY_UNKNOWN_IMP1(ICryptoSetPassword)
-
- STDMETHOD(Init)();
- STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
- STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
+ MY_UNKNOWN_IMP
+ INTERFACE_ICompressFilter(;)
};
}}
diff --git a/CPP/7zip/Crypto/Rar5Aes.cpp b/CPP/7zip/Crypto/Rar5Aes.cpp
new file mode 100644
index 00000000..648a3d4d
--- /dev/null
+++ b/CPP/7zip/Crypto/Rar5Aes.cpp
@@ -0,0 +1,257 @@
+// Crypto/Rar5Aes.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#ifndef _7ZIP_ST
+#include "../../Windows/Synchronization.h"
+#endif
+
+#include "Rar5Aes.h"
+
+namespace NCrypto {
+namespace NRar5 {
+
+static const unsigned kNumIterationsLog_Max = 24;
+
+static const unsigned kPswCheckCsumSize = 4;
+static const unsigned kCheckSize = kPswCheckSize + kPswCheckCsumSize;
+
+CKey::CKey():
+ _needCalc(true),
+ _numIterationsLog(0)
+{
+ for (unsigned i = 0; i < sizeof(_salt); i++)
+ _salt[i] = 0;
+}
+
+CDecoder::CDecoder(): CAesCbcDecoder(kAesKeySize) {}
+
+static unsigned ReadVarInt(const Byte *p, unsigned maxSize, UInt64 *val)
+{
+ unsigned i;
+ *val = 0;
+
+ for (i = 0; i < maxSize;)
+ {
+ Byte b = p[i];
+ if (i < 10)
+ *val |= (UInt64)(b & 0x7F) << (7 * i++);
+ if ((b & 0x80) == 0)
+ return i;
+ }
+ return 0;
+}
+
+HRESULT CDecoder::SetDecoderProps(const Byte *p, unsigned size, bool includeIV, bool isService)
+{
+ UInt64 Version;
+
+ unsigned num = ReadVarInt(p, size, &Version);
+ if (num == 0)
+ return E_NOTIMPL;
+ p += num;
+ size -= num;
+
+ if (Version != 0)
+ return E_NOTIMPL;
+
+ num = ReadVarInt(p, size, &Flags);
+ if (num == 0)
+ return E_NOTIMPL;
+ p += num;
+ size -= num;
+
+ bool isCheck = IsThereCheck();
+ if (size != 1 + kSaltSize + (includeIV ? AES_BLOCK_SIZE : 0) + (unsigned)(isCheck ? kCheckSize : 0))
+ return E_NOTIMPL;
+
+ if (_numIterationsLog != p[0])
+ {
+ _numIterationsLog = p[0];
+ _needCalc = true;
+ }
+
+ p++;
+
+ if (memcmp(_salt, p, kSaltSize) != 0)
+ {
+ memcpy(_salt, p, kSaltSize);
+ _needCalc = true;
+ }
+
+ p += kSaltSize;
+
+ if (includeIV)
+ {
+ memcpy(_iv, p, AES_BLOCK_SIZE);
+ p += AES_BLOCK_SIZE;
+ }
+
+ _canCheck = true;
+
+ if (isCheck)
+ {
+ memcpy(_check, p, kPswCheckSize);
+ CSha256 sha;
+ Byte digest[SHA256_DIGEST_SIZE];
+ Sha256_Init(&sha);
+ Sha256_Update(&sha, _check, kPswCheckSize);
+ Sha256_Final(&sha, digest);
+ _canCheck = (memcmp(digest, p + kPswCheckSize, kPswCheckCsumSize) == 0);
+ if (_canCheck && isService)
+ {
+ // There was bug in RAR 5.21- : PswCheck field in service records ("QO") contained zeros.
+ // so we disable password checking for such bad records.
+ _canCheck = false;
+ for (unsigned i = 0; i < kPswCheckSize; i++)
+ if (p[i] != 0)
+ {
+ _canCheck = true;
+ break;
+ }
+ }
+ }
+
+ return (_numIterationsLog <= kNumIterationsLog_Max ? S_OK : E_NOTIMPL);
+}
+
+
+void CDecoder::SetPassword(const Byte *data, size_t size)
+{
+ if (size != _password.Size() || memcmp(data, _password, size) != 0)
+ {
+ _needCalc = true;
+ _password.CopyFrom(data, size);
+ }
+}
+
+
+STDMETHODIMP CDecoder::Init()
+{
+ CalcKey_and_CheckPassword();
+ RINOK(SetKey(_key, kAesKeySize));
+ RINOK(SetInitVector(_iv, AES_BLOCK_SIZE));
+ return CAesCbcCoder::Init();
+}
+
+
+UInt32 CDecoder::Hmac_Convert_Crc32(UInt32 crc) const
+{
+ NSha256::CHmac ctx;
+ ctx.SetKey(_hashKey, NSha256::kDigestSize);
+ Byte v[4];
+ SetUi32(v, crc);
+ ctx.Update(v, 4);
+ Byte h[NSha256::kDigestSize];
+ ctx.Final(h);
+ crc = 0;
+ for (unsigned i = 0; i < NSha256::kDigestSize; i++)
+ crc ^= (UInt32)h[i] << ((i & 3) * 8);
+ return crc;
+};
+
+
+void CDecoder::Hmac_Convert_32Bytes(Byte *data) const
+{
+ NSha256::CHmac ctx;
+ ctx.SetKey(_hashKey, NSha256::kDigestSize);
+ ctx.Update(data, NSha256::kDigestSize);
+ ctx.Final(data);
+};
+
+
+#ifndef _7ZIP_ST
+ static CKey g_Key;
+ static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;
+ #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);
+#else
+ #define MT_LOCK
+#endif
+
+bool CDecoder::CalcKey_and_CheckPassword()
+{
+ if (_needCalc)
+ {
+ {
+ MT_LOCK
+ if (!g_Key._needCalc && IsKeyEqualTo(g_Key))
+ {
+ CopyCalcedKeysFrom(g_Key);
+ _needCalc = false;
+ }
+ }
+
+ if (_needCalc)
+ {
+ Byte pswCheck[SHA256_DIGEST_SIZE];
+
+ {
+ // Pbkdf HMAC-SHA-256
+
+ NSha256::CHmac baseCtx;
+ baseCtx.SetKey(_password, _password.Size());
+
+ NSha256::CHmac ctx = baseCtx;
+ ctx.Update(_salt, sizeof(_salt));
+
+ Byte u[NSha256::kDigestSize];
+ Byte key[NSha256::kDigestSize];
+
+ u[0] = 0;
+ u[1] = 0;
+ u[2] = 0;
+ u[3] = 1;
+
+ ctx.Update(u, 4);
+ ctx.Final(u);
+
+ memcpy(key, u, NSha256::kDigestSize);
+
+ UInt32 numIterations = ((UInt32)1 << _numIterationsLog) - 1;
+
+ for (unsigned i = 0; i < 3; i++)
+ {
+ UInt32 j = numIterations;
+
+ for (; j != 0; j--)
+ {
+ ctx = baseCtx;
+ ctx.Update(u, NSha256::kDigestSize);
+ ctx.Final(u);
+ for (unsigned s = 0; s < NSha256::kDigestSize; s++)
+ key[s] ^= u[s];
+ }
+
+ // RAR uses additional iterations for additional keys
+ memcpy((i == 0 ? _key : (i == 1 ? _hashKey : pswCheck)), key, NSha256::kDigestSize);
+ numIterations = 16;
+ }
+ }
+
+ {
+ unsigned i;
+
+ for (i = 0; i < kPswCheckSize; i++)
+ _check_Calced[i] = pswCheck[i];
+
+ for (i = kPswCheckSize; i < SHA256_DIGEST_SIZE; i++)
+ _check_Calced[i & (kPswCheckSize - 1)] ^= pswCheck[i];
+ }
+
+ _needCalc = false;
+
+ {
+ MT_LOCK
+ g_Key = *this;
+ }
+ }
+ }
+
+ if (IsThereCheck() && _canCheck)
+ return (memcmp(_check_Calced, _check, kPswCheckSize) == 0);
+ return true;
+}
+
+}}
diff --git a/CPP/7zip/Crypto/Rar5Aes.h b/CPP/7zip/Crypto/Rar5Aes.h
new file mode 100644
index 00000000..c69b24e4
--- /dev/null
+++ b/CPP/7zip/Crypto/Rar5Aes.h
@@ -0,0 +1,84 @@
+// Crypto/Rar5Aes.h
+
+#ifndef __CRYPTO_RAR5_AES_H
+#define __CRYPTO_RAR5_AES_H
+
+#include "../../../C/Aes.h"
+
+#include "../../Common/MyBuffer.h"
+
+#include "HmacSha256.h"
+#include "MyAes.h"
+
+namespace NCrypto {
+namespace NRar5 {
+
+const unsigned kSaltSize = 16;
+const unsigned kPswCheckSize = 8;
+const unsigned kAesKeySize = 32;
+
+namespace NCryptoFlags
+{
+ const unsigned kPswCheck = 1 << 0;
+ const unsigned kUseMAC = 1 << 1;
+}
+
+struct CKey
+{
+ bool _needCalc;
+
+ unsigned _numIterationsLog;
+ Byte _salt[kSaltSize];
+ CByteBuffer _password;
+
+ Byte _key[kAesKeySize];
+ Byte _check_Calced[kPswCheckSize];
+ Byte _hashKey[SHA256_DIGEST_SIZE];
+
+ void CopyCalcedKeysFrom(const CKey &k)
+ {
+ memcpy(_key, k._key, sizeof(_key));
+ memcpy(_check_Calced, k._check_Calced, sizeof(_check_Calced));
+ memcpy(_hashKey, k._hashKey, sizeof(_hashKey));
+ }
+
+ bool IsKeyEqualTo(const CKey &key)
+ {
+ return (_numIterationsLog == key._numIterationsLog
+ && memcmp(_salt, key._salt, sizeof(_salt)) == 0
+ && _password == key._password);
+ }
+
+ CKey();
+};
+
+
+class CDecoder:
+ public CAesCbcDecoder,
+ public CKey
+{
+ Byte _check[kPswCheckSize];
+ bool _canCheck;
+ UInt64 Flags;
+
+ bool IsThereCheck() const { return ((Flags & NCryptoFlags::kPswCheck) != 0); }
+public:
+ Byte _iv[AES_BLOCK_SIZE];
+
+ CDecoder();
+
+ STDMETHOD(Init)();
+
+ void SetPassword(const Byte *data, size_t size);
+ HRESULT SetDecoderProps(const Byte *data, unsigned size, bool includeIV, bool isService);
+
+ bool CalcKey_and_CheckPassword();
+
+ bool UseMAC() const { return (Flags & NCryptoFlags::kUseMAC) != 0; }
+ UInt32 Hmac_Convert_Crc32(UInt32 crc) const;
+ void Hmac_Convert_32Bytes(Byte *data) const;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Crypto/RarAes.cpp b/CPP/7zip/Crypto/RarAes.cpp
index f562023a..5bae8529 100644
--- a/CPP/7zip/Crypto/RarAes.cpp
+++ b/CPP/7zip/Crypto/RarAes.cpp
@@ -1,5 +1,4 @@
// Crypto/RarAes.cpp
-// Note: you must include MyAes.cpp to project to initialize AES tables
#include "StdAfx.h"
@@ -7,10 +6,10 @@
#include "Sha1Cls.h"
namespace NCrypto {
-namespace NRar29 {
+namespace NRar3 {
CDecoder::CDecoder():
- CAesCbcDecoder(kRarAesKeySize),
+ CAesCbcDecoder(kAesKeySize),
_thereIsSalt(false),
_needCalc(true),
_rar350Mode(false)
@@ -19,7 +18,7 @@ CDecoder::CDecoder():
_salt[i] = 0;
}
-STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
+HRESULT CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
{
bool prev = _thereIsSalt;
_thereIsSalt = false;
@@ -53,12 +52,12 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
return S_OK;
}
-static const unsigned kPasswordLen_MAX = 127 * 2;
+static const unsigned kPasswordLen_Bytes_MAX = 127 * 2;
-STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
+void CDecoder::SetPassword(const Byte *data, unsigned size)
{
- if (size > kPasswordLen_MAX)
- size = kPasswordLen_MAX;
+ if (size > kPasswordLen_Bytes_MAX)
+ size = kPasswordLen_Bytes_MAX;
bool same = false;
if (size == _password.Size())
{
@@ -73,13 +72,12 @@ STDMETHODIMP CDecoder::CryptoSetPassword(const Byte *data, UInt32 size)
if (!_needCalc && !same)
_needCalc = true;
_password.CopyFrom(data, (size_t)size);
- return S_OK;
}
STDMETHODIMP CDecoder::Init()
{
CalcKey();
- RINOK(SetKey(_key, kRarAesKeySize));
+ RINOK(SetKey(_key, kAesKeySize));
RINOK(SetInitVector(_iv, AES_BLOCK_SIZE));
return CAesCbcCoder::Init();
}
@@ -91,7 +89,7 @@ void CDecoder::CalcKey()
const unsigned kSaltSize = 8;
- Byte buf[kPasswordLen_MAX + kSaltSize];
+ Byte buf[kPasswordLen_Bytes_MAX + kSaltSize];
if (_password.Size() != 0)
memcpy(buf, _password, _password.Size());
@@ -109,7 +107,7 @@ void CDecoder::CalcKey()
Byte digest[NSha1::kDigestSize];
// rar reverts hash for sha.
- const UInt32 kNumRounds = (1 << 18);
+ const UInt32 kNumRounds = ((UInt32)1 << 18);
UInt32 i;
for (i = 0; i < kNumRounds; i++)
{
diff --git a/CPP/7zip/Crypto/RarAes.h b/CPP/7zip/Crypto/RarAes.h
index 197a0b2d..083b4104 100644
--- a/CPP/7zip/Crypto/RarAes.h
+++ b/CPP/7zip/Crypto/RarAes.h
@@ -12,14 +12,14 @@
#include "MyAes.h"
namespace NCrypto {
-namespace NRar29 {
+namespace NRar3 {
-const UInt32 kRarAesKeySize = 16;
+const unsigned kAesKeySize = 16;
class CDecoder:
- public CAesCbcDecoder,
+ public CAesCbcDecoder
// public ICompressSetDecoderProperties2,
- public ICryptoSetPassword
+ // public ICryptoSetPassword
{
Byte _salt[8];
bool _thereIsSalt;
@@ -28,17 +28,20 @@ class CDecoder:
CByteBuffer _password;
- Byte _key[kRarAesKeySize];
+ Byte _key[kAesKeySize];
Byte _iv[AES_BLOCK_SIZE];
void CalcKey();
public:
+ /*
MY_UNKNOWN_IMP1(
- ICryptoSetPassword)
+ ICryptoSetPassword
// ICompressSetDecoderProperties2
+ */
STDMETHOD(Init)();
- STDMETHOD(CryptoSetPassword)(const Byte *aData, UInt32 aSize);
- STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+
+ void SetPassword(const Byte *data, unsigned size);
+ HRESULT SetDecoderProperties2(const Byte *data, UInt32 size);
CDecoder();
void SetRar350Mode(bool rar350Mode) { _rar350Mode = rar350Mode; }
diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt
index 64214e80..1ab1b7a2 100644
--- a/CPP/7zip/Guid.txt
+++ b/CPP/7zip/Guid.txt
@@ -163,6 +163,7 @@ Handler GUIDs:
0C xz
0D ppmd
+ CC Rar5
CD IHex
CE Hxs
CF TE
diff --git a/CPP/7zip/IProgress.h b/CPP/7zip/IProgress.h
index 59c55aea..fac951ec 100644
--- a/CPP/7zip/IProgress.h
+++ b/CPP/7zip/IProgress.h
@@ -4,7 +4,6 @@
#define __IPROGRESS_H
#include "../Common/MyTypes.h"
-#include "../Common/MyUnknown.h"
#include "IDecl.h"
diff --git a/CPP/7zip/IStream.h b/CPP/7zip/IStream.h
index 70cb3620..9a0bcbf3 100644
--- a/CPP/7zip/IStream.h
+++ b/CPP/7zip/IStream.h
@@ -4,7 +4,7 @@
#define __ISTREAM_H
#include "../Common/MyTypes.h"
-#include "../Common/MyUnknown.h"
+#include "../Common/MyWindows.h"
#include "IDecl.h"
diff --git a/CPP/7zip/PropID.h b/CPP/7zip/PropID.h
index 3f3acb2d..1822f402 100644
--- a/CPP/7zip/PropID.h
+++ b/CPP/7zip/PropID.h
@@ -102,6 +102,7 @@ enum
kpidStreamId,
kpidReadOnly,
kpidOutName,
+ kpidCopyLink,
kpid_NUM_DEFINED,
diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp
index 3fed8cba..0468fdd1 100644
--- a/CPP/7zip/UI/Agent/AgentOut.cpp
+++ b/CPP/7zip/UI/Agent/AgentOut.cpp
@@ -380,6 +380,21 @@ STDMETHODIMP CAgent::DoOperation(
HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback);
if (res == S_OK && processedPaths)
{
+ {
+ /* OutHandler for 7z archives doesn't report compression operation for empty files.
+ So we must include these files manually */
+ FOR_VECTOR(i, updatePairs2)
+ {
+ const CUpdatePair2 &up = updatePairs2[i];
+ if (up.DirIndex >= 0 && up.NewData)
+ {
+ const CDirItem &di = dirItems.Items[up.DirIndex];
+ if (!di.IsDir() && di.Size == 0)
+ processedItems[up.DirIndex] = 1;
+ }
+ }
+ }
+
FOR_VECTOR (i, dirItems.Items)
if (processedItems[i] != 0)
processedPaths->Add(dirItems.GetPhyPath(i));
diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp
index 4df4b199..4d85754d 100644
--- a/CPP/7zip/UI/Client7z/Client7z.cpp
+++ b/CPP/7zip/UI/Client7z/Client7z.cpp
@@ -4,6 +4,8 @@
#include <stdio.h>
+#include "../../../Common/MyWindows.h"
+
#include "../../../Common/Defs.h"
#include "../../../Common/MyInitGuid.h"
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
index 8410756a..8e4936a9 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -5,6 +5,8 @@
#undef sprintf
#undef printf
+#include "../../../../C/Alloc.h"
+
#include "../../../Common/ComTry.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
@@ -23,6 +25,7 @@
#endif
#include "../../Common/FilePathAutoRename.h"
+// #include "../../Common/StreamUtils.h"
#include "../Common/ExtractingFilePath.h"
#include "../Common/PropIDUtils.h"
@@ -541,11 +544,54 @@ static FString MakePath_from_2_Parts(const FString &prefix, const FString &path)
return s;
}
+
+/*
+#ifdef SUPPORT_LINKS
+
+struct CTempMidBuffer
+{
+ void *Buf;
+
+ CTempMidBuffer(size_t size): Buf(NULL) { Buf = ::MidAlloc(size); }
+ ~CTempMidBuffer() { ::MidFree(Buf); }
+};
+
+HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream)
+{
+ const size_t kBufSize = 1 << 16;
+ CTempMidBuffer buf(kBufSize);
+ if (!buf.Buf)
+ return E_OUTOFMEMORY;
+
+ NIO::CInFile inFile;
+ NIO::COutFile outFile;
+
+ if (!inFile.Open(_CopyFile_Path))
+ return SendMessageError_with_LastError("Open error", _CopyFile_Path);
+
+ for (;;)
+ {
+ UInt32 num;
+
+ if (!inFile.Read(buf.Buf, kBufSize, num))
+ return SendMessageError_with_LastError("Read error", _CopyFile_Path);
+
+ if (num == 0)
+ return S_OK;
+
+
+ RINOK(WriteStream(outStream, buf.Buf, num));
+ }
+}
+
+#endif
+*/
+
STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
{
COM_TRY_BEGIN
- *outStream = 0;
+ *outStream = NULL;
#ifndef _SFX
if (_hashStream)
@@ -563,6 +609,11 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
_curSizeDefined = false;
_index = index;
+ #ifdef SUPPORT_LINKS
+ // _CopyFile_Path.Empty();
+ linkPath.Empty();
+ #endif
+
IInArchive *archive = _arc->Archive;
#ifndef _SFX
@@ -596,46 +647,56 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
#ifdef SUPPORT_LINKS
+ // bool isCopyLink = false;
bool isHardLink = false;
bool isJunction = false;
bool isRelative = false;
- UString linkPath;
- // RINOK(Archive_GetItemBoolProp(archive, index, kpidIsHardLink, isHardLink));
- // if (isHardLink)
{
NCOM::CPropVariant prop;
RINOK(archive->GetProperty(index, kpidHardLink, &prop));
if (prop.vt == VT_BSTR)
{
isHardLink = true;
+ // isCopyLink = false;
+ isRelative = false; // RAR5, TAR: hard links are from root folder of archive
linkPath.SetFromBstr(prop.bstrVal);
- isRelative = false; // TAR: hard links are from root folder of archive
}
- else if (prop.vt == VT_EMPTY)
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ }
+
+ /*
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidCopyLink, &prop));
+ if (prop.vt == VT_BSTR)
{
- // linkPath.Empty();
+ isHardLink = false;
+ isCopyLink = true;
+ isRelative = false; // RAR5: copy links are from root folder of archive
+ linkPath.SetFromBstr(prop.bstrVal);
}
- else
+ else if (prop.vt != VT_EMPTY)
return E_FAIL;
}
+ */
+
{
NCOM::CPropVariant prop;
RINOK(archive->GetProperty(index, kpidSymLink, &prop));
if (prop.vt == VT_BSTR)
{
isHardLink = false;
+ // isCopyLink = false;
+ isRelative = true; // RAR5, TAR: symbolic links can be relative
linkPath.SetFromBstr(prop.bstrVal);
- isRelative = true; // TAR: symbolic links are relative
}
- else if (prop.vt == VT_EMPTY)
- {
- // linkPath.Empty();
- }
- else
+ else if (prop.vt != VT_EMPTY)
return E_FAIL;
}
+
bool isOkReparse = false;
if (linkPath.IsEmpty() && _arc->GetRawProps)
@@ -643,7 +704,9 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
const void *data;
UInt32 dataSize;
UInt32 propType;
+
_arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType);
+
if (dataSize != 0)
{
if (propType != NPropDataType::kRaw)
@@ -654,6 +717,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
if (isOkReparse)
{
isHardLink = false;
+ // isCopyLink = false;
linkPath = reparse.GetPath();
isJunction = reparse.IsMountPoint();
isRelative = reparse.IsRelative();
@@ -669,6 +733,13 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
#ifdef _WIN32
linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR);
#endif
+
+ // rar5 uses "\??\" prefix for absolute links
+ if (linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR))
+ {
+ isRelative = false;
+ linkPath.DeleteFrontal(4);
+ }
for (;;)
// while (NName::IsAbsolutePath(linkPath))
@@ -1108,7 +1179,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
else
{
FString existPath;
- if (isHardLink || !isRelative)
+ if (isHardLink /* || isCopyLink */ || !isRelative)
{
if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath))
{
@@ -1122,13 +1193,37 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
if (!existPath.IsEmpty())
{
- if (isHardLink)
+ if (isHardLink /* || isCopyLink */)
{
- if (!MyCreateHardLink(fullProcessedPath, existPath))
+ // if (isHardLink)
{
- RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath));
- // return S_OK;
+ if (!MyCreateHardLink(fullProcessedPath, existPath))
+ {
+ RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath));
+ // return S_OK;
+ }
}
+ /*
+ else
+ {
+ NFind::CFileInfo fi;
+ if (!fi.Find(existPath))
+ {
+ RINOK(SendMessageError2("Can not find the file for copying", existPath, fullProcessedPath));
+ }
+ else
+ {
+ if (_curSizeDefined && _curSize == fi.Size)
+ _CopyFile_Path = existPath;
+ else
+ {
+ RINOK(SendMessageError2("File size collision for file copying", existPath, fullProcessedPath));
+ }
+
+ // RINOK(MyCopyFile(existPath, fullProcessedPath));
+ }
+ }
+ */
}
else if (_ntOptions.SymLinks.Val)
{
@@ -1161,7 +1256,8 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
#endif
}
- else
+
+ if (linkPath.IsEmpty() /* || !_CopyFile_Path.IsEmpty() */)
#endif // SUPPORT_LINKS
{
bool needWriteFile = true;
@@ -1225,6 +1321,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
{
RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
}
+
_outFileStream = outStreamLoc;
}
}
@@ -1250,12 +1347,34 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
#endif
+
if (outStreamLoc)
+ {
+ /*
+ #ifdef SUPPORT_LINKS
+
+ if (!_CopyFile_Path.IsEmpty())
+ {
+ RINOK(PrepareOperation(askExtractMode));
+ RINOK(MyCopyFile(outStreamLoc));
+ return SetOperationResult(NArchive::NExtract::NOperationResult::kOK);
+ }
+
+ if (isCopyLink && _testMode)
+ return S_OK;
+
+ #endif
+ */
+
*outStream = outStreamLoc.Detach();
+ }
+
return S_OK;
+
COM_TRY_END
}
+
STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
{
COM_TRY_BEGIN
@@ -1266,6 +1385,7 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
#endif
_extractMode = false;
+
switch (askExtractMode)
{
case NArchive::NExtract::NAskMode::kExtract:
@@ -1282,6 +1402,7 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
COM_TRY_END
}
+
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
{
COM_TRY_BEGIN
@@ -1346,6 +1467,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
if (!_curSizeDefined)
GetUnpackSize();
+
if (_curSizeDefined)
{
#ifdef SUPPORT_ALT_STREAMS
@@ -1367,8 +1489,11 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
if (_extractMode && _fi.AttribDefined)
SetFileAttrib(_diskFilePath, _fi.Attrib);
+
RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)));
+
return S_OK;
+
COM_TRY_END
}
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
index 561a6e42..7d4155fe 100644
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -299,14 +299,23 @@ public:
const UStringVector &removePathParts, bool removePartsForAltStreams,
UInt64 packSize);
+
#ifdef SUPPORT_LINKS
+
private:
CHardLinks _hardLinks;
+ UString linkPath;
+
+ // FString _CopyFile_Path;
+ // HRESULT MyCopyFile(ISequentialOutStream *outStream);
+
public:
// call PrepareHardLinks() after Init()
HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items
+
#endif
+
#ifdef SUPPORT_ALT_STREAMS
CObjectVector<CIndexToPathPair> _renamedFiles;
#endif
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
index afa03766..e9575f56 100644
--- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h
@@ -48,18 +48,13 @@ class COpenCallbackImp:
public CMyUnknownImp
{
public:
+ MY_QUERYINTERFACE_BEGIN2(IArchiveOpenVolumeCallback)
+ MY_QUERYINTERFACE_ENTRY(IArchiveOpenSetSubArchiveName)
#ifndef _NO_CRYPTO
- MY_UNKNOWN_IMP3(
- IArchiveOpenVolumeCallback,
- ICryptoGetTextPassword,
- IArchiveOpenSetSubArchiveName
- )
- #else
- MY_UNKNOWN_IMP2(
- IArchiveOpenVolumeCallback,
- IArchiveOpenSetSubArchiveName
- )
+ MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
#endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
INTERFACE_IArchiveOpenCallback(;)
INTERFACE_IArchiveOpenVolumeCallback(;)
@@ -93,7 +88,8 @@ public:
CMyComPtr<IArchiveOpenCallback> ReOpenCallback;
// UInt64 TotalSize;
- COpenCallbackImp(): Callback(NULL) {}
+ COpenCallbackImp(): Callback(NULL), _subArchiveMode(false) {}
+
void Init(const FString &folderPrefix, const FString &fileName)
{
_folderPrefix = folderPrefix;
@@ -106,6 +102,7 @@ public:
// TotalSize = 0;
PasswordWasAsked = false;
}
+
bool SetSecondFileInfo(CFSTR newName)
{
return _fileInfo.Find(newName) && !_fileInfo.IsDir();
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp
index c38b132c..5f6373f4 100644
--- a/CPP/7zip/UI/Common/Bench.cpp
+++ b/CPP/7zip/UI/Common/Bench.cpp
@@ -1566,7 +1566,8 @@ static const CBenchHash g_Hash[] =
{ 10, 339, 0x8F8FEDAB, "CRC32:8" },
{ 10, 512, 0xDF1C17CC, "CRC64" },
{ 10, 5100, 0x2D79FF2E, "SHA256" },
- { 10, 2340, 0x4C25132B, "SHA1" }
+ { 10, 2340, 0x4C25132B, "SHA1" },
+ { 2, 5500, 0xE084E913, "BLAKE2sp" }
};
struct CTotalBenchRes
diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp
index 696b6749..5435499b 100644
--- a/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -865,7 +865,7 @@ STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)
{
const CCodecLib &lib = Libs[ci.LibIndex];
if (lib.CreateDecoder)
- return lib.CreateDecoder(index - NUM_EXPORT_CODECS, iid, (void **)coder);
+ return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder);
return lib.CreateObject(&ci.Decoder, iid, (void **)coder);
}
return S_OK;
@@ -887,7 +887,7 @@ STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)
{
const CCodecLib &lib = Libs[ci.LibIndex];
if (lib.CreateEncoder)
- return lib.CreateEncoder(index - NUM_EXPORT_CODECS, iid, (void **)coder);
+ return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder);
return lib.CreateObject(&ci.Encoder, iid, (void **)coder);
}
return S_OK;
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
index acc10876..a7488044 100644
--- a/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -1083,6 +1083,7 @@ static bool IsNewStyleSignature(const CArcInfoEx &ai)
class CArchiveOpenCallback_Offset:
public IArchiveOpenCallback,
+ public IArchiveOpenVolumeCallback,
#ifndef _NO_CRYPTO
public ICryptoGetTextPassword,
#endif
@@ -1090,19 +1091,24 @@ class CArchiveOpenCallback_Offset:
{
public:
CMyComPtr<IArchiveOpenCallback> Callback;
+ CMyComPtr<IArchiveOpenVolumeCallback> OpenVolumeCallback;
UInt64 Files;
UInt64 Offset;
#ifndef _NO_CRYPTO
CMyComPtr<ICryptoGetTextPassword> GetTextPassword;
- MY_UNKNOWN_IMP2(
- IArchiveOpenCallback,
- ICryptoGetTextPassword)
- #else
- MY_UNKNOWN_IMP1(IArchiveOpenCallback)
#endif
- STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);
- STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);
+
+ MY_QUERYINTERFACE_BEGIN2(IArchiveOpenCallback)
+ MY_QUERYINTERFACE_ENTRY(IArchiveOpenVolumeCallback)
+ #ifndef _NO_CRYPTO
+ MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
+ #endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+
+ INTERFACE_IArchiveOpenCallback(;)
+ INTERFACE_IArchiveOpenVolumeCallback(;)
#ifndef _NO_CRYPTO
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
#endif
@@ -1119,12 +1125,12 @@ STDMETHODIMP CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password)
}
#endif
-STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)
+STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 *, const UInt64 *)
{
return S_OK;
}
-STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files */, const UInt64 *bytes)
+STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 *, const UInt64 *bytes)
{
if (!Callback)
return S_OK;
@@ -1134,8 +1140,25 @@ STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files *
return Callback->SetCompleted(&Files, &value);
}
+STDMETHODIMP CArchiveOpenCallback_Offset::GetProperty(PROPID propID, PROPVARIANT *value)
+{
+ if (OpenVolumeCallback)
+ return OpenVolumeCallback->GetProperty(propID, value);
+ NCOM::PropVariant_Clear(value);
+ return S_OK;
+ // return E_NOTIMPL;
+}
+
+STDMETHODIMP CArchiveOpenCallback_Offset::GetStream(const wchar_t *name, IInStream **inStream)
+{
+ if (OpenVolumeCallback)
+ return OpenVolumeCallback->GetStream(name, inStream);
+ return S_FALSE;
+}
+
#endif
+
UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp)
{
if (isDefinedProp != NULL)
@@ -2208,9 +2231,6 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
{
- CArchiveOpenCallback_Offset *openCallback_Offset_Spec = new CArchiveOpenCallback_Offset;
- CMyComPtr<IArchiveOpenCallback> openCallback_Offset = openCallback_Offset_Spec;
-
const size_t kBeforeSize = 1 << 16;
const size_t kAfterSize = 1 << 20;
const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize
@@ -2288,14 +2308,18 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
CMyComPtr<IInStream> limitedStream = limitedStreamSpec;
limitedStreamSpec->SetStream(op.stream);
- openCallback_Offset_Spec->Callback = op.callback;
-
- #ifndef _NO_CRYPTO
+ CArchiveOpenCallback_Offset *openCallback_Offset_Spec = NULL;
+ CMyComPtr<IArchiveOpenCallback> openCallback_Offset;
if (op.callback)
{
+ openCallback_Offset_Spec = new CArchiveOpenCallback_Offset;
+ openCallback_Offset = openCallback_Offset_Spec;
+ openCallback_Offset_Spec->Callback = op.callback;
+ openCallback_Offset_Spec->Callback.QueryInterface(IID_IArchiveOpenVolumeCallback, &openCallback_Offset_Spec->OpenVolumeCallback);
+ #ifndef _NO_CRYPTO
openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword);
+ #endif
}
- #endif
if (op.callback)
RINOK(op.callback->SetTotal(NULL, &fileSize));
@@ -2382,12 +2406,19 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
}
- if (pos >= callbackPrev + (1 << 23))
+ bool useOffsetCallback = false;
+ if (openCallback_Offset)
{
openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
openCallback_Offset_Spec->Offset = pos;
- RINOK(openCallback_Offset->SetCompleted(NULL, NULL));
- callbackPrev = pos;
+
+ useOffsetCallback = (!op.openType.CanReturnArc || handlerSpec->_items.Size() > 1);
+
+ if (pos >= callbackPrev + (1 << 23))
+ {
+ RINOK(openCallback_Offset_Spec->SetCompleted(NULL, NULL));
+ callbackPrev = pos;
+ }
}
{
@@ -2557,14 +2588,21 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
UInt64 maxCheckStartPosition = 0;
- openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
- openCallback_Offset_Spec->Offset = startArcPos;
+
+ if (openCallback_Offset)
+ {
+ openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
+ openCallback_Offset_Spec->Offset = startArcPos;
+ }
+
// HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset);
extractCallback_To_OpenCallback_Spec->Files = 0;
extractCallback_To_OpenCallback_Spec->Offset = startArcPos;
- HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition, openCallback_Offset, extractCallback_To_OpenCallback);
-
+ HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition,
+ useOffsetCallback ? (IArchiveOpenCallback *)openCallback_Offset : (IArchiveOpenCallback *)op.callback,
+ extractCallback_To_OpenCallback);
+
RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result));
bool isOpen = false;
diff --git a/CPP/7zip/UI/Common/UpdateAction.h b/CPP/7zip/UI/Common/UpdateAction.h
index 28dd28c3..bc53fcdb 100644
--- a/CPP/7zip/UI/Common/UpdateAction.h
+++ b/CPP/7zip/UI/Common/UpdateAction.h
@@ -35,7 +35,7 @@ namespace NUpdateArchive {
{
NPairAction::EEnum StateActions[NPairState::kNumValues];
- const bool IsEqualTo(const CActionSet &a) const
+ bool IsEqualTo(const CActionSet &a) const
{
for (unsigned i = 0; i < NPairState::kNumValues; i++)
if (StateActions[i] != a.StateActions[i])
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp
index 993ab266..058e9153 100644
--- a/CPP/7zip/UI/Common/UpdateCallback.cpp
+++ b/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -413,7 +413,7 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
{
case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break;
case kpidIsDir: prop = di.IsDir(); break;
- case kpidSize: prop = di.Size; break;
+ case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break;
case kpidAttrib: prop = di.Attrib; break;
case kpidCTime: prop = di.CTime; break;
case kpidATime: prop = di.ATime; break;
diff --git a/CPP/7zip/UI/Console/ConsoleClose.cpp b/CPP/7zip/UI/Console/ConsoleClose.cpp
index 75bd9e51..6bf2531d 100644
--- a/CPP/7zip/UI/Console/ConsoleClose.cpp
+++ b/CPP/7zip/UI/Console/ConsoleClose.cpp
@@ -4,6 +4,10 @@
#include "ConsoleClose.h"
+#if !defined(UNDER_CE) && defined(_WIN32)
+#include "../../../Common/MyWindows.h"
+#endif
+
namespace NConsoleClose {
unsigned g_BreakCounter = 0;
diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp
index 64abb1fb..e70f1b67 100644
--- a/CPP/7zip/UI/Console/List.cpp
+++ b/CPP/7zip/UI/Console/List.cpp
@@ -123,6 +123,7 @@ static const char * const kPropIdToName[] =
, "Stream ID"
, "Read-only"
, "Out Name"
+ , "Copy Link"
};
static const char kEmptyAttribChar = '.';
diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp
index 83e6ef5b..b9cb4eb9 100644
--- a/CPP/7zip/UI/Console/Main.cpp
+++ b/CPP/7zip/UI/Console/Main.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include <Psapi.h>
#include "../../../../C/CpuArch.h"
@@ -230,42 +232,51 @@ static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so)
}
static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
- const CUpdateErrorInfo &errorInfo, CStdOutStream &so, bool showHeaders)
+ const CUpdateErrorInfo &errorInfo,
+ CStdOutStream *so,
+ CStdOutStream *se,
+ bool showHeaders)
{
int exitCode = NExitCode::kSuccess;
if (callback.ScanErrors.Paths.Size() != 0)
{
- so << endl;
- so << "Scan WARNINGS for files and folders:" << endl << endl;
- PrintWarningsPaths(callback.ScanErrors, so);
- so << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();
- so << endl;
+ if (se)
+ {
+ *se << endl;
+ *se << "Scan WARNINGS for files and folders:" << endl << endl;
+ PrintWarningsPaths(callback.ScanErrors, *se);
+ *se << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size();
+ *se << endl;
+ }
exitCode = NExitCode::kWarning;
}
if (result != S_OK || errorInfo.ThereIsError())
{
- UString message;
- if (!errorInfo.Message.IsEmpty())
- {
- message.AddAscii(errorInfo.Message);
- message.Add_LF();
- }
+ if (se)
{
- FOR_VECTOR(i, errorInfo.FileNames)
+ UString message;
+ if (!errorInfo.Message.IsEmpty())
{
- message += fs2us(errorInfo.FileNames[i]);
+ message.AddAscii(errorInfo.Message);
message.Add_LF();
}
+ {
+ FOR_VECTOR(i, errorInfo.FileNames)
+ {
+ message += fs2us(errorInfo.FileNames[i]);
+ message.Add_LF();
+ }
+ }
+ if (errorInfo.SystemError != 0)
+ {
+ message += NError::MyFormatMessage(errorInfo.SystemError);
+ message.Add_LF();
+ }
+ if (!message.IsEmpty())
+ *se << L"\nError:\n" << message;
}
- if (errorInfo.SystemError != 0)
- {
- message += NError::MyFormatMessage(errorInfo.SystemError);
- message.Add_LF();
- }
- if (!message.IsEmpty())
- so << L"\nError:\n" << message;
// we will work with (result) later
// throw CSystemException(result);
@@ -277,17 +288,25 @@ static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback,
{
if (showHeaders)
if (callback.ScanErrors.Paths.Size() == 0)
- so << kEverythingIsOk << endl;
+ if (so)
+ {
+ if (se)
+ se->Flush();
+ *so << kEverythingIsOk << endl;
+ }
}
else
{
- so << endl;
- so << "WARNINGS for files:" << endl << endl;
- PrintWarningsPaths(callback.FailedFiles, so);
- so << "WARNING: Cannot open " << numErrors << " file";
- if (numErrors > 1)
- so << 's';
- so << endl;
+ if (se)
+ {
+ *se << endl;
+ *se << "WARNINGS for files:" << endl << endl;
+ PrintWarningsPaths(callback.FailedFiles, *se);
+ *se << "WARNING: Cannot open " << numErrors << " file";
+ if (numErrors > 1)
+ *se << 's';
+ *se << endl;
+ }
exitCode = NExitCode::kWarning;
}
@@ -473,10 +492,7 @@ int Main2(
CStdOutStream *percentsStream = NULL;
if (options.Number_for_Percents != k_OutStream_disabled)
percentsStream = (options.Number_for_Percents == k_OutStream_stderr) ? &g_StdErr : &g_StdOut;;
-
- CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
-
if (options.HelpMode)
{
ShowCopyrightAndHelp(g_StdStream, true);
@@ -589,6 +605,7 @@ int Main2(
if (options.Command.CommandType == NCommandType::kInfo)
{
+ CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
unsigned i;
#ifdef EXTERNAL_CODECS
@@ -754,6 +771,7 @@ int Main2(
}
else if (options.Command.CommandType == NCommandType::kBenchmark)
{
+ CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut);
hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L
options.Properties, options.NumIterations, (FILE *)so);
if (hresultMain == S_FALSE)
@@ -890,73 +908,91 @@ int Main2(
hresultMain = E_FAIL;
}
- so << endl;
+ CStdOutStream *so = g_StdStream;
+
+ bool isError = false;
- if (ecs->NumTryArcs > 1)
+ if (so)
{
- so << "Archives: " << ecs->NumTryArcs << endl;
- so << "OK archives: " << ecs->NumOkArcs << endl;
+ *so << endl;
+
+ if (ecs->NumTryArcs > 1)
+ {
+ *so << "Archives: " << ecs->NumTryArcs << endl;
+ *so << "OK archives: " << ecs->NumOkArcs << endl;
+ }
}
- bool isError = false;
+
if (ecs->NumCantOpenArcs != 0)
{
isError = true;
- so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl;
+ if (so)
+ *so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl;
}
+
if (ecs->NumArcsWithError != 0)
{
isError = true;
- so << "Archives with Errors: " << ecs->NumArcsWithError << endl;
+ if (so)
+ *so << "Archives with Errors: " << ecs->NumArcsWithError << endl;
}
- if (ecs->NumArcsWithWarnings != 0)
- so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
- if (ecs->NumOpenArcWarnings != 0)
+ if (so)
{
- so << endl;
+ if (ecs->NumArcsWithWarnings != 0)
+ *so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl;
+
if (ecs->NumOpenArcWarnings != 0)
- so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
+ {
+ *so << endl;
+ if (ecs->NumOpenArcWarnings != 0)
+ *so << "Warnings: " << ecs->NumOpenArcWarnings << endl;
+ }
}
if (ecs->NumOpenArcErrors != 0)
{
isError = true;
- so << endl;
- if (ecs->NumOpenArcErrors != 0)
- so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
+ if (so)
+ {
+ *so << endl;
+ if (ecs->NumOpenArcErrors != 0)
+ *so << "Open Errors: " << ecs->NumOpenArcErrors << endl;
+ }
}
if (isError)
retCode = NExitCode::kFatalError;
+ if (so)
if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)
{
// if (ecs->NumArchives > 1)
{
- so << endl;
+ *so << endl;
if (ecs->NumFileErrors != 0)
- so << "Sub items Errors: " << ecs->NumFileErrors << endl;
+ *so << "Sub items Errors: " << ecs->NumFileErrors << endl;
}
}
else if (hresultMain == S_OK)
{
if (stat.NumFolders != 0)
- so << "Folders: " << stat.NumFolders << endl;
+ *so << "Folders: " << stat.NumFolders << endl;
if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0)
- so << "Files: " << stat.NumFiles << endl;
+ *so << "Files: " << stat.NumFiles << endl;
if (stat.NumAltStreams != 0)
{
- so << "Alternate Streams: " << stat.NumAltStreams << endl;
- so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;
+ *so << "Alternate Streams: " << stat.NumAltStreams << endl;
+ *so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl;
}
- so
+ *so
<< "Size: " << stat.UnpackSize << endl
<< "Compressed: " << stat.PackSize << endl;
if (hashCalc)
{
- so << endl;
- PrintHashStat(so, hb);
+ *so << endl;
+ PrintHashStat(*so, hb);
}
}
}
@@ -1047,9 +1083,14 @@ int Main2(
callback.ClosePercents2();
- retCode = WarningsCheck(hresultMain, callback, errorInfo, so,
- // options.EnableHeaders
- true);
+ CStdOutStream *se = g_StdStream;
+ if (!se)
+ se = g_ErrStream;
+
+ retCode = WarningsCheck(hresultMain, callback, errorInfo,
+ g_StdStream, se,
+ true // options.EnableHeaders
+ );
}
else if (options.Command.CommandType == NCommandType::kHash)
{
@@ -1068,7 +1109,10 @@ int Main2(
errorInfoString, &callback);
CUpdateErrorInfo errorInfo;
errorInfo.Message = errorInfoString;
- retCode = WarningsCheck(hresultMain, callback, errorInfo, so, options.EnableHeaders);
+ CStdOutStream *se = g_StdStream;
+ if (!se)
+ se = g_ErrStream;
+ retCode = WarningsCheck(hresultMain, callback, errorInfo, g_StdStream, se, options.EnableHeaders);
}
else
ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h
index a3b1174b..90ca0e64 100644
--- a/CPP/7zip/UI/Explorer/ContextMenu.h
+++ b/CPP/7zip/UI/Explorer/ContextMenu.h
@@ -3,6 +3,10 @@
#ifndef __CONTEXT_MENU_H
#define __CONTEXT_MENU_H
+#include "../../../Common/MyWindows.h"
+
+#include <ShlObj.h>
+
#include "../../../Common/MyString.h"
#include "../FileManager/MyCom2.h"
diff --git a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
index d620cb70..3b04e7be 100644
--- a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
+++ b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp
@@ -8,11 +8,13 @@
#include "StdAfx.h"
-#include "../../../Common/MyInitGuid.h"
+#include "../../../Common/MyWindows.h"
#include <ShlGuid.h>
#include <OleCtl.h>
+#include "../../../Common/MyInitGuid.h"
+
#include "../../../Common/ComTry.h"
#include "../../../Common/StringConvert.h"
diff --git a/CPP/7zip/UI/Far/Far.cpp b/CPP/7zip/UI/Far/Far.cpp
index 3ae5bba2..d5656e29 100644
--- a/CPP/7zip/UI/Far/Far.cpp
+++ b/CPP/7zip/UI/Far/Far.cpp
@@ -3,6 +3,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include "../../../Common/MyInitGuid.h"
#include "../../../Common/StringConvert.h"
@@ -96,6 +98,7 @@ EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info)
class COpenArchiveCallback:
public IArchiveOpenCallback,
public IArchiveOpenVolumeCallback,
+ public IArchiveOpenSetSubArchiveName,
public IProgress,
public ICryptoGetTextPassword,
public CMyUnknownImp
@@ -109,6 +112,8 @@ class COpenArchiveCallback:
bool _numBytesTotalDefined;
NFind::CFileInfo _fileInfo;
+ bool _subArchiveMode;
+ UString _subArchiveName;
public:
bool PasswordIsDefined;
UString Password;
@@ -116,8 +121,9 @@ public:
FString _folderPrefix;
public:
- MY_UNKNOWN_IMP3(
+ MY_UNKNOWN_IMP4(
IArchiveOpenVolumeCallback,
+ IArchiveOpenSetSubArchiveName,
IProgress,
ICryptoGetTextPassword
)
@@ -134,13 +140,24 @@ public:
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);
+ STDMETHOD(SetSubArchiveName(const wchar_t *name))
+ {
+ _subArchiveMode = true;
+ _subArchiveName = name;
+ return S_OK;
+ }
+
// ICryptoGetTextPassword
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+ COpenArchiveCallback(): _subArchiveMode(false) {}
+
void Init()
{
PasswordIsDefined = false;
+ _subArchiveMode = false;
+
_numFilesTotalDefined = false;
_numBytesTotalDefined = false;
@@ -220,6 +237,8 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in
{
if (WasEscPressed())
return E_ABORT;
+ if (_subArchiveMode)
+ return S_FALSE;
*inStream = NULL;
FString fullPath = _folderPrefix + us2fs(name);
if (!_fileInfo.Find(fullPath))
@@ -238,6 +257,14 @@ STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **in
STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
+ if (_subArchiveMode)
+ {
+ switch(propID)
+ {
+ case kpidName: prop = _subArchiveName; break;
+ }
+ }
+ else
switch(propID)
{
case kpidName: prop = GetUnicodeString(_fileInfo.Name, CP_OEMCP); break;
diff --git a/CPP/7zip/UI/Far/Messages.h b/CPP/7zip/UI/Far/Messages.h
index e6972392..0697a163 100644
--- a/CPP/7zip/UI/Far/Messages.h
+++ b/CPP/7zip/UI/Far/Messages.h
@@ -7,7 +7,7 @@
namespace NMessageID {
-const UINT k_Last_PropId_supported_by_plugin = kpidStreamId;
+const unsigned k_Last_PropId_supported_by_plugin = kpidStreamId;
enum EEnum
{
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
index 89a6b45a..8b605d0f 100644
--- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
@@ -2,6 +2,10 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
+#include <commctrl.h>
+
#ifndef UNDER_CE
#include "../../../Windows/CommonDialog.h"
#include "../../../Windows/Shell.h"
@@ -106,7 +110,7 @@ class CBrowseDialog: public NControl::CModalDialog
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
virtual void OnOK();
- void Post_RefreshPathEdit() { PostMessage(k_Message_RefreshPathEdit); }
+ void Post_RefreshPathEdit() { PostMsg(k_Message_RefreshPathEdit); }
bool GetParentPath(const UString &path, UString &parentPrefix, UString &name);
// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter
@@ -295,7 +299,7 @@ bool CBrowseDialog::OnInit()
#ifndef UNDER_CE
/* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible,
even if we use mouse for pressing the button to open this dialog. */
- PostMessage(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS));
+ PostMsg(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS));
#endif
return CModalDialog::OnInit();
diff --git a/CPP/7zip/UI/FileManager/ClassDefs.cpp b/CPP/7zip/UI/FileManager/ClassDefs.cpp
index b092a9ed..33197fc3 100644
--- a/CPP/7zip/UI/FileManager/ClassDefs.cpp
+++ b/CPP/7zip/UI/FileManager/ClassDefs.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include "../../../Common/MyInitGuid.h"
#include "../Agent/Agent.h"
diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp
index 00b152c8..1a7ed060 100644
--- a/CPP/7zip/UI/FileManager/FM.cpp
+++ b/CPP/7zip/UI/FileManager/FM.cpp
@@ -2,6 +2,10 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
+#include <shlwapi.h>
+
#include "../../../../C/Alloc.h"
#include "../../../Common/IntToString.h"
diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
index 54dabc57..af0cd8cc 100644
--- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
+++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include <Winbase.h>
#include "../../../Common/Defs.h"
@@ -585,7 +587,6 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
CCopyState state;
state.ProgressInfo.TotalSize = stat.Size;
- state.ProgressInfo.TotalSize = stat.Size;
state.ProgressInfo.StartPos = 0;
state.ProgressInfo.Progress = callback;
state.ProgressInfo.Init();
@@ -593,7 +594,6 @@ STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
state.MoveMode = IntToBool(moveMode);
state.UseReadWriteMode = isAltDest;
state.Prepare();
- state.TotalSize = stat.Size;
for (UInt32 i = 0; i < numItems; i++)
{
diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp
index bc482e4b..07f046e1 100644
--- a/CPP/7zip/UI/FileManager/LinkDialog.cpp
+++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp
@@ -42,7 +42,7 @@ static const UInt32 kLangIDs[] =
static bool GetSymLink(CFSTR path, CReparseAttr &attr)
{
- NFile::NIO::CInFile file;
+ NIO::CInFile file;
if (!file.Open(path,
FILE_SHARE_READ,
OPEN_EXISTING,
@@ -88,12 +88,13 @@ bool CLinkDialog::OnInit()
LangSetWindowText(*this, IDD_LINK);
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
#endif
+
_pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM));
_pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO));
if (!FilePath.IsEmpty())
{
- NFile::NFind::CFileInfo fi;
+ NFind::CFileInfo fi;
int linkType = 0;
if (!fi.Find(us2fs(FilePath)))
linkType = IDR_LINK_TYPE_SYM_FILE;
@@ -219,7 +220,7 @@ void CLinkDialog::OnButton_SetPath(bool to)
UString resultPath;
if (!MyBrowseForFolder(*this, title, currentPath, resultPath))
return;
- NFile::NName::NormalizeDirPathPrefix(resultPath);
+ NName::NormalizeDirPathPrefix(resultPath);
combo.SetCurSel(-1);
combo.SetText(resultPath);
}
@@ -239,16 +240,23 @@ void CLinkDialog::OnButton_Link()
UString from, to;
_pathFromCombo.GetText(from);
_pathToCombo.GetText(to);
- int i;
- for (i = 0; i < ARRAY_SIZE(k_LinkType_Buttons); i++)
- if (IsButtonCheckedBool(k_LinkType_Buttons[i]))
- break;
- if (i >= ARRAY_SIZE(k_LinkType_Buttons))
+
+ if (from.IsEmpty())
return;
+ if (!NName::IsAbsolutePath(from))
+ from.Insert(0, CurDirPrefix);
- int idb = k_LinkType_Buttons[i];
+ int idb = -1;
+ for (unsigned i = 0;; i++)
+ {
+ if (i >= ARRAY_SIZE(k_LinkType_Buttons))
+ return;
+ idb = k_LinkType_Buttons[i];
+ if (IsButtonCheckedBool(idb))
+ break;
+ }
- NFile::NFind::CFileInfo info1, info2;
+ NFind::CFileInfo info1, info2;
bool finded1 = info1.Find(us2fs(from));
bool finded2 = info2.Find(us2fs(to));
@@ -259,14 +267,13 @@ void CLinkDialog::OnButton_Link()
if (finded1 && info1.IsDir() != isDirLink ||
finded2 && info2.IsDir() != isDirLink)
{
- ShowError(L"Incorrect linkType");
+ ShowError(L"Incorrect link type");
return;
}
if (idb == IDR_LINK_TYPE_HARD)
{
- bool res = NFile::NDir::MyCreateHardLink(us2fs(from), us2fs(to));
- if (!res)
+ if (!NDir::MyCreateHardLink(us2fs(from), us2fs(to)))
{
ShowLastErrorMessage();
return;
@@ -291,9 +298,10 @@ void CLinkDialog::OnButton_Link()
}
- if (!NFile::NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size()))
+ if (!NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size()))
{
ShowLastErrorMessage();
+ return;
}
}
@@ -321,7 +329,8 @@ void CApp::Link()
int index = indices[0];
const UString itemName = srcPanel.GetItemName(index);
- UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
+ const UString fsPrefix = srcPanel.GetFsPath();
+ const UString srcPath = fsPrefix + srcPanel.GetItemPrefix(index);
UString path = srcPath;
{
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
@@ -332,6 +341,7 @@ void CApp::Link()
}
CLinkDialog dlg;
+ dlg.CurDirPrefix = fsPrefix;
dlg.FilePath = srcPath + itemName;
dlg.AnotherPath = path;
diff --git a/CPP/7zip/UI/FileManager/LinkDialog.h b/CPP/7zip/UI/FileManager/LinkDialog.h
index 8417fac8..56deec9d 100644
--- a/CPP/7zip/UI/FileManager/LinkDialog.h
+++ b/CPP/7zip/UI/FileManager/LinkDialog.h
@@ -23,6 +23,7 @@ class CLinkDialog: public NWindows::NControl::CModalDialog
void ShowError(const wchar_t *s);
void Set_LinkType_Radio(int idb);
public:
+ UString CurDirPrefix;
UString FilePath;
UString AnotherPath;
diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp
index a7416a4c..96a34af8 100644
--- a/CPP/7zip/UI/FileManager/Panel.cpp
+++ b/CPP/7zip/UI/FileManager/Panel.cpp
@@ -795,7 +795,7 @@ void CPanel::Change_ShowNtfsStrems_Mode()
void CPanel::Post_Refresh_StatusBar()
{
if (_processStatusBar)
- PostMessage(kRefresh_StatusBar);
+ PostMsg(kRefresh_StatusBar);
}
void CPanel::AddToArchive()
diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h
index 39915a27..5d03f6da 100644
--- a/CPP/7zip/UI/FileManager/Panel.h
+++ b/CPP/7zip/UI/FileManager/Panel.h
@@ -3,6 +3,10 @@
#ifndef __PANEL_H
#define __PANEL_H
+#include "../../../Common/MyWindows.h"
+
+#include <ShlObj.h>
+
#include "../../../../C/Alloc.h"
#include "../../../Common/Defs.h"
diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
index cd70c727..4d9ce51f 100644
--- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
+++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
@@ -359,7 +359,7 @@ LRESULT CPanel::OnNotifyComboBoxEnter(const UString &s)
{
if (BindToPathAndRefresh(GetUnicodeString(s)) == S_OK)
{
- PostMessage(kSetFocusToListView);
+ PostMsg(kSetFocusToListView);
return TRUE;
}
return FALSE;
@@ -370,7 +370,7 @@ bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result)
if (info->iWhy == CBENF_ESCAPE)
{
_headerComboBox.SetText(_currentFolderPrefix);
- PostMessage(kSetFocusToListView);
+ PostMsg(kSetFocusToListView);
result = FALSE;
return true;
}
@@ -401,7 +401,7 @@ bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result)
if (info->iWhy == CBENF_ESCAPE)
{
_headerComboBox.SetText(_currentFolderPrefix);
- PostMessage(kSetFocusToListView);
+ PostMsg(kSetFocusToListView);
result = FALSE;
return true;
}
@@ -528,9 +528,9 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
// _headerComboBox.SetText(pass); // it's fix for seclecting by mouse.
if (BindToPathAndRefresh(pass) == S_OK)
{
- PostMessage(kSetFocusToListView);
+ PostMsg(kSetFocusToListView);
#ifdef UNDER_CE
- PostMessage(kRefresh_HeaderComboBox);
+ PostMsg(kRefresh_HeaderComboBox);
#endif
return true;
}
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
index a485522f..b47a30a3 100644
--- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
+++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
#include <tlhelp32.h>
#include "../../../Common/AutoPtr.h"
diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp
index 62a08e13..0afbc07b 100644
--- a/CPP/7zip/UI/FileManager/PanelOperations.cpp
+++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp
@@ -354,7 +354,7 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
_dontShowMode = true;
- PostMessage(kReLoadMessage);
+ PostMsg(kReLoadMessage);
return TRUE;
}
diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp
index 7b53eb00..de9cf4b5 100644
--- a/CPP/7zip/UI/FileManager/PanelSelect.cpp
+++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp
@@ -70,7 +70,7 @@ void CPanel::OnArrowWithShift()
}
_prevFocusedItem = focusedItem;
- PostMessage(kShiftSelectMessage);
+ PostMsg(kShiftSelectMessage);
_listView.RedrawItem(focusedItem);
}
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
index b4195c18..4b20f1a9 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog.cpp
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
@@ -184,7 +184,7 @@ void CProgressDialog::CheckNeedClose()
{
if (_needClose)
{
- PostMessage(kCloseMessage);
+ PostMsg(kCloseMessage);
_needClose = false;
}
}
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.h b/CPP/7zip/UI/FileManager/ProgressDialog.h
index 175db017..0f41b57a 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog.h
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.h
@@ -152,7 +152,7 @@ public:
{
WaitCreating();
if (_wasCreated)
- PostMessage(kCloseMessage);
+ PostMsg(kCloseMessage);
else
_needClose = true;
};
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
index 231d0ace..dc828e72 100644
--- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
@@ -1229,7 +1229,7 @@ void CProgressDialog::CheckNeedClose()
{
if (_needClose)
{
- PostMessage(kCloseMessage);
+ PostMsg(kCloseMessage);
_needClose = false;
}
}
@@ -1241,7 +1241,7 @@ void CProgressDialog::ProcessWasFinished()
WaitCreating();
if (_wasCreated)
- PostMessage(kCloseMessage);
+ PostMsg(kCloseMessage);
else
_needClose = true;
}
diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc
index 8b8c7899..5de5aeec 100644
--- a/CPP/7zip/UI/FileManager/PropertyName.rc
+++ b/CPP/7zip/UI/FileManager/PropertyName.rc
@@ -96,4 +96,5 @@ BEGIN
IDS_PROP_STREAM_ID "Stream ID"
IDS_PROP_READ_ONLY "Read-only"
IDS_PROP_OUT_NAME "Out Name"
+ IDS_PROP_COPY_LINK "Copy Link"
END
diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h
index 3696ed2e..67f33902 100644
--- a/CPP/7zip/UI/FileManager/PropertyNameRes.h
+++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h
@@ -92,3 +92,4 @@
#define IDS_PROP_STREAM_ID 1092
#define IDS_PROP_READ_ONLY 1093
#define IDS_PROP_OUT_NAME 1094
+#define IDS_PROP_COPY_LINK 1095
diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp
index c5b57821..2a5d513a 100644
--- a/CPP/7zip/UI/FileManager/RootFolder.cpp
+++ b/CPP/7zip/UI/FileManager/RootFolder.cpp
@@ -2,6 +2,10 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
+#include <ShlObj.h>
+
#include "../../../Common/StringConvert.h"
#include "../../../Windows/DLL.h"
diff --git a/CPP/7zip/UI/FileManager/StdAfx.h b/CPP/7zip/UI/FileManager/StdAfx.h
index 85389112..e6d96041 100644
--- a/CPP/7zip/UI/FileManager/StdAfx.h
+++ b/CPP/7zip/UI/FileManager/StdAfx.h
@@ -12,8 +12,10 @@
#include "../../../Common/Common.h"
-#include <commctrl.h>
-#include <ShlObj.h>
-#include <shlwapi.h>
+// #include "../../../Common/MyWindows.h"
+
+// #include <commctrl.h>
+// #include <ShlObj.h>
+// #include <shlwapi.h>
#endif
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
index 2c35c191..c400bc29 100644
--- a/CPP/7zip/UI/FileManager/SysIconUtils.cpp
+++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
@@ -10,6 +10,8 @@
#include "SysIconUtils.h"
+#include <ShlObj.h>
+
#ifndef _UNICODE
extern bool g_IsNT;
#endif
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.h b/CPP/7zip/UI/FileManager/SysIconUtils.h
index 20199acb..f1b27fa1 100644
--- a/CPP/7zip/UI/FileManager/SysIconUtils.h
+++ b/CPP/7zip/UI/FileManager/SysIconUtils.h
@@ -3,6 +3,10 @@
#ifndef __SYS_ICON_UTILS_H
#define __SYS_ICON_UTILS_H
+#include "../../../Common/MyWindows.h"
+
+#include <commctrl.h>
+
#include "../../../Common/MyString.h"
struct CExtIconPair
diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp
index a7f0c3fb..d60d7b4f 100644
--- a/CPP/7zip/UI/FileManager/SystemPage.cpp
+++ b/CPP/7zip/UI/FileManager/SystemPage.cpp
@@ -2,6 +2,10 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
+#include <ShlObj.h>
+
#include "../../../Common/StringConvert.h"
#include "../../../Common/Defs.h"
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
index 2f118846..db4b1378 100644
--- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
+++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
@@ -114,7 +114,7 @@ bool CBenchmarkDialog::OnInit()
// f.lfFaceName[0] = 0;
_font.Create(&f);
if (_font._font)
- _consoleEdit.SendMessage(WM_SETFONT, (WPARAM)_font._font, TRUE);
+ _consoleEdit.SendMsg(WM_SETFONT, (WPARAM)_font._font, TRUE);
}
{
diff --git a/CPP/7zip/UI/GUI/GUI.cpp b/CPP/7zip/UI/GUI/GUI.cpp
index 134ac021..0f3cde94 100644
--- a/CPP/7zip/UI/GUI/GUI.cpp
+++ b/CPP/7zip/UI/GUI/GUI.cpp
@@ -2,6 +2,10 @@
#include "StdAfx.h"
+#include "../../../Common/MyWindows.h"
+
+#include <shlwapi.h>
+
#include "../../../../C/Alloc.h"
#include "../../../Common/MyInitGuid.h"
diff --git a/CPP/7zip/UI/GUI/StdAfx.h b/CPP/7zip/UI/GUI/StdAfx.h
index 9e322f96..64290769 100644
--- a/CPP/7zip/UI/GUI/StdAfx.h
+++ b/CPP/7zip/UI/GUI/StdAfx.h
@@ -9,9 +9,11 @@
#include "../../../Common/Common.h"
+// #include "../../../Common/MyWindows.h"
+
// #include <commctrl.h>
-#include <ShlObj.h>
-#include <shlwapi.h>
+// #include <ShlObj.h>
+// #include <shlwapi.h>
// #define printf(x) NO_PRINTF_(x)
// #define sprintf(x) NO_SPRINTF_(x)