This commit is contained in:
Igor Pavlov
2015-08-16 00:00:00 +00:00
committed by Kornel Lesiński
parent 54490d51d5
commit cba375916f
152 changed files with 6544 additions and 2001 deletions

View File

@@ -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

View File

@@ -44,6 +44,7 @@ public:
UInt64 _numSolidBytes;
bool _numSolidBytesDefined;
bool _solidExtension;
bool _useTypeSorting;
bool _compressHeaders;
bool _encryptHeadersSpecified;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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)
{}

View File

@@ -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"

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include <string.h>
#include "../../../Common/MyBuffer.h"
#include "../../Common/StreamUtils.h"

View File

@@ -1,7 +1,7 @@
// FindSignature.h
#ifndef __FINDSIGNATURE_H
#define __FINDSIGNATURE_H
#ifndef __FIND_SIGNATURE_H
#define __FIND_SIGNATURE_H
#include "../../IStream.h"

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../Common/MyWindows.h"
#include "../../Common/MyInitGuid.h"
#if defined(_7ZIP_LARGE_PAGES)

View File

@@ -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 {

View File

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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);
MY_UNKNOWN_IMP
CRecordVector<UInt32> CRCs;
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
void Init(const CObjectVector<CArc> *arcs,
const CObjectVector<CItem> *items,
const CRefItem &refItem)
{
_arcs = arcs;
_items = items;
_refItem = refItem;
_curIndex = 0;
_stream = NULL;
CrcIsOK = true;
}
bool CrcIsOK;
};
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;
}
HRESULT CFolderInStream::OpenStream()
{
while (_curIndex < _refItem.NumItems)
{
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;
}
return S_OK;
}
HRESULT CFolderInStream::CloseStream()
{
CRCs.Add(CRC_GET_DIGEST(_crc));
_stream.Release();
_fileIsOpen = false;
return S_OK;
}
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++)
if (!volsInStream)
{
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)
{
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())
*/
if (result != S_OK)
{
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));
if (result == S_FALSE)
opRes = NExtract::NOperationResult::kDataError;
else if (result == E_NOTIMPL)
opRes = NExtract::NOperationResult::kUnsupportedMethod;
else
return result;
}
/*
else
{
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));
}
*/
RINOK(extractCallback->SetOperationResult(opRes));
}
return S_OK;
COM_TRY_END
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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();

View File

@@ -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,

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;
}
}