mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 09:15:00 -06:00
15.06
This commit is contained in:
committed by
Kornel Lesiński
parent
54490d51d5
commit
cba375916f
@@ -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
|
||||
|
||||
@@ -44,6 +44,7 @@ public:
|
||||
UInt64 _numSolidBytes;
|
||||
bool _numSolidBytesDefined;
|
||||
bool _solidExtension;
|
||||
bool _useTypeSorting;
|
||||
|
||||
bool _compressHeaders;
|
||||
bool _encryptHeadersSpecified;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// FindSignature.h
|
||||
|
||||
#ifndef __FINDSIGNATURE_H
|
||||
#define __FINDSIGNATURE_H
|
||||
#ifndef __FIND_SIGNATURE_H
|
||||
#define __FIND_SIGNATURE_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/MyWindows.h"
|
||||
|
||||
#include "../../Common/MyInitGuid.h"
|
||||
|
||||
#if defined(_7ZIP_LARGE_PAGES)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
2683
CPP/7zip/Archive/Rar/Rar5Handler.cpp
Normal file
2683
CPP/7zip/Archive/Rar/Rar5Handler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
410
CPP/7zip/Archive/Rar/Rar5Handler.h
Normal file
410
CPP/7zip/Archive/Rar/Rar5Handler.h
Normal 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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
129
CPP/7zip/Archive/Rar/RarVol.h
Normal file
129
CPP/7zip/Archive/Rar/RarVol.h
Normal 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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user