mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 11:14:58 -06:00
9.34
This commit is contained in:
committed by
Kornel Lesiński
parent
83f8ddcc5b
commit
f08f4dcc3c
16
CPP/7zip/Archive/7z/7z.dsp
Executable file → Normal file
16
CPP/7zip/Archive/7z/7z.dsp
Executable file → Normal file
@@ -328,6 +328,14 @@ SOURCE=..\..\..\Common\StringToInt.cpp
|
||||
|
||||
SOURCE=..\..\..\Common\StringToInt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Wildcard.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Wildcard.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Archive Common"
|
||||
|
||||
@@ -482,6 +490,10 @@ SOURCE=..\..\Common\ProgressUtils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\PropId.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\RegisterArc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -558,6 +570,10 @@ SOURCE=..\..\..\Windows\FileIO.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileName.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\FileName.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
0
CPP/7zip/Archive/7z/7z.dsw
Executable file → Normal file
0
CPP/7zip/Archive/7z/7z.dsw
Executable file → Normal file
0
CPP/7zip/Archive/7z/7zCompressionMode.cpp
Executable file → Normal file
0
CPP/7zip/Archive/7z/7zCompressionMode.cpp
Executable file → Normal file
0
CPP/7zip/Archive/7z/7zCompressionMode.h
Executable file → Normal file
0
CPP/7zip/Archive/7z/7zCompressionMode.h
Executable file → Normal file
123
CPP/7zip/Archive/7z/7zDecode.cpp
Executable file → Normal file
123
CPP/7zip/Archive/7z/7zDecode.cpp
Executable file → Normal file
@@ -16,29 +16,33 @@ static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
|
||||
CBindInfoEx &bindInfo)
|
||||
{
|
||||
bindInfo.Clear();
|
||||
int i;
|
||||
bindInfo.BindPairs.ClearAndSetSize(folder.BindPairs.Size());
|
||||
unsigned i;
|
||||
for (i = 0; i < folder.BindPairs.Size(); i++)
|
||||
{
|
||||
NCoderMixer::CBindPair bindPair;
|
||||
NCoderMixer::CBindPair &bindPair = bindInfo.BindPairs[i];
|
||||
bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
|
||||
bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
|
||||
bindInfo.BindPairs.Add(bindPair);
|
||||
}
|
||||
|
||||
bindInfo.Coders.ClearAndSetSize(folder.Coders.Size());
|
||||
bindInfo.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
|
||||
|
||||
UInt32 outStreamIndex = 0;
|
||||
for (i = 0; i < folder.Coders.Size(); i++)
|
||||
{
|
||||
NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
|
||||
NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
|
||||
const CCoderInfo &coderInfo = folder.Coders[i];
|
||||
coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
|
||||
coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
|
||||
bindInfo.Coders.Add(coderStreamsInfo);
|
||||
bindInfo.CoderMethodIDs.Add(coderInfo.MethodID);
|
||||
bindInfo.CoderMethodIDs[i] = coderInfo.MethodID;
|
||||
for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
|
||||
if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
|
||||
bindInfo.OutStreams.Add(outStreamIndex);
|
||||
}
|
||||
bindInfo.InStreams.ClearAndSetSize(folder.PackStreams.Size());
|
||||
for (i = 0; i < folder.PackStreams.Size(); i++)
|
||||
bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);
|
||||
bindInfo.InStreams[i] = (UInt32)folder.PackStreams[i];
|
||||
}
|
||||
|
||||
static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
|
||||
@@ -58,7 +62,7 @@ static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
|
||||
{
|
||||
if (a1.Coders.Size() != a2.Coders.Size())
|
||||
return false;
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 0; i < a1.Coders.Size(); i++)
|
||||
if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
|
||||
return false;
|
||||
@@ -90,45 +94,49 @@ HRESULT CDecoder::Decode(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
IInStream *inStream,
|
||||
UInt64 startPos,
|
||||
const UInt64 *packSizes,
|
||||
const CFolder &folderInfo,
|
||||
const CFolders &folders, int folderIndex,
|
||||
ISequentialOutStream *outStream,
|
||||
ICompressProgressInfo *compressProgress
|
||||
#ifndef _NO_CRYPTO
|
||||
, ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
|
||||
#endif
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, bool mtMode, UInt32 numThreads
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (!folderInfo.CheckStructure())
|
||||
const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
|
||||
CFolder folderInfo;
|
||||
folders.ParseFolderInfo(folderIndex, folderInfo);
|
||||
|
||||
if (!folderInfo.CheckStructure(folders.GetNumFolderUnpackSizes(folderIndex)))
|
||||
return E_NOTIMPL;
|
||||
|
||||
/*
|
||||
We don't need to init isEncrypted and passwordIsDefined
|
||||
We must upgrade them only
|
||||
#ifndef _NO_CRYPTO
|
||||
isEncrypted = false;
|
||||
passwordIsDefined = false;
|
||||
#endif
|
||||
*/
|
||||
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
|
||||
|
||||
CLockedInStream lockedInStream;
|
||||
lockedInStream.Init(inStream);
|
||||
|
||||
for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
|
||||
for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
|
||||
{
|
||||
CLockedSequentialInStreamImp *lockedStreamImpSpec = new
|
||||
CLockedSequentialInStreamImp;
|
||||
CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp;
|
||||
CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
|
||||
lockedStreamImpSpec->Init(&lockedInStream, startPos);
|
||||
startPos += packSizes[j];
|
||||
|
||||
CLimitedSequentialInStream *streamSpec = new
|
||||
CLimitedSequentialInStream;
|
||||
lockedStreamImpSpec->Init(&lockedInStream, startPos + packPositions[j]);
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream = streamSpec;
|
||||
streamSpec->SetStream(lockedStreamImp);
|
||||
streamSpec->Init(packSizes[j]);
|
||||
streamSpec->Init(packPositions[j + 1] - packPositions[j]);
|
||||
inStreams.Add(inStream);
|
||||
}
|
||||
|
||||
int numCoders = folderInfo.Coders.Size();
|
||||
unsigned numCoders = folderInfo.Coders.Size();
|
||||
|
||||
CBindInfoEx bindInfo;
|
||||
ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
|
||||
@@ -139,7 +147,7 @@ HRESULT CDecoder::Decode(
|
||||
createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
|
||||
if (createNewCoders)
|
||||
{
|
||||
int i;
|
||||
unsigned i;
|
||||
_decoders.Clear();
|
||||
// _decoders2.Clear();
|
||||
|
||||
@@ -204,17 +212,19 @@ HRESULT CDecoder::Decode(
|
||||
decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
|
||||
if (setCompressCodecsInfo)
|
||||
{
|
||||
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
|
||||
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
_bindInfoExPrev = bindInfo;
|
||||
_bindInfoExPrevIsDefined = true;
|
||||
}
|
||||
int i;
|
||||
unsigned i;
|
||||
_mixerCoderCommon->ReInit();
|
||||
|
||||
UInt32 packStreamIndex = 0, unpackStreamIndex = 0;
|
||||
UInt32 packStreamIndex = 0;
|
||||
UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
|
||||
UInt32 unpackStreamIndex = unpackStreamIndexStart;
|
||||
UInt32 coderIndex = 0;
|
||||
// UInt32 coder2Index = 0;
|
||||
|
||||
@@ -229,7 +239,7 @@ HRESULT CDecoder::Decode(
|
||||
if (setDecoderProperties)
|
||||
{
|
||||
const CByteBuffer &props = coderInfo.Props;
|
||||
size_t size = props.GetCapacity();
|
||||
size_t size = props.Size();
|
||||
if (size > 0xFFFFFFFF)
|
||||
return E_NOTIMPL;
|
||||
// if (size > 0)
|
||||
@@ -257,22 +267,23 @@ HRESULT CDecoder::Decode(
|
||||
decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
|
||||
if (cryptoSetPassword)
|
||||
{
|
||||
if (getTextPassword == 0)
|
||||
return E_FAIL;
|
||||
isEncrypted = true;
|
||||
if (!getTextPassword)
|
||||
return E_NOTIMPL;
|
||||
CMyComBSTR passwordBSTR;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
|
||||
CByteBuffer buffer;
|
||||
passwordIsDefined = true;
|
||||
const UString password(passwordBSTR);
|
||||
const UInt32 sizeInBytes = password.Length() * 2;
|
||||
buffer.SetCapacity(sizeInBytes);
|
||||
for (int i = 0; i < password.Length(); i++)
|
||||
size_t len = 0;
|
||||
if (passwordBSTR)
|
||||
len = MyStringLen((BSTR)passwordBSTR);
|
||||
CByteBuffer buffer(len * 2);
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = password[i];
|
||||
wchar_t c = passwordBSTR[i];
|
||||
((Byte *)buffer)[i * 2] = (Byte)c;
|
||||
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
|
||||
}
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
|
||||
RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -281,32 +292,30 @@ HRESULT CDecoder::Decode(
|
||||
|
||||
UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
|
||||
UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
|
||||
CRecordVector<const UInt64 *> packSizesPointers;
|
||||
CRecordVector<const UInt64 *> unpackSizesPointers;
|
||||
packSizesPointers.Reserve(numInStreams);
|
||||
unpackSizesPointers.Reserve(numOutStreams);
|
||||
CObjArray<UInt64> packSizes(numInStreams);
|
||||
CObjArray<const UInt64 *> packSizesPointers(numInStreams);
|
||||
CObjArray<const UInt64 *> unpackSizesPointers(numOutStreams);
|
||||
UInt32 j;
|
||||
|
||||
for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)
|
||||
unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]);
|
||||
unpackSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndex];
|
||||
|
||||
for (j = 0; j < numInStreams; j++, packStreamIndex++)
|
||||
{
|
||||
int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
|
||||
if (bindPairIndex >= 0)
|
||||
packSizesPointers.Add(
|
||||
&folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);
|
||||
packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + (UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex];
|
||||
else
|
||||
{
|
||||
int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
|
||||
if (index < 0)
|
||||
return E_FAIL;
|
||||
packSizesPointers.Add(&packSizes[index]);
|
||||
return S_FALSE; // check it
|
||||
packSizes[j] = packPositions[index + 1] - packPositions[index];
|
||||
packSizesPointers[j] = &packSizes[j];
|
||||
}
|
||||
}
|
||||
|
||||
_mixerCoderCommon->SetCoderInfo(i,
|
||||
&packSizesPointers.Front(),
|
||||
&unpackSizesPointers.Front());
|
||||
_mixerCoderCommon->SetCoderInfo(i, packSizesPointers, unpackSizesPointers);
|
||||
}
|
||||
UInt32 mainCoder, temp;
|
||||
bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
|
||||
@@ -320,13 +329,15 @@ HRESULT CDecoder::Decode(
|
||||
|
||||
if (numCoders == 0)
|
||||
return 0;
|
||||
CRecordVector<ISequentialInStream *> inStreamPointers;
|
||||
inStreamPointers.Reserve(inStreams.Size());
|
||||
for (i = 0; i < inStreams.Size(); i++)
|
||||
inStreamPointers.Add(inStreams[i]);
|
||||
unsigned num = inStreams.Size();
|
||||
CObjArray<ISequentialInStream *> inStreamPointers(num);
|
||||
for (i = 0; i < num; i++)
|
||||
inStreamPointers[i] = inStreams[i];
|
||||
ISequentialOutStream *outStreamPointer = outStream;
|
||||
return _mixerCoder->Code(&inStreamPointers.Front(), NULL,
|
||||
inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);
|
||||
return _mixerCoder->Code(
|
||||
inStreamPointers, NULL, num,
|
||||
&outStreamPointer, NULL, 1,
|
||||
compressProgress);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
9
CPP/7zip/Archive/7z/7zDecode.h
Executable file → Normal file
9
CPP/7zip/Archive/7z/7zDecode.h
Executable file → Normal file
@@ -14,7 +14,7 @@
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#include "7zItem.h"
|
||||
#include "7zIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
@@ -50,13 +50,10 @@ public:
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
IInStream *inStream,
|
||||
UInt64 startPos,
|
||||
const UInt64 *packSizes,
|
||||
const CFolder &folder,
|
||||
const CFolders &folders, int folderIndex,
|
||||
ISequentialOutStream *outStream,
|
||||
ICompressProgressInfo *compressProgress
|
||||
#ifndef _NO_CRYPTO
|
||||
, ICryptoGetTextPassword *getTextPasswordSpec, bool &passwordIsDefined
|
||||
#endif
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, bool mtMode, UInt32 numThreads
|
||||
#endif
|
||||
|
||||
94
CPP/7zip/Archive/7z/7zEncode.cpp
Executable file → Normal file
94
CPP/7zip/Archive/7z/7zEncode.cpp
Executable file → Normal file
@@ -23,30 +23,30 @@ static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindIn
|
||||
const CRecordVector<CMethodId> decompressionMethods,
|
||||
CFolder &folder)
|
||||
{
|
||||
folder.Coders.Clear();
|
||||
// bindInfo.CoderMethodIDs.Clear();
|
||||
// folder.OutStreams.Clear();
|
||||
folder.PackStreams.Clear();
|
||||
folder.BindPairs.Clear();
|
||||
int i;
|
||||
folder.BindPairs.SetSize(bindInfo.BindPairs.Size());
|
||||
unsigned i;
|
||||
for (i = 0; i < bindInfo.BindPairs.Size(); i++)
|
||||
{
|
||||
CBindPair bindPair;
|
||||
bindPair.InIndex = bindInfo.BindPairs[i].InIndex;
|
||||
bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex;
|
||||
folder.BindPairs.Add(bindPair);
|
||||
CBindPair &bp = folder.BindPairs[i];
|
||||
const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i];
|
||||
bp.InIndex = mixerBp.InIndex;
|
||||
bp.OutIndex = mixerBp.OutIndex;
|
||||
}
|
||||
folder.Coders.SetSize(bindInfo.Coders.Size());
|
||||
for (i = 0; i < bindInfo.Coders.Size(); i++)
|
||||
{
|
||||
CCoderInfo coderInfo;
|
||||
CCoderInfo &coderInfo = folder.Coders[i];
|
||||
const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
|
||||
coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
|
||||
coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
|
||||
coderInfo.MethodID = decompressionMethods[i];
|
||||
folder.Coders.Add(coderInfo);
|
||||
// coderInfo.Props can be nonFree;
|
||||
}
|
||||
folder.PackStreams.SetSize(bindInfo.InStreams.Size());
|
||||
for (i = 0; i < bindInfo.InStreams.Size(); i++)
|
||||
folder.PackStreams.Add(bindInfo.InStreams[i]);
|
||||
folder.PackStreams[i] = bindInfo.InStreams[i];
|
||||
}
|
||||
|
||||
static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)
|
||||
@@ -65,11 +65,10 @@ HRESULT CEncoder::CreateMixerCoder(
|
||||
_mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;
|
||||
_mixerCoder = _mixerCoderSpec;
|
||||
RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));
|
||||
for (int i = 0; i < _options.Methods.Size(); i++)
|
||||
FOR_VECTOR (i, _options.Methods)
|
||||
{
|
||||
const CMethodFull &methodFull = _options.Methods[i];
|
||||
_codersInfo.Add(CCoderInfo());
|
||||
CCoderInfo &encodingInfo = _codersInfo.Back();
|
||||
CCoderInfo &encodingInfo = _codersInfo.AddNew();
|
||||
encodingInfo.MethodID = methodFull.Id;
|
||||
CMyComPtr<ICompressCoder> encoder;
|
||||
CMyComPtr<ICompressCoder2> encoder2;
|
||||
@@ -100,7 +99,7 @@ HRESULT CEncoder::CreateMixerCoder(
|
||||
/*
|
||||
CMyComPtr<ICryptoResetSalt> resetSalt;
|
||||
encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);
|
||||
if (resetSalt != NULL)
|
||||
if (resetSalt)
|
||||
{
|
||||
resetSalt->ResetSalt();
|
||||
}
|
||||
@@ -111,7 +110,7 @@ HRESULT CEncoder::CreateMixerCoder(
|
||||
encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
|
||||
if (setCompressCodecsInfo)
|
||||
{
|
||||
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
|
||||
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -120,10 +119,9 @@ HRESULT CEncoder::CreateMixerCoder(
|
||||
|
||||
if (cryptoSetPassword)
|
||||
{
|
||||
CByteBuffer buffer;
|
||||
const UInt32 sizeInBytes = _options.Password.Length() * 2;
|
||||
buffer.SetCapacity(sizeInBytes);
|
||||
for (int i = 0; i < _options.Password.Length(); i++)
|
||||
const UInt32 sizeInBytes = _options.Password.Len() * 2;
|
||||
CByteBuffer buffer(sizeInBytes);
|
||||
for (unsigned i = 0; i < _options.Password.Len(); i++)
|
||||
{
|
||||
wchar_t c = _options.Password[i];
|
||||
((Byte *)buffer)[i * 2] = (Byte)c;
|
||||
@@ -145,13 +143,15 @@ HRESULT CEncoder::Encode(
|
||||
ISequentialInStream *inStream,
|
||||
const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
|
||||
CFolder &folderItem,
|
||||
CRecordVector<UInt64> &coderUnpackSizes,
|
||||
UInt64 &unpackSize,
|
||||
ISequentialOutStream *outStream,
|
||||
CRecordVector<UInt64> &packSizes,
|
||||
ICompressProgressInfo *compressProgress)
|
||||
{
|
||||
RINOK(EncoderConstr());
|
||||
|
||||
if (_mixerCoderSpec == NULL)
|
||||
if (!_mixerCoderSpec)
|
||||
{
|
||||
RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
|
||||
}
|
||||
@@ -161,13 +161,13 @@ HRESULT CEncoder::Encode(
|
||||
CObjectVector<CInOutTempBuffer> inOutTempBuffers;
|
||||
CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
|
||||
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
|
||||
int numMethods = _bindInfo.Coders.Size();
|
||||
int i;
|
||||
unsigned numMethods = _bindInfo.Coders.Size();
|
||||
unsigned i;
|
||||
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
|
||||
{
|
||||
inOutTempBuffers.Add(CInOutTempBuffer());
|
||||
inOutTempBuffers.Back().Create();
|
||||
inOutTempBuffers.Back().InitWriting();
|
||||
CInOutTempBuffer &iotb = inOutTempBuffers.AddNew();
|
||||
iotb.Create();
|
||||
iotb.InitWriting();
|
||||
}
|
||||
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
|
||||
{
|
||||
@@ -186,7 +186,7 @@ HRESULT CEncoder::Encode(
|
||||
UInt32 mainCoderIndex, mainStreamIndex;
|
||||
_bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);
|
||||
|
||||
if (inStreamSize != NULL)
|
||||
if (inStreamSize)
|
||||
{
|
||||
CRecordVector<const UInt64 *> sizePointers;
|
||||
for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
|
||||
@@ -203,17 +203,24 @@ HRESULT CEncoder::Encode(
|
||||
|
||||
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
|
||||
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
|
||||
CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
|
||||
CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;
|
||||
CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
|
||||
CMyComPtr<ISequentialOutStream> outStreamSizeCount;
|
||||
|
||||
inStreamSizeCountSpec->Init(inStream);
|
||||
outStreamSizeCountSpec->SetStream(outStream);
|
||||
outStreamSizeCountSpec->Init();
|
||||
|
||||
CRecordVector<ISequentialInStream *> inStreamPointers;
|
||||
CRecordVector<ISequentialOutStream *> outStreamPointers;
|
||||
inStreamPointers.Add(inStreamSizeCount);
|
||||
outStreamPointers.Add(outStreamSizeCount);
|
||||
|
||||
if (_bindInfo.OutStreams.Size() != 0)
|
||||
{
|
||||
outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
|
||||
outStreamSizeCount = outStreamSizeCountSpec;
|
||||
outStreamSizeCountSpec->SetStream(outStream);
|
||||
outStreamSizeCountSpec->Init();
|
||||
outStreamPointers.Add(outStreamSizeCount);
|
||||
}
|
||||
|
||||
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
|
||||
outStreamPointers.Add(tempBuffers[i - 1]);
|
||||
|
||||
@@ -223,14 +230,14 @@ HRESULT CEncoder::Encode(
|
||||
|
||||
CMyComPtr<ICryptoResetInitVector> resetInitVector;
|
||||
_mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
|
||||
if (resetInitVector != NULL)
|
||||
if (resetInitVector)
|
||||
{
|
||||
resetInitVector->ResetInitVector();
|
||||
}
|
||||
|
||||
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
|
||||
_mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
|
||||
if (writeCoderProperties != NULL)
|
||||
if (writeCoderProperties)
|
||||
{
|
||||
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
@@ -256,7 +263,8 @@ HRESULT CEncoder::Encode(
|
||||
|
||||
ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);
|
||||
|
||||
packSizes.Add(outStreamSizeCountSpec->GetSize());
|
||||
if (_bindInfo.OutStreams.Size() != 0)
|
||||
packSizes.Add(outStreamSizeCountSpec->GetSize());
|
||||
|
||||
for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
|
||||
{
|
||||
@@ -264,19 +272,23 @@ HRESULT CEncoder::Encode(
|
||||
RINOK(inOutTempBuffer.WriteToStream(outStream));
|
||||
packSizes.Add(inOutTempBuffer.GetDataSize());
|
||||
}
|
||||
|
||||
|
||||
unpackSize = 0;
|
||||
for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
|
||||
{
|
||||
int binder = _bindInfo.FindBinderForInStream(
|
||||
_bindReverseConverter->DestOutToSrcInMap[i]);
|
||||
UInt64 streamSize;
|
||||
if (binder < 0)
|
||||
{
|
||||
streamSize = inStreamSizeCountSpec->GetSize();
|
||||
unpackSize = streamSize;
|
||||
}
|
||||
else
|
||||
streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
|
||||
folderItem.UnpackSizes.Add(streamSize);
|
||||
coderUnpackSizes.Add(streamSize);
|
||||
}
|
||||
for (i = numMethods - 1; i >= 0; i--)
|
||||
for (i = 0; i < numMethods; i++)
|
||||
folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -323,7 +335,7 @@ HRESULT CEncoder::EncoderConstr()
|
||||
{
|
||||
|
||||
UInt32 numInStreams = 0, numOutStreams = 0;
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 0; i < _options.Methods.Size(); i++)
|
||||
{
|
||||
const CMethodFull &methodFull = _options.Methods[i];
|
||||
@@ -339,7 +351,7 @@ HRESULT CEncoder::EncoderConstr()
|
||||
bindPair.OutIndex = numOutStreams;
|
||||
_bindInfo.BindPairs.Add(bindPair);
|
||||
}
|
||||
else
|
||||
else if (coderStreamsInfo.NumOutStreams != 0)
|
||||
_bindInfo.OutStreams.Insert(0, numOutStreams);
|
||||
for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
|
||||
_bindInfo.OutStreams.Add(numOutStreams + j);
|
||||
@@ -398,7 +410,7 @@ HRESULT CEncoder::EncoderConstr()
|
||||
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
int numCryptoStreams = _bindInfo.OutStreams.Size();
|
||||
unsigned numCryptoStreams = _bindInfo.OutStreams.Size();
|
||||
|
||||
for (i = 0; i < numCryptoStreams; i++)
|
||||
{
|
||||
|
||||
2
CPP/7zip/Archive/7z/7zEncode.h
Executable file → Normal file
2
CPP/7zip/Archive/7z/7zEncode.h
Executable file → Normal file
@@ -45,6 +45,8 @@ public:
|
||||
ISequentialInStream *inStream,
|
||||
const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
|
||||
CFolder &folderItem,
|
||||
CRecordVector<UInt64> &coderUnpackSizes,
|
||||
UInt64 &unpackSize,
|
||||
ISequentialOutStream *outStream,
|
||||
CRecordVector<UInt64> &packSizes,
|
||||
ICompressProgressInfo *compressProgress);
|
||||
|
||||
46
CPP/7zip/Archive/7z/7zExtract.cpp
Executable file → Normal file
46
CPP/7zip/Archive/7z/7zExtract.cpp
Executable file → Normal file
@@ -37,8 +37,8 @@ struct CExtractFolderInfo
|
||||
{
|
||||
if (fileIndex != kNumNoIndex)
|
||||
{
|
||||
ExtractStatuses.Reserve(1);
|
||||
ExtractStatuses.Add(true);
|
||||
ExtractStatuses.ClearAndSetSize(1);
|
||||
ExtractStatuses[0] = true;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -51,7 +51,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
|
||||
UInt64 importantTotalUnpacked = 0;
|
||||
|
||||
bool allFilesMode = (numItems == (UInt32)-1);
|
||||
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems =
|
||||
#ifdef _7Z_VOL
|
||||
@@ -67,7 +67,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if(_volumes.Size() != 1)
|
||||
return E_FAIL;
|
||||
const CVolume &volume = _volumes.Front();
|
||||
const CArchiveDatabaseEx &_db = volume.Database;
|
||||
const CDbEx &_db = volume.Database;
|
||||
IInStream *_inStream = volume.Stream;
|
||||
*/
|
||||
|
||||
@@ -86,10 +86,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
int volumeIndex = ref.VolumeIndex;
|
||||
const CVolume &volume = _volumes[volumeIndex];
|
||||
const CArchiveDatabaseEx &db = volume.Database;
|
||||
const CDbEx &db = volume.Database;
|
||||
UInt32 fileIndex = ref.ItemIndex;
|
||||
#else
|
||||
const CArchiveDatabaseEx &db = _db;
|
||||
const CDbEx &db = _db;
|
||||
UInt32 fileIndex = ref2Index;
|
||||
#endif
|
||||
|
||||
@@ -115,8 +115,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
volumeIndex,
|
||||
#endif
|
||||
kNumNoIndex, folderIndex));
|
||||
const CFolder &folderInfo = db.Folders[folderIndex];
|
||||
UInt64 unpackSize = folderInfo.GetUnpackSize();
|
||||
UInt64 unpackSize = db.GetFolderUnpackSize(folderIndex);
|
||||
importantTotalUnpacked += unpackSize;
|
||||
extractFolderInfoVector.Back().UnpackSize = unpackSize;
|
||||
}
|
||||
@@ -156,7 +155,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
for (int i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)
|
||||
for (unsigned i = 0;; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)
|
||||
{
|
||||
lps->OutSize = totalUnpacked;
|
||||
lps->InSize = totalPacked;
|
||||
@@ -174,9 +173,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
#ifdef _7Z_VOL
|
||||
const CVolume &volume = _volumes[efi.VolumeIndex];
|
||||
const CArchiveDatabaseEx &db = volume.Database;
|
||||
const CDbEx &db = volume.Database;
|
||||
#else
|
||||
const CArchiveDatabaseEx &db = _db;
|
||||
const CDbEx &db = _db;
|
||||
#endif
|
||||
|
||||
CNum startIndex;
|
||||
@@ -200,13 +199,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
continue;
|
||||
|
||||
CNum folderIndex = efi.FolderIndex;
|
||||
const CFolder &folderInfo = db.Folders[folderIndex];
|
||||
|
||||
curPacked = _db.GetFolderFullPackSize(folderIndex);
|
||||
|
||||
CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex];
|
||||
UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0);
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
if (extractCallback)
|
||||
@@ -216,26 +210,24 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
try
|
||||
{
|
||||
#ifndef _NO_CRYPTO
|
||||
bool passwordIsDefined;
|
||||
bool isEncrypted = false;
|
||||
bool passwordIsDefined = false;
|
||||
#endif
|
||||
|
||||
HRESULT result = decoder.Decode(
|
||||
EXTERNAL_CODECS_VARS
|
||||
#ifdef _7Z_VOL
|
||||
volume.Stream,
|
||||
volume.Stream,
|
||||
#else
|
||||
_inStream,
|
||||
_inStream,
|
||||
#endif
|
||||
folderStartPackPos,
|
||||
&db.PackSizes[packStreamIndex],
|
||||
folderInfo,
|
||||
db.ArcInfo.DataStartPosition,
|
||||
db, folderIndex,
|
||||
outStream,
|
||||
progress
|
||||
#ifndef _NO_CRYPTO
|
||||
, getTextPassword, passwordIsDefined
|
||||
#endif
|
||||
_7Z_DECODER_CRYPRO_VARS
|
||||
#if !defined(_7ZIP_ST) && !defined(_SFX)
|
||||
, true, _numThreads
|
||||
, true, _numThreads
|
||||
#endif
|
||||
);
|
||||
|
||||
@@ -246,7 +238,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
}
|
||||
if (result == E_NOTIMPL)
|
||||
{
|
||||
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnSupportedMethod));
|
||||
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kUnsupportedMethod));
|
||||
continue;
|
||||
}
|
||||
if (result != S_OK)
|
||||
|
||||
4
CPP/7zip/Archive/7z/7zFolderInStream.cpp
Executable file → Normal file
4
CPP/7zip/Archive/7z/7zFolderInStream.cpp
Executable file → Normal file
@@ -106,8 +106,8 @@ STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSiz
|
||||
STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
|
||||
{
|
||||
*value = 0;
|
||||
int index2 = (int)subStream;
|
||||
if (index2 < 0 || subStream > Sizes.Size())
|
||||
unsigned index2 = (unsigned)subStream;
|
||||
if (subStream > Sizes.Size())
|
||||
return E_FAIL;
|
||||
if (index2 < Sizes.Size())
|
||||
{
|
||||
|
||||
2
CPP/7zip/Archive/7z/7zFolderInStream.h
Executable file → Normal file
2
CPP/7zip/Archive/7z/7zFolderInStream.h
Executable file → Normal file
@@ -47,7 +47,7 @@ public:
|
||||
UInt64 GetFullSize() const
|
||||
{
|
||||
UInt64 size = 0;
|
||||
for (int i = 0; i < Sizes.Size(); i++)
|
||||
FOR_VECTOR (i, Sizes)
|
||||
size += Sizes[i];
|
||||
return size;
|
||||
}
|
||||
|
||||
2
CPP/7zip/Archive/7z/7zFolderOutStream.cpp
Executable file → Normal file
2
CPP/7zip/Archive/7z/7zFolderOutStream.cpp
Executable file → Normal file
@@ -14,7 +14,7 @@ CFolderOutStream::CFolderOutStream()
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::Init(
|
||||
const CArchiveDatabaseEx *db,
|
||||
const CDbEx *db,
|
||||
UInt32 ref2Offset, UInt32 startIndex,
|
||||
const CBoolVector *extractStatuses,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
|
||||
6
CPP/7zip/Archive/7z/7zFolderOutStream.h
Executable file → Normal file
6
CPP/7zip/Archive/7z/7zFolderOutStream.h
Executable file → Normal file
@@ -19,12 +19,12 @@ class CFolderOutStream:
|
||||
{
|
||||
COutStreamWithCRC *_crcStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> _crcStream;
|
||||
const CArchiveDatabaseEx *_db;
|
||||
const CDbEx *_db;
|
||||
const CBoolVector *_extractStatuses;
|
||||
CMyComPtr<IArchiveExtractCallback> _extractCallback;
|
||||
UInt32 _ref2Offset;
|
||||
UInt32 _startIndex;
|
||||
int _currentIndex;
|
||||
unsigned _currentIndex;
|
||||
bool _testMode;
|
||||
bool _checkCrc;
|
||||
bool _fileIsOpen;
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
|
||||
|
||||
HRESULT Init(
|
||||
const CArchiveDatabaseEx *db,
|
||||
const CDbEx *db,
|
||||
UInt32 ref2Offset, UInt32 startIndex,
|
||||
const CBoolVector *extractStatuses,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
|
||||
755
CPP/7zip/Archive/7z/7zHandler.cpp
Executable file → Normal file
755
CPP/7zip/Archive/7z/7zHandler.cpp
Executable file → Normal file
@@ -23,6 +23,7 @@
|
||||
#endif
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NCOM;
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
@@ -30,6 +31,7 @@ namespace N7z {
|
||||
CHandler::CHandler()
|
||||
{
|
||||
#ifndef _NO_CRYPTO
|
||||
_isEncrypted = false;
|
||||
_passwordIsDefined = false;
|
||||
#endif
|
||||
|
||||
@@ -49,11 +51,12 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
|
||||
#ifdef _SFX
|
||||
|
||||
IMP_IInArchive_ArcProps_NO
|
||||
IMP_IInArchive_ArcProps_NO_Table
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)
|
||||
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
*numProps = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
|
||||
@@ -62,156 +65,473 @@ STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
static const STATPROPSTG kArcProps[] =
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidMethod, VT_BSTR},
|
||||
{ NULL, kpidSolid, VT_BOOL},
|
||||
{ NULL, kpidNumBlocks, VT_UI4},
|
||||
{ NULL, kpidPhySize, VT_UI8},
|
||||
{ NULL, kpidHeadersSize, VT_UI8},
|
||||
{ NULL, kpidOffset, VT_UI8}
|
||||
kpidHeadersSize,
|
||||
kpidMethod,
|
||||
kpidSolid,
|
||||
kpidNumBlocks
|
||||
// , kpidIsTree
|
||||
};
|
||||
|
||||
static inline wchar_t GetHex(Byte value)
|
||||
{
|
||||
return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
|
||||
}
|
||||
|
||||
static UString ConvertMethodIdToString(UInt64 id)
|
||||
{
|
||||
wchar_t s[32];
|
||||
int len = 32;
|
||||
s[--len] = 0;
|
||||
do
|
||||
{
|
||||
s[--len] = GetHex((Byte)id & 0xF); id >>= 4;
|
||||
s[--len] = GetHex((Byte)id & 0xF); id >>= 4;
|
||||
}
|
||||
while (id != 0);
|
||||
return s + len;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
{
|
||||
case kpidMethod:
|
||||
{
|
||||
UString resString;
|
||||
CRecordVector<UInt64> ids;
|
||||
int i;
|
||||
for (i = 0; i < _db.Folders.Size(); i++)
|
||||
{
|
||||
const CFolder &f = _db.Folders[i];
|
||||
for (int j = f.Coders.Size() - 1; j >= 0; j--)
|
||||
ids.AddToUniqueSorted(f.Coders[j].MethodID);
|
||||
}
|
||||
|
||||
for (i = 0; i < ids.Size(); i++)
|
||||
{
|
||||
UInt64 id = ids[i];
|
||||
UString methodName;
|
||||
/* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);
|
||||
if (methodName.IsEmpty())
|
||||
methodName = ConvertMethodIdToString(id);
|
||||
if (!resString.IsEmpty())
|
||||
resString += L' ';
|
||||
resString += methodName;
|
||||
}
|
||||
prop = resString;
|
||||
break;
|
||||
}
|
||||
case kpidSolid: prop = _db.IsSolid(); break;
|
||||
case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break;
|
||||
case kpidHeadersSize: prop = _db.HeadersSize; break;
|
||||
case kpidPhySize: prop = _db.PhySize; break;
|
||||
case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
#endif
|
||||
|
||||
static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop)
|
||||
static inline char GetHex(unsigned value)
|
||||
{
|
||||
UInt64 value;
|
||||
if (v.GetItem(index, value))
|
||||
{
|
||||
FILETIME ft;
|
||||
ft.dwLowDateTime = (DWORD)value;
|
||||
ft.dwHighDateTime = (DWORD)(value >> 32);
|
||||
prop = ft;
|
||||
}
|
||||
return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
|
||||
}
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
static UString ConvertUInt32ToString(UInt32 value)
|
||||
static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id)
|
||||
{
|
||||
wchar_t buffer[32];
|
||||
ConvertUInt64ToString(value, buffer);
|
||||
return buffer;
|
||||
int len = 0;
|
||||
do
|
||||
{
|
||||
s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
|
||||
s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;
|
||||
}
|
||||
while (id != 0);
|
||||
return (unsigned)-len;
|
||||
}
|
||||
|
||||
static UString GetStringForSizeValue(UInt32 value)
|
||||
static void ConvertMethodIdToString(AString &res, UInt64 id)
|
||||
{
|
||||
for (int i = 31; i >= 0; i--)
|
||||
if ((UInt32(1) << i) == value)
|
||||
return ConvertUInt32ToString(i);
|
||||
UString result;
|
||||
if (value % (1 << 20) == 0)
|
||||
{
|
||||
result += ConvertUInt32ToString(value >> 20);
|
||||
result += L"m";
|
||||
}
|
||||
else if (value % (1 << 10) == 0)
|
||||
{
|
||||
result += ConvertUInt32ToString(value >> 10);
|
||||
result += L"k";
|
||||
}
|
||||
else
|
||||
{
|
||||
result += ConvertUInt32ToString(value);
|
||||
result += L"b";
|
||||
}
|
||||
return result;
|
||||
const unsigned kLen = 32;
|
||||
char s[kLen];
|
||||
unsigned len = kLen - 1;
|
||||
s[len] = 0;
|
||||
res += s + len - ConvertMethodIdToString_Back(s + len, id);
|
||||
}
|
||||
|
||||
static unsigned GetStringForSizeValue(char *s, UInt32 val)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i <= 31; i++)
|
||||
if (((UInt32)1 << i) == val)
|
||||
{
|
||||
if (i < 10)
|
||||
{
|
||||
s[0] = (char)('0' + i);
|
||||
s[1] = 0;
|
||||
return 1;
|
||||
}
|
||||
if (i < 20) { s[0] = '1'; s[1] = (char)('0' + i - 10); }
|
||||
else if (i < 30) { s[0] = '2'; s[1] = (char)('0' + i - 20); }
|
||||
else { s[0] = '3'; s[1] = (char)('0' + i - 30); }
|
||||
s[2] = 0;
|
||||
return 2;
|
||||
}
|
||||
char c = 'b';
|
||||
if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
|
||||
else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
|
||||
::ConvertUInt32ToString(val, s);
|
||||
unsigned pos = MyStringLen(s);
|
||||
s[pos++] = c;
|
||||
s[pos] = 0;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/*
|
||||
static inline void AddHexToString(UString &res, Byte value)
|
||||
{
|
||||
res += GetHex((Byte)(value >> 4));
|
||||
res += GetHex((Byte)(value & 0xF));
|
||||
}
|
||||
*/
|
||||
|
||||
static void AddProp32(UString &s, const wchar_t *name, UInt32 v)
|
||||
static char *AddProp32(char *s, const char *name, UInt32 v)
|
||||
{
|
||||
s += name;
|
||||
s += ConvertUInt32ToString(v);
|
||||
*s++ = ':';
|
||||
s = MyStpCpy(s, name);
|
||||
::ConvertUInt32ToString(v, s);
|
||||
return s + MyStringLen(s);
|
||||
}
|
||||
|
||||
void CHandler::AddMethodName(AString &s, UInt64 id)
|
||||
{
|
||||
UString methodName;
|
||||
FindMethod(EXTERNAL_CODECS_VARS id, methodName);
|
||||
if (methodName.IsEmpty())
|
||||
{
|
||||
for (unsigned i = 0; i < methodName.Len(); i++)
|
||||
if (methodName[i] >= 0x80)
|
||||
{
|
||||
methodName.Empty();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (methodName.IsEmpty())
|
||||
ConvertMethodIdToString(s, id);
|
||||
else
|
||||
for (unsigned i = 0; i < methodName.Len(); i++)
|
||||
s += (char)methodName[i];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool CHandler::IsEncrypted(UInt32 index2) const
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
|
||||
if (folderIndex != kNumNoIndex)
|
||||
return _db.Folders[folderIndex].IsEncrypted();
|
||||
#ifndef _SFX
|
||||
COM_TRY_BEGIN
|
||||
#endif
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
#ifndef _SFX
|
||||
case kpidMethod:
|
||||
{
|
||||
AString s;
|
||||
const CParsedMethods &pm = _db.ParsedMethods;
|
||||
FOR_VECTOR (i, pm.IDs)
|
||||
{
|
||||
UInt64 id = pm.IDs[i];
|
||||
if (!s.IsEmpty())
|
||||
s += ' ';
|
||||
char temp[16];
|
||||
if (id == k_LZMA2)
|
||||
{
|
||||
s += "LZMA2:";
|
||||
if ((pm.Lzma2Prop & 1) == 0)
|
||||
ConvertUInt32ToString((pm.Lzma2Prop >> 1) + 12, temp);
|
||||
else
|
||||
GetStringForSizeValue(temp, 3 << ((pm.Lzma2Prop >> 1) + 11));
|
||||
s += temp;
|
||||
}
|
||||
else if (id == k_LZMA)
|
||||
{
|
||||
s += "LZMA:";
|
||||
GetStringForSizeValue(temp, pm.LzmaDic);
|
||||
s += temp;
|
||||
}
|
||||
else
|
||||
AddMethodName(s, id);
|
||||
}
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
case kpidSolid: prop = _db.IsSolid(); break;
|
||||
case kpidNumBlocks: prop = (UInt32)_db.NumFolders; break;
|
||||
case kpidHeadersSize: prop = _db.HeadersSize; break;
|
||||
case kpidPhySize: prop = _db.PhySize; break;
|
||||
case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break;
|
||||
/*
|
||||
case kpidIsTree: if (_db.IsTree) prop = true; break;
|
||||
case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break;
|
||||
case kpidIsAux: if (_db.IsTree) prop = true; break;
|
||||
*/
|
||||
// case kpidError: if (_db.ThereIsHeaderError) prop = "Header error"; break;
|
||||
#endif
|
||||
|
||||
case kpidWarningFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError;
|
||||
if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature;
|
||||
if (v != 0)
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError;
|
||||
if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
// if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported;
|
||||
if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
#ifndef _SFX
|
||||
COM_TRY_END
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index)
|
||||
{
|
||||
UInt64 value;
|
||||
if (v.GetItem(index, value))
|
||||
PropVarEm_Set_FileTime64(prop, value);
|
||||
}
|
||||
|
||||
bool CHandler::IsFolderEncrypted(CNum folderIndex) const
|
||||
{
|
||||
if (folderIndex == kNumNoIndex)
|
||||
return false;
|
||||
size_t startPos = _db.FoCodersDataOffset[folderIndex];
|
||||
const Byte *p = _db.CodersData + startPos;
|
||||
size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
|
||||
CInByte2 inByte;
|
||||
inByte.Init(p, size);
|
||||
|
||||
CNum numCoders = inByte.ReadNum();
|
||||
for (; numCoders != 0; numCoders--)
|
||||
{
|
||||
Byte mainByte = inByte.ReadByte();
|
||||
unsigned idSize = (mainByte & 0xF);
|
||||
const Byte *longID = inByte.GetPtr();
|
||||
UInt64 id64 = 0;
|
||||
for (unsigned j = 0; j < idSize; j++)
|
||||
id64 = ((id64 << 8) | longID[j]);
|
||||
inByte.SkipDataNoCheck(idSize);
|
||||
if (id64 == k_AES)
|
||||
return true;
|
||||
if ((mainByte & 0x20) != 0)
|
||||
inByte.SkipDataNoCheck(inByte.ReadNum());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
*numProps = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
|
||||
{
|
||||
*name = NULL;
|
||||
*propID = kpidNtSecure;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)
|
||||
{
|
||||
/*
|
||||
const CFileItem &file = _db.Files[index];
|
||||
*parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir);
|
||||
*parent = (UInt32)(Int32)file.Parent;
|
||||
*/
|
||||
*parentType = NParentType::kDir;
|
||||
*parent = (UInt32)(Int32)-1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
|
||||
{
|
||||
*data = NULL;
|
||||
*dataSize = 0;
|
||||
*propType = 0;
|
||||
|
||||
if (/* _db.IsTree && propID == kpidName ||
|
||||
!_db.IsTree && */ propID == kpidPath)
|
||||
{
|
||||
*data = (void *)_db.GetName(index);
|
||||
if (*data)
|
||||
{
|
||||
*dataSize = (UInt32)((_db.NameOffsets[index + 1] - _db.NameOffsets[index]) * 2);
|
||||
*propType = NPropDataType::kUtf16z;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
/*
|
||||
if (propID == kpidNtSecure)
|
||||
{
|
||||
if (index < (UInt32)_db.SecureIDs.Size())
|
||||
{
|
||||
int id = _db.SecureIDs[index];
|
||||
size_t offs = _db.SecureOffsets[id];
|
||||
size_t size = _db.SecureOffsets[id + 1] - offs;
|
||||
if (size >= 0)
|
||||
{
|
||||
*data = _db.SecureBuf + offs;
|
||||
*dataSize = (UInt32)size;
|
||||
*propType = NPropDataType::kRaw;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
|
||||
{
|
||||
PropVariant_Clear(prop);
|
||||
if (folderIndex == kNumNoIndex)
|
||||
return S_OK;
|
||||
// for (int ttt = 0; ttt < 1; ttt++) {
|
||||
const unsigned kTempSize = 256;
|
||||
char temp[kTempSize];
|
||||
unsigned pos = kTempSize;
|
||||
temp[--pos] = 0;
|
||||
|
||||
size_t startPos = _db.FoCodersDataOffset[folderIndex];
|
||||
const Byte *p = _db.CodersData + startPos;
|
||||
size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
|
||||
CInByte2 inByte;
|
||||
inByte.Init(p, size);
|
||||
|
||||
// numCoders == 0 ???
|
||||
CNum numCoders = inByte.ReadNum();
|
||||
bool needSpace = false;
|
||||
for (; numCoders != 0; numCoders--, needSpace = true)
|
||||
{
|
||||
if (pos < 32) // max size of property
|
||||
break;
|
||||
Byte mainByte = inByte.ReadByte();
|
||||
unsigned idSize = (mainByte & 0xF);
|
||||
const Byte *longID = inByte.GetPtr();
|
||||
UInt64 id64 = 0;
|
||||
for (unsigned j = 0; j < idSize; j++)
|
||||
id64 = ((id64 << 8) | longID[j]);
|
||||
inByte.SkipDataNoCheck(idSize);
|
||||
CNum propsSize = 0;
|
||||
const Byte *props = NULL;
|
||||
if ((mainByte & 0x20) != 0)
|
||||
{
|
||||
propsSize = inByte.ReadNum();
|
||||
props = inByte.GetPtr();
|
||||
inByte.SkipDataNoCheck(propsSize);
|
||||
}
|
||||
|
||||
const char *name = NULL;
|
||||
char s[32];
|
||||
s[0] = 0;
|
||||
|
||||
if (id64 <= (UInt32)0xFFFFFFFF)
|
||||
{
|
||||
UInt32 id = (UInt32)id64;
|
||||
if (id == k_LZMA)
|
||||
{
|
||||
name = "LZMA";
|
||||
if (propsSize == 5)
|
||||
{
|
||||
UInt32 dicSize = GetUi32((const Byte *)props + 1);
|
||||
char *dest = s + GetStringForSizeValue(s, dicSize);
|
||||
UInt32 d = props[0];
|
||||
if (d != 0x5D)
|
||||
{
|
||||
UInt32 lc = d % 9;
|
||||
d /= 9;
|
||||
UInt32 pb = d / 5;
|
||||
UInt32 lp = d % 5;
|
||||
if (lc != 3) dest = AddProp32(dest, "lc", lc);
|
||||
if (lp != 0) dest = AddProp32(dest, "lp", lp);
|
||||
if (pb != 2) dest = AddProp32(dest, "pb", pb);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (id == k_LZMA2)
|
||||
{
|
||||
name = "LZMA2";
|
||||
if (propsSize == 1)
|
||||
{
|
||||
Byte p = props[0];
|
||||
if ((p & 1) == 0)
|
||||
ConvertUInt32ToString((UInt32)((p >> 1) + 12), s);
|
||||
else
|
||||
GetStringForSizeValue(s, 3 << ((p >> 1) + 11));
|
||||
}
|
||||
}
|
||||
else if (id == k_PPMD)
|
||||
{
|
||||
name = "PPMD";
|
||||
if (propsSize == 5)
|
||||
{
|
||||
Byte order = *props;
|
||||
char *dest = s;
|
||||
*dest++ = 'o';
|
||||
ConvertUInt32ToString(order, dest);
|
||||
dest += MyStringLen(dest);
|
||||
dest = MyStpCpy(dest, ":mem");
|
||||
GetStringForSizeValue(dest, GetUi32(props + 1));
|
||||
}
|
||||
}
|
||||
else if (id == k_Delta)
|
||||
{
|
||||
name = "Delta";
|
||||
if (propsSize == 1)
|
||||
ConvertUInt32ToString((UInt32)props[0] + 1, s);
|
||||
}
|
||||
else if (id == k_BCJ2) name = "BCJ2";
|
||||
else if (id == k_BCJ) name = "BCJ";
|
||||
else if (id == k_AES)
|
||||
{
|
||||
name = "7zAES";
|
||||
if (propsSize >= 1)
|
||||
{
|
||||
Byte firstByte = props[0];
|
||||
UInt32 numCyclesPower = firstByte & 0x3F;
|
||||
ConvertUInt32ToString(numCyclesPower, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (name)
|
||||
{
|
||||
unsigned nameLen = MyStringLen(name);
|
||||
unsigned propsLen = MyStringLen(s);
|
||||
unsigned totalLen = nameLen + propsLen;
|
||||
if (propsLen != 0)
|
||||
totalLen++;
|
||||
if (needSpace)
|
||||
totalLen++;
|
||||
if (totalLen + 5 >= pos)
|
||||
break;
|
||||
pos -= totalLen;
|
||||
MyStringCopy(temp + pos, name);
|
||||
if (propsLen != 0)
|
||||
{
|
||||
char *dest = temp + pos + nameLen;
|
||||
*dest++ = ':';
|
||||
MyStringCopy(dest, s);
|
||||
}
|
||||
if (needSpace)
|
||||
temp[pos + totalLen - 1] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
UString methodName;
|
||||
FindMethod(EXTERNAL_CODECS_VARS id64, methodName);
|
||||
if (methodName.IsEmpty())
|
||||
{
|
||||
for (unsigned j = 0; j < methodName.Len(); j++)
|
||||
if (methodName[j] >= 0x80)
|
||||
{
|
||||
methodName.Empty();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (needSpace)
|
||||
temp[--pos] = ' ';
|
||||
if (methodName.IsEmpty())
|
||||
pos -= ConvertMethodIdToString_Back(temp + pos, id64);
|
||||
else
|
||||
{
|
||||
unsigned len = methodName.Len();
|
||||
if (len + 5 > pos)
|
||||
break;
|
||||
pos -= len;
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
temp[pos + i] = (char)methodName[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (numCoders != 0 && pos >= 4)
|
||||
{
|
||||
temp[--pos] = ' ';
|
||||
temp[--pos] = '.';
|
||||
temp[--pos] = '.';
|
||||
temp[--pos] = '.';
|
||||
}
|
||||
return PropVarEm_Set_Str(prop, temp + pos);
|
||||
// }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
PropVariant_Clear(value);
|
||||
// COM_TRY_BEGIN
|
||||
// NCOM::CPropVariant prop;
|
||||
|
||||
/*
|
||||
const CRef2 &ref2 = _refs[index];
|
||||
@@ -225,14 +545,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPath:
|
||||
if (!item.Name.IsEmpty())
|
||||
prop = NItemName::GetOSName(item.Name);
|
||||
break;
|
||||
case kpidIsDir: prop = item.IsDir; break;
|
||||
case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;
|
||||
case kpidSize:
|
||||
{
|
||||
prop = item.Size;
|
||||
PropVarEm_Set_UInt64(value, item.Size);
|
||||
// prop = ref2.Size;
|
||||
break;
|
||||
}
|
||||
@@ -244,130 +560,49 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
if (folderIndex != kNumNoIndex)
|
||||
{
|
||||
if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)
|
||||
prop = _db.GetFolderFullPackSize(folderIndex);
|
||||
PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex));
|
||||
/*
|
||||
else
|
||||
prop = (UInt64)0;
|
||||
PropVarEm_Set_UInt64(value, 0);
|
||||
*/
|
||||
}
|
||||
else
|
||||
prop = (UInt64)0;
|
||||
PropVarEm_Set_UInt64(value, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; }
|
||||
case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break;
|
||||
case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break;
|
||||
case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break;
|
||||
case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break;
|
||||
case kpidCRC: if (item.CrcDefined) prop = item.Crc; break;
|
||||
case kpidEncrypted: prop = IsEncrypted(index2); break;
|
||||
case kpidIsAnti: prop = _db.IsItemAnti(index2); break;
|
||||
#ifndef _SFX
|
||||
case kpidMethod:
|
||||
// case kpidIsAux: prop = _db.IsItemAux(index2); break;
|
||||
case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; }
|
||||
case kpidCTime: SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break;
|
||||
case kpidATime: SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break;
|
||||
case kpidMTime: SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break;
|
||||
case kpidAttrib: if (item.AttribDefined) PropVarEm_Set_UInt32(value, item.Attrib); break;
|
||||
case kpidCRC: if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break;
|
||||
case kpidEncrypted: PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break;
|
||||
case kpidIsAnti: PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break;
|
||||
/*
|
||||
case kpidIsAltStream: prop = item.IsAltStream; break;
|
||||
case kpidNtSecure:
|
||||
{
|
||||
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
|
||||
if (folderIndex != kNumNoIndex)
|
||||
int id = _db.SecureIDs[index];
|
||||
size_t offs = _db.SecureOffsets[id];
|
||||
size_t size = _db.SecureOffsets[id + 1] - offs;
|
||||
if (size >= 0)
|
||||
{
|
||||
const CFolder &folderInfo = _db.Folders[folderIndex];
|
||||
UString methodsString;
|
||||
for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
const CCoderInfo &coder = folderInfo.Coders[i];
|
||||
if (!methodsString.IsEmpty())
|
||||
methodsString += L' ';
|
||||
|
||||
UString methodName, propsString;
|
||||
bool methodIsKnown = FindMethod(
|
||||
EXTERNAL_CODECS_VARS
|
||||
coder.MethodID, methodName);
|
||||
|
||||
if (!methodIsKnown)
|
||||
methodsString += ConvertMethodIdToString(coder.MethodID);
|
||||
else
|
||||
{
|
||||
methodsString += methodName;
|
||||
if (coder.MethodID == k_Delta && coder.Props.GetCapacity() == 1)
|
||||
propsString = ConvertUInt32ToString((UInt32)coder.Props[0] + 1);
|
||||
else if (coder.MethodID == k_LZMA && coder.Props.GetCapacity() == 5)
|
||||
{
|
||||
UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
|
||||
propsString = GetStringForSizeValue(dicSize);
|
||||
UInt32 d = coder.Props[0];
|
||||
UInt32 lc = d % 9;
|
||||
d /= 9;
|
||||
UInt32 pb = d / 5;
|
||||
UInt32 lp = d % 5;
|
||||
if (lc != 3) AddProp32(propsString, L":lc", lc);
|
||||
if (lp != 0) AddProp32(propsString, L":lp", lp);
|
||||
if (pb != 2) AddProp32(propsString, L":pb", pb);
|
||||
}
|
||||
else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1)
|
||||
{
|
||||
Byte p = coder.Props[0];
|
||||
UInt32 dicSize = (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11));
|
||||
propsString = GetStringForSizeValue(dicSize);
|
||||
}
|
||||
else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5)
|
||||
{
|
||||
Byte order = *(const Byte *)coder.Props;
|
||||
propsString = L'o';
|
||||
propsString += ConvertUInt32ToString(order);
|
||||
propsString += L":mem";
|
||||
UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
|
||||
propsString += GetStringForSizeValue(dicSize);
|
||||
}
|
||||
else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1)
|
||||
{
|
||||
const Byte *data = (const Byte *)coder.Props;
|
||||
Byte firstByte = *data++;
|
||||
UInt32 numCyclesPower = firstByte & 0x3F;
|
||||
propsString = ConvertUInt32ToString(numCyclesPower);
|
||||
/*
|
||||
if ((firstByte & 0xC0) != 0)
|
||||
{
|
||||
UInt32 saltSize = (firstByte >> 7) & 1;
|
||||
UInt32 ivSize = (firstByte >> 6) & 1;
|
||||
if (coder.Props.GetCapacity() >= 2)
|
||||
{
|
||||
Byte secondByte = *data++;
|
||||
saltSize += (secondByte >> 4);
|
||||
ivSize += (secondByte & 0x0F);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
if (!propsString.IsEmpty())
|
||||
{
|
||||
methodsString += L':';
|
||||
methodsString += propsString;
|
||||
}
|
||||
else if (coder.Props.GetCapacity() > 0)
|
||||
{
|
||||
methodsString += L":[";
|
||||
for (size_t bi = 0; bi < coder.Props.GetCapacity(); bi++)
|
||||
{
|
||||
if (bi > 5 && bi + 1 < coder.Props.GetCapacity())
|
||||
{
|
||||
methodsString += L"..";
|
||||
break;
|
||||
}
|
||||
else
|
||||
AddHexToString(methodsString, coder.Props[bi]);
|
||||
}
|
||||
methodsString += L']';
|
||||
}
|
||||
}
|
||||
prop = methodsString;
|
||||
prop.SetBlob(_db.SecureBuf + offs, (ULONG)size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
*/
|
||||
|
||||
case kpidPath: return _db.GetPath(index, value);
|
||||
#ifndef _SFX
|
||||
case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);
|
||||
case kpidBlock:
|
||||
{
|
||||
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
|
||||
if (folderIndex != kNumNoIndex)
|
||||
prop = (UInt32)folderIndex;
|
||||
PropVarEm_Set_UInt32(value, (UInt32)folderIndex);
|
||||
}
|
||||
break;
|
||||
case kpidPackedSize0:
|
||||
@@ -376,6 +611,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
case kpidPackedSize3:
|
||||
case kpidPackedSize4:
|
||||
{
|
||||
/*
|
||||
CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];
|
||||
if (folderIndex != kNumNoIndex)
|
||||
{
|
||||
@@ -390,13 +626,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
}
|
||||
else
|
||||
prop = (UInt64)0;
|
||||
*/
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
prop.Detach(value);
|
||||
// prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
// COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
@@ -408,6 +645,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
#ifndef _SFX
|
||||
_fileInfoPopIDs.Clear();
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
|
||||
@@ -415,31 +653,30 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
#ifndef _NO_CRYPTO
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
if (openArchiveCallback)
|
||||
{
|
||||
openArchiveCallbackTemp.QueryInterface(
|
||||
IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
}
|
||||
openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
#endif
|
||||
|
||||
CInArchive archive;
|
||||
_db.IsArc = false;
|
||||
RINOK(archive.Open(stream, maxCheckStartPosition));
|
||||
#ifndef _NO_CRYPTO
|
||||
_passwordIsDefined = false;
|
||||
UString password;
|
||||
#endif
|
||||
_db.IsArc = true;
|
||||
|
||||
HRESULT result = archive.ReadDatabase(
|
||||
EXTERNAL_CODECS_VARS
|
||||
_db
|
||||
#ifndef _NO_CRYPTO
|
||||
, getTextPassword, _passwordIsDefined
|
||||
#endif
|
||||
);
|
||||
EXTERNAL_CODECS_VARS
|
||||
_db
|
||||
#ifndef _NO_CRYPTO
|
||||
, getTextPassword, _isEncrypted, _passwordIsDefined
|
||||
#endif
|
||||
);
|
||||
RINOK(result);
|
||||
_db.Fill();
|
||||
|
||||
_inStream = stream;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
Close();
|
||||
// return E_INVALIDARG;
|
||||
// we must return out_of_memory here
|
||||
return S_FALSE;
|
||||
}
|
||||
// _inStream = stream;
|
||||
@@ -455,6 +692,10 @@ STDMETHODIMP CHandler::Close()
|
||||
COM_TRY_BEGIN
|
||||
_inStream.Release();
|
||||
_db.Clear();
|
||||
#ifndef _NO_CRYPTO
|
||||
_isEncrypted = false;
|
||||
_passwordIsDefined = false;
|
||||
#endif
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
@@ -462,16 +703,16 @@ STDMETHODIMP CHandler::Close()
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
#ifdef EXTRACT_ONLY
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
|
||||
_numThreads = numProcessors;
|
||||
|
||||
for (int i = 0; i < numProperties; i++)
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
UString name = names[i];
|
||||
name.MakeUpper();
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
const PROPVARIANT &value = values[i];
|
||||
@@ -479,9 +720,9 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
int index = ParseStringToUInt32(name, number);
|
||||
if (index == 0)
|
||||
{
|
||||
if(name.Left(2).CompareNoCase(L"MT") == 0)
|
||||
if (name.IsPrefixedBy(L"mt"))
|
||||
{
|
||||
RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
|
||||
RINOK(ParseMtProp(name.Ptr(2), value, numProcessors, _numThreads));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
||||
25
CPP/7zip/Archive/7z/7zHandler.h
Executable file → Normal file
25
CPP/7zip/Archive/7z/7zHandler.h
Executable file → Normal file
@@ -58,10 +58,11 @@ public:
|
||||
bool _compressHeaders;
|
||||
bool _encryptHeadersSpecified;
|
||||
bool _encryptHeaders;
|
||||
// bool _useParents; 9.26
|
||||
|
||||
bool WriteCTime;
|
||||
bool WriteATime;
|
||||
bool WriteMTime;
|
||||
CBoolPair Write_CTime;
|
||||
CBoolPair Write_ATime;
|
||||
CBoolPair Write_MTime;
|
||||
|
||||
bool _volumeMode;
|
||||
|
||||
@@ -85,10 +86,8 @@ public:
|
||||
#endif
|
||||
|
||||
class CHandler:
|
||||
#ifndef EXTRACT_ONLY
|
||||
public COutHandler,
|
||||
#endif
|
||||
public IInArchive,
|
||||
public IArchiveGetRawProps,
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
public ISetProperties,
|
||||
#endif
|
||||
@@ -97,9 +96,13 @@ class CHandler:
|
||||
#endif
|
||||
PUBLIC_ISetCompressCodecsInfo
|
||||
public CMyUnknownImp
|
||||
#ifndef EXTRACT_ONLY
|
||||
, public COutHandler
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(IInArchive)
|
||||
// MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
MY_QUERYINTERFACE_ENTRY(ISetProperties)
|
||||
#endif
|
||||
@@ -111,9 +114,10 @@ public:
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_IInArchive(;)
|
||||
INTERFACE_IArchiveGetRawProps(;)
|
||||
|
||||
#ifdef __7Z_SET_PROPERTIES
|
||||
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);
|
||||
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
|
||||
#endif
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
@@ -126,8 +130,9 @@ public:
|
||||
|
||||
private:
|
||||
CMyComPtr<IInStream> _inStream;
|
||||
NArchive::N7z::CArchiveDatabaseEx _db;
|
||||
NArchive::N7z::CDbEx _db;
|
||||
#ifndef _NO_CRYPTO
|
||||
bool _isEncrypted;
|
||||
bool _passwordIsDefined;
|
||||
#endif
|
||||
|
||||
@@ -156,11 +161,13 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
bool IsEncrypted(UInt32 index2) const;
|
||||
bool IsFolderEncrypted(CNum folderIndex) const;
|
||||
#ifndef _SFX
|
||||
|
||||
CRecordVector<UInt64> _fileInfoPopIDs;
|
||||
void FillPopIDs();
|
||||
void AddMethodName(AString &s, UInt64 id);
|
||||
HRESULT SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
378
CPP/7zip/Archive/7z/7zHandlerOut.cpp
Executable file → Normal file
378
CPP/7zip/Archive/7z/7zHandlerOut.cpp
Executable file → Normal file
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/StringToInt.h"
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
#include "../Common/ParseProperties.h"
|
||||
@@ -18,7 +19,7 @@ namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
static const wchar_t *k_LZMA_Name = L"LZMA";
|
||||
static const wchar_t *kDefaultMethodName = k_LZMA_Name;
|
||||
static const wchar_t *kDefaultMethodName = L"LZMA2";
|
||||
static const wchar_t *k_Copy_Name = L"Copy";
|
||||
|
||||
static const wchar_t *k_MatchFinder_ForHeaders = L"BT2";
|
||||
@@ -67,9 +68,9 @@ HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)
|
||||
|
||||
void CHandler::AddDefaultMethod()
|
||||
{
|
||||
for (int i = 0; i < _methods.Size(); i++)
|
||||
FOR_VECTOR (i, _methods)
|
||||
{
|
||||
UString &methodName = _methods[0].MethodName;
|
||||
UString &methodName = _methods[i].MethodName;
|
||||
if (methodName.IsEmpty())
|
||||
methodName = kDefaultMethodName;
|
||||
}
|
||||
@@ -95,7 +96,7 @@ HRESULT CHandler::SetMainMethod(
|
||||
const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1;
|
||||
|
||||
bool needSolid = false;
|
||||
for (int i = 0; i < methods.Size(); i++)
|
||||
FOR_VECTOR (i, methods)
|
||||
{
|
||||
COneMethodInfo &oneMethodInfo = methods[i];
|
||||
SetGlobalLevelAndThreads(oneMethodInfo
|
||||
@@ -139,12 +140,10 @@ HRESULT CHandler::SetMainMethod(
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool writeTime, PROPID propID, UInt64 &ft, bool &ftDefined)
|
||||
static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, UInt64 &ft, bool &ftDefined)
|
||||
{
|
||||
ft = 0;
|
||||
ftDefined = false;
|
||||
if (!writeTime)
|
||||
return S_OK;
|
||||
// ft = 0;
|
||||
// ftDefined = false;
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(index, propID, &prop));
|
||||
if (prop.vt == VT_FILETIME)
|
||||
@@ -154,15 +153,87 @@ static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool w
|
||||
}
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
{
|
||||
ft = 0;
|
||||
ftDefined = false;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
#ifdef _WIN32
|
||||
static const wchar_t kDirDelimiter1 = L'\\';
|
||||
#endif
|
||||
static const wchar_t kDirDelimiter2 = L'/';
|
||||
|
||||
static inline bool IsCharDirLimiter(wchar_t c)
|
||||
{
|
||||
return (
|
||||
#ifdef _WIN32
|
||||
c == kDirDelimiter1 ||
|
||||
#endif
|
||||
c == kDirDelimiter2);
|
||||
}
|
||||
|
||||
static int FillSortIndex(CObjectVector<CTreeFolder> &treeFolders, int cur, int curSortIndex)
|
||||
{
|
||||
CTreeFolder &tf = treeFolders[cur];
|
||||
tf.SortIndex = curSortIndex++;
|
||||
for (int i = 0; i < tf.SubFolders.Size(); i++)
|
||||
curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex);
|
||||
tf.SortIndexEnd = curSortIndex;
|
||||
return curSortIndex;
|
||||
}
|
||||
|
||||
static int FindSubFolder(const CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name, int &insertPos)
|
||||
{
|
||||
const CIntVector &subFolders = treeFolders[cur].SubFolders;
|
||||
int left = 0, right = subFolders.Size();
|
||||
insertPos = -1;
|
||||
for (;;)
|
||||
{
|
||||
if (left == right)
|
||||
{
|
||||
insertPos = left;
|
||||
return -1;
|
||||
}
|
||||
int mid = (left + right) / 2;
|
||||
int midFolder = subFolders[mid];
|
||||
int compare = CompareFileNames(name, treeFolders[midFolder].Name);
|
||||
if (compare == 0)
|
||||
return midFolder;
|
||||
if (compare < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int AddFolder(CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name)
|
||||
{
|
||||
int insertPos;
|
||||
int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos);
|
||||
if (folderIndex < 0)
|
||||
{
|
||||
folderIndex = treeFolders.Size();
|
||||
CTreeFolder &newFolder = treeFolders.AddNew();
|
||||
newFolder.Parent = cur;
|
||||
newFolder.Name = name;
|
||||
treeFolders[cur].SubFolders.Insert(insertPos, folderIndex);
|
||||
}
|
||||
// else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234;
|
||||
return folderIndex;
|
||||
}
|
||||
*/
|
||||
|
||||
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
const CArchiveDatabaseEx *db = 0;
|
||||
const CDbEx *db = 0;
|
||||
#ifdef _7Z_VOL
|
||||
if (_volumes.Size() > 1)
|
||||
return E_FAIL;
|
||||
@@ -177,8 +248,35 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
db = &_db;
|
||||
#endif
|
||||
|
||||
/*
|
||||
CMyComPtr<IArchiveGetRawProps> getRawProps;
|
||||
updateCallback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps);
|
||||
|
||||
CUniqBlocks secureBlocks;
|
||||
secureBlocks.AddUniq(NULL, 0);
|
||||
|
||||
CObjectVector<CTreeFolder> treeFolders;
|
||||
{
|
||||
CTreeFolder folder;
|
||||
folder.Parent = -1;
|
||||
treeFolders.Add(folder);
|
||||
}
|
||||
*/
|
||||
|
||||
CObjectVector<CUpdateItem> updateItems;
|
||||
|
||||
|
||||
bool need_CTime = (Write_CTime.Def && Write_CTime.Val);
|
||||
bool need_ATime = (Write_ATime.Def && Write_ATime.Val);
|
||||
bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def);
|
||||
if (db)
|
||||
{
|
||||
if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();
|
||||
if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();
|
||||
if (!Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty();
|
||||
}
|
||||
|
||||
UString s;
|
||||
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
Int32 newData, newProps;
|
||||
@@ -194,24 +292,35 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
ui.IsAnti = false;
|
||||
ui.Size = 0;
|
||||
|
||||
UString name;
|
||||
// bool isAltStream = false;
|
||||
if (ui.IndexInArchive != -1)
|
||||
{
|
||||
if (db == 0 || ui.IndexInArchive >= db->Files.Size())
|
||||
if (db == 0 || (unsigned)ui.IndexInArchive >= db->Files.Size())
|
||||
return E_INVALIDARG;
|
||||
const CFileItem &fi = db->Files[ui.IndexInArchive];
|
||||
ui.Name = fi.Name;
|
||||
if (!ui.NewProps)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(_db.GetPath(ui.IndexInArchive, &prop));
|
||||
if (prop.vt == VT_BSTR)
|
||||
name = prop.bstrVal;
|
||||
}
|
||||
ui.IsDir = fi.IsDir;
|
||||
ui.Size = fi.Size;
|
||||
// isAltStream = fi.IsAltStream;
|
||||
ui.IsAnti = db->IsItemAnti(ui.IndexInArchive);
|
||||
|
||||
ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime);
|
||||
ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime);
|
||||
ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime);
|
||||
if (!ui.NewProps)
|
||||
{
|
||||
ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime);
|
||||
ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime);
|
||||
ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (ui.NewProps)
|
||||
{
|
||||
bool nameIsDefined;
|
||||
bool folderStatusIsDefined;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
@@ -228,21 +337,35 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
}
|
||||
|
||||
// we need MTime to sort files.
|
||||
RINOK(GetTime(updateCallback, i, WriteCTime, kpidCTime, ui.CTime, ui.CTimeDefined));
|
||||
RINOK(GetTime(updateCallback, i, WriteATime, kpidATime, ui.ATime, ui.ATimeDefined));
|
||||
RINOK(GetTime(updateCallback, i, true, kpidMTime, ui.MTime, ui.MTimeDefined));
|
||||
if (need_CTime) RINOK(GetTime(updateCallback, i, kpidCTime, ui.CTime, ui.CTimeDefined));
|
||||
if (need_ATime) RINOK(GetTime(updateCallback, i, kpidATime, ui.ATime, ui.ATimeDefined));
|
||||
if (need_MTime) RINOK(GetTime(updateCallback, i, kpidMTime, ui.MTime, ui.MTimeDefined));
|
||||
|
||||
/*
|
||||
if (getRawProps)
|
||||
{
|
||||
const void *data;
|
||||
UInt32 dataSize;
|
||||
UInt32 propType;
|
||||
|
||||
getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType);
|
||||
if (dataSize != 0 && propType != NPropDataType::kRaw)
|
||||
return E_FAIL;
|
||||
ui.SecureIndex = secureBlocks.AddUniq((const Byte *)data, dataSize);
|
||||
}
|
||||
*/
|
||||
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidPath, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
nameIsDefined = false;
|
||||
{
|
||||
}
|
||||
else if (prop.vt != VT_BSTR)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
{
|
||||
ui.Name = NItemName::MakeLegalName(prop.bstrVal);
|
||||
nameIsDefined = true;
|
||||
name = NItemName::MakeLegalName(prop.bstrVal);
|
||||
}
|
||||
}
|
||||
{
|
||||
@@ -270,6 +393,19 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
ui.IsAnti = (prop.boolVal != VARIANT_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidIsAltStream, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
isAltStream = false;
|
||||
else if (prop.vt != VT_BOOL)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
isAltStream = (prop.boolVal != VARIANT_FALSE);
|
||||
}
|
||||
*/
|
||||
|
||||
if (ui.IsAnti)
|
||||
{
|
||||
ui.AttribDefined = false;
|
||||
@@ -284,6 +420,80 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (!folderStatusIsDefined && ui.AttribDefined)
|
||||
ui.SetDirStatusFromAttrib();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
if (_db.SecureIDs.IsEmpty())
|
||||
ui.SecureIndex = secureBlocks.AddUniq(NULL, 0);
|
||||
else
|
||||
{
|
||||
int id = _db.SecureIDs[ui.IndexInArchive];
|
||||
size_t offs = _db.SecureOffsets[id];
|
||||
size_t size = _db.SecureOffsets[id + 1] - offs;
|
||||
ui.SecureIndex = secureBlocks.AddUniq(_db.SecureBuf + offs, size);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
int folderIndex = 0;
|
||||
if (_useParents)
|
||||
{
|
||||
int j;
|
||||
s.Empty();
|
||||
for (j = 0; j < name.Len(); j++)
|
||||
{
|
||||
wchar_t c = name[j];
|
||||
if (IsCharDirLimiter(c))
|
||||
{
|
||||
folderIndex = AddFolder(treeFolders, folderIndex, s);
|
||||
s.Empty();
|
||||
continue;
|
||||
}
|
||||
s += c;
|
||||
}
|
||||
if (isAltStream)
|
||||
{
|
||||
int colonPos = s.Find(':');
|
||||
if (colonPos < 0)
|
||||
{
|
||||
// isAltStream = false;
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
UString mainName = s.Left(colonPos);
|
||||
int newFolderIndex = AddFolder(treeFolders, folderIndex, mainName);
|
||||
if (treeFolders[newFolderIndex].UpdateItemIndex < 0)
|
||||
{
|
||||
for (int j = updateItems.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
CUpdateItem &ui2 = updateItems[j];
|
||||
if (ui2.ParentFolderIndex == folderIndex
|
||||
&& ui2.Name == mainName)
|
||||
{
|
||||
ui2.TreeFolderIndex = newFolderIndex;
|
||||
treeFolders[newFolderIndex].UpdateItemIndex = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
folderIndex = newFolderIndex;
|
||||
s.Delete(0, colonPos + 1);
|
||||
}
|
||||
ui.Name = s;
|
||||
}
|
||||
else
|
||||
ui.Name = name;
|
||||
ui.IsAltStream = isAltStream;
|
||||
ui.ParentFolderIndex = folderIndex;
|
||||
ui.TreeFolderIndex = -1;
|
||||
if (ui.IsDir && !s.IsEmpty())
|
||||
{
|
||||
ui.TreeFolderIndex = AddFolder(treeFolders, folderIndex, s);
|
||||
treeFolders[ui.TreeFolderIndex].UpdateItemIndex = updateItems.Size();
|
||||
}
|
||||
}
|
||||
*/
|
||||
ui.Name = name;
|
||||
|
||||
if (ui.NewData)
|
||||
{
|
||||
@@ -298,6 +508,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
updateItems.Add(ui);
|
||||
}
|
||||
|
||||
/*
|
||||
FillSortIndex(treeFolders, 0, 0);
|
||||
for (i = 0; i < (UInt32)updateItems.Size(); i++)
|
||||
{
|
||||
CUpdateItem &ui = updateItems[i];
|
||||
ui.ParentSortIndex = treeFolders[ui.ParentFolderIndex].SortIndex;
|
||||
ui.ParentSortIndexEnd = treeFolders[ui.ParentFolderIndex].SortIndexEnd;
|
||||
}
|
||||
*/
|
||||
|
||||
CCompressionMethodMode methodMode, headerMethod;
|
||||
|
||||
HRESULT res = SetMainMethod(methodMode, _methods
|
||||
@@ -317,17 +537,17 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
CMyComPtr<ICryptoGetTextPassword2> getPassword2;
|
||||
updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2);
|
||||
|
||||
methodMode.PasswordIsDefined = false;
|
||||
methodMode.Password.Empty();
|
||||
if (getPassword2)
|
||||
{
|
||||
CMyComBSTR password;
|
||||
Int32 passwordIsDefined;
|
||||
RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
|
||||
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
|
||||
if (methodMode.PasswordIsDefined)
|
||||
if (methodMode.PasswordIsDefined && (BSTR)password)
|
||||
methodMode.Password = password;
|
||||
}
|
||||
else
|
||||
methodMode.PasswordIsDefined = false;
|
||||
|
||||
bool compressMainHeader = _compressHeaders; // check it
|
||||
|
||||
@@ -360,9 +580,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
options.MaxFilter = level >= 8;
|
||||
|
||||
options.HeaderOptions.CompressMainHeader = compressMainHeader;
|
||||
options.HeaderOptions.WriteCTime = WriteCTime;
|
||||
options.HeaderOptions.WriteATime = WriteATime;
|
||||
options.HeaderOptions.WriteMTime = WriteMTime;
|
||||
/*
|
||||
options.HeaderOptions.WriteCTime = Write_CTime;
|
||||
options.HeaderOptions.WriteATime = Write_ATime;
|
||||
options.HeaderOptions.WriteMTime = Write_MTime;
|
||||
*/
|
||||
|
||||
options.NumSolidFiles = _numSolidFiles;
|
||||
options.NumSolidBytes = _numSolidBytes;
|
||||
@@ -371,11 +593,23 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
options.VolumeMode = _volumeMode;
|
||||
|
||||
COutArchive archive;
|
||||
CArchiveDatabase newDatabase;
|
||||
CArchiveDatabaseOut newDatabase;
|
||||
|
||||
CMyComPtr<ICryptoGetTextPassword> getPassword;
|
||||
updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword);
|
||||
|
||||
/*
|
||||
if (secureBlocks.Sorted.Size() > 1)
|
||||
{
|
||||
secureBlocks.GetReverseMap();
|
||||
for (int i = 0; i < updateItems.Size(); i++)
|
||||
{
|
||||
int &secureIndex = updateItems[i].SecureIndex;
|
||||
secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
res = Update(
|
||||
EXTERNAL_CODECS_VARS
|
||||
#ifdef _7Z_VOL
|
||||
@@ -386,6 +620,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
db,
|
||||
#endif
|
||||
updateItems,
|
||||
// treeFolders,
|
||||
// secureBlocks,
|
||||
archive, newDatabase, outStream, updateCallback, options
|
||||
#ifndef _NO_CRYPTO
|
||||
, getPassword
|
||||
@@ -409,7 +645,7 @@ static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream
|
||||
if (index == 0)
|
||||
return E_INVALIDARG;
|
||||
srcString.Delete(0, index);
|
||||
if (srcString[0] == 'S')
|
||||
if (srcString[0] == 's')
|
||||
{
|
||||
srcString.Delete(0);
|
||||
int index = ParseStringToUInt32(srcString, stream);
|
||||
@@ -428,11 +664,12 @@ void COutHandler::InitProps()
|
||||
_compressHeaders = true;
|
||||
_encryptHeadersSpecified = false;
|
||||
_encryptHeaders = false;
|
||||
// _useParents = false;
|
||||
|
||||
WriteCTime = false;
|
||||
WriteATime = false;
|
||||
WriteMTime = true;
|
||||
|
||||
Write_CTime.Init();
|
||||
Write_ATime.Init();
|
||||
Write_MTime.Init();
|
||||
|
||||
_volumeMode = false;
|
||||
InitSolid();
|
||||
}
|
||||
@@ -440,24 +677,24 @@ void COutHandler::InitProps()
|
||||
HRESULT COutHandler::SetSolidFromString(const UString &s)
|
||||
{
|
||||
UString s2 = s;
|
||||
s2.MakeUpper();
|
||||
for (int i = 0; i < s2.Length();)
|
||||
s2.MakeLower_Ascii();
|
||||
for (unsigned i = 0; i < s2.Len();)
|
||||
{
|
||||
const wchar_t *start = ((const wchar_t *)s2) + i;
|
||||
const wchar_t *end;
|
||||
UInt64 v = ConvertStringToUInt64(start, &end);
|
||||
if (start == end)
|
||||
{
|
||||
if (s2[i++] != 'E')
|
||||
if (s2[i++] != 'e')
|
||||
return E_INVALIDARG;
|
||||
_solidExtension = true;
|
||||
continue;
|
||||
}
|
||||
i += (int)(end - start);
|
||||
if (i == s2.Length())
|
||||
if (i == s2.Len())
|
||||
return E_INVALIDARG;
|
||||
wchar_t c = s2[i++];
|
||||
if (c == 'F')
|
||||
if (c == 'f')
|
||||
{
|
||||
if (v < 1)
|
||||
v = 1;
|
||||
@@ -468,10 +705,11 @@ HRESULT COutHandler::SetSolidFromString(const UString &s)
|
||||
unsigned numBits;
|
||||
switch (c)
|
||||
{
|
||||
case 'B': numBits = 0; break;
|
||||
case 'K': numBits = 10; break;
|
||||
case 'M': numBits = 20; break;
|
||||
case 'G': numBits = 30; break;
|
||||
case 'b': numBits = 0; break;
|
||||
case 'k': numBits = 10; break;
|
||||
case 'm': numBits = 20; break;
|
||||
case 'g': numBits = 30; break;
|
||||
case 't': numBits = 40; break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
_numSolidBytes = (v << numBits);
|
||||
@@ -501,14 +739,21 @@ HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest)
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(prop, dest.Val));
|
||||
dest.Def = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
|
||||
{
|
||||
UString name = nameSpec;
|
||||
name.MakeUpper();
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (name[0] == L'S')
|
||||
if (name[0] == L's')
|
||||
{
|
||||
name.Delete(0);
|
||||
if (name.IsEmpty())
|
||||
@@ -520,47 +765,52 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
|
||||
|
||||
UInt32 number;
|
||||
int index = ParseStringToUInt32(name, number);
|
||||
UString realName = name.Mid(index);
|
||||
UString realName = name.Ptr(index);
|
||||
if (index == 0)
|
||||
{
|
||||
if (name.CompareNoCase(L"RSFX") == 0) return PROPVARIANT_to_bool(value, _removeSfxBlock);
|
||||
if (name.CompareNoCase(L"HC") == 0) return PROPVARIANT_to_bool(value, _compressHeaders);
|
||||
if (name.CompareNoCase(L"HCF") == 0)
|
||||
if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock);
|
||||
if (name.IsEqualTo("hc")) return PROPVARIANT_to_bool(value, _compressHeaders);
|
||||
// if (name.IsEqualToNoCase(L"HS")) return PROPVARIANT_to_bool(value, _useParents);
|
||||
|
||||
if (name.IsEqualTo("hcf"))
|
||||
{
|
||||
bool compressHeadersFull = true;
|
||||
RINOK(PROPVARIANT_to_bool(value, compressHeadersFull));
|
||||
return compressHeadersFull ? S_OK: E_INVALIDARG;
|
||||
}
|
||||
if (name.CompareNoCase(L"HE") == 0)
|
||||
|
||||
if (name.IsEqualTo("he"))
|
||||
{
|
||||
RINOK(PROPVARIANT_to_bool(value, _encryptHeaders));
|
||||
_encryptHeadersSpecified = true;
|
||||
return S_OK;
|
||||
}
|
||||
if (name.CompareNoCase(L"TC") == 0) return PROPVARIANT_to_bool(value, WriteCTime);
|
||||
if (name.CompareNoCase(L"TA") == 0) return PROPVARIANT_to_bool(value, WriteATime);
|
||||
if (name.CompareNoCase(L"TM") == 0) return PROPVARIANT_to_bool(value, WriteMTime);
|
||||
if (name.CompareNoCase(L"V") == 0) return PROPVARIANT_to_bool(value, _volumeMode);
|
||||
|
||||
if (name.IsEqualTo("tc")) return PROPVARIANT_to_BoolPair(value, Write_CTime);
|
||||
if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime);
|
||||
if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime);
|
||||
|
||||
if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
|
||||
}
|
||||
return CMultiMethodProps::SetProperty(name, value);
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
_binds.Clear();
|
||||
InitProps();
|
||||
|
||||
for (int i = 0; i < numProps; i++)
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
UString name = names[i];
|
||||
name.MakeUpper();
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
|
||||
const PROPVARIANT &value = values[i];
|
||||
|
||||
if (name[0] == 'B')
|
||||
if (name[0] == 'b')
|
||||
{
|
||||
if (value.vt != VT_EMPTY)
|
||||
return E_INVALIDARG;
|
||||
@@ -580,10 +830,10 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
RINOK(SetProperty(name, value));
|
||||
}
|
||||
|
||||
int numEmptyMethods = GetNumEmptyMethods();
|
||||
unsigned numEmptyMethods = GetNumEmptyMethods();
|
||||
if (numEmptyMethods > 0)
|
||||
{
|
||||
int k;
|
||||
unsigned k;
|
||||
for (k = 0; k < _binds.Size(); k++)
|
||||
{
|
||||
const CBind &bind = _binds[k];
|
||||
@@ -597,14 +847,14 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
bind.InCoder -= (UInt32)numEmptyMethods;
|
||||
bind.OutCoder -= (UInt32)numEmptyMethods;
|
||||
}
|
||||
_methods.Delete(0, numEmptyMethods);
|
||||
_methods.DeleteFrontal(numEmptyMethods);
|
||||
}
|
||||
|
||||
AddDefaultMethod();
|
||||
|
||||
if (!_filterMethod.MethodName.IsEmpty())
|
||||
{
|
||||
for (int k = 0; k < _binds.Size(); k++)
|
||||
FOR_VECTOR (k, _binds)
|
||||
{
|
||||
CBind &bind = _binds[k];
|
||||
bind.InCoder++;
|
||||
@@ -613,7 +863,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
_methods.Insert(0, _filterMethod);
|
||||
}
|
||||
|
||||
for (int k = 0; k < _binds.Size(); k++)
|
||||
FOR_VECTOR (k, _binds)
|
||||
{
|
||||
const CBind &bind = _binds[k];
|
||||
if (bind.InCoder >= (UInt32)_methods.Size() ||
|
||||
|
||||
5
CPP/7zip/Archive/7z/7zHeader.cpp
Executable file → Normal file
5
CPP/7zip/Archive/7z/7zHeader.cpp
Executable file → Normal file
@@ -1,6 +1,7 @@
|
||||
// 7zHeader.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "7zHeader.h"
|
||||
|
||||
namespace NArchive {
|
||||
@@ -11,4 +12,8 @@ Byte kSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
||||
Byte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};
|
||||
#endif
|
||||
|
||||
// We can change signature. So file doesn't contain correct signature.
|
||||
// struct SignatureInitializer { SignatureInitializer() { kSignature[0]--; } };
|
||||
// static SignatureInitializer g_SignatureInitializer;
|
||||
|
||||
}}
|
||||
|
||||
10
CPP/7zip/Archive/7z/7zHeader.h
Executable file → Normal file
10
CPP/7zip/Archive/7z/7zHeader.h
Executable file → Normal file
@@ -3,12 +3,12 @@
|
||||
#ifndef __7Z_HEADER_H
|
||||
#define __7Z_HEADER_H
|
||||
|
||||
#include "../../../Common/Types.h"
|
||||
#include "../../../Common/MyTypes.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
const int kSignatureSize = 6;
|
||||
const unsigned kSignatureSize = 6;
|
||||
extern Byte kSignature[kSignatureSize];
|
||||
|
||||
// #define _7Z_VOL
|
||||
@@ -82,13 +82,17 @@ namespace NID
|
||||
kCTime,
|
||||
kATime,
|
||||
kMTime,
|
||||
kWinAttributes,
|
||||
kWinAttrib,
|
||||
kComment,
|
||||
|
||||
kEncodedHeader,
|
||||
|
||||
kStartPos,
|
||||
kDummy
|
||||
|
||||
// kNtSecure,
|
||||
// kParent,
|
||||
// kIsAux
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
1376
CPP/7zip/Archive/7z/7zIn.cpp
Executable file → Normal file
1376
CPP/7zip/Archive/7z/7zIn.cpp
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
335
CPP/7zip/Archive/7z/7zIn.h
Executable file → Normal file
335
CPP/7zip/Archive/7z/7zIn.h
Executable file → Normal file
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
|
||||
#include "../../IPassword.h"
|
||||
#include "../../IStream.h"
|
||||
|
||||
@@ -15,7 +17,147 @@
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
/*
|
||||
We don't need to init isEncrypted and passwordIsDefined
|
||||
We must upgrade them only */
|
||||
|
||||
#ifdef _NO_CRYPTO
|
||||
#define _7Z_DECODER_CRYPRO_VARS_DECL
|
||||
#define _7Z_DECODER_CRYPRO_VARS
|
||||
#else
|
||||
#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined
|
||||
#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined
|
||||
#endif
|
||||
|
||||
struct CParsedMethods
|
||||
{
|
||||
Byte Lzma2Prop;
|
||||
UInt32 LzmaDic;
|
||||
CRecordVector<UInt64> IDs;
|
||||
|
||||
CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}
|
||||
};
|
||||
|
||||
struct CFolders
|
||||
{
|
||||
CNum NumPackStreams;
|
||||
CNum NumFolders;
|
||||
|
||||
CObjArray<UInt64> PackPositions; // NumPackStreams + 1
|
||||
// CUInt32DefVector PackCRCs; // we don't use PackCRCs now
|
||||
|
||||
CUInt32DefVector FolderCRCs; // NumFolders
|
||||
CObjArray<CNum> NumUnpackStreamsVector; // NumFolders
|
||||
|
||||
CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders
|
||||
CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1
|
||||
CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1
|
||||
CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders
|
||||
|
||||
CObjArray<size_t> FoCodersDataOffset; // NumFolders + 1
|
||||
CByteBuffer CodersData;
|
||||
|
||||
CParsedMethods ParsedMethods;
|
||||
|
||||
void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const;
|
||||
|
||||
unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const
|
||||
{
|
||||
return FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex];
|
||||
}
|
||||
|
||||
UInt64 GetFolderUnpackSize(unsigned folderIndex) const
|
||||
{
|
||||
return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]];
|
||||
}
|
||||
|
||||
UInt64 GetStreamPackSize(unsigned index) const
|
||||
{
|
||||
return PackPositions[index + 1] - PackPositions[index];
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
NumPackStreams = 0;
|
||||
PackPositions.Free();
|
||||
// PackCRCs.Clear();
|
||||
|
||||
NumFolders = 0;
|
||||
FolderCRCs.Clear();
|
||||
NumUnpackStreamsVector.Free();
|
||||
CoderUnpackSizes.Free();
|
||||
FoToCoderUnpackSizes.Free();
|
||||
FoStartPackStreamIndex.Free();
|
||||
FoToMainUnpackSizeIndex.Free();
|
||||
FoCodersDataOffset.Free();
|
||||
CodersData.Free();
|
||||
}
|
||||
};
|
||||
|
||||
struct CDatabase: public CFolders
|
||||
{
|
||||
CRecordVector<CFileItem> Files;
|
||||
|
||||
CUInt64DefVector CTime;
|
||||
CUInt64DefVector ATime;
|
||||
CUInt64DefVector MTime;
|
||||
CUInt64DefVector StartPos;
|
||||
CRecordVector<bool> IsAnti;
|
||||
/*
|
||||
CRecordVector<bool> IsAux;
|
||||
CByteBuffer SecureBuf;
|
||||
CRecordVector<UInt32> SecureIDs;
|
||||
*/
|
||||
|
||||
CByteBuffer NamesBuf;
|
||||
CObjArray<size_t> NameOffsets; // numFiles + 1, conatins offsets of UINt16 symbols.
|
||||
|
||||
/*
|
||||
void ClearSecure()
|
||||
{
|
||||
SecureBuf.Free();
|
||||
SecureIDs.Clear();
|
||||
}
|
||||
*/
|
||||
|
||||
void Clear()
|
||||
{
|
||||
CFolders::Clear();
|
||||
// ClearSecure();
|
||||
|
||||
NamesBuf.Free();
|
||||
NameOffsets.Free();
|
||||
|
||||
Files.Clear();
|
||||
CTime.Clear();
|
||||
ATime.Clear();
|
||||
MTime.Clear();
|
||||
StartPos.Clear();
|
||||
IsAnti.Clear();
|
||||
// IsAux.Clear();
|
||||
}
|
||||
|
||||
bool IsSolid() const
|
||||
{
|
||||
for (CNum i = 0; i < NumFolders; i++)
|
||||
if (NumUnpackStreamsVector[i] > 1)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
|
||||
// bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
|
||||
|
||||
const wchar_t * GetName(unsigned index) const
|
||||
{
|
||||
if (!NameOffsets || !NamesBuf)
|
||||
return NULL;
|
||||
return (const wchar_t *)(const Byte *)NamesBuf + NameOffsets[index];
|
||||
};
|
||||
|
||||
HRESULT GetPath(unsigned index, PROPVARIANT *path) const;
|
||||
};
|
||||
|
||||
struct CInArchiveInfo
|
||||
{
|
||||
CArchiveVersion Version;
|
||||
@@ -24,29 +166,73 @@ struct CInArchiveInfo
|
||||
UInt64 DataStartPosition;
|
||||
UInt64 DataStartPosition2;
|
||||
CRecordVector<UInt64> FileInfoPopIDs;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
StartPosition = 0;
|
||||
StartPositionAfterHeader = 0;
|
||||
DataStartPosition = 0;
|
||||
DataStartPosition2 = 0;
|
||||
FileInfoPopIDs.Clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct CArchiveDatabaseEx: public CArchiveDatabase
|
||||
struct CDbEx: public CDatabase
|
||||
{
|
||||
CInArchiveInfo ArchiveInfo;
|
||||
CRecordVector<UInt64> PackStreamStartPositions;
|
||||
CRecordVector<CNum> FolderStartPackStreamIndex;
|
||||
CInArchiveInfo ArcInfo;
|
||||
CRecordVector<CNum> FolderStartFileIndex;
|
||||
CRecordVector<CNum> FileIndexToFolderIndexMap;
|
||||
|
||||
UInt64 HeadersSize;
|
||||
UInt64 PhySize;
|
||||
|
||||
/*
|
||||
CRecordVector<size_t> SecureOffsets;
|
||||
bool IsTree;
|
||||
bool ThereAreAltStreams;
|
||||
*/
|
||||
|
||||
bool IsArc;
|
||||
bool PhySizeWasConfirmed;
|
||||
|
||||
bool ThereIsHeaderError;
|
||||
bool UnexpectedEnd;
|
||||
// bool UnsupportedVersion;
|
||||
|
||||
bool StartHeaderWasRecovered;
|
||||
bool UnsupportedFeatureWarning;
|
||||
bool UnsupportedFeatureError;
|
||||
|
||||
/*
|
||||
void ClearSecureEx()
|
||||
{
|
||||
ClearSecure();
|
||||
SecureOffsets.Clear();
|
||||
}
|
||||
*/
|
||||
|
||||
void Clear()
|
||||
{
|
||||
CArchiveDatabase::Clear();
|
||||
ArchiveInfo.Clear();
|
||||
PackStreamStartPositions.Clear();
|
||||
FolderStartPackStreamIndex.Clear();
|
||||
IsArc = false;
|
||||
PhySizeWasConfirmed = false;
|
||||
|
||||
ThereIsHeaderError = false;
|
||||
UnexpectedEnd = false;
|
||||
// UnsupportedVersion = false;
|
||||
|
||||
StartHeaderWasRecovered = false;
|
||||
UnsupportedFeatureError = false;
|
||||
UnsupportedFeatureWarning = false;
|
||||
|
||||
/*
|
||||
IsTree = false;
|
||||
ThereAreAltStreams = false;
|
||||
*/
|
||||
|
||||
CDatabase::Clear();
|
||||
|
||||
// SecureOffsets.Clear();
|
||||
ArcInfo.Clear();
|
||||
FolderStartFileIndex.Clear();
|
||||
FileIndexToFolderIndexMap.Clear();
|
||||
|
||||
@@ -54,36 +240,25 @@ struct CArchiveDatabaseEx: public CArchiveDatabase
|
||||
PhySize = 0;
|
||||
}
|
||||
|
||||
void FillFolderStartPackStream();
|
||||
void FillStartPos();
|
||||
void FillFolderStartFileIndex();
|
||||
|
||||
void Fill()
|
||||
void FillLinks();
|
||||
|
||||
UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const
|
||||
{
|
||||
FillFolderStartPackStream();
|
||||
FillStartPos();
|
||||
FillFolderStartFileIndex();
|
||||
return ArcInfo.DataStartPosition +
|
||||
PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder];
|
||||
}
|
||||
|
||||
UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const
|
||||
UInt64 GetFolderFullPackSize(unsigned folderIndex) const
|
||||
{
|
||||
return ArchiveInfo.DataStartPosition +
|
||||
PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder];
|
||||
return
|
||||
PackPositions[FoStartPackStreamIndex[folderIndex + 1]] -
|
||||
PackPositions[FoStartPackStreamIndex[folderIndex]];
|
||||
}
|
||||
|
||||
UInt64 GetFolderFullPackSize(int folderIndex) const
|
||||
UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned streamIndex) const
|
||||
{
|
||||
CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex];
|
||||
const CFolder &folder = Folders[folderIndex];
|
||||
UInt64 size = 0;
|
||||
for (int i = 0; i < folder.PackStreams.Size(); i++)
|
||||
size += PackSizes[packStreamIndex + i];
|
||||
return size;
|
||||
}
|
||||
|
||||
UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const
|
||||
{
|
||||
return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
|
||||
unsigned i = FoStartPackStreamIndex[folderIndex] + streamIndex;
|
||||
return PackPositions[i + 1] - PackPositions[i];
|
||||
}
|
||||
|
||||
UInt64 GetFilePackSize(CNum fileIndex) const
|
||||
@@ -96,12 +271,17 @@ struct CArchiveDatabaseEx: public CArchiveDatabase
|
||||
}
|
||||
};
|
||||
|
||||
class CInByte2
|
||||
const unsigned kNumBufLevelsMax = 4;
|
||||
|
||||
struct CInByte2
|
||||
{
|
||||
const Byte *_buffer;
|
||||
size_t _size;
|
||||
public:
|
||||
size_t _size;
|
||||
size_t _pos;
|
||||
|
||||
size_t GetRem() const { return _size - _pos; }
|
||||
const Byte *GetPtr() const { return _buffer + _pos; }
|
||||
void Init(const Byte *buffer, size_t size)
|
||||
{
|
||||
_buffer = buffer;
|
||||
@@ -110,13 +290,17 @@ public:
|
||||
}
|
||||
Byte ReadByte();
|
||||
void ReadBytes(Byte *data, size_t size);
|
||||
void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }
|
||||
void SkipData(UInt64 size);
|
||||
|
||||
void SkipData();
|
||||
void SkipRem() { _pos = _size; }
|
||||
UInt64 ReadNumber();
|
||||
CNum ReadNum();
|
||||
UInt32 ReadUInt32();
|
||||
UInt64 ReadUInt64();
|
||||
void ReadString(UString &s);
|
||||
|
||||
void ParseFolder(CFolder &folder);
|
||||
};
|
||||
|
||||
class CStreamSwitch;
|
||||
@@ -129,8 +313,11 @@ class CInArchive
|
||||
|
||||
CMyComPtr<IInStream> _stream;
|
||||
|
||||
CObjectVector<CInByte2> _inByteVector;
|
||||
unsigned _numInByteBufs;
|
||||
CInByte2 _inByteVector[kNumBufLevelsMax];
|
||||
|
||||
CInByte2 *_inByteBack;
|
||||
bool ThereIsHeaderError;
|
||||
|
||||
UInt64 _arhiveBeginStreamPosition;
|
||||
UInt64 _fileEndPosition;
|
||||
@@ -139,18 +326,17 @@ class CInArchive
|
||||
|
||||
UInt64 HeadersSize;
|
||||
|
||||
void AddByteStream(const Byte *buffer, size_t size)
|
||||
{
|
||||
_inByteVector.Add(CInByte2());
|
||||
_inByteBack = &_inByteVector.Back();
|
||||
_inByteBack->Init(buffer, size);
|
||||
}
|
||||
void AddByteStream(const Byte *buffer, size_t size);
|
||||
|
||||
void DeleteByteStream()
|
||||
void DeleteByteStream(bool needUpdatePos)
|
||||
{
|
||||
_inByteVector.DeleteBack();
|
||||
if (!_inByteVector.IsEmpty())
|
||||
_inByteBack = &_inByteVector.Back();
|
||||
_numInByteBufs--;
|
||||
if (_numInByteBufs > 0)
|
||||
{
|
||||
_inByteBack = &_inByteVector[_numInByteBufs - 1];
|
||||
if (needUpdatePos)
|
||||
_inByteBack->_pos += _inByteVector[_numInByteBufs]._pos;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -165,79 +351,58 @@ private:
|
||||
UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
|
||||
void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
|
||||
void SkipData() { _inByteBack->SkipData(); }
|
||||
void WaitAttribute(UInt64 attribute);
|
||||
void WaitId(UInt64 id);
|
||||
|
||||
void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
|
||||
void GetNextFolderItem(CFolder &itemInfo);
|
||||
void ReadHashDigests(int numItems,
|
||||
CBoolVector &digestsDefined, CRecordVector<UInt32> &digests);
|
||||
void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);
|
||||
|
||||
void ReadPackInfo(
|
||||
UInt64 &dataOffset,
|
||||
CRecordVector<UInt64> &packSizes,
|
||||
CBoolVector &packCRCsDefined,
|
||||
CRecordVector<UInt32> &packCRCs);
|
||||
void ReadPackInfo(CFolders &f);
|
||||
|
||||
void ReadUnpackInfo(
|
||||
const CObjectVector<CByteBuffer> *dataVector,
|
||||
CObjectVector<CFolder> &folders);
|
||||
CFolders &folders);
|
||||
|
||||
void ReadSubStreamsInfo(
|
||||
const CObjectVector<CFolder> &folders,
|
||||
CRecordVector<CNum> &numUnpackStreamsInFolders,
|
||||
CFolders &folders,
|
||||
CRecordVector<UInt64> &unpackSizes,
|
||||
CBoolVector &digestsDefined,
|
||||
CRecordVector<UInt32> &digests);
|
||||
CUInt32DefVector &digests);
|
||||
|
||||
void ReadStreamsInfo(
|
||||
const CObjectVector<CByteBuffer> *dataVector,
|
||||
UInt64 &dataOffset,
|
||||
CRecordVector<UInt64> &packSizes,
|
||||
CBoolVector &packCRCsDefined,
|
||||
CRecordVector<UInt32> &packCRCs,
|
||||
CObjectVector<CFolder> &folders,
|
||||
CRecordVector<CNum> &numUnpackStreamsInFolders,
|
||||
CFolders &folders,
|
||||
CRecordVector<UInt64> &unpackSizes,
|
||||
CBoolVector &digestsDefined,
|
||||
CRecordVector<UInt32> &digests);
|
||||
CUInt32DefVector &digests);
|
||||
|
||||
|
||||
void ReadBoolVector(int numItems, CBoolVector &v);
|
||||
void ReadBoolVector2(int numItems, CBoolVector &v);
|
||||
void ReadBoolVector(unsigned numItems, CBoolVector &v);
|
||||
void ReadBoolVector2(unsigned numItems, CBoolVector &v);
|
||||
void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,
|
||||
CUInt64DefVector &v, int numFiles);
|
||||
CUInt64DefVector &v, unsigned numItems);
|
||||
HRESULT ReadAndDecodePackedStreams(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
UInt64 baseOffset, UInt64 &dataOffset,
|
||||
CObjectVector<CByteBuffer> &dataVector
|
||||
#ifndef _NO_CRYPTO
|
||||
, ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
|
||||
#endif
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
);
|
||||
HRESULT ReadHeader(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CArchiveDatabaseEx &db
|
||||
#ifndef _NO_CRYPTO
|
||||
,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
|
||||
#endif
|
||||
CDbEx &db
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
);
|
||||
HRESULT ReadDatabase2(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CArchiveDatabaseEx &db
|
||||
#ifndef _NO_CRYPTO
|
||||
,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
|
||||
#endif
|
||||
CDbEx &db
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
);
|
||||
public:
|
||||
CInArchive(): _numInByteBufs(0) { }
|
||||
HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
|
||||
void Close();
|
||||
|
||||
HRESULT ReadDatabase(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CArchiveDatabaseEx &db
|
||||
#ifndef _NO_CRYPTO
|
||||
,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
|
||||
#endif
|
||||
CDbEx &db
|
||||
_7Z_DECODER_CRYPRO_VARS_DECL
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
208
CPP/7zip/Archive/7z/7zItem.h
Executable file → Normal file
208
CPP/7zip/Archive/7z/7zItem.h
Executable file → Normal file
@@ -3,7 +3,7 @@
|
||||
#ifndef __7Z_ITEM_H
|
||||
#define __7Z_ITEM_H
|
||||
|
||||
#include "../../../Common/Buffer.h"
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "../../Common/MethodId.h"
|
||||
@@ -25,6 +25,7 @@ struct CCoderInfo
|
||||
CByteBuffer Props;
|
||||
CNum NumInStreams;
|
||||
CNum NumOutStreams;
|
||||
|
||||
bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
|
||||
};
|
||||
|
||||
@@ -36,55 +37,48 @@ struct CBindPair
|
||||
|
||||
struct CFolder
|
||||
{
|
||||
CObjectVector<CCoderInfo> Coders;
|
||||
CRecordVector<CBindPair> BindPairs;
|
||||
CRecordVector<CNum> PackStreams;
|
||||
CRecordVector<UInt64> UnpackSizes;
|
||||
UInt32 UnpackCRC;
|
||||
bool UnpackCRCDefined;
|
||||
|
||||
CFolder(): UnpackCRCDefined(false) {}
|
||||
|
||||
UInt64 GetUnpackSize() const // test it
|
||||
{
|
||||
if (UnpackSizes.IsEmpty())
|
||||
return 0;
|
||||
for (int i = UnpackSizes.Size() - 1; i >= 0; i--)
|
||||
if (FindBindPairForOutStream(i) < 0)
|
||||
return UnpackSizes[i];
|
||||
throw 1;
|
||||
}
|
||||
CObjArray2<CCoderInfo> Coders;
|
||||
CObjArray2<CBindPair> BindPairs;
|
||||
CObjArray2<CNum> PackStreams;
|
||||
|
||||
CNum GetNumOutStreams() const
|
||||
{
|
||||
CNum result = 0;
|
||||
for (int i = 0; i < Coders.Size(); i++)
|
||||
FOR_VECTOR(i, Coders)
|
||||
result += Coders[i].NumOutStreams;
|
||||
return result;
|
||||
}
|
||||
|
||||
int FindBindPairForInStream(CNum inStreamIndex) const
|
||||
{
|
||||
for(int i = 0; i < BindPairs.Size(); i++)
|
||||
FOR_VECTOR(i, BindPairs)
|
||||
if (BindPairs[i].InIndex == inStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
int FindBindPairForOutStream(CNum outStreamIndex) const
|
||||
{
|
||||
for(int i = 0; i < BindPairs.Size(); i++)
|
||||
FOR_VECTOR(i, BindPairs)
|
||||
if (BindPairs[i].OutIndex == outStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
int FindPackStreamArrayIndex(CNum inStreamIndex) const
|
||||
{
|
||||
for(int i = 0; i < PackStreams.Size(); i++)
|
||||
FOR_VECTOR(i, PackStreams)
|
||||
if (PackStreams[i] == inStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int GetIndexOfMainOutStream() const
|
||||
{
|
||||
for (int i = (int)GetNumOutStreams() - 1; i >= 0; i--)
|
||||
if (FindBindPairForOutStream(i) < 0)
|
||||
return i;
|
||||
throw 1;
|
||||
}
|
||||
|
||||
bool IsEncrypted() const
|
||||
{
|
||||
for (int i = Coders.Size() - 1; i >= 0; i--)
|
||||
@@ -93,50 +87,66 @@ struct CFolder
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckStructure() const;
|
||||
bool CheckStructure(unsigned numUnpackSizes) const;
|
||||
};
|
||||
|
||||
struct CUInt32DefVector
|
||||
{
|
||||
CBoolVector Defs;
|
||||
CRecordVector<UInt32> Vals;
|
||||
|
||||
void ClearAndSetSize(unsigned newSize)
|
||||
{
|
||||
Defs.ClearAndSetSize(newSize);
|
||||
Vals.ClearAndSetSize(newSize);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Defs.Clear();
|
||||
Vals.Clear();
|
||||
}
|
||||
|
||||
void ReserveDown()
|
||||
{
|
||||
Defs.ReserveDown();
|
||||
Vals.ReserveDown();
|
||||
}
|
||||
|
||||
bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; }
|
||||
};
|
||||
|
||||
struct CUInt64DefVector
|
||||
{
|
||||
CRecordVector<UInt64> Values;
|
||||
CRecordVector<bool> Defined;
|
||||
CBoolVector Defs;
|
||||
CRecordVector<UInt64> Vals;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Values.Clear();
|
||||
Defined.Clear();
|
||||
Defs.Clear();
|
||||
Vals.Clear();
|
||||
}
|
||||
|
||||
void ReserveDown()
|
||||
{
|
||||
Values.ReserveDown();
|
||||
Values.ReserveDown();
|
||||
Defs.ReserveDown();
|
||||
Vals.ReserveDown();
|
||||
}
|
||||
|
||||
bool GetItem(int index, UInt64 &value) const
|
||||
bool GetItem(unsigned index, UInt64 &value) const
|
||||
{
|
||||
if (index < Defined.Size() && Defined[index])
|
||||
if (index < Defs.Size() && Defs[index])
|
||||
{
|
||||
value = Values[index];
|
||||
value = Vals[index];
|
||||
return true;
|
||||
}
|
||||
value = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetItem(int index, bool defined, UInt64 value)
|
||||
{
|
||||
while (index >= Defined.Size())
|
||||
Defined.Add(false);
|
||||
Defined[index] = defined;
|
||||
if (!defined)
|
||||
return;
|
||||
while (index >= Values.Size())
|
||||
Values.Add(0);
|
||||
Values[index] = value;
|
||||
}
|
||||
void SetItem(unsigned index, bool defined, UInt64 value);
|
||||
|
||||
bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; }
|
||||
bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
|
||||
};
|
||||
|
||||
struct CFileItem
|
||||
@@ -144,8 +154,10 @@ struct CFileItem
|
||||
UInt64 Size;
|
||||
UInt32 Attrib;
|
||||
UInt32 Crc;
|
||||
UString Name;
|
||||
|
||||
/*
|
||||
int Parent;
|
||||
bool IsAltStream;
|
||||
*/
|
||||
bool HasStream; // Test it !!! it means that there is
|
||||
// stream in some folder. It can be empty stream
|
||||
bool IsDir;
|
||||
@@ -153,6 +165,10 @@ struct CFileItem
|
||||
bool AttribDefined;
|
||||
|
||||
CFileItem():
|
||||
/*
|
||||
Parent(-1),
|
||||
IsAltStream(false),
|
||||
*/
|
||||
HasStream(true),
|
||||
IsDir(false),
|
||||
CrcDefined(false),
|
||||
@@ -165,104 +181,6 @@ struct CFileItem
|
||||
}
|
||||
};
|
||||
|
||||
struct CFileItem2
|
||||
{
|
||||
UInt64 CTime;
|
||||
UInt64 ATime;
|
||||
UInt64 MTime;
|
||||
UInt64 StartPos;
|
||||
bool CTimeDefined;
|
||||
bool ATimeDefined;
|
||||
bool MTimeDefined;
|
||||
bool StartPosDefined;
|
||||
bool IsAnti;
|
||||
};
|
||||
|
||||
struct CArchiveDatabase
|
||||
{
|
||||
CRecordVector<UInt64> PackSizes;
|
||||
CRecordVector<bool> PackCRCsDefined;
|
||||
CRecordVector<UInt32> PackCRCs;
|
||||
CObjectVector<CFolder> Folders;
|
||||
CRecordVector<CNum> NumUnpackStreamsVector;
|
||||
CObjectVector<CFileItem> Files;
|
||||
|
||||
CUInt64DefVector CTime;
|
||||
CUInt64DefVector ATime;
|
||||
CUInt64DefVector MTime;
|
||||
CUInt64DefVector StartPos;
|
||||
CRecordVector<bool> IsAnti;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
PackSizes.Clear();
|
||||
PackCRCsDefined.Clear();
|
||||
PackCRCs.Clear();
|
||||
Folders.Clear();
|
||||
NumUnpackStreamsVector.Clear();
|
||||
Files.Clear();
|
||||
CTime.Clear();
|
||||
ATime.Clear();
|
||||
MTime.Clear();
|
||||
StartPos.Clear();
|
||||
IsAnti.Clear();
|
||||
}
|
||||
|
||||
void ReserveDown()
|
||||
{
|
||||
PackSizes.ReserveDown();
|
||||
PackCRCsDefined.ReserveDown();
|
||||
PackCRCs.ReserveDown();
|
||||
Folders.ReserveDown();
|
||||
NumUnpackStreamsVector.ReserveDown();
|
||||
Files.ReserveDown();
|
||||
CTime.ReserveDown();
|
||||
ATime.ReserveDown();
|
||||
MTime.ReserveDown();
|
||||
StartPos.ReserveDown();
|
||||
IsAnti.ReserveDown();
|
||||
}
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return (PackSizes.IsEmpty() &&
|
||||
PackCRCsDefined.IsEmpty() &&
|
||||
PackCRCs.IsEmpty() &&
|
||||
Folders.IsEmpty() &&
|
||||
NumUnpackStreamsVector.IsEmpty() &&
|
||||
Files.IsEmpty());
|
||||
}
|
||||
|
||||
bool CheckNumFiles() const
|
||||
{
|
||||
int size = Files.Size();
|
||||
return (
|
||||
CTime.CheckSize(size) &&
|
||||
ATime.CheckSize(size) &&
|
||||
MTime.CheckSize(size) &&
|
||||
StartPos.CheckSize(size) &&
|
||||
(size == IsAnti.Size() || IsAnti.Size() == 0));
|
||||
}
|
||||
|
||||
bool IsSolid() const
|
||||
{
|
||||
for (int i = 0; i < NumUnpackStreamsVector.Size(); i++)
|
||||
if (NumUnpackStreamsVector[i] > 1)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool IsItemAnti(int index) const { return (index < IsAnti.Size() && IsAnti[index]); }
|
||||
void SetItemAnti(int index, bool isAnti)
|
||||
{
|
||||
while (index >= IsAnti.Size())
|
||||
IsAnti.Add(false);
|
||||
IsAnti[index] = isAnti;
|
||||
}
|
||||
|
||||
void GetFile(int index, CFileItem &file, CFileItem2 &file2) const;
|
||||
void AddFile(const CFileItem &file, const CFileItem2 &file2);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
469
CPP/7zip/Archive/7z/7zOut.cpp
Executable file → Normal file
469
CPP/7zip/Archive/7z/7zOut.cpp
Executable file → Normal file
@@ -10,35 +10,15 @@
|
||||
|
||||
#include "7zOut.h"
|
||||
|
||||
static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size)
|
||||
{
|
||||
while (size > 0)
|
||||
{
|
||||
UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF);
|
||||
UInt32 processedSize;
|
||||
RINOK(stream->Write(data, curSize, &processedSize));
|
||||
if (processedSize == 0)
|
||||
return E_FAIL;
|
||||
data = (const void *)((const Byte *)data + processedSize);
|
||||
size -= processedSize;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
HRESULT COutArchive::WriteDirect(const void *data, UInt32 size)
|
||||
{
|
||||
return ::WriteBytes(SeqStream, data, size);
|
||||
}
|
||||
|
||||
HRESULT COutArchive::WriteSignature()
|
||||
{
|
||||
Byte buf[8];
|
||||
memcpy(buf, kSignature, kSignatureSize);
|
||||
buf[kSignatureSize] = kMajorVersion;
|
||||
buf[kSignatureSize + 1] = 3;
|
||||
buf[kSignatureSize + 1] = 4;
|
||||
return WriteDirect(buf, 8);
|
||||
}
|
||||
|
||||
@@ -145,7 +125,9 @@ HRESULT COutArchive::SkipPrefixArchiveHeader()
|
||||
if (_endMarker)
|
||||
return S_OK;
|
||||
#endif
|
||||
return Stream->Seek(24, STREAM_SEEK_CUR, NULL);
|
||||
Byte buf[24];
|
||||
memset(buf, 0, 24);
|
||||
return WriteDirect(buf, 24);
|
||||
}
|
||||
|
||||
UInt64 COutArchive::GetPos() const
|
||||
@@ -271,19 +253,19 @@ UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)
|
||||
void COutArchive::WriteFolder(const CFolder &folder)
|
||||
{
|
||||
WriteNumber(folder.Coders.Size());
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 0; i < folder.Coders.Size(); i++)
|
||||
{
|
||||
const CCoderInfo &coder = folder.Coders[i];
|
||||
{
|
||||
size_t propsSize = coder.Props.GetCapacity();
|
||||
size_t propsSize = coder.Props.Size();
|
||||
|
||||
UInt64 id = coder.MethodID;
|
||||
int idSize;
|
||||
for (idSize = 1; idSize < sizeof(id); idSize++)
|
||||
if ((id >> (8 * idSize)) == 0)
|
||||
break;
|
||||
BYTE longID[15];
|
||||
Byte longID[15];
|
||||
for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)
|
||||
longID[t] = (Byte)(id & 0xFF);
|
||||
Byte b;
|
||||
@@ -321,7 +303,7 @@ void COutArchive::WriteBoolVector(const CBoolVector &boolVector)
|
||||
{
|
||||
Byte b = 0;
|
||||
Byte mask = 0x80;
|
||||
for (int i = 0; i < boolVector.Size(); i++)
|
||||
FOR_VECTOR (i, boolVector)
|
||||
{
|
||||
if (boolVector[i])
|
||||
b |= mask;
|
||||
@@ -337,37 +319,42 @@ void COutArchive::WriteBoolVector(const CBoolVector &boolVector)
|
||||
WriteByte(b);
|
||||
}
|
||||
|
||||
static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }
|
||||
|
||||
void COutArchive::WriteHashDigests(
|
||||
const CRecordVector<bool> &digestsDefined,
|
||||
const CRecordVector<UInt32> &digests)
|
||||
void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)
|
||||
{
|
||||
int numDefined = 0;
|
||||
int i;
|
||||
for (i = 0; i < digestsDefined.Size(); i++)
|
||||
if (digestsDefined[i])
|
||||
WriteByte(id);
|
||||
WriteNumber(Bv_GetSizeInBytes(boolVector));
|
||||
WriteBoolVector(boolVector);
|
||||
}
|
||||
|
||||
void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
|
||||
{
|
||||
unsigned numDefined = 0;
|
||||
unsigned i;
|
||||
for (i = 0; i < digests.Defs.Size(); i++)
|
||||
if (digests.Defs[i])
|
||||
numDefined++;
|
||||
if (numDefined == 0)
|
||||
return;
|
||||
|
||||
WriteByte(NID::kCRC);
|
||||
if (numDefined == digestsDefined.Size())
|
||||
if (numDefined == digests.Defs.Size())
|
||||
WriteByte(1);
|
||||
else
|
||||
{
|
||||
WriteByte(0);
|
||||
WriteBoolVector(digestsDefined);
|
||||
WriteBoolVector(digests.Defs);
|
||||
}
|
||||
for (i = 0; i < digests.Size(); i++)
|
||||
if (digestsDefined[i])
|
||||
WriteUInt32(digests[i]);
|
||||
for (i = 0; i < digests.Defs.Size(); i++)
|
||||
if (digests.Defs[i])
|
||||
WriteUInt32(digests.Vals[i]);
|
||||
}
|
||||
|
||||
void COutArchive::WritePackInfo(
|
||||
UInt64 dataOffset,
|
||||
const CRecordVector<UInt64> &packSizes,
|
||||
const CRecordVector<bool> &packCRCsDefined,
|
||||
const CRecordVector<UInt32> &packCRCs)
|
||||
const CUInt32DefVector &packCRCs)
|
||||
{
|
||||
if (packSizes.IsEmpty())
|
||||
return;
|
||||
@@ -375,15 +362,15 @@ void COutArchive::WritePackInfo(
|
||||
WriteNumber(dataOffset);
|
||||
WriteNumber(packSizes.Size());
|
||||
WriteByte(NID::kSize);
|
||||
for (int i = 0; i < packSizes.Size(); i++)
|
||||
FOR_VECTOR (i, packSizes)
|
||||
WriteNumber(packSizes[i]);
|
||||
|
||||
WriteHashDigests(packCRCsDefined, packCRCs);
|
||||
WriteHashDigests(packCRCs);
|
||||
|
||||
WriteByte(NID::kEnd);
|
||||
}
|
||||
|
||||
void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders)
|
||||
void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders, const COutFolders &outFolders)
|
||||
{
|
||||
if (folders.IsEmpty())
|
||||
return;
|
||||
@@ -394,44 +381,29 @@ void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders)
|
||||
WriteNumber(folders.Size());
|
||||
{
|
||||
WriteByte(0);
|
||||
for (int i = 0; i < folders.Size(); i++)
|
||||
FOR_VECTOR (i, folders)
|
||||
WriteFolder(folders[i]);
|
||||
}
|
||||
|
||||
WriteByte(NID::kCodersUnpackSize);
|
||||
int i;
|
||||
for (i = 0; i < folders.Size(); i++)
|
||||
{
|
||||
const CFolder &folder = folders[i];
|
||||
for (int j = 0; j < folder.UnpackSizes.Size(); j++)
|
||||
WriteNumber(folder.UnpackSizes[j]);
|
||||
}
|
||||
|
||||
CRecordVector<bool> unpackCRCsDefined;
|
||||
CRecordVector<UInt32> unpackCRCs;
|
||||
for (i = 0; i < folders.Size(); i++)
|
||||
{
|
||||
const CFolder &folder = folders[i];
|
||||
unpackCRCsDefined.Add(folder.UnpackCRCDefined);
|
||||
unpackCRCs.Add(folder.UnpackCRC);
|
||||
}
|
||||
WriteHashDigests(unpackCRCsDefined, unpackCRCs);
|
||||
|
||||
FOR_VECTOR (i, outFolders.CoderUnpackSizes)
|
||||
WriteNumber(outFolders.CoderUnpackSizes[i]);
|
||||
|
||||
WriteHashDigests(outFolders.FolderUnpackCRCs);
|
||||
|
||||
WriteByte(NID::kEnd);
|
||||
}
|
||||
|
||||
void COutArchive::WriteSubStreamsInfo(
|
||||
const CObjectVector<CFolder> &folders,
|
||||
const CRecordVector<CNum> &numUnpackStreamsInFolders,
|
||||
void COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders,
|
||||
const COutFolders &outFolders,
|
||||
const CRecordVector<UInt64> &unpackSizes,
|
||||
const CRecordVector<bool> &digestsDefined,
|
||||
const CRecordVector<UInt32> &digests)
|
||||
const CUInt32DefVector &digests)
|
||||
{
|
||||
const CRecordVector<CNum> &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector;
|
||||
WriteByte(NID::kSubStreamsInfo);
|
||||
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
|
||||
{
|
||||
if (numUnpackStreamsInFolders[i] != 1)
|
||||
{
|
||||
WriteByte(NID::kNumUnpackStream);
|
||||
@@ -439,54 +411,50 @@ void COutArchive::WriteSubStreamsInfo(
|
||||
WriteNumber(numUnpackStreamsInFolders[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool needFlag = true;
|
||||
CNum index = 0;
|
||||
for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
|
||||
for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++)
|
||||
if (numUnpackStreamsInFolders[i] > 1)
|
||||
{
|
||||
if (j + 1 != numUnpackStreamsInFolders[i])
|
||||
WriteByte(NID::kSize);
|
||||
CNum index = 0;
|
||||
for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
|
||||
{
|
||||
if (needFlag)
|
||||
WriteByte(NID::kSize);
|
||||
needFlag = false;
|
||||
WriteNumber(unpackSizes[index]);
|
||||
CNum num = numUnpackStreamsInFolders[i];
|
||||
for (CNum j = 0; j < num; j++)
|
||||
{
|
||||
if (j + 1 != num)
|
||||
WriteNumber(unpackSizes[index]);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
break;
|
||||
}
|
||||
|
||||
CRecordVector<bool> digestsDefined2;
|
||||
CRecordVector<UInt32> digests2;
|
||||
CUInt32DefVector digests2;
|
||||
|
||||
int digestIndex = 0;
|
||||
unsigned digestIndex = 0;
|
||||
for (i = 0; i < folders.Size(); i++)
|
||||
{
|
||||
int numSubStreams = (int)numUnpackStreamsInFolders[i];
|
||||
if (numSubStreams == 1 && folders[i].UnpackCRCDefined)
|
||||
unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i];
|
||||
if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i))
|
||||
digestIndex++;
|
||||
else
|
||||
for (int j = 0; j < numSubStreams; j++, digestIndex++)
|
||||
for (unsigned j = 0; j < numSubStreams; j++, digestIndex++)
|
||||
{
|
||||
digestsDefined2.Add(digestsDefined[digestIndex]);
|
||||
digests2.Add(digests[digestIndex]);
|
||||
digests2.Defs.Add(digests.Defs[digestIndex]);
|
||||
digests2.Vals.Add(digests.Vals[digestIndex]);
|
||||
}
|
||||
}
|
||||
WriteHashDigests(digestsDefined2, digests2);
|
||||
WriteHashDigests(digests2);
|
||||
WriteByte(NID::kEnd);
|
||||
}
|
||||
|
||||
void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.
|
||||
// 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.
|
||||
|
||||
void COutArchive::SkipAlign(unsigned pos, unsigned alignSize)
|
||||
{
|
||||
if (!_useAlign)
|
||||
return;
|
||||
pos += (unsigned)GetPos();
|
||||
pos &= (alignSize - 1);
|
||||
if (pos == 0)
|
||||
@@ -500,11 +468,8 @@ void COutArchive::SkipAlign(unsigned pos, unsigned alignSize)
|
||||
for (unsigned i = 0; i < skip; i++)
|
||||
WriteByte(0);
|
||||
}
|
||||
*/
|
||||
|
||||
static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }
|
||||
|
||||
void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize)
|
||||
void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize)
|
||||
{
|
||||
const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);
|
||||
const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2;
|
||||
@@ -524,48 +489,53 @@ void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, B
|
||||
|
||||
void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
|
||||
{
|
||||
int numDefined = 0;
|
||||
unsigned numDefined = 0;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < v.Defined.Size(); i++)
|
||||
if (v.Defined[i])
|
||||
unsigned i;
|
||||
for (i = 0; i < v.Defs.Size(); i++)
|
||||
if (v.Defs[i])
|
||||
numDefined++;
|
||||
|
||||
if (numDefined == 0)
|
||||
return;
|
||||
|
||||
WriteAlignedBoolHeader(v.Defined, numDefined, type, 8);
|
||||
WriteAlignedBoolHeader(v.Defs, numDefined, type, 8);
|
||||
|
||||
for (i = 0; i < v.Defined.Size(); i++)
|
||||
if (v.Defined[i])
|
||||
WriteUInt64(v.Values[i]);
|
||||
for (i = 0; i < v.Defs.Size(); i++)
|
||||
if (v.Defs[i])
|
||||
WriteUInt64(v.Vals[i]);
|
||||
}
|
||||
|
||||
HRESULT COutArchive::EncodeStream(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CEncoder &encoder, const CByteBuffer &data,
|
||||
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)
|
||||
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders)
|
||||
{
|
||||
CBufInStream *streamSpec = new CBufInStream;
|
||||
CMyComPtr<ISequentialInStream> stream = streamSpec;
|
||||
streamSpec->Init(data, data.GetCapacity());
|
||||
CFolder folderItem;
|
||||
folderItem.UnpackCRCDefined = true;
|
||||
folderItem.UnpackCRC = CrcCalc(data, data.GetCapacity());
|
||||
UInt64 dataSize64 = data.GetCapacity();
|
||||
streamSpec->Init(data, data.Size());
|
||||
outFolders.FolderUnpackCRCs.Defs.Add(true);
|
||||
outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));
|
||||
// outFolders.NumUnpackStreamsVector.Add(1);
|
||||
UInt64 dataSize64 = data.Size();
|
||||
UInt64 unpackSize;
|
||||
RINOK(encoder.Encode(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL))
|
||||
folders.Add(folderItem);
|
||||
stream, NULL, &dataSize64, folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL))
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void COutArchive::WriteHeader(
|
||||
const CArchiveDatabase &db,
|
||||
const CHeaderOptions &headerOptions,
|
||||
const CArchiveDatabaseOut &db,
|
||||
// const CHeaderOptions &headerOptions,
|
||||
UInt64 &headerOffset)
|
||||
{
|
||||
int i;
|
||||
/*
|
||||
bool thereIsSecure = (db.SecureBuf.Size() != 0);
|
||||
*/
|
||||
_useAlign = true;
|
||||
|
||||
unsigned i;
|
||||
|
||||
UInt64 packedSize = 0;
|
||||
for (i = 0; i < db.PackSizes.Size(); i++)
|
||||
@@ -580,31 +550,22 @@ void COutArchive::WriteHeader(
|
||||
if (db.Folders.Size() > 0)
|
||||
{
|
||||
WriteByte(NID::kMainStreamsInfo);
|
||||
WritePackInfo(0, db.PackSizes,
|
||||
db.PackCRCsDefined,
|
||||
db.PackCRCs);
|
||||
|
||||
WriteUnpackInfo(db.Folders);
|
||||
WritePackInfo(0, db.PackSizes, db.PackCRCs);
|
||||
WriteUnpackInfo(db.Folders, (const COutFolders &)db);
|
||||
|
||||
CRecordVector<UInt64> unpackSizes;
|
||||
CRecordVector<bool> digestsDefined;
|
||||
CRecordVector<UInt32> digests;
|
||||
CUInt32DefVector digests;
|
||||
for (i = 0; i < db.Files.Size(); i++)
|
||||
{
|
||||
const CFileItem &file = db.Files[i];
|
||||
if (!file.HasStream)
|
||||
continue;
|
||||
unpackSizes.Add(file.Size);
|
||||
digestsDefined.Add(file.CrcDefined);
|
||||
digests.Add(file.Crc);
|
||||
digests.Defs.Add(file.CrcDefined);
|
||||
digests.Vals.Add(file.Crc);
|
||||
}
|
||||
|
||||
WriteSubStreamsInfo(
|
||||
db.Folders,
|
||||
db.NumUnpackStreamsVector,
|
||||
unpackSizes,
|
||||
digestsDefined,
|
||||
digests);
|
||||
WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests);
|
||||
WriteByte(NID::kEnd);
|
||||
}
|
||||
|
||||
@@ -618,85 +579,75 @@ void COutArchive::WriteHeader(
|
||||
WriteNumber(db.Files.Size());
|
||||
|
||||
{
|
||||
/* ---------- Empty Streams ---------- */
|
||||
CBoolVector emptyStreamVector;
|
||||
emptyStreamVector.Reserve(db.Files.Size());
|
||||
int numEmptyStreams = 0;
|
||||
for (i = 0; i < db.Files.Size(); i++)
|
||||
if (db.Files[i].HasStream)
|
||||
emptyStreamVector.Add(false);
|
||||
else
|
||||
{
|
||||
emptyStreamVector.Add(true);
|
||||
numEmptyStreams++;
|
||||
}
|
||||
if (numEmptyStreams > 0)
|
||||
{
|
||||
WriteByte(NID::kEmptyStream);
|
||||
WriteNumber(Bv_GetSizeInBytes(emptyStreamVector));
|
||||
WriteBoolVector(emptyStreamVector);
|
||||
|
||||
CBoolVector emptyFileVector, antiVector;
|
||||
emptyFileVector.Reserve(numEmptyStreams);
|
||||
antiVector.Reserve(numEmptyStreams);
|
||||
CNum numEmptyFiles = 0, numAntiItems = 0;
|
||||
/* ---------- Empty Streams ---------- */
|
||||
CBoolVector emptyStreamVector;
|
||||
emptyStreamVector.ClearAndSetSize(db.Files.Size());
|
||||
unsigned numEmptyStreams = 0;
|
||||
for (i = 0; i < db.Files.Size(); i++)
|
||||
{
|
||||
const CFileItem &file = db.Files[i];
|
||||
if (!file.HasStream)
|
||||
if (db.Files[i].HasStream)
|
||||
emptyStreamVector[i] = false;
|
||||
else
|
||||
{
|
||||
emptyFileVector.Add(!file.IsDir);
|
||||
if (!file.IsDir)
|
||||
numEmptyFiles++;
|
||||
bool isAnti = db.IsItemAnti(i);
|
||||
antiVector.Add(isAnti);
|
||||
if (isAnti)
|
||||
numAntiItems++;
|
||||
emptyStreamVector[i] = true;
|
||||
numEmptyStreams++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numEmptyFiles > 0)
|
||||
if (numEmptyStreams != 0)
|
||||
{
|
||||
WriteByte(NID::kEmptyFile);
|
||||
WriteNumber(Bv_GetSizeInBytes(emptyFileVector));
|
||||
WriteBoolVector(emptyFileVector);
|
||||
WritePropBoolVector(NID::kEmptyStream, emptyStreamVector);
|
||||
|
||||
CBoolVector emptyFileVector, antiVector;
|
||||
emptyFileVector.ClearAndSetSize(numEmptyStreams);
|
||||
antiVector.ClearAndSetSize(numEmptyStreams);
|
||||
bool thereAreEmptyFiles = false, thereAreAntiItems = false;
|
||||
unsigned cur = 0;
|
||||
for (i = 0; i < db.Files.Size(); i++)
|
||||
{
|
||||
const CFileItem &file = db.Files[i];
|
||||
if (file.HasStream)
|
||||
continue;
|
||||
emptyFileVector[cur] = !file.IsDir;
|
||||
if (!file.IsDir)
|
||||
thereAreEmptyFiles = true;
|
||||
bool isAnti = db.IsItemAnti(i);
|
||||
antiVector[cur] = isAnti;
|
||||
if (isAnti)
|
||||
thereAreAntiItems = true;
|
||||
cur++;
|
||||
}
|
||||
|
||||
if (thereAreEmptyFiles)
|
||||
WritePropBoolVector(NID::kEmptyFile, emptyFileVector);
|
||||
if (thereAreAntiItems)
|
||||
WritePropBoolVector(NID::kAnti, antiVector);
|
||||
}
|
||||
|
||||
if (numAntiItems > 0)
|
||||
{
|
||||
WriteByte(NID::kAnti);
|
||||
WriteNumber(Bv_GetSizeInBytes(antiVector));
|
||||
WriteBoolVector(antiVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
/* ---------- Names ---------- */
|
||||
|
||||
int numDefined = 0;
|
||||
unsigned numDefined = 0;
|
||||
size_t namesDataSize = 0;
|
||||
for (int i = 0; i < db.Files.Size(); i++)
|
||||
FOR_VECTOR (i, db.Files)
|
||||
{
|
||||
const UString &name = db.Files[i].Name;
|
||||
const UString &name = db.Names[i];
|
||||
if (!name.IsEmpty())
|
||||
numDefined++;
|
||||
namesDataSize += (name.Length() + 1) * 2;
|
||||
namesDataSize += (name.Len() + 1) * 2;
|
||||
}
|
||||
|
||||
if (numDefined > 0)
|
||||
{
|
||||
namesDataSize++;
|
||||
SkipAlign(2 + GetBigNumberSize(namesDataSize), 2);
|
||||
SkipAlign(2 + GetBigNumberSize(namesDataSize), 16);
|
||||
|
||||
WriteByte(NID::kName);
|
||||
WriteNumber(namesDataSize);
|
||||
WriteByte(0);
|
||||
for (int i = 0; i < db.Files.Size(); i++)
|
||||
FOR_VECTOR (i, db.Files)
|
||||
{
|
||||
const UString &name = db.Files[i].Name;
|
||||
for (int t = 0; t <= name.Length(); t++)
|
||||
const UString &name = db.Names[i];
|
||||
for (unsigned t = 0; t <= name.Len(); t++)
|
||||
{
|
||||
wchar_t c = name[t];
|
||||
WriteByte((Byte)c);
|
||||
@@ -706,26 +657,26 @@ void COutArchive::WriteHeader(
|
||||
}
|
||||
}
|
||||
|
||||
if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime);
|
||||
if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime);
|
||||
if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime);
|
||||
/* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime);
|
||||
/* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime);
|
||||
/* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime);
|
||||
WriteUInt64DefVector(db.StartPos, NID::kStartPos);
|
||||
|
||||
{
|
||||
/* ---------- Write Attrib ---------- */
|
||||
CBoolVector boolVector;
|
||||
boolVector.Reserve(db.Files.Size());
|
||||
int numDefined = 0;
|
||||
boolVector.ClearAndSetSize(db.Files.Size());
|
||||
unsigned numDefined = 0;
|
||||
for (i = 0; i < db.Files.Size(); i++)
|
||||
{
|
||||
bool defined = db.Files[i].AttribDefined;
|
||||
boolVector.Add(defined);
|
||||
boolVector[i] = defined;
|
||||
if (defined)
|
||||
numDefined++;
|
||||
}
|
||||
if (numDefined > 0)
|
||||
if (numDefined != 0)
|
||||
{
|
||||
WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4);
|
||||
WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4);
|
||||
for (i = 0; i < db.Files.Size(); i++)
|
||||
{
|
||||
const CFileItem &file = db.Files[i];
|
||||
@@ -735,13 +686,95 @@ void COutArchive::WriteHeader(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
// ---------- Write IsAux ----------
|
||||
unsigned numAux = 0;
|
||||
const CBoolVector &isAux = db.IsAux;
|
||||
for (i = 0; i < isAux.Size(); i++)
|
||||
if (isAux[i])
|
||||
numAux++;
|
||||
if (numAux > 0)
|
||||
{
|
||||
const unsigned bvSize = Bv_GetSizeInBytes(isAux);
|
||||
WriteByte(NID::kIsAux);
|
||||
WriteNumber(bvSize);
|
||||
WriteBoolVector(isAux);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// ---------- Write Parent ----------
|
||||
CBoolVector boolVector;
|
||||
boolVector.Reserve(db.Files.Size());
|
||||
unsigned numIsDir = 0;
|
||||
unsigned numParentLinks = 0;
|
||||
for (i = 0; i < db.Files.Size(); i++)
|
||||
{
|
||||
const CFileItem &file = db.Files[i];
|
||||
bool defined = !file.IsAltStream;
|
||||
boolVector.Add(defined);
|
||||
if (defined)
|
||||
numIsDir++;
|
||||
if (file.Parent >= 0)
|
||||
numParentLinks++;
|
||||
}
|
||||
if (numParentLinks > 0)
|
||||
{
|
||||
// WriteAlignedBoolHeader(boolVector, numDefined, NID::kParent, 4);
|
||||
const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector);
|
||||
const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1;
|
||||
SkipAlign(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 4);
|
||||
|
||||
WriteByte(NID::kParent);
|
||||
WriteNumber(dataSize);
|
||||
if (numIsDir == boolVector.Size())
|
||||
WriteByte(1);
|
||||
else
|
||||
{
|
||||
WriteByte(0);
|
||||
WriteBoolVector(boolVector);
|
||||
}
|
||||
for (i = 0; i < db.Files.Size(); i++)
|
||||
{
|
||||
const CFileItem &file = db.Files[i];
|
||||
// if (file.Parent >= 0)
|
||||
WriteUInt32(file.Parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (thereIsSecure)
|
||||
{
|
||||
UInt64 secureDataSize = 1 + 4 +
|
||||
db.SecureBuf.Size() +
|
||||
db.SecureSizes.Size() * 4;
|
||||
// secureDataSize += db.SecureIDs.Size() * 4;
|
||||
for (i = 0; i < db.SecureIDs.Size(); i++)
|
||||
secureDataSize += GetBigNumberSize(db.SecureIDs[i]);
|
||||
SkipAlign(2 + GetBigNumberSize(secureDataSize), 4);
|
||||
WriteByte(NID::kNtSecure);
|
||||
WriteNumber(secureDataSize);
|
||||
WriteByte(0);
|
||||
WriteUInt32(db.SecureSizes.Size());
|
||||
for (i = 0; i < db.SecureSizes.Size(); i++)
|
||||
WriteUInt32(db.SecureSizes[i]);
|
||||
WriteBytes(db.SecureBuf, db.SecureBuf.Size());
|
||||
for (i = 0; i < db.SecureIDs.Size(); i++)
|
||||
{
|
||||
WriteNumber(db.SecureIDs[i]);
|
||||
// WriteUInt32(db.SecureIDs[i]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
WriteByte(NID::kEnd); // for files
|
||||
WriteByte(NID::kEnd); // for headers
|
||||
}
|
||||
|
||||
HRESULT COutArchive::WriteDatabase(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const CArchiveDatabase &db,
|
||||
const CArchiveDatabaseOut &db,
|
||||
const CCompressionMethodMode *options,
|
||||
const CHeaderOptions &headerOptions)
|
||||
{
|
||||
@@ -773,17 +806,16 @@ HRESULT COutArchive::WriteDatabase(
|
||||
_countMode = encodeHeaders;
|
||||
_writeToStream = true;
|
||||
_countSize = 0;
|
||||
WriteHeader(db, headerOptions, headerOffset);
|
||||
WriteHeader(db, /* headerOptions, */ headerOffset);
|
||||
|
||||
if (encodeHeaders)
|
||||
{
|
||||
CByteBuffer buf;
|
||||
buf.SetCapacity(_countSize);
|
||||
CByteBuffer buf(_countSize);
|
||||
_outByte2.Init((Byte *)buf, _countSize);
|
||||
|
||||
_countMode = false;
|
||||
_writeToStream = false;
|
||||
WriteHeader(db, headerOptions, headerOffset);
|
||||
WriteHeader(db, /* headerOptions, */ headerOffset);
|
||||
|
||||
if (_countSize != _outByte2.GetPos())
|
||||
return E_FAIL;
|
||||
@@ -794,10 +826,12 @@ HRESULT COutArchive::WriteDatabase(
|
||||
CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);
|
||||
CRecordVector<UInt64> packSizes;
|
||||
CObjectVector<CFolder> folders;
|
||||
COutFolders outFolders;
|
||||
|
||||
RINOK(EncodeStream(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
encoder, buf,
|
||||
packSizes, folders));
|
||||
packSizes, folders, outFolders));
|
||||
|
||||
_writeToStream = true;
|
||||
|
||||
@@ -805,11 +839,10 @@ HRESULT COutArchive::WriteDatabase(
|
||||
throw 1;
|
||||
|
||||
WriteID(NID::kEncodedHeader);
|
||||
WritePackInfo(headerOffset, packSizes,
|
||||
CRecordVector<bool>(), CRecordVector<UInt32>());
|
||||
WriteUnpackInfo(folders);
|
||||
WritePackInfo(headerOffset, packSizes, CUInt32DefVector());
|
||||
WriteUnpackInfo(folders, outFolders);
|
||||
WriteByte(NID::kEnd);
|
||||
for (int i = 0; i < packSizes.Size(); i++)
|
||||
FOR_VECTOR (i, packSizes)
|
||||
headerOffset += packSizes[i];
|
||||
}
|
||||
RINOK(_outByte.Flush());
|
||||
@@ -842,24 +875,28 @@ HRESULT COutArchive::WriteDatabase(
|
||||
}
|
||||
}
|
||||
|
||||
void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const
|
||||
void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value)
|
||||
{
|
||||
file = Files[index];
|
||||
file2.CTimeDefined = CTime.GetItem(index, file2.CTime);
|
||||
file2.ATimeDefined = ATime.GetItem(index, file2.ATime);
|
||||
file2.MTimeDefined = MTime.GetItem(index, file2.MTime);
|
||||
file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos);
|
||||
file2.IsAnti = IsItemAnti(index);
|
||||
while (index >= Defs.Size())
|
||||
Defs.Add(false);
|
||||
Defs[index] = defined;
|
||||
if (!defined)
|
||||
return;
|
||||
while (index >= Vals.Size())
|
||||
Vals.Add(0);
|
||||
Vals[index] = value;
|
||||
}
|
||||
|
||||
void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2)
|
||||
void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name)
|
||||
{
|
||||
int index = Files.Size();
|
||||
unsigned index = Files.Size();
|
||||
CTime.SetItem(index, file2.CTimeDefined, file2.CTime);
|
||||
ATime.SetItem(index, file2.ATimeDefined, file2.ATime);
|
||||
MTime.SetItem(index, file2.MTimeDefined, file2.MTime);
|
||||
StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);
|
||||
SetItemAnti(index, file2.IsAnti);
|
||||
SetItem_Anti(index, file2.IsAnti);
|
||||
// SetItem_Aux(index, file2.IsAux);
|
||||
Names.Add(name);
|
||||
Files.Add(file);
|
||||
}
|
||||
|
||||
|
||||
207
CPP/7zip/Archive/7z/7zOut.h
Executable file → Normal file
207
CPP/7zip/Archive/7z/7zOut.h
Executable file → Normal file
@@ -9,6 +9,7 @@
|
||||
#include "7zItem.h"
|
||||
|
||||
#include "../../Common/OutBuffer.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
@@ -45,27 +46,191 @@ public:
|
||||
struct CHeaderOptions
|
||||
{
|
||||
bool CompressMainHeader;
|
||||
/*
|
||||
bool WriteCTime;
|
||||
bool WriteATime;
|
||||
bool WriteMTime;
|
||||
*/
|
||||
|
||||
CHeaderOptions():
|
||||
CompressMainHeader(true),
|
||||
WriteCTime(false),
|
||||
WriteATime(false),
|
||||
WriteMTime(true)
|
||||
CompressMainHeader(true)
|
||||
/*
|
||||
, WriteCTime(false)
|
||||
, WriteATime(false)
|
||||
, WriteMTime(true)
|
||||
*/
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
struct CFileItem2
|
||||
{
|
||||
UInt64 CTime;
|
||||
UInt64 ATime;
|
||||
UInt64 MTime;
|
||||
UInt64 StartPos;
|
||||
bool CTimeDefined;
|
||||
bool ATimeDefined;
|
||||
bool MTimeDefined;
|
||||
bool StartPosDefined;
|
||||
bool IsAnti;
|
||||
// bool IsAux;
|
||||
|
||||
void Init()
|
||||
{
|
||||
CTimeDefined = false;
|
||||
ATimeDefined = false;
|
||||
MTimeDefined = false;
|
||||
StartPosDefined = false;
|
||||
IsAnti = false;
|
||||
// IsAux = false;
|
||||
}
|
||||
};
|
||||
|
||||
struct COutFolders
|
||||
{
|
||||
CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.
|
||||
|
||||
CRecordVector<CNum> NumUnpackStreamsVector;
|
||||
CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bind coders
|
||||
|
||||
void OutFoldersClear()
|
||||
{
|
||||
FolderUnpackCRCs.Clear();
|
||||
NumUnpackStreamsVector.Clear();
|
||||
CoderUnpackSizes.Clear();
|
||||
}
|
||||
|
||||
void OutFoldersReserveDown()
|
||||
{
|
||||
FolderUnpackCRCs.ReserveDown();
|
||||
NumUnpackStreamsVector.ReserveDown();
|
||||
CoderUnpackSizes.ReserveDown();
|
||||
}
|
||||
};
|
||||
|
||||
struct CArchiveDatabaseOut: public COutFolders
|
||||
{
|
||||
CRecordVector<UInt64> PackSizes;
|
||||
CUInt32DefVector PackCRCs;
|
||||
CObjectVector<CFolder> Folders;
|
||||
|
||||
CRecordVector<CFileItem> Files;
|
||||
UStringVector Names;
|
||||
CUInt64DefVector CTime;
|
||||
CUInt64DefVector ATime;
|
||||
CUInt64DefVector MTime;
|
||||
CUInt64DefVector StartPos;
|
||||
CRecordVector<bool> IsAnti;
|
||||
|
||||
/*
|
||||
CRecordVector<bool> IsAux;
|
||||
|
||||
CByteBuffer SecureBuf;
|
||||
CRecordVector<UInt32> SecureSizes;
|
||||
CRecordVector<UInt32> SecureIDs;
|
||||
|
||||
void ClearSecure()
|
||||
{
|
||||
SecureBuf.Free();
|
||||
SecureSizes.Clear();
|
||||
SecureIDs.Clear();
|
||||
}
|
||||
*/
|
||||
|
||||
void Clear()
|
||||
{
|
||||
OutFoldersClear();
|
||||
|
||||
PackSizes.Clear();
|
||||
PackCRCs.Clear();
|
||||
Folders.Clear();
|
||||
|
||||
Files.Clear();
|
||||
Names.Clear();
|
||||
CTime.Clear();
|
||||
ATime.Clear();
|
||||
MTime.Clear();
|
||||
StartPos.Clear();
|
||||
IsAnti.Clear();
|
||||
|
||||
/*
|
||||
IsAux.Clear();
|
||||
ClearSecure();
|
||||
*/
|
||||
}
|
||||
|
||||
void ReserveDown()
|
||||
{
|
||||
OutFoldersReserveDown();
|
||||
|
||||
PackSizes.ReserveDown();
|
||||
PackCRCs.ReserveDown();
|
||||
Folders.ReserveDown();
|
||||
|
||||
Files.ReserveDown();
|
||||
Names.ReserveDown();
|
||||
CTime.ReserveDown();
|
||||
ATime.ReserveDown();
|
||||
MTime.ReserveDown();
|
||||
StartPos.ReserveDown();
|
||||
IsAnti.ReserveDown();
|
||||
|
||||
/*
|
||||
IsAux.ReserveDown();
|
||||
*/
|
||||
}
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return (
|
||||
PackSizes.IsEmpty() &&
|
||||
NumUnpackStreamsVector.IsEmpty() &&
|
||||
Folders.IsEmpty() &&
|
||||
Files.IsEmpty());
|
||||
}
|
||||
|
||||
bool CheckNumFiles() const
|
||||
{
|
||||
unsigned size = Files.Size();
|
||||
return (
|
||||
CTime.CheckSize(size) &&
|
||||
ATime.CheckSize(size) &&
|
||||
MTime.CheckSize(size) &&
|
||||
StartPos.CheckSize(size) &&
|
||||
(size == IsAnti.Size() || IsAnti.Size() == 0));
|
||||
}
|
||||
|
||||
bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
|
||||
// bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }
|
||||
|
||||
void SetItem_Anti(unsigned index, bool isAnti)
|
||||
{
|
||||
while (index >= IsAnti.Size())
|
||||
IsAnti.Add(false);
|
||||
IsAnti[index] = isAnti;
|
||||
}
|
||||
/*
|
||||
void SetItem_Aux(unsigned index, bool isAux)
|
||||
{
|
||||
while (index >= IsAux.Size())
|
||||
IsAux.Add(false);
|
||||
IsAux[index] = isAux;
|
||||
}
|
||||
*/
|
||||
|
||||
void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name);
|
||||
};
|
||||
|
||||
class COutArchive
|
||||
{
|
||||
UInt64 _prefixHeaderPos;
|
||||
|
||||
HRESULT WriteDirect(const void *data, UInt32 size);
|
||||
HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); }
|
||||
|
||||
UInt64 GetPos() const;
|
||||
void WriteBytes(const void *data, size_t size);
|
||||
void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.GetCapacity()); }
|
||||
void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); }
|
||||
void WriteByte(Byte b);
|
||||
void WriteUInt32(UInt32 value);
|
||||
void WriteUInt64(UInt64 value);
|
||||
@@ -75,36 +240,36 @@ class COutArchive
|
||||
void WriteFolder(const CFolder &folder);
|
||||
HRESULT WriteFileHeader(const CFileItem &itemInfo);
|
||||
void WriteBoolVector(const CBoolVector &boolVector);
|
||||
void WriteHashDigests(
|
||||
const CRecordVector<bool> &digestsDefined,
|
||||
const CRecordVector<UInt32> &hashDigests);
|
||||
void WritePropBoolVector(Byte id, const CBoolVector &boolVector);
|
||||
|
||||
void WriteHashDigests(const CUInt32DefVector &digests);
|
||||
|
||||
void WritePackInfo(
|
||||
UInt64 dataOffset,
|
||||
const CRecordVector<UInt64> &packSizes,
|
||||
const CRecordVector<bool> &packCRCsDefined,
|
||||
const CRecordVector<UInt32> &packCRCs);
|
||||
const CUInt32DefVector &packCRCs);
|
||||
|
||||
void WriteUnpackInfo(const CObjectVector<CFolder> &folders);
|
||||
void WriteUnpackInfo(
|
||||
const CObjectVector<CFolder> &folders,
|
||||
const COutFolders &outFolders);
|
||||
|
||||
void WriteSubStreamsInfo(
|
||||
const CObjectVector<CFolder> &folders,
|
||||
const CRecordVector<CNum> &numUnpackStreamsInFolders,
|
||||
const COutFolders &outFolders,
|
||||
const CRecordVector<UInt64> &unpackSizes,
|
||||
const CRecordVector<bool> &digestsDefined,
|
||||
const CRecordVector<UInt32> &hashDigests);
|
||||
const CUInt32DefVector &digests);
|
||||
|
||||
void SkipAlign(unsigned pos, unsigned alignSize);
|
||||
void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize);
|
||||
void WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize);
|
||||
void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type);
|
||||
|
||||
HRESULT EncodeStream(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CEncoder &encoder, const CByteBuffer &data,
|
||||
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders);
|
||||
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders);
|
||||
void WriteHeader(
|
||||
const CArchiveDatabase &db,
|
||||
const CHeaderOptions &headerOptions,
|
||||
const CArchiveDatabaseOut &db,
|
||||
// const CHeaderOptions &headerOptions,
|
||||
UInt64 &headerOffset);
|
||||
|
||||
bool _countMode;
|
||||
@@ -118,6 +283,8 @@ class COutArchive
|
||||
bool _endMarker;
|
||||
#endif
|
||||
|
||||
bool _useAlign;
|
||||
|
||||
HRESULT WriteSignature();
|
||||
#ifdef _7Z_VOL
|
||||
HRESULT WriteFinishSignature();
|
||||
@@ -136,7 +303,7 @@ public:
|
||||
HRESULT SkipPrefixArchiveHeader();
|
||||
HRESULT WriteDatabase(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
const CArchiveDatabase &db,
|
||||
const CArchiveDatabaseOut &db,
|
||||
const CCompressionMethodMode *options,
|
||||
const CHeaderOptions &headerOptions);
|
||||
|
||||
|
||||
48
CPP/7zip/Archive/7z/7zProperties.cpp
Executable file → Normal file
48
CPP/7zip/Archive/7z/7zProperties.cpp
Executable file → Normal file
@@ -17,7 +17,7 @@ struct CPropMap
|
||||
STATPROPSTG StatPROPSTG;
|
||||
};
|
||||
|
||||
CPropMap kPropMap[] =
|
||||
static const CPropMap kPropMap[] =
|
||||
{
|
||||
{ NID::kName, { NULL, kpidPath, VT_BSTR } },
|
||||
{ NID::kSize, { NULL, kpidSize, VT_UI8 } },
|
||||
@@ -34,11 +34,12 @@ CPropMap kPropMap[] =
|
||||
{ NID::kCTime, { NULL, kpidCTime, VT_FILETIME } },
|
||||
{ NID::kMTime, { NULL, kpidMTime, VT_FILETIME } },
|
||||
{ NID::kATime, { NULL, kpidATime, VT_FILETIME } },
|
||||
{ NID::kWinAttributes, { NULL, kpidAttrib, VT_UI4 } },
|
||||
{ NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } },
|
||||
{ NID::kStartPos, { NULL, kpidPosition, VT_UI4 } },
|
||||
|
||||
{ NID::kCRC, { NULL, kpidCRC, VT_UI4 } },
|
||||
|
||||
// { NID::kIsAux, { NULL, kpidIsAux, VT_BOOL } },
|
||||
{ NID::kAnti, { NULL, kpidIsAnti, VT_BOOL } }
|
||||
|
||||
#ifndef _SFX
|
||||
@@ -49,11 +50,9 @@ CPropMap kPropMap[] =
|
||||
#endif
|
||||
};
|
||||
|
||||
static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]);
|
||||
|
||||
static int FindPropInMap(UInt64 filePropID)
|
||||
{
|
||||
for (int i = 0; i < kPropMapSize; i++)
|
||||
for (int i = 0; i < ARRAY_SIZE(kPropMap); i++)
|
||||
if (kPropMap[i].FilePropID == filePropID)
|
||||
return i;
|
||||
return -1;
|
||||
@@ -62,7 +61,7 @@ static int FindPropInMap(UInt64 filePropID)
|
||||
static void CopyOneItem(CRecordVector<UInt64> &src,
|
||||
CRecordVector<UInt64> &dest, UInt32 item)
|
||||
{
|
||||
for (int i = 0; i < src.Size(); i++)
|
||||
FOR_VECTOR (i, src)
|
||||
if (src[i] == item)
|
||||
{
|
||||
dest.Add(item);
|
||||
@@ -73,7 +72,7 @@ static void CopyOneItem(CRecordVector<UInt64> &src,
|
||||
|
||||
static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item)
|
||||
{
|
||||
for (int i = 0; i < src.Size(); i++)
|
||||
FOR_VECTOR (i, src)
|
||||
if (src[i] == item)
|
||||
{
|
||||
src.Delete(i);
|
||||
@@ -83,7 +82,7 @@ static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item)
|
||||
|
||||
static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item)
|
||||
{
|
||||
for (int i = 0; i < dest.Size(); i++)
|
||||
FOR_VECTOR (i, dest)
|
||||
if (dest[i] == item)
|
||||
{
|
||||
dest.Delete(i);
|
||||
@@ -92,6 +91,8 @@ static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item)
|
||||
dest.Insert(0, item);
|
||||
}
|
||||
|
||||
#define COPY_ONE_ITEM(id) CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::id);
|
||||
|
||||
void CHandler::FillPopIDs()
|
||||
{
|
||||
_fileInfoPopIDs.Clear();
|
||||
@@ -103,21 +104,26 @@ void CHandler::FillPopIDs()
|
||||
const CArchiveDatabaseEx &_db = volume.Database;
|
||||
#endif
|
||||
|
||||
CRecordVector<UInt64> fileInfoPopIDs = _db.ArchiveInfo.FileInfoPopIDs;
|
||||
CRecordVector<UInt64> fileInfoPopIDs = _db.ArcInfo.FileInfoPopIDs;
|
||||
|
||||
RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);
|
||||
RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);
|
||||
/*
|
||||
RemoveOneItem(fileInfoPopIDs, NID::kParent);
|
||||
RemoveOneItem(fileInfoPopIDs, NID::kNtSecure);
|
||||
*/
|
||||
|
||||
COPY_ONE_ITEM(kName);
|
||||
COPY_ONE_ITEM(kAnti);
|
||||
COPY_ONE_ITEM(kSize);
|
||||
COPY_ONE_ITEM(kPackInfo);
|
||||
COPY_ONE_ITEM(kCTime);
|
||||
COPY_ONE_ITEM(kMTime);
|
||||
COPY_ONE_ITEM(kATime);
|
||||
COPY_ONE_ITEM(kWinAttrib);
|
||||
COPY_ONE_ITEM(kCRC);
|
||||
COPY_ONE_ITEM(kComment);
|
||||
|
||||
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName);
|
||||
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti);
|
||||
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize);
|
||||
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo);
|
||||
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCTime);
|
||||
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kMTime);
|
||||
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kATime);
|
||||
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes);
|
||||
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC);
|
||||
CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment);
|
||||
_fileInfoPopIDs += fileInfoPopIDs;
|
||||
|
||||
#ifndef _SFX
|
||||
@@ -141,9 +147,9 @@ void CHandler::FillPopIDs()
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties)
|
||||
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps)
|
||||
{
|
||||
*numProperties = _fileInfoPopIDs.Size();
|
||||
*numProps = _fileInfoPopIDs.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
0
CPP/7zip/Archive/7z/7zProperties.h
Executable file → Normal file
0
CPP/7zip/Archive/7z/7zProperties.h
Executable file → Normal file
23
CPP/7zip/Archive/7z/7zRegister.cpp
Executable file → Normal file
23
CPP/7zip/Archive/7z/7zRegister.cpp
Executable file → Normal file
@@ -5,14 +5,21 @@
|
||||
#include "../../Common/RegisterArc.h"
|
||||
|
||||
#include "7zHandler.h"
|
||||
static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; }
|
||||
#ifndef EXTRACT_ONLY
|
||||
static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; }
|
||||
#else
|
||||
#define CreateArcOut 0
|
||||
#endif
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
IMP_CreateArcIn
|
||||
IMP_CreateArcOut
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"7z", L"7z", 0, 7, {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut };
|
||||
{ "7z", "7z", 0, 7,
|
||||
6, {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C},
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature,
|
||||
REF_CreateArc_Pair };
|
||||
|
||||
REGISTER_ARC(7z)
|
||||
REGISTER_ARC_DEC_SIG(7z)
|
||||
// REGISTER_ARC(7z)
|
||||
|
||||
}}
|
||||
|
||||
10
CPP/7zip/Archive/7z/7zSpecStream.cpp
Executable file → Normal file
10
CPP/7zip/Archive/7z/7zSpecStream.cpp
Executable file → Normal file
@@ -9,16 +9,14 @@ STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->Read(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
if (processedSize != 0)
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(
|
||||
UInt64 subStream, UInt64 *value)
|
||||
STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(UInt64 subStream, UInt64 *value)
|
||||
{
|
||||
if (_getSubStreamSize == NULL)
|
||||
if (!_getSubStreamSize)
|
||||
return E_NOTIMPL;
|
||||
return _getSubStreamSize->GetSubStreamSize(subStream, value);
|
||||
return _getSubStreamSize->GetSubStreamSize(subStream, value);
|
||||
}
|
||||
|
||||
|
||||
0
CPP/7zip/Archive/7z/7zSpecStream.h
Executable file → Normal file
0
CPP/7zip/Archive/7z/7zSpecStream.h
Executable file → Normal file
509
CPP/7zip/Archive/7z/7zUpdate.cpp
Executable file → Normal file
509
CPP/7zip/Archive/7z/7zUpdate.cpp
Executable file → Normal file
@@ -4,10 +4,11 @@
|
||||
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
|
||||
#include "../../Compress/CopyCoder.h"
|
||||
|
||||
@@ -58,19 +59,20 @@ int CUpdateItem::GetExtensionPos() const
|
||||
int slashPos = GetReverseSlashPos(Name);
|
||||
int dotPos = Name.ReverseFind(L'.');
|
||||
if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
|
||||
return Name.Length();
|
||||
return Name.Len();
|
||||
return dotPos + 1;
|
||||
}
|
||||
|
||||
UString CUpdateItem::GetExtension() const
|
||||
{
|
||||
return Name.Mid(GetExtensionPos());
|
||||
return Name.Ptr(GetExtensionPos());
|
||||
}
|
||||
|
||||
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
||||
|
||||
#define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b))
|
||||
|
||||
/*
|
||||
static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)
|
||||
{
|
||||
size_t c1 = a1.GetCapacity();
|
||||
@@ -110,11 +112,12 @@ static int CompareFolders(const CFolder &f1, const CFolder &f2)
|
||||
RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
|
||||
{
|
||||
return MyStringCompareNoCase(f1.Name, f2.Name);
|
||||
return CompareFileNames(f1.Name, f2.Name);
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -125,15 +128,19 @@ struct CFolderRepack
|
||||
CNum NumCopyFiles;
|
||||
};
|
||||
|
||||
static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *param)
|
||||
static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void * /* param */)
|
||||
{
|
||||
RINOZ_COMP(p1->Group, p2->Group);
|
||||
int i1 = p1->FolderIndex;
|
||||
int i2 = p2->FolderIndex;
|
||||
const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param;
|
||||
/*
|
||||
// In that version we don't want to parse folders here, so we don't compare folders
|
||||
// probably it must be improved in future
|
||||
const CDbEx &db = *(const CDbEx *)param;
|
||||
RINOZ(CompareFolders(
|
||||
db.Folders[i1],
|
||||
db.Folders[i2]));
|
||||
*/
|
||||
return MyCompare(i1, i2);
|
||||
/*
|
||||
RINOZ_COMP(
|
||||
@@ -147,25 +154,31 @@ static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/*
|
||||
we sort empty files and dirs in such order:
|
||||
- Dir.NonAnti (name sorted)
|
||||
- File.NonAnti (name sorted)
|
||||
- File.Anti (name sorted)
|
||||
- Dir.Anti (reverse name sorted)
|
||||
*/
|
||||
|
||||
static int CompareEmptyItems(const int *p1, const int *p2, void *param)
|
||||
{
|
||||
const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;
|
||||
const CUpdateItem &u1 = updateItems[*p1];
|
||||
const CUpdateItem &u2 = updateItems[*p2];
|
||||
if (u1.IsDir != u2.IsDir)
|
||||
return (u1.IsDir) ? 1 : -1;
|
||||
if (u1.IsDir)
|
||||
{
|
||||
if (u1.IsAnti != u2.IsAnti)
|
||||
return (u1.IsAnti ? 1 : -1);
|
||||
int n = MyStringCompareNoCase(u1.Name, u2.Name);
|
||||
return -n;
|
||||
}
|
||||
// NonAnti < Anti
|
||||
if (u1.IsAnti != u2.IsAnti)
|
||||
return (u1.IsAnti ? 1 : -1);
|
||||
return MyStringCompareNoCase(u1.Name, u2.Name);
|
||||
if (u1.IsDir != u2.IsDir)
|
||||
{
|
||||
// Dir.NonAnti < File < Dir.Anti
|
||||
if (u1.IsDir)
|
||||
return (u1.IsAnti ? 1 : -1);
|
||||
return (u2.IsAnti ? -1 : 1);
|
||||
}
|
||||
int n = CompareFileNames(u1.Name, u2.Name);
|
||||
return (u1.IsDir && u1.IsAnti) ? -n : n;
|
||||
}
|
||||
|
||||
static const char *g_Exts =
|
||||
@@ -198,7 +211,7 @@ static const char *g_Exts =
|
||||
" exe dll ocx vbx sfx sys tlb awx com obj lib out o so "
|
||||
" pdb pch idb ncb opt";
|
||||
|
||||
int GetExtIndex(const char *ext)
|
||||
static int GetExtIndex(const char *ext)
|
||||
{
|
||||
int extIndex = 1;
|
||||
const char *p = g_Exts;
|
||||
@@ -237,7 +250,9 @@ struct CRefItem
|
||||
UInt32 Index;
|
||||
UInt32 ExtensionPos;
|
||||
UInt32 NamePos;
|
||||
int ExtensionIndex;
|
||||
unsigned ExtensionIndex;
|
||||
|
||||
CRefItem() {};
|
||||
CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType):
|
||||
UpdateItem(&ui),
|
||||
Index(index),
|
||||
@@ -248,64 +263,134 @@ struct CRefItem
|
||||
if (sortByType)
|
||||
{
|
||||
int slashPos = GetReverseSlashPos(ui.Name);
|
||||
NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0);
|
||||
NamePos = slashPos + 1;
|
||||
int dotPos = ui.Name.ReverseFind(L'.');
|
||||
if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
|
||||
ExtensionPos = ui.Name.Length();
|
||||
if (dotPos < 0 || dotPos < slashPos)
|
||||
ExtensionPos = ui.Name.Len();
|
||||
else
|
||||
{
|
||||
ExtensionPos = dotPos + 1;
|
||||
UString us = ui.Name.Mid(ExtensionPos);
|
||||
if (!us.IsEmpty())
|
||||
if (ExtensionPos != ui.Name.Len())
|
||||
{
|
||||
us.MakeLower();
|
||||
int i;
|
||||
AString s;
|
||||
for (i = 0; i < us.Length(); i++)
|
||||
for (unsigned pos = ExtensionPos;; pos++)
|
||||
{
|
||||
wchar_t c = us[i];
|
||||
wchar_t c = ui.Name[pos];
|
||||
if (c >= 0x80)
|
||||
break;
|
||||
s += (char)c;
|
||||
if (c == 0)
|
||||
{
|
||||
ExtensionIndex = GetExtIndex(s);
|
||||
break;
|
||||
}
|
||||
s += (char)MyCharLower_Ascii((char)c);
|
||||
}
|
||||
if (i == us.Length())
|
||||
ExtensionIndex = GetExtIndex(s);
|
||||
else
|
||||
ExtensionIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct CSortParam
|
||||
{
|
||||
// const CObjectVector<CTreeFolder> *TreeFolders;
|
||||
bool SortByType;
|
||||
};
|
||||
|
||||
/*
|
||||
we sort files in such order:
|
||||
- Dir.NonAnti (name sorted)
|
||||
- alt streams
|
||||
- Dirs
|
||||
- Dir.Anti (reverse name sorted)
|
||||
*/
|
||||
|
||||
|
||||
static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param)
|
||||
{
|
||||
const CRefItem &a1 = *p1;
|
||||
const CRefItem &a2 = *p2;
|
||||
const CUpdateItem &u1 = *a1.UpdateItem;
|
||||
const CUpdateItem &u2 = *a2.UpdateItem;
|
||||
int n;
|
||||
|
||||
/*
|
||||
if (u1.IsAltStream != u2.IsAltStream)
|
||||
return u1.IsAltStream ? 1 : -1;
|
||||
*/
|
||||
|
||||
// Actually there are no dirs that time. They were stored in other steps
|
||||
// So that code is unused?
|
||||
if (u1.IsDir != u2.IsDir)
|
||||
return (u1.IsDir) ? 1 : -1;
|
||||
return u1.IsDir ? 1 : -1;
|
||||
if (u1.IsDir)
|
||||
{
|
||||
if (u1.IsAnti != u2.IsAnti)
|
||||
return (u1.IsAnti ? 1 : -1);
|
||||
n = MyStringCompareNoCase(u1.Name, u2.Name);
|
||||
int n = CompareFileNames(u1.Name, u2.Name);
|
||||
return -n;
|
||||
}
|
||||
bool sortByType = *(bool *)param;
|
||||
|
||||
// bool sortByType = *(bool *)param;
|
||||
const CSortParam *sortParam = (const CSortParam *)param;
|
||||
bool sortByType = sortParam->SortByType;
|
||||
if (sortByType)
|
||||
{
|
||||
RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex);
|
||||
RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos));
|
||||
RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos));
|
||||
RINOZ(CompareFileNames(u1.Name.Ptr(a1.ExtensionPos), u2.Name.Ptr(a2.ExtensionPos)));
|
||||
RINOZ(CompareFileNames(u1.Name.Ptr(a1.NamePos), u2.Name.Ptr(a2.NamePos)));
|
||||
if (!u1.MTimeDefined && u2.MTimeDefined) return 1;
|
||||
if (u1.MTimeDefined && !u2.MTimeDefined) return -1;
|
||||
if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime);
|
||||
RINOZ_COMP(u1.Size, u2.Size);
|
||||
}
|
||||
return MyStringCompareNoCase(u1.Name, u2.Name);
|
||||
/*
|
||||
int par1 = a1.UpdateItem->ParentFolderIndex;
|
||||
int par2 = a2.UpdateItem->ParentFolderIndex;
|
||||
const CTreeFolder &tf1 = (*sortParam->TreeFolders)[par1];
|
||||
const CTreeFolder &tf2 = (*sortParam->TreeFolders)[par2];
|
||||
|
||||
int b1 = tf1.SortIndex, e1 = tf1.SortIndexEnd;
|
||||
int b2 = tf2.SortIndex, e2 = tf2.SortIndexEnd;
|
||||
if (b1 < b2)
|
||||
{
|
||||
if (e1 <= b2)
|
||||
return -1;
|
||||
// p2 in p1
|
||||
int par = par2;
|
||||
for (;;)
|
||||
{
|
||||
const CTreeFolder &tf = (*sortParam->TreeFolders)[par];
|
||||
par = tf.Parent;
|
||||
if (par == par1)
|
||||
{
|
||||
RINOZ(CompareFileNames(u1.Name, tf.Name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (b2 < b1)
|
||||
{
|
||||
if (e2 <= b1)
|
||||
return 1;
|
||||
// p1 in p2
|
||||
int par = par1;
|
||||
for (;;)
|
||||
{
|
||||
const CTreeFolder &tf = (*sortParam->TreeFolders)[par];
|
||||
par = tf.Parent;
|
||||
if (par == par2)
|
||||
{
|
||||
RINOZ(CompareFileNames(tf.Name, u2.Name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
// RINOZ_COMP(a1.UpdateItem->ParentSortIndex, a2.UpdateItem->ParentSortIndex);
|
||||
RINOK(CompareFileNames(u1.Name, u2.Name));
|
||||
RINOZ_COMP(a1.UpdateItem->IndexInClient, a2.UpdateItem->IndexInClient);
|
||||
RINOZ_COMP(a1.UpdateItem->IndexInArchive, a2.UpdateItem->IndexInArchive);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct CSolidGroup
|
||||
@@ -313,19 +398,19 @@ struct CSolidGroup
|
||||
CRecordVector<UInt32> Indices;
|
||||
};
|
||||
|
||||
static wchar_t *g_ExeExts[] =
|
||||
static const wchar_t *g_ExeExts[] =
|
||||
{
|
||||
L"dll",
|
||||
L"exe",
|
||||
L"ocx",
|
||||
L"sfx",
|
||||
L"sys"
|
||||
L"dll"
|
||||
, L"exe"
|
||||
, L"ocx"
|
||||
, L"sfx"
|
||||
, L"sys"
|
||||
};
|
||||
|
||||
static bool IsExeExt(const UString &ext)
|
||||
static bool IsExeExt(const wchar_t *ext)
|
||||
{
|
||||
for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++)
|
||||
if (ext.CompareNoCase(g_ExeExts[i]) == 0)
|
||||
for (int i = 0; i < ARRAY_SIZE(g_ExeExts); i++)
|
||||
if (MyStringCompareNoCase(ext, g_ExeExts[i]) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -402,7 +487,6 @@ static void MakeExeMethod(CCompressionMethodMode &mode,
|
||||
static void FromUpdateItemToFileItem(const CUpdateItem &ui,
|
||||
CFileItem &file, CFileItem2 &file2)
|
||||
{
|
||||
file.Name = NItemName::MakeLegalName(ui.Name);
|
||||
if (ui.AttribDefined)
|
||||
file.SetAttrib(ui.Attrib);
|
||||
|
||||
@@ -410,11 +494,13 @@ static void FromUpdateItemToFileItem(const CUpdateItem &ui,
|
||||
file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined;
|
||||
file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined;
|
||||
file2.IsAnti = ui.IsAnti;
|
||||
// file2.IsAux = false;
|
||||
file2.StartPosDefined = false;
|
||||
|
||||
file.Size = ui.Size;
|
||||
file.IsDir = ui.IsDir;
|
||||
file.HasStream = ui.HasStream();
|
||||
// file.IsAltStream = ui.IsAltStream;
|
||||
}
|
||||
|
||||
class CFolderOutStream2:
|
||||
@@ -423,11 +509,11 @@ class CFolderOutStream2:
|
||||
{
|
||||
COutStreamWithCRC *_crcStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> _crcStream;
|
||||
const CArchiveDatabaseEx *_db;
|
||||
const CDbEx *_db;
|
||||
const CBoolVector *_extractStatuses;
|
||||
CMyComPtr<ISequentialOutStream> _outStream;
|
||||
UInt32 _startIndex;
|
||||
int _currentIndex;
|
||||
unsigned _currentIndex;
|
||||
bool _fileIsOpen;
|
||||
UInt64 _rem;
|
||||
|
||||
@@ -444,7 +530,7 @@ public:
|
||||
_crcStream = _crcStreamSpec;
|
||||
}
|
||||
|
||||
HRESULT Init(const CArchiveDatabaseEx *db, UInt32 startIndex,
|
||||
HRESULT Init(const CDbEx *db, UInt32 startIndex,
|
||||
const CBoolVector *extractStatuses, ISequentialOutStream *outStream);
|
||||
void ReleaseOutStream();
|
||||
HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
|
||||
@@ -452,7 +538,7 @@ public:
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
HRESULT CFolderOutStream2::Init(const CArchiveDatabaseEx *db, UInt32 startIndex,
|
||||
HRESULT CFolderOutStream2::Init(const CDbEx *db, UInt32 startIndex,
|
||||
const CBoolVector *extractStatuses, ISequentialOutStream *outStream)
|
||||
{
|
||||
_db = db;
|
||||
@@ -551,13 +637,13 @@ public:
|
||||
CMyComPtr<ISequentialOutStream> Fos;
|
||||
|
||||
UInt64 StartPos;
|
||||
const UInt64 *PackSizes;
|
||||
const CFolder *Folder;
|
||||
const CFolders *Folders;
|
||||
int FolderIndex;
|
||||
#ifndef _NO_CRYPTO
|
||||
CMyComPtr<ICryptoGetTextPassword> GetTextPassword;
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
#endif
|
||||
|
||||
DECL_EXTERNAL_CODECS_VARS
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS2;
|
||||
CDecoder Decoder;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
@@ -585,21 +671,20 @@ void CThreadDecoder::Execute()
|
||||
try
|
||||
{
|
||||
#ifndef _NO_CRYPTO
|
||||
bool passwordIsDefined;
|
||||
bool isEncrypted = false;
|
||||
bool passwordIsDefined = false;
|
||||
#endif
|
||||
|
||||
Result = Decoder.Decode(
|
||||
EXTERNAL_CODECS_VARS
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
InStream,
|
||||
StartPos,
|
||||
PackSizes,
|
||||
*Folder,
|
||||
*Folders, FolderIndex,
|
||||
Fos,
|
||||
NULL
|
||||
#ifndef _NO_CRYPTO
|
||||
, GetTextPassword, passwordIsDefined
|
||||
#endif
|
||||
_7Z_DECODER_CRYPRO_VARS
|
||||
#ifndef _7ZIP_ST
|
||||
, MtMode, NumThreads
|
||||
, MtMode, NumThreads
|
||||
#endif
|
||||
);
|
||||
}
|
||||
@@ -614,7 +699,7 @@ void CThreadDecoder::Execute()
|
||||
|
||||
bool static Is86FilteredFolder(const CFolder &f)
|
||||
{
|
||||
for (int i = 0; i < f.Coders.Size(); i++)
|
||||
FOR_VECTOR(i, f.Coders)
|
||||
{
|
||||
CMethodId m = f.Coders[i].MethodID;
|
||||
if (m == k_BCJ || m == k_BCJ2)
|
||||
@@ -650,13 +735,26 @@ static bool IsEncryptedGroup(int group) { return (group & 2) != 0; }
|
||||
static int GetGroupIndex(bool encrypted, int bcjFiltered)
|
||||
{ return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); }
|
||||
|
||||
static void GetFile(const CDatabase &inDb, int index, CFileItem &file, CFileItem2 &file2)
|
||||
{
|
||||
file = inDb.Files[index];
|
||||
file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime);
|
||||
file2.ATimeDefined = inDb.ATime.GetItem(index, file2.ATime);
|
||||
file2.MTimeDefined = inDb.MTime.GetItem(index, file2.MTime);
|
||||
file2.StartPosDefined = inDb.StartPos.GetItem(index, file2.StartPos);
|
||||
file2.IsAnti = inDb.IsItemAnti(index);
|
||||
// file2.IsAux = inDb.IsItemAux(index);
|
||||
}
|
||||
|
||||
HRESULT Update(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
IInStream *inStream,
|
||||
const CArchiveDatabaseEx *db,
|
||||
const CDbEx *db,
|
||||
const CObjectVector<CUpdateItem> &updateItems,
|
||||
// const CObjectVector<CTreeFolder> &treeFolders,
|
||||
// const CUniqBlocks &secureBlocks,
|
||||
COutArchive &archive,
|
||||
CArchiveDatabase &newDatabase,
|
||||
CArchiveDatabaseOut &newDatabase,
|
||||
ISequentialOutStream *seqOutStream,
|
||||
IArchiveUpdateCallback *updateCallback,
|
||||
const CUpdateOptions &options
|
||||
@@ -668,6 +766,9 @@ HRESULT Update(
|
||||
UInt64 numSolidFiles = options.NumSolidFiles;
|
||||
if (numSolidFiles == 0)
|
||||
numSolidFiles = 1;
|
||||
|
||||
// size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes();
|
||||
|
||||
/*
|
||||
CMyComPtr<IOutStream> outStream;
|
||||
RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));
|
||||
@@ -675,23 +776,23 @@ HRESULT Update(
|
||||
return E_NOTIMPL;
|
||||
*/
|
||||
|
||||
UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0;
|
||||
UInt64 startBlockSize = db != 0 ? db->ArcInfo.StartPosition: 0;
|
||||
if (startBlockSize > 0 && !options.RemoveSfxBlock)
|
||||
{
|
||||
RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL));
|
||||
}
|
||||
|
||||
CRecordVector<int> fileIndexToUpdateIndexMap;
|
||||
CIntArr fileIndexToUpdateIndexMap;
|
||||
CRecordVector<CFolderRepack> folderRefs;
|
||||
UInt64 complexity = 0;
|
||||
UInt64 inSizeForReduce2 = 0;
|
||||
bool needEncryptedRepack = false;
|
||||
if (db != 0)
|
||||
{
|
||||
fileIndexToUpdateIndexMap.Reserve(db->Files.Size());
|
||||
int i;
|
||||
fileIndexToUpdateIndexMap.Alloc(db->Files.Size());
|
||||
unsigned i;
|
||||
for (i = 0; i < db->Files.Size(); i++)
|
||||
fileIndexToUpdateIndexMap.Add(-1);
|
||||
fileIndexToUpdateIndexMap[i] = -1;
|
||||
|
||||
for (i = 0; i < updateItems.Size(); i++)
|
||||
{
|
||||
@@ -700,7 +801,7 @@ HRESULT Update(
|
||||
fileIndexToUpdateIndexMap[index] = i;
|
||||
}
|
||||
|
||||
for (i = 0; i < db->Folders.Size(); i++)
|
||||
for (i = 0; i < (int)db->NumFolders; i++)
|
||||
{
|
||||
CNum indexInFolder = 0;
|
||||
CNum numCopyItems = 0;
|
||||
@@ -727,7 +828,8 @@ HRESULT Update(
|
||||
CFolderRepack rep;
|
||||
rep.FolderIndex = i;
|
||||
rep.NumCopyFiles = numCopyItems;
|
||||
const CFolder &f = db->Folders[i];
|
||||
CFolder f;
|
||||
db->ParseFolderInfo(i, f);
|
||||
bool isEncrypted = f.IsEncrypted();
|
||||
rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f));
|
||||
folderRefs.Add(rep);
|
||||
@@ -746,7 +848,7 @@ HRESULT Update(
|
||||
}
|
||||
|
||||
UInt64 inSizeForReduce = 0;
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 0; i < updateItems.Size(); i++)
|
||||
{
|
||||
const CUpdateItem &ui = updateItems[i];
|
||||
@@ -776,18 +878,17 @@ HRESULT Update(
|
||||
if (!folderRefs.IsEmpty())
|
||||
{
|
||||
#ifdef EXTERNAL_CODECS
|
||||
threadDecoder._codecsInfo = codecsInfo;
|
||||
threadDecoder._externalCodecs = *externalCodecs;
|
||||
threadDecoder.__externalCodecs = __externalCodecs;
|
||||
#endif
|
||||
RINOK(threadDecoder.Create());
|
||||
}
|
||||
|
||||
CObjectVector<CSolidGroup> groups;
|
||||
for (i = 0; i < kNumGroupsMax; i++)
|
||||
groups.Add(CSolidGroup());
|
||||
groups.AddNew();
|
||||
|
||||
{
|
||||
// ---------- Split files to 2 groups ----------
|
||||
// ---------- Split files to groups ----------
|
||||
|
||||
bool useFilters = options.UseFilters;
|
||||
const CCompressionMethodMode &method = *options.Method;
|
||||
@@ -803,7 +904,7 @@ HRESULT Update(
|
||||
{
|
||||
int dotPos = ui.Name.ReverseFind(L'.');
|
||||
if (dotPos >= 0)
|
||||
filteredGroup = IsExeExt(ui.Name.Mid(dotPos + 1));
|
||||
filteredGroup = IsExeExt(ui.Name.Ptr(dotPos + 1));
|
||||
}
|
||||
groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i);
|
||||
}
|
||||
@@ -815,7 +916,7 @@ HRESULT Update(
|
||||
if (needEncryptedRepack)
|
||||
{
|
||||
getPasswordSpec = new CCryptoGetTextPassword;
|
||||
threadDecoder.GetTextPassword = getPasswordSpec;
|
||||
threadDecoder.getTextPassword = getPasswordSpec;
|
||||
|
||||
if (options.Method->PasswordIsDefined)
|
||||
getPasswordSpec->Password = options.Method->Password;
|
||||
@@ -825,18 +926,111 @@ HRESULT Update(
|
||||
return E_NOTIMPL;
|
||||
CMyComBSTR password;
|
||||
RINOK(getDecoderPassword->CryptoGetTextPassword(&password));
|
||||
getPasswordSpec->Password = password;
|
||||
if ((BSTR)password)
|
||||
getPasswordSpec->Password = password;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// ---------- Compress ----------
|
||||
|
||||
RINOK(archive.Create(seqOutStream, false));
|
||||
RINOK(archive.SkipPrefixArchiveHeader());
|
||||
|
||||
int folderRefIndex = 0;
|
||||
/*
|
||||
CIntVector treeFolderToArcIndex;
|
||||
treeFolderToArcIndex.Reserve(treeFolders.Size());
|
||||
for (i = 0; i < treeFolders.Size(); i++)
|
||||
treeFolderToArcIndex.Add(-1);
|
||||
// ---------- Write Tree (only AUX dirs) ----------
|
||||
for (i = 1; i < treeFolders.Size(); i++)
|
||||
{
|
||||
const CTreeFolder &treeFolder = treeFolders[i];
|
||||
CFileItem file;
|
||||
CFileItem2 file2;
|
||||
file2.Init();
|
||||
int secureID = 0;
|
||||
if (treeFolder.UpdateItemIndex < 0)
|
||||
{
|
||||
// we can store virtual dir item wuthout attrib, but we want all items have attrib.
|
||||
file.SetAttrib(FILE_ATTRIBUTE_DIRECTORY);
|
||||
file2.IsAux = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
const CUpdateItem &ui = updateItems[treeFolder.UpdateItemIndex];
|
||||
// if item is not dir, then it's parent for alt streams.
|
||||
// we will write such items later
|
||||
if (!ui.IsDir)
|
||||
continue;
|
||||
secureID = ui.SecureIndex;
|
||||
if (ui.NewProps)
|
||||
FromUpdateItemToFileItem(ui, file, file2);
|
||||
else
|
||||
GetFile(*db, ui.IndexInArchive, file, file2);
|
||||
}
|
||||
file.Size = 0;
|
||||
file.HasStream = false;
|
||||
file.IsDir = true;
|
||||
file.Parent = treeFolder.Parent;
|
||||
|
||||
treeFolderToArcIndex[i] = newDatabase.Files.Size();
|
||||
newDatabase.AddFile(file, file2, treeFolder.Name);
|
||||
|
||||
if (totalSecureDataSize != 0)
|
||||
newDatabase.SecureIDs.Add(secureID);
|
||||
}
|
||||
*/
|
||||
|
||||
{
|
||||
/* ---------- Write non-AUX dirs and Empty files ---------- */
|
||||
CRecordVector<int> emptyRefs;
|
||||
for (i = 0; i < updateItems.Size(); i++)
|
||||
{
|
||||
const CUpdateItem &ui = updateItems[i];
|
||||
if (ui.NewData)
|
||||
{
|
||||
if (ui.HasStream())
|
||||
continue;
|
||||
}
|
||||
else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream)
|
||||
continue;
|
||||
/*
|
||||
if (ui.TreeFolderIndex >= 0)
|
||||
continue;
|
||||
*/
|
||||
emptyRefs.Add(i);
|
||||
}
|
||||
emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
|
||||
for (i = 0; i < emptyRefs.Size(); i++)
|
||||
{
|
||||
const CUpdateItem &ui = updateItems[emptyRefs[i]];
|
||||
CFileItem file;
|
||||
CFileItem2 file2;
|
||||
UString name;
|
||||
if (ui.NewProps)
|
||||
{
|
||||
FromUpdateItemToFileItem(ui, file, file2);
|
||||
name = ui.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetFile(*db, ui.IndexInArchive, file, file2);
|
||||
name = db->GetName(ui.IndexInArchive);
|
||||
}
|
||||
|
||||
/*
|
||||
if (totalSecureDataSize != 0)
|
||||
newDatabase.SecureIDs.Add(ui.SecureIndex);
|
||||
file.Parent = ui.ParentFolderIndex;
|
||||
*/
|
||||
newDatabase.AddFile(file, file2, name);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned folderRefIndex = 0;
|
||||
lps->ProgressOffset = 0;
|
||||
|
||||
for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++)
|
||||
@@ -879,15 +1073,20 @@ HRESULT Update(
|
||||
db->GetFolderStreamPos(folderIndex, 0), packSize, progress));
|
||||
lps->ProgressOffset += packSize;
|
||||
|
||||
const CFolder &folder = db->Folders[folderIndex];
|
||||
CNum startIndex = db->FolderStartPackStreamIndex[folderIndex];
|
||||
for (int j = 0; j < folder.PackStreams.Size(); j++)
|
||||
CFolder &folder = newDatabase.Folders.AddNew();
|
||||
db->ParseFolderInfo(folderIndex, folder);
|
||||
CNum startIndex = db->FoStartPackStreamIndex[folderIndex];
|
||||
for (unsigned j = 0; j < folder.PackStreams.Size(); j++)
|
||||
{
|
||||
newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]);
|
||||
newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j));
|
||||
// newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]);
|
||||
// newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);
|
||||
}
|
||||
newDatabase.Folders.Add(folder);
|
||||
|
||||
UInt32 indexStart = db->FoToCoderUnpackSizes[folderIndex];
|
||||
UInt32 indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];
|
||||
for (; indexStart < indexEnd; indexStart++)
|
||||
newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -909,8 +1108,8 @@ HRESULT Update(
|
||||
extractStatuses.Add(needExtract);
|
||||
}
|
||||
|
||||
int startPackIndex = newDatabase.PackSizes.Size();
|
||||
CFolder newFolder;
|
||||
unsigned startPackIndex = newDatabase.PackSizes.Size();
|
||||
UInt64 curUnpackSize;
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> sbInStream;
|
||||
{
|
||||
@@ -921,16 +1120,17 @@ HRESULT Update(
|
||||
}
|
||||
|
||||
threadDecoder.InStream = inStream;
|
||||
threadDecoder.Folder = &db->Folders[folderIndex];
|
||||
threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0);
|
||||
threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]];
|
||||
threadDecoder.Folders = (const CFolders *)db;
|
||||
threadDecoder.FolderIndex = folderIndex;
|
||||
threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0);
|
||||
|
||||
threadDecoder.Start();
|
||||
|
||||
RINOK(encoder.Encode(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
sbInStream, NULL, &inSizeForReduce, newFolder,
|
||||
archive.SeqStream, newDatabase.PackSizes, progress));
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
sbInStream, NULL, &inSizeForReduce,
|
||||
newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize,
|
||||
archive.SeqStream, newDatabase.PackSizes, progress));
|
||||
|
||||
threadDecoder.WaitExecuteFinish();
|
||||
}
|
||||
@@ -939,9 +1139,7 @@ HRESULT Update(
|
||||
|
||||
for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
|
||||
lps->OutSize += newDatabase.PackSizes[startPackIndex];
|
||||
lps->InSize += newFolder.GetUnpackSize();
|
||||
|
||||
newDatabase.Folders.Add(newFolder);
|
||||
lps->InSize += curUnpackSize;
|
||||
}
|
||||
|
||||
newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles);
|
||||
@@ -953,7 +1151,8 @@ HRESULT Update(
|
||||
{
|
||||
CFileItem file;
|
||||
CFileItem2 file2;
|
||||
db->GetFile(fi, file, file2);
|
||||
GetFile(*db, fi, file, file2);
|
||||
UString name = db->GetName(fi);
|
||||
if (file.HasStream)
|
||||
{
|
||||
indexInFolder++;
|
||||
@@ -972,30 +1171,40 @@ HRESULT Update(
|
||||
uf.CrcDefined = file.CrcDefined;
|
||||
uf.HasStream = file.HasStream;
|
||||
file = uf;
|
||||
name = ui.Name;
|
||||
}
|
||||
newDatabase.AddFile(file, file2);
|
||||
/*
|
||||
file.Parent = ui.ParentFolderIndex;
|
||||
if (ui.TreeFolderIndex >= 0)
|
||||
treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size();
|
||||
if (totalSecureDataSize != 0)
|
||||
newDatabase.SecureIDs.Add(ui.SecureIndex);
|
||||
*/
|
||||
newDatabase.AddFile(file, file2, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int numFiles = group.Indices.Size();
|
||||
unsigned numFiles = group.Indices.Size();
|
||||
if (numFiles == 0)
|
||||
continue;
|
||||
CRecordVector<CRefItem> refItems;
|
||||
refItems.Reserve(numFiles);
|
||||
refItems.ClearAndSetSize(numFiles);
|
||||
bool sortByType = (numSolidFiles > 1);
|
||||
for (i = 0; i < numFiles; i++)
|
||||
refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType));
|
||||
refItems.Sort(CompareUpdateItems, (void *)&sortByType);
|
||||
refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);
|
||||
CSortParam sortParam;
|
||||
// sortParam.TreeFolders = &treeFolders;
|
||||
sortParam.SortByType = sortByType;
|
||||
refItems.Sort(CompareUpdateItems, (void *)&sortParam);
|
||||
|
||||
CRecordVector<UInt32> indices;
|
||||
indices.Reserve(numFiles);
|
||||
CObjArray<UInt32> indices(numFiles);
|
||||
|
||||
for (i = 0; i < numFiles; i++)
|
||||
{
|
||||
UInt32 index = refItems[i].Index;
|
||||
indices.Add(index);
|
||||
indices[i] = index;
|
||||
/*
|
||||
const CUpdateItem &ui = updateItems[index];
|
||||
CFileItem file;
|
||||
@@ -1027,7 +1236,7 @@ HRESULT Update(
|
||||
if (numSubFiles == 0)
|
||||
prevExtension = ext;
|
||||
else
|
||||
if (ext.CompareNoCase(prevExtension) != 0)
|
||||
if (!ext.IsEqualToNoCase(prevExtension))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1038,34 +1247,39 @@ HRESULT Update(
|
||||
CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);
|
||||
inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);
|
||||
|
||||
CFolder folderItem;
|
||||
|
||||
int startPackIndex = newDatabase.PackSizes.Size();
|
||||
unsigned startPackIndex = newDatabase.PackSizes.Size();
|
||||
UInt64 curFolderUnpackSize;
|
||||
RINOK(encoder.Encode(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
solidInStream, NULL, &inSizeForReduce, folderItem,
|
||||
solidInStream, NULL, &inSizeForReduce,
|
||||
newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curFolderUnpackSize,
|
||||
archive.SeqStream, newDatabase.PackSizes, progress));
|
||||
|
||||
for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
|
||||
lps->OutSize += newDatabase.PackSizes[startPackIndex];
|
||||
|
||||
lps->InSize += folderItem.GetUnpackSize();
|
||||
lps->InSize += curFolderUnpackSize;
|
||||
// for ()
|
||||
// newDatabase.PackCRCsDefined.Add(false);
|
||||
// newDatabase.PackCRCs.Add(0);
|
||||
|
||||
newDatabase.Folders.Add(folderItem);
|
||||
|
||||
CNum numUnpackStreams = 0;
|
||||
for (int subIndex = 0; subIndex < numSubFiles; subIndex++)
|
||||
{
|
||||
const CUpdateItem &ui = updateItems[indices[i + subIndex]];
|
||||
CFileItem file;
|
||||
CFileItem2 file2;
|
||||
UString name;
|
||||
if (ui.NewProps)
|
||||
{
|
||||
FromUpdateItemToFileItem(ui, file, file2);
|
||||
name = ui.Name;
|
||||
}
|
||||
else
|
||||
db->GetFile(ui.IndexInArchive, file, file2);
|
||||
{
|
||||
GetFile(*db, ui.IndexInArchive, file, file2);
|
||||
name = db->GetName(ui.IndexInArchive);
|
||||
}
|
||||
if (file2.IsAnti || file.IsDir)
|
||||
return E_FAIL;
|
||||
|
||||
@@ -1092,7 +1306,14 @@ HRESULT Update(
|
||||
file.CrcDefined = false;
|
||||
file.HasStream = false;
|
||||
}
|
||||
newDatabase.AddFile(file, file2);
|
||||
/*
|
||||
file.Parent = ui.ParentFolderIndex;
|
||||
if (ui.TreeFolderIndex >= 0)
|
||||
treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size();
|
||||
if (totalSecureDataSize != 0)
|
||||
newDatabase.SecureIDs.Add(ui.SecureIndex);
|
||||
*/
|
||||
newDatabase.AddFile(file, file2, name);
|
||||
}
|
||||
// numUnpackStreams = 0 is very bad case for locked files
|
||||
// v3.13 doesn't understand it.
|
||||
@@ -1112,36 +1333,28 @@ HRESULT Update(
|
||||
groups.ClearAndFree();
|
||||
*/
|
||||
|
||||
/*
|
||||
for (i = 0; i < newDatabase.Files.Size(); i++)
|
||||
{
|
||||
// ---------- Write Folders & Empty Files ----------
|
||||
|
||||
CRecordVector<int> emptyRefs;
|
||||
for (i = 0; i < updateItems.Size(); i++)
|
||||
{
|
||||
const CUpdateItem &ui = updateItems[i];
|
||||
if (ui.NewData)
|
||||
{
|
||||
if (ui.HasStream())
|
||||
continue;
|
||||
}
|
||||
else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream)
|
||||
continue;
|
||||
emptyRefs.Add(i);
|
||||
}
|
||||
emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
|
||||
for (i = 0; i < emptyRefs.Size(); i++)
|
||||
{
|
||||
const CUpdateItem &ui = updateItems[emptyRefs[i]];
|
||||
CFileItem file;
|
||||
CFileItem2 file2;
|
||||
if (ui.NewProps)
|
||||
FromUpdateItemToFileItem(ui, file, file2);
|
||||
else
|
||||
db->GetFile(ui.IndexInArchive, file, file2);
|
||||
newDatabase.AddFile(file, file2);
|
||||
}
|
||||
CFileItem &file = newDatabase.Files[i];
|
||||
file.Parent = treeFolderToArcIndex[file.Parent];
|
||||
}
|
||||
|
||||
if (totalSecureDataSize != 0)
|
||||
{
|
||||
newDatabase.SecureBuf.SetCapacity(totalSecureDataSize);
|
||||
size_t pos = 0;
|
||||
newDatabase.SecureSizes.Reserve(secureBlocks.Sorted.Size());
|
||||
for (i = 0; i < secureBlocks.Sorted.Size(); i++)
|
||||
{
|
||||
const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]];
|
||||
size_t size = buf.GetCapacity();
|
||||
memcpy(newDatabase.SecureBuf + pos, buf, size);
|
||||
newDatabase.SecureSizes.Add((UInt32)size);
|
||||
pos += size;
|
||||
}
|
||||
}
|
||||
*/
|
||||
newDatabase.ReserveDown();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
40
CPP/7zip/Archive/7z/7zUpdate.h
Executable file → Normal file
40
CPP/7zip/Archive/7z/7zUpdate.h
Executable file → Normal file
@@ -3,15 +3,31 @@
|
||||
#ifndef __7Z_UPDATE_H
|
||||
#define __7Z_UPDATE_H
|
||||
|
||||
#include "../IArchive.h"
|
||||
|
||||
// #include "../../Common/UniqBlocks.h"
|
||||
|
||||
#include "7zCompressionMode.h"
|
||||
#include "7zIn.h"
|
||||
#include "7zOut.h"
|
||||
|
||||
#include "../IArchive.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
/*
|
||||
struct CTreeFolder
|
||||
{
|
||||
UString Name;
|
||||
int Parent;
|
||||
CIntVector SubFolders;
|
||||
int UpdateItemIndex;
|
||||
int SortIndex;
|
||||
int SortIndexEnd;
|
||||
|
||||
CTreeFolder(): UpdateItemIndex(-1) {}
|
||||
};
|
||||
*/
|
||||
|
||||
struct CUpdateItem
|
||||
{
|
||||
int IndexInArchive;
|
||||
@@ -23,6 +39,15 @@ struct CUpdateItem
|
||||
|
||||
UInt64 Size;
|
||||
UString Name;
|
||||
/*
|
||||
bool IsAltStream;
|
||||
int ParentFolderIndex;
|
||||
int TreeFolderIndex;
|
||||
*/
|
||||
|
||||
// that code is not used in 9.26
|
||||
// int ParentSortIndex;
|
||||
// int ParentSortIndexEnd;
|
||||
|
||||
UInt32 Attrib;
|
||||
|
||||
@@ -37,15 +62,20 @@ struct CUpdateItem
|
||||
bool ATimeDefined;
|
||||
bool MTimeDefined;
|
||||
|
||||
// int SecureIndex; // 0 means (no_security)
|
||||
|
||||
bool HasStream() const { return !IsDir && !IsAnti && Size != 0; }
|
||||
|
||||
CUpdateItem():
|
||||
// ParentSortIndex(-1),
|
||||
// IsAltStream(false),
|
||||
IsAnti(false),
|
||||
IsDir(false),
|
||||
AttribDefined(false),
|
||||
CTimeDefined(false),
|
||||
ATimeDefined(false),
|
||||
MTimeDefined(false)
|
||||
// SecureIndex(0)
|
||||
{}
|
||||
void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); };
|
||||
|
||||
@@ -72,10 +102,12 @@ struct CUpdateOptions
|
||||
HRESULT Update(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
IInStream *inStream,
|
||||
const CArchiveDatabaseEx *db,
|
||||
const CDbEx *db,
|
||||
const CObjectVector<CUpdateItem> &updateItems,
|
||||
// const CObjectVector<CTreeFolder> &treeFolders, // treeFolders[0] is root
|
||||
// const CUniqBlocks &secureBlocks,
|
||||
COutArchive &archive,
|
||||
CArchiveDatabase &newDatabase,
|
||||
CArchiveDatabaseOut &newDatabase,
|
||||
ISequentialOutStream *seqOutStream,
|
||||
IArchiveUpdateCallback *updateCallback,
|
||||
const CUpdateOptions &options
|
||||
|
||||
0
CPP/7zip/Archive/7z/StdAfx.cpp
Executable file → Normal file
0
CPP/7zip/Archive/7z/StdAfx.cpp
Executable file → Normal file
3
CPP/7zip/Archive/7z/StdAfx.h
Executable file → Normal file
3
CPP/7zip/Archive/7z/StdAfx.h
Executable file → Normal file
@@ -3,7 +3,6 @@
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
#include "../../../Common/NewHandler.h"
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
|
||||
43
CPP/7zip/Archive/7z/makefile
Executable file → Normal file
43
CPP/7zip/Archive/7z/makefile
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
PROG = 7z.dll
|
||||
DEF_FILE = ../Archive.def
|
||||
CFLAGS = $(CFLAGS) -I ../../../ \
|
||||
DEF_FILE = ../../Archive/Archive2.def
|
||||
CFLAGS = $(CFLAGS) \
|
||||
-DEXTERNAL_CODECS \
|
||||
|
||||
AR_OBJS = \
|
||||
@@ -32,12 +32,14 @@ COMMON_OBJS = \
|
||||
$O\StringConvert.obj \
|
||||
$O\StringToInt.obj \
|
||||
$O\MyVector.obj \
|
||||
$O\Wildcard.obj \
|
||||
|
||||
WIN_OBJS = \
|
||||
$O\DLL.obj \
|
||||
$O\FileDir.obj \
|
||||
$O\FileFind.obj \
|
||||
$O\FileIO.obj \
|
||||
$O\FileName.obj \
|
||||
$O\PropVariant.obj \
|
||||
$O\Synchronization.obj \
|
||||
$O\System.obj \
|
||||
@@ -52,6 +54,7 @@ WIN_OBJS = \
|
||||
$O\MethodProps.obj \
|
||||
$O\OutBuffer.obj \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\PropId.obj \
|
||||
$O\StreamBinder.obj \
|
||||
$O\StreamObjects.obj \
|
||||
$O\StreamUtils.obj \
|
||||
@@ -73,38 +76,4 @@ C_OBJS = \
|
||||
$O\CpuArch.obj \
|
||||
$O\Threads.obj \
|
||||
|
||||
!include "../../Crc.mak"
|
||||
|
||||
OBJS = \
|
||||
$O\StdAfx.obj \
|
||||
$(AR_OBJS) \
|
||||
$(7Z_OBJS) \
|
||||
$(COMMON_OBJS) \
|
||||
$(WIN_OBJS) \
|
||||
$(7ZIP_COMMON_OBJS) \
|
||||
$(AR_COMMON_OBJS) \
|
||||
$O\CopyCoder.obj \
|
||||
$(C_OBJS) \
|
||||
$(ASM_OBJS) \
|
||||
$O\resource.res
|
||||
|
||||
!include "../../../Build.mak"
|
||||
|
||||
$(AR_OBJS): ../$(*B).cpp
|
||||
$(COMPL)
|
||||
$(7Z_OBJS): $(*B).cpp
|
||||
$(COMPL)
|
||||
$(COMMON_OBJS): ../../../Common/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(WIN_OBJS): ../../../Windows/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(AR_COMMON_OBJS): ../Common/$(*B).cpp
|
||||
$(COMPL)
|
||||
$O\CopyCoder.obj: ../../Compress/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(C_OBJS): ../../../../C/$(*B).c
|
||||
$(COMPL_O2)
|
||||
|
||||
!include "../../Asm.mak"
|
||||
!include "../../7zip.mak"
|
||||
|
||||
0
CPP/7zip/Archive/7z/resource.rc
Executable file → Normal file
0
CPP/7zip/Archive/7z/resource.rc
Executable file → Normal file
113
CPP/7zip/Archive/ApmHandler.cpp
Executable file → Normal file
113
CPP/7zip/Archive/ApmHandler.cpp
Executable file → Normal file
@@ -4,11 +4,12 @@
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/IntToString.h"
|
||||
#include "Common/MyString.h"
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/Defs.h"
|
||||
#include "../../Common/IntToString.h"
|
||||
#include "../../Common/MyString.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
@@ -25,6 +26,9 @@ using namespace NWindows;
|
||||
namespace NArchive {
|
||||
namespace NApm {
|
||||
|
||||
static const Byte kSig0 = 'E';
|
||||
static const Byte kSig1 = 'R';
|
||||
|
||||
struct CItem
|
||||
{
|
||||
UInt32 StartBlock;
|
||||
@@ -45,13 +49,13 @@ struct CItem
|
||||
|
||||
bool Parse(const Byte *p, UInt32 &numBlocksInMap)
|
||||
{
|
||||
if (p[0] != 0x50 || p[1] != 0x4D || p[2] != 0 || p[3] != 0)
|
||||
return false;
|
||||
numBlocksInMap = Get32(p + 4);
|
||||
StartBlock = Get32(p + 8);
|
||||
NumBlocks = Get32(p + 0xC);
|
||||
memcpy(Name, p + 0x10, 32);
|
||||
memcpy(Type, p + 0x30, 32);
|
||||
if (p[0] != 0x50 || p[1] != 0x4D || p[2] != 0 || p[3] != 0)
|
||||
return false;
|
||||
/*
|
||||
DataStartBlock = Get32(p + 0x50);
|
||||
NumDataBlocks = Get32(p + 0x54);
|
||||
@@ -76,42 +80,56 @@ class CHandler:
|
||||
public IInArchiveGetStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CRecordVector<CItem> _items;
|
||||
|
||||
int _blockSizeLog;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
unsigned _blockSizeLog;
|
||||
UInt32 _numBlocks;
|
||||
UInt64 _phySize;
|
||||
bool _isArc;
|
||||
|
||||
HRESULT ReadTables(IInStream *stream);
|
||||
UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; }
|
||||
UInt64 GetItemSize(const CItem &item) { return BlocksToBytes(item.NumBlocks); }
|
||||
UInt64 GetItemSize(const CItem &item) const { return BlocksToBytes(item.NumBlocks); }
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
};
|
||||
|
||||
static inline int GetLog(UInt32 num)
|
||||
static const UInt32 kSectorSize = 512;
|
||||
|
||||
API_FUNC_static_IsArc IsArc_Apm(const Byte *p, size_t size)
|
||||
{
|
||||
for (int i = 0; i < 31; i++)
|
||||
if (((UInt32)1 << i) == num)
|
||||
return i;
|
||||
return -1;
|
||||
if (size < kSectorSize)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
if (p[0] != kSig0 || p[1] != kSig1)
|
||||
return k_IsArc_Res_NO;
|
||||
unsigned i;
|
||||
for (i = 8; i < 16; i++)
|
||||
if (p[i] != 0)
|
||||
return k_IsArc_Res_NO;
|
||||
UInt32 blockSize = Get16(p + 2);
|
||||
for (i = 9; ((UInt32)1 << i) != blockSize; i++)
|
||||
if (i >= 12)
|
||||
return k_IsArc_Res_NO;
|
||||
return k_IsArc_Res_YES;
|
||||
}
|
||||
|
||||
HRESULT CHandler::ReadTables(IInStream *stream)
|
||||
{
|
||||
const UInt32 kSectorSize = 512;
|
||||
Byte buf[kSectorSize];
|
||||
{
|
||||
RINOK(ReadStream_FALSE(stream, buf, kSectorSize));
|
||||
if (buf[0] != 0x45 || buf[1] != 0x52)
|
||||
return S_FALSE;
|
||||
_blockSizeLog = GetLog(Get16(buf + 2));
|
||||
if (_blockSizeLog < 9 || _blockSizeLog > 14)
|
||||
if (buf[0] != kSig0 || buf[1] != kSig1)
|
||||
return S_FALSE;
|
||||
UInt32 blockSize = Get16(buf + 2);
|
||||
unsigned i;
|
||||
for (i = 9; ((UInt32)1 << i) != blockSize; i++)
|
||||
if (i >= 12)
|
||||
return S_FALSE;
|
||||
_blockSizeLog = i;
|
||||
_numBlocks = Get32(buf + 4);
|
||||
for (int i = 8; i < 16; i++)
|
||||
for (i = 8; i < 16; i++)
|
||||
if (buf[i] != 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
@@ -123,13 +141,14 @@ HRESULT CHandler::ReadTables(IInStream *stream)
|
||||
}
|
||||
|
||||
UInt32 numBlocksInMap = 0;
|
||||
|
||||
for (unsigned i = 0;;)
|
||||
{
|
||||
RINOK(ReadStream_FALSE(stream, buf, kSectorSize));
|
||||
|
||||
CItem item;
|
||||
|
||||
UInt32 numBlocksInMap2;
|
||||
UInt32 numBlocksInMap2 = 0;
|
||||
if (!item.Parse(buf, numBlocksInMap2))
|
||||
return S_FALSE;
|
||||
if (i == 0)
|
||||
@@ -154,12 +173,13 @@ HRESULT CHandler::ReadTables(IInStream *stream)
|
||||
if (++i == numBlocksInMap)
|
||||
break;
|
||||
}
|
||||
|
||||
_phySize = BlocksToBytes(_numBlocks);
|
||||
_isArc = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */)
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
@@ -171,22 +191,23 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_isArc = false;
|
||||
_phySize = 0;
|
||||
_items.Clear();
|
||||
_stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STATPROPSTG kProps[] =
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidSize, VT_UI8},
|
||||
{ NULL, kpidOffset, VT_UI8}
|
||||
kpidPath,
|
||||
kpidSize,
|
||||
kpidOffset
|
||||
};
|
||||
|
||||
STATPROPSTG kArcProps[] =
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidClusterSize, VT_UI4},
|
||||
{ NULL, kpidPhySize, VT_UI8}
|
||||
kpidClusterSize
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
@@ -195,7 +216,7 @@ IMP_IInArchive_ArcProps
|
||||
static AString GetString(const char *s)
|
||||
{
|
||||
AString res;
|
||||
for (int i = 0; i < 32 && s[i] != 0; i++)
|
||||
for (unsigned i = 0; i < 32 && s[i] != 0; i++)
|
||||
res += s[i];
|
||||
return res;
|
||||
}
|
||||
@@ -204,12 +225,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
switch (propID)
|
||||
{
|
||||
case kpidMainSubfile:
|
||||
{
|
||||
int mainIndex = -1;
|
||||
for (int i = 0; i < _items.Size(); i++)
|
||||
FOR_VECTOR (i, _items)
|
||||
{
|
||||
AString s = GetString(_items[i].Type);
|
||||
if (s != "Apple_Free" &&
|
||||
@@ -228,7 +249,15 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
break;
|
||||
}
|
||||
case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break;
|
||||
case kpidPhySize: prop = BlocksToBytes(_numBlocks); break;
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -246,7 +275,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
const CItem &item = _items[index];
|
||||
switch(propID)
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath:
|
||||
{
|
||||
@@ -283,7 +312,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == (UInt32)-1);
|
||||
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _items.Size();
|
||||
if (numItems == 0)
|
||||
@@ -346,10 +375,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static IInArchive *CreateArc() { return new CHandler; }
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"APM", L"", 0, 0xD4, { 0x50, 0x4D, 0, 0, 0, 0, 0 }, 7, false, CreateArc, 0 };
|
||||
{ "APM", "apm", 0, 0xD4,
|
||||
2, { kSig0, kSig1 },
|
||||
0,
|
||||
0,
|
||||
CreateArc, NULL, IsArc_Apm };
|
||||
|
||||
REGISTER_ARC(Apm)
|
||||
|
||||
|
||||
857
CPP/7zip/Archive/ArHandler.cpp
Normal file
857
CPP/7zip/Archive/ArHandler.cpp
Normal file
@@ -0,0 +1,857 @@
|
||||
// ArHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/IntToString.h"
|
||||
#include "../../Common/StringConvert.h"
|
||||
#include "../../Common/StringToInt.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
#include "../../Windows/TimeUtils.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamObjects.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "../Compress/CopyCoder.h"
|
||||
|
||||
#include "Common/ItemNameUtils.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NTime;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NAr {
|
||||
|
||||
/*
|
||||
The end of each file member (including last file in archive) is 2-bytes aligned.
|
||||
It uses 0xA padding if required.
|
||||
|
||||
File Names:
|
||||
|
||||
GNU/SVR4 variant (.a static library):
|
||||
/ - archive symbol table
|
||||
// - the list of the long filenames, separated by one or more LF characters.
|
||||
/N - the reference to name string in long filenames list
|
||||
name/ - the name
|
||||
|
||||
Microsoft variant (.lib static library):
|
||||
/ - First linker file (archive symbol table)
|
||||
/ - Second linker file
|
||||
// - the list of the long filenames, null-terminated. Each string begins
|
||||
immediately after the null byte in the previous string.
|
||||
/N - the reference to name string in long filenames list
|
||||
name/ - the name
|
||||
|
||||
BSD (Mac OS X) variant:
|
||||
"__.SYMDEF" - archive symbol table
|
||||
or
|
||||
"__.SYMDEF SORTED" - archive symbol table
|
||||
#1/N - the real filename of length N is appended to the file header.
|
||||
*/
|
||||
|
||||
static const unsigned kSignatureLen = 8;
|
||||
|
||||
#define SIGNATURE { '!', '<', 'a', 'r', 'c', 'h', '>', 0x0A }
|
||||
|
||||
static const Byte kSignature[kSignatureLen] = SIGNATURE;
|
||||
|
||||
static const unsigned kNameSize = 16;
|
||||
static const unsigned kTimeSize = 12;
|
||||
static const unsigned kUserSize = 6;
|
||||
static const unsigned kModeSize = 8;
|
||||
static const unsigned kSizeSize = 10;
|
||||
|
||||
static const unsigned kHeaderSize = kNameSize + kTimeSize + kUserSize * 2 + kModeSize + kSizeSize + 1 + 1;
|
||||
|
||||
enum EType
|
||||
{
|
||||
kType_Ar,
|
||||
kType_ALib,
|
||||
kType_Deb,
|
||||
kType_Lib
|
||||
};
|
||||
|
||||
static const char *k_TypeExtionsions[] =
|
||||
{
|
||||
"ar"
|
||||
, "a"
|
||||
, "deb"
|
||||
, "lib"
|
||||
};
|
||||
|
||||
enum ESubType
|
||||
{
|
||||
kSubType_None,
|
||||
kSubType_BSD
|
||||
};
|
||||
|
||||
/*
|
||||
struct CHeader
|
||||
{
|
||||
char Name[kNameSize];
|
||||
char MTime[kTimeSize];
|
||||
char User[kUserSize];
|
||||
char Group[kUserSize];
|
||||
char Mode[kModeSize];
|
||||
char Size[kSizeSize];
|
||||
char Quote;
|
||||
char NewLine;
|
||||
};
|
||||
*/
|
||||
|
||||
struct CItem
|
||||
{
|
||||
AString Name;
|
||||
UInt64 Size;
|
||||
UInt32 MTime;
|
||||
UInt32 User;
|
||||
UInt32 Group;
|
||||
UInt32 Mode;
|
||||
|
||||
UInt64 HeaderPos;
|
||||
UInt64 HeaderSize;
|
||||
|
||||
int TextFileIndex;
|
||||
int SameNameIndex;
|
||||
|
||||
CItem(): TextFileIndex(-1), SameNameIndex(-1) {}
|
||||
UInt64 GetDataPos() const { return HeaderPos + HeaderSize; };
|
||||
};
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
|
||||
public:
|
||||
UInt64 Position;
|
||||
ESubType SubType;
|
||||
|
||||
HRESULT GetNextItem(CItem &itemInfo, bool &filled);
|
||||
HRESULT Open(IInStream *inStream);
|
||||
HRESULT SkipData(UInt64 dataSize)
|
||||
{
|
||||
return m_Stream->Seek(dataSize + (dataSize & 1), STREAM_SEEK_CUR, &Position);
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT CInArchive::Open(IInStream *inStream)
|
||||
{
|
||||
SubType = kSubType_None;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &Position));
|
||||
char signature[kSignatureLen];
|
||||
RINOK(ReadStream_FALSE(inStream, signature, kSignatureLen));
|
||||
Position += kSignatureLen;
|
||||
if (memcmp(signature, kSignature, kSignatureLen) != 0)
|
||||
return S_FALSE;
|
||||
m_Stream = inStream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static unsigned RemoveTailSpaces(char *dest, const char *s, unsigned size)
|
||||
{
|
||||
memcpy(dest, s, size);
|
||||
for (; size != 0; size--)
|
||||
{
|
||||
if (dest[size - 1] != ' ')
|
||||
break;
|
||||
}
|
||||
dest[size] = 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
static bool OctalToNumber32(const char *s, unsigned size, UInt32 &res)
|
||||
{
|
||||
res = 0;
|
||||
char sz[32];
|
||||
size = RemoveTailSpaces(sz, s, size);
|
||||
if (size == 0)
|
||||
return true; // some items doesn't contaion any numbers
|
||||
const char *end;
|
||||
UInt64 res64 = ConvertOctStringToUInt64(sz, &end);
|
||||
if ((unsigned)(end - sz) != size)
|
||||
return false;
|
||||
res = (UInt32)res64;
|
||||
return (res64 <= 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
static bool DecimalToNumber(const char *s, unsigned size, UInt64 &res)
|
||||
{
|
||||
res = 0;
|
||||
char sz[32];
|
||||
size = RemoveTailSpaces(sz, s, size);
|
||||
if (size == 0)
|
||||
return true; // some items doesn't contaion any numbers
|
||||
const char *end;
|
||||
res = ConvertStringToUInt64(sz, &end);
|
||||
return ((unsigned)(end - sz) == size);
|
||||
}
|
||||
|
||||
static bool DecimalToNumber32(const char *s, unsigned size, UInt32 &res)
|
||||
{
|
||||
UInt64 res64;
|
||||
if (!DecimalToNumber(s, size, res64))
|
||||
return false;
|
||||
res = (UInt32)res64;
|
||||
return (res64 <= 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
#define RIF(x) { if (!(x)) return S_FALSE; }
|
||||
|
||||
|
||||
HRESULT CInArchive::GetNextItem(CItem &item, bool &filled)
|
||||
{
|
||||
filled = false;
|
||||
|
||||
char header[kHeaderSize];
|
||||
const char *cur = header;
|
||||
|
||||
{
|
||||
size_t processedSize = sizeof(header);
|
||||
item.HeaderPos = Position;
|
||||
item.HeaderSize = kHeaderSize;
|
||||
RINOK(ReadStream(m_Stream, header, &processedSize));
|
||||
if (processedSize != sizeof(header))
|
||||
return S_OK;
|
||||
if (header[kHeaderSize - 2] != 0x60 ||
|
||||
header[kHeaderSize - 1] != 0x0A)
|
||||
return S_OK;
|
||||
for (unsigned i = 0; i < kHeaderSize - 2; i++)
|
||||
// if (header[i] < 0x20)
|
||||
if (header[i] == 0)
|
||||
return S_OK;
|
||||
Position += processedSize;
|
||||
}
|
||||
|
||||
UInt32 longNameLen = 0;
|
||||
if (cur[0] == '#' &&
|
||||
cur[1] == '1' &&
|
||||
cur[2] == '/' &&
|
||||
cur[3] != 0)
|
||||
{
|
||||
// BSD variant
|
||||
RIF(DecimalToNumber32(cur + 3, kNameSize - 3 , longNameLen));
|
||||
if (longNameLen >= (1 << 12))
|
||||
longNameLen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
char tempString[kNameSize + 1];
|
||||
RemoveTailSpaces(tempString, cur, kNameSize);
|
||||
item.Name = tempString;
|
||||
}
|
||||
cur += kNameSize;
|
||||
|
||||
RIF(DecimalToNumber32(cur, kTimeSize, item.MTime)); cur += kTimeSize;
|
||||
RIF(DecimalToNumber32(cur, kUserSize, item.User)); cur += kUserSize;
|
||||
RIF(DecimalToNumber32(cur, kUserSize, item.Group)); cur += kUserSize;
|
||||
RIF(OctalToNumber32(cur, kModeSize, item.Mode)); cur += kModeSize;
|
||||
RIF(DecimalToNumber(cur, kSizeSize, item.Size)); cur += kSizeSize;
|
||||
|
||||
if (longNameLen != 0 && longNameLen <= item.Size)
|
||||
{
|
||||
SubType = kSubType_BSD;
|
||||
size_t processedSize = longNameLen;
|
||||
char *s = item.Name.GetBuffer(longNameLen);
|
||||
HRESULT res = ReadStream(m_Stream, s, &processedSize);
|
||||
s[longNameLen] = 0;
|
||||
item.Name.ReleaseBuffer();
|
||||
RINOK(res);
|
||||
if (processedSize != longNameLen)
|
||||
return S_OK;
|
||||
item.Size -= longNameLen;
|
||||
item.HeaderSize += longNameLen;
|
||||
Position += processedSize;
|
||||
}
|
||||
|
||||
filled = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IInArchiveGetStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CObjectVector<CItem> _items;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
Int32 _mainSubfile;
|
||||
UInt64 _phySize;
|
||||
|
||||
EType _type;
|
||||
ESubType _subType;
|
||||
int _longNames_FileIndex;
|
||||
AString _libFiles[2];
|
||||
unsigned _numLibFiles;
|
||||
AString _errorMessage;
|
||||
bool _isArc;
|
||||
|
||||
|
||||
void UpdateErrorMessage(const char *s);
|
||||
|
||||
HRESULT ParseLongNames(IInStream *stream);
|
||||
void ChangeDuplicateNames();
|
||||
int FindItem(UInt32 offset) const;
|
||||
HRESULT AddFunc(UInt32 offset, const Byte *data, size_t size, size_t &pos);
|
||||
HRESULT ParseLibSymbols(IInStream *stream, unsigned fileIndex);
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
};
|
||||
|
||||
void CHandler::UpdateErrorMessage(const char *s)
|
||||
{
|
||||
if (!_errorMessage.IsEmpty())
|
||||
_errorMessage += '\n';
|
||||
_errorMessage += s;
|
||||
}
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidSubType
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidPath,
|
||||
kpidSize,
|
||||
kpidMTime,
|
||||
kpidPosixAttrib,
|
||||
kpidUser,
|
||||
kpidGroup
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
HRESULT CHandler::ParseLongNames(IInStream *stream)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < _items.Size(); i++)
|
||||
if (_items[i].Name == "//")
|
||||
break;
|
||||
if (i == _items.Size())
|
||||
return S_OK;
|
||||
|
||||
unsigned fileIndex = i;
|
||||
const CItem &item = _items[fileIndex];
|
||||
if (item.Size > ((UInt32)1 << 30))
|
||||
return S_FALSE;
|
||||
RINOK(stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL));
|
||||
size_t size = (size_t)item.Size;
|
||||
|
||||
CByteArr p(size);
|
||||
RINOK(ReadStream_FALSE(stream, p, size));
|
||||
for (i = 0; i < _items.Size(); i++)
|
||||
{
|
||||
CItem &item = _items[i];
|
||||
if (item.Name[0] != '/')
|
||||
continue;
|
||||
const char *ptr = item.Name.Ptr(1);
|
||||
const char *end;
|
||||
UInt32 pos = ConvertStringToUInt32(ptr, &end);
|
||||
if (*end != 0 || end == ptr)
|
||||
continue;
|
||||
if (pos >= size)
|
||||
continue;
|
||||
UInt32 start = pos;
|
||||
for (;;)
|
||||
{
|
||||
if (pos >= size)
|
||||
return S_FALSE;
|
||||
char c = p[pos];
|
||||
if (c == 0 || c == 0x0A)
|
||||
break;
|
||||
pos++;
|
||||
}
|
||||
item.Name.SetFrom((const char *)(p + start), pos - start);
|
||||
}
|
||||
_longNames_FileIndex = fileIndex;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CHandler::ChangeDuplicateNames()
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 1; i < _items.Size(); i++)
|
||||
{
|
||||
CItem &item = _items[i];
|
||||
if (item.Name[0] == '/')
|
||||
continue;
|
||||
CItem &prev = _items[i - 1];
|
||||
if (item.Name == prev.Name)
|
||||
{
|
||||
if (prev.SameNameIndex < 0)
|
||||
prev.SameNameIndex = 0;
|
||||
item.SameNameIndex = prev.SameNameIndex + 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < _items.Size(); i++)
|
||||
{
|
||||
CItem &item = _items[i];
|
||||
if (item.SameNameIndex < 0)
|
||||
continue;
|
||||
char sz[32];
|
||||
ConvertUInt32ToString(item.SameNameIndex + 1, sz);
|
||||
unsigned len = MyStringLen(sz);
|
||||
sz[len++] = '.';
|
||||
sz[len] = 0;
|
||||
item.Name.Insert(0, sz);
|
||||
}
|
||||
}
|
||||
|
||||
int CHandler::FindItem(UInt32 offset) const
|
||||
{
|
||||
unsigned left = 0, right = _items.Size();
|
||||
while (left != right)
|
||||
{
|
||||
unsigned mid = (left + right) / 2;
|
||||
UInt64 midVal = _items[mid].HeaderPos;
|
||||
if (offset == midVal)
|
||||
return mid;
|
||||
if (offset < midVal)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
HRESULT CHandler::AddFunc(UInt32 offset, const Byte *data, size_t size, size_t &pos)
|
||||
{
|
||||
int fileIndex = FindItem(offset);
|
||||
if (fileIndex < (int)0)
|
||||
return S_FALSE;
|
||||
|
||||
size_t i = pos;
|
||||
do
|
||||
{
|
||||
if (i >= size)
|
||||
return S_FALSE;
|
||||
}
|
||||
while (data[i++] != 0);
|
||||
|
||||
AString &s = _libFiles[_numLibFiles];
|
||||
const AString &name = _items[fileIndex].Name;
|
||||
s += name;
|
||||
if (!name.IsEmpty() && name.Back() == '/')
|
||||
s.DeleteBack();
|
||||
s += " ";
|
||||
s += (const char *)(data + pos);
|
||||
s += (char)0xD;
|
||||
s += (char)0xA;
|
||||
pos = i;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static UInt32 Get32(const Byte *p, unsigned be) { if (be) return GetBe32(p); return GetUi32(p); }
|
||||
|
||||
HRESULT CHandler::ParseLibSymbols(IInStream *stream, unsigned fileIndex)
|
||||
{
|
||||
CItem &item = _items[fileIndex];
|
||||
if (item.Name != "/" &&
|
||||
item.Name != "__.SYMDEF" &&
|
||||
item.Name != "__.SYMDEF SORTED")
|
||||
return S_OK;
|
||||
if (item.Size > ((UInt32)1 << 30) ||
|
||||
item.Size < 4)
|
||||
return S_OK;
|
||||
RINOK(stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL));
|
||||
size_t size = (size_t)item.Size;
|
||||
CByteArr p(size);
|
||||
RINOK(ReadStream_FALSE(stream, p, size));
|
||||
|
||||
size_t pos = 0;
|
||||
|
||||
if (item.Name != "/")
|
||||
{
|
||||
// __.SYMDEF parsing (BSD)
|
||||
unsigned be;
|
||||
for (be = 0; be < 2; be++)
|
||||
{
|
||||
UInt32 tableSize = Get32(p, be);
|
||||
pos = 4;
|
||||
if (size - pos < tableSize || (tableSize & 7) != 0)
|
||||
continue;
|
||||
size_t namesStart = pos + tableSize;
|
||||
UInt32 namesSize = Get32(p + namesStart, be);
|
||||
namesStart += 4;
|
||||
if (namesStart > size || namesStart + namesSize != size)
|
||||
continue;
|
||||
|
||||
UInt32 numSymbols = tableSize >> 3;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numSymbols; i++, pos += 8)
|
||||
{
|
||||
size_t namePos = Get32(p + pos, be);
|
||||
UInt32 offset = Get32(p + pos + 4, be);
|
||||
if (AddFunc(offset, p + namesStart, namesSize, namePos) != S_OK)
|
||||
break;
|
||||
}
|
||||
if (i == numSymbols)
|
||||
{
|
||||
pos = size;
|
||||
_type = kType_ALib;
|
||||
_subType = kSubType_BSD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (be == 2)
|
||||
return S_FALSE;
|
||||
}
|
||||
else if (_numLibFiles == 0)
|
||||
{
|
||||
// archive symbol table (GNU)
|
||||
UInt32 numSymbols = GetBe32(p);
|
||||
pos = 4;
|
||||
if (numSymbols > (size - pos) / 4)
|
||||
return S_FALSE;
|
||||
pos += 4 * numSymbols;
|
||||
|
||||
for (UInt32 i = 0; i < numSymbols; i++)
|
||||
{
|
||||
UInt32 offset = GetBe32(p + 4 + i * 4);
|
||||
RINOK(AddFunc(offset, p, size, pos));
|
||||
}
|
||||
_type = kType_ALib;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Second linker file (Microsoft .lib)
|
||||
UInt32 numMembers = GetUi32(p);
|
||||
pos = 4;
|
||||
if (numMembers > (size - pos) / 4)
|
||||
return S_FALSE;
|
||||
pos += 4 * numMembers;
|
||||
|
||||
if (size - pos < 4)
|
||||
return S_FALSE;
|
||||
UInt32 numSymbols = GetUi32(p + pos);
|
||||
pos += 4;
|
||||
if (numSymbols > (size - pos) / 2)
|
||||
return S_FALSE;
|
||||
size_t indexStart = pos;
|
||||
pos += 2 * numSymbols;
|
||||
|
||||
for (UInt32 i = 0; i < numSymbols; i++)
|
||||
{
|
||||
// index is 1-based. So 32-bit numSymbols field works as item[0]
|
||||
UInt32 index = GetUi16(p + indexStart + i * 2);
|
||||
if (index == 0 || index > numMembers)
|
||||
return S_FALSE;
|
||||
UInt32 offset = GetUi32(p + index * 4);
|
||||
RINOK(AddFunc(offset, p, size, pos));
|
||||
}
|
||||
_type = kType_Lib;
|
||||
}
|
||||
// size can be 2-byte aligned in linux files
|
||||
if (pos != size && pos + (pos & 1) != size)
|
||||
return S_FALSE;
|
||||
item.TextFileIndex = _numLibFiles++;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback *callback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
{
|
||||
Close();
|
||||
|
||||
UInt64 fileSize = 0;
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
|
||||
CInArchive arc;
|
||||
RINOK(arc.Open(stream));
|
||||
|
||||
if (callback)
|
||||
{
|
||||
RINOK(callback->SetTotal(NULL, &fileSize));
|
||||
UInt64 numFiles = _items.Size();
|
||||
RINOK(callback->SetCompleted(&numFiles, &arc.Position));
|
||||
}
|
||||
|
||||
CItem item;
|
||||
for (;;)
|
||||
{
|
||||
bool filled;
|
||||
RINOK(arc.GetNextItem(item, filled));
|
||||
if (!filled)
|
||||
break;
|
||||
_items.Add(item);
|
||||
arc.SkipData(item.Size);
|
||||
if (callback && (_items.Size() & 0xFF) == 0)
|
||||
{
|
||||
UInt64 numFiles = _items.Size();
|
||||
RINOK(callback->SetCompleted(&numFiles, &arc.Position));
|
||||
}
|
||||
}
|
||||
|
||||
if (_items.IsEmpty())
|
||||
{
|
||||
// we don't need false empty archives (8-bytes signature only)
|
||||
if (arc.Position != fileSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
_isArc = true;
|
||||
|
||||
_subType = arc.SubType;
|
||||
|
||||
if (ParseLongNames(stream) != S_OK)
|
||||
UpdateErrorMessage("Long file names parsing error");
|
||||
if (_longNames_FileIndex >= 0)
|
||||
_items.Delete(_longNames_FileIndex);
|
||||
|
||||
if (!_items.IsEmpty() && _items[0].Name == "debian-binary")
|
||||
{
|
||||
_type = kType_Deb;
|
||||
_items.DeleteFrontal(1);
|
||||
for (unsigned i = 0; i < _items.Size(); i++)
|
||||
if (_items[i].Name.IsPrefixedBy("data.tar."))
|
||||
if (_mainSubfile < 0)
|
||||
_mainSubfile = i;
|
||||
else
|
||||
{
|
||||
_mainSubfile = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ChangeDuplicateNames();
|
||||
bool error = false;
|
||||
for (unsigned li = 0; li < 2 && li < _items.Size(); li++)
|
||||
if (ParseLibSymbols(stream, li) != S_OK)
|
||||
error = true;
|
||||
if (error)
|
||||
UpdateErrorMessage("Library symbols information error");
|
||||
}
|
||||
|
||||
_stream = stream;
|
||||
_phySize = arc.Position;
|
||||
|
||||
/*
|
||||
if (fileSize < _phySize)
|
||||
UpdateErrorMessage("Unexpected end of archive");
|
||||
*/
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_isArc = false;
|
||||
_phySize = 0;
|
||||
|
||||
_errorMessage.Empty();
|
||||
_stream.Release();
|
||||
_items.Clear();
|
||||
|
||||
_type = kType_Ar;
|
||||
_subType = kSubType_None;
|
||||
_mainSubfile = -1;
|
||||
_longNames_FileIndex = -1;
|
||||
|
||||
_numLibFiles = 0;
|
||||
_libFiles[0].Empty();
|
||||
_libFiles[1].Empty();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
*numItems = _items.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
|
||||
case kpidExtension: prop = k_TypeExtionsions[_type]; break;
|
||||
case kpidShortComment:
|
||||
case kpidSubType:
|
||||
{
|
||||
AString s = k_TypeExtionsions[_type];
|
||||
if (_subType == kSubType_BSD)
|
||||
s += ":BSD";
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
case kpidWarning: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
|
||||
case kpidIsNotArcType: if (_type != kType_Deb) prop = true; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
const CItem &item = _items[index];
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath:
|
||||
if (item.TextFileIndex >= 0)
|
||||
prop = (item.TextFileIndex == 0) ? "1.txt" : "2.txt";
|
||||
else
|
||||
prop = (const wchar_t *)NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP));
|
||||
break;
|
||||
case kpidSize:
|
||||
case kpidPackSize:
|
||||
if (item.TextFileIndex >= 0)
|
||||
prop = (UInt64)_libFiles[item.TextFileIndex].Len();
|
||||
else
|
||||
prop = item.Size;
|
||||
break;
|
||||
case kpidMTime:
|
||||
{
|
||||
if (item.MTime != 0)
|
||||
{
|
||||
FILETIME fileTime;
|
||||
NTime::UnixTimeToFileTime(item.MTime, fileTime);
|
||||
prop = fileTime;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kpidUser: if (item.User != 0) prop = item.User; break;
|
||||
case kpidGroup: if (item.Group != 0) prop = item.Group; break;
|
||||
case kpidPosixAttrib:
|
||||
if (item.TextFileIndex < 0)
|
||||
prop = item.Mode;
|
||||
break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _items.Size();
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
UInt64 totalSize = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
const CItem &item = _items[allFilesMode ? i : indices[i]];
|
||||
totalSize +=
|
||||
(item.TextFileIndex >= 0) ?
|
||||
(UInt64)_libFiles[item.TextFileIndex].Len() : item.Size;
|
||||
}
|
||||
extractCallback->SetTotal(totalSize);
|
||||
|
||||
UInt64 currentTotalSize = 0;
|
||||
|
||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
|
||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
streamSpec->SetStream(_stream);
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
lps->InSize = lps->OutSize = currentTotalSize;
|
||||
RINOK(lps->SetCur());
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
Int32 index = allFilesMode ? i : indices[i];
|
||||
const CItem &item = _items[index];
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
||||
currentTotalSize += (item.TextFileIndex >= 0) ?
|
||||
(UInt64)_libFiles[item.TextFileIndex].Len() : item.Size;
|
||||
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
if (testMode)
|
||||
{
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
|
||||
continue;
|
||||
}
|
||||
bool isOk = true;
|
||||
if (item.TextFileIndex >= 0)
|
||||
{
|
||||
const AString &f = _libFiles[item.TextFileIndex];
|
||||
if (realOutStream)
|
||||
RINOK(WriteStream(realOutStream, f, f.Len()));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(_stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(item.Size);
|
||||
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
|
||||
isOk = (copyCoderSpec->TotalSize == item.Size);
|
||||
}
|
||||
realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(isOk ?
|
||||
NExtract::NOperationResult::kOK:
|
||||
NExtract::NOperationResult::kDataError));
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const CItem &item = _items[index];
|
||||
if (item.TextFileIndex >= 0)
|
||||
{
|
||||
const AString &f = _libFiles[item.TextFileIndex];
|
||||
Create_BufInStream_WithNewBuf((const void *)(const char *)f, f.Len(), stream);
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
return CreateLimitedInStream(_stream, item.GetDataPos(), item.Size, stream);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Ar", "ar a deb lib", 0, 0xEC,
|
||||
kSignatureLen, SIGNATURE,
|
||||
0,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Ar)
|
||||
|
||||
}}
|
||||
0
CPP/7zip/Archive/Archive.def
Executable file → Normal file
0
CPP/7zip/Archive/Archive.def
Executable file → Normal file
4
CPP/7zip/Archive/Archive2.def
Executable file → Normal file
4
CPP/7zip/Archive/Archive2.def
Executable file → Normal file
@@ -3,7 +3,9 @@ EXPORTS
|
||||
GetHandlerProperty PRIVATE
|
||||
GetNumberOfFormats PRIVATE
|
||||
GetHandlerProperty2 PRIVATE
|
||||
CreateObject PRIVATE
|
||||
GetNumberOfMethods PRIVATE
|
||||
GetMethodProperty PRIVATE
|
||||
GetHashers PRIVATE
|
||||
SetLargePageMode PRIVATE
|
||||
SetCaseSensitive PRIVATE
|
||||
GetIsArc PRIVATE
|
||||
64
CPP/7zip/Archive/ArchiveExports.cpp
Executable file → Normal file
64
CPP/7zip/Archive/ArchiveExports.cpp
Executable file → Normal file
@@ -2,24 +2,28 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/7zVersion.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../Common/RegisterArc.h"
|
||||
|
||||
static const unsigned int kNumArcsMax = 48;
|
||||
static unsigned int g_NumArcs = 0;
|
||||
static unsigned int g_DefaultArcIndex = 0;
|
||||
static const unsigned kNumArcsMax = 64;
|
||||
static unsigned g_NumArcs = 0;
|
||||
static unsigned g_DefaultArcIndex = 0;
|
||||
static const CArcInfo *g_Arcs[kNumArcsMax];
|
||||
|
||||
void RegisterArc(const CArcInfo *arcInfo)
|
||||
{
|
||||
if (g_NumArcs < kNumArcsMax)
|
||||
{
|
||||
const wchar_t *p = arcInfo->Name;
|
||||
const char *p = arcInfo->Name;
|
||||
if (p[0] == '7' && p[1] == 'z' && p[2] == 0)
|
||||
g_DefaultArcIndex = g_NumArcs;
|
||||
g_Arcs[g_NumArcs++] = arcInfo;
|
||||
g_Arcs[g_NumArcs] = arcInfo;
|
||||
g_NumArcs++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +32,7 @@ DEFINE_GUID(CLSID_CArchiveHandler,
|
||||
|
||||
#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])
|
||||
|
||||
static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)
|
||||
static inline HRESULT SetPropString(const char *s, unsigned size, PROPVARIANT *value)
|
||||
{
|
||||
if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
|
||||
value->vt = VT_BSTR;
|
||||
@@ -86,37 +90,38 @@ STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)
|
||||
STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::PropVariant_Clear(value);
|
||||
if (formatIndex >= g_NumArcs)
|
||||
return E_INVALIDARG;
|
||||
const CArcInfo &arc = *g_Arcs[formatIndex];
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
switch (propID)
|
||||
{
|
||||
case NArchive::kName:
|
||||
prop = arc.Name;
|
||||
break;
|
||||
case NArchive::kClassID:
|
||||
case NArchive::NHandlerPropID::kName: prop = arc.Name; break;
|
||||
case NArchive::NHandlerPropID::kClassID:
|
||||
{
|
||||
GUID clsId = CLSID_CArchiveHandler;
|
||||
CLS_ARC_ID_ITEM(clsId) = arc.ClassId;
|
||||
return SetPropGUID(clsId, value);
|
||||
}
|
||||
case NArchive::kExtension:
|
||||
if (arc.Ext != 0)
|
||||
prop = arc.Ext;
|
||||
case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break;
|
||||
case NArchive::NHandlerPropID::kAddExtension: if (arc.AddExt) prop = arc.AddExt; break;
|
||||
case NArchive::NHandlerPropID::kUpdate: prop = (bool)(arc.CreateOutArchive != NULL); break;
|
||||
case NArchive::NHandlerPropID::kKeepName: prop = ((arc.Flags & NArcInfoFlags::kKeepName) != 0); break;
|
||||
case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break;
|
||||
case NArchive::NHandlerPropID::kNtSecure: prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break;
|
||||
case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break;
|
||||
case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break;
|
||||
// case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break;
|
||||
|
||||
case NArchive::NHandlerPropID::kSignature:
|
||||
if (!arc.IsMultiSignature())
|
||||
return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
|
||||
break;
|
||||
case NArchive::kAddExtension:
|
||||
if (arc.AddExt != 0)
|
||||
prop = arc.AddExt;
|
||||
case NArchive::NHandlerPropID::kMultiSignature:
|
||||
if (arc.IsMultiSignature())
|
||||
return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
|
||||
break;
|
||||
case NArchive::kUpdate:
|
||||
prop = (bool)(arc.CreateOutArchive != 0);
|
||||
break;
|
||||
case NArchive::kKeepName:
|
||||
prop = arc.KeepName;
|
||||
break;
|
||||
case NArchive::kStartSignature:
|
||||
return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -133,3 +138,12 @@ STDAPI GetNumberOfFormats(UINT32 *numFormats)
|
||||
*numFormats = g_NumArcs;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc)
|
||||
{
|
||||
*isArc = NULL;
|
||||
if (formatIndex >= g_NumArcs)
|
||||
return E_INVALIDARG;
|
||||
*isArc = g_Arcs[formatIndex]->IsArc;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
648
CPP/7zip/Archive/ArjHandler.cpp
Executable file → Normal file
648
CPP/7zip/Archive/ArjHandler.cpp
Executable file → Normal file
@@ -4,11 +4,12 @@
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/StringConvert.h"
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/IntToString.h"
|
||||
#include "../../Common/StringConvert.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/Time.h"
|
||||
#include "../../Windows/PropVariant.h"
|
||||
#include "../../Windows/TimeUtils.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
@@ -31,74 +32,85 @@ using namespace NWindows;
|
||||
namespace NArchive {
|
||||
namespace NArj {
|
||||
|
||||
const int kBlockSizeMin = 30;
|
||||
const int kBlockSizeMax = 2600;
|
||||
static const unsigned kBlockSizeMin = 30;
|
||||
static const unsigned kBlockSizeMax = 2600;
|
||||
|
||||
namespace NSignature
|
||||
static const Byte kSig0 = 0x60;
|
||||
static const Byte kSig1 = 0xEA;
|
||||
|
||||
namespace NCompressionMethod
|
||||
{
|
||||
const Byte kSig0 = 0x60;
|
||||
const Byte kSig1 = 0xEA;
|
||||
enum
|
||||
{
|
||||
kStored = 0,
|
||||
kCompressed1a = 1,
|
||||
kCompressed1b = 2,
|
||||
kCompressed1c = 3,
|
||||
kCompressed2 = 4,
|
||||
kNoDataNoCRC = 8,
|
||||
kNoData = 9
|
||||
};
|
||||
}
|
||||
|
||||
namespace NFileHeader
|
||||
namespace NFileType
|
||||
{
|
||||
namespace NCompressionMethod
|
||||
enum
|
||||
{
|
||||
enum
|
||||
{
|
||||
kStored = 0,
|
||||
kCompressed1a = 1,
|
||||
kCompressed1b = 2,
|
||||
kCompressed1c = 3,
|
||||
kCompressed2 = 4,
|
||||
kNoDataNoCRC = 8,
|
||||
kNoData = 9
|
||||
};
|
||||
}
|
||||
|
||||
namespace NFileType
|
||||
{
|
||||
enum
|
||||
{
|
||||
kBinary = 0,
|
||||
k7BitText = 1,
|
||||
kArchiveHeader = 2,
|
||||
kDirectory = 3,
|
||||
kVolumeLablel = 4,
|
||||
kChapterLabel = 5
|
||||
};
|
||||
}
|
||||
|
||||
namespace NFlags
|
||||
{
|
||||
const Byte kGarbled = 1;
|
||||
const Byte kVolume = 4;
|
||||
const Byte kExtFile = 8;
|
||||
const Byte kPathSym = 0x10;
|
||||
const Byte kBackup = 0x20;
|
||||
}
|
||||
|
||||
namespace NHostOS
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kMSDOS = 0, // filesystem used by MS-DOS, OS/2, Win32
|
||||
// pkarj 2.50 (FAT / VFAT / FAT32 file systems)
|
||||
kPRIMOS,
|
||||
kUnix,
|
||||
kAMIGA,
|
||||
kMac,
|
||||
kOS_2,
|
||||
kAPPLE_GS,
|
||||
kAtari_ST,
|
||||
kNext,
|
||||
kVAX_VMS,
|
||||
kWIN95
|
||||
};
|
||||
}
|
||||
kBinary = 0,
|
||||
k7BitText,
|
||||
kArchiveHeader,
|
||||
kDirectory,
|
||||
kVolumeLablel,
|
||||
kChapterLabel
|
||||
};
|
||||
}
|
||||
|
||||
struct CArchiveHeader
|
||||
namespace NFlags
|
||||
{
|
||||
const Byte kGarbled = 1 << 0;
|
||||
const Byte kAnsiPage = 1 << 1; // or (OLD_SECURED_FLAG) obsolete
|
||||
const Byte kVolume = 1 << 2;
|
||||
const Byte kExtFile = 1 << 3;
|
||||
const Byte kPathSym = 1 << 4;
|
||||
const Byte kBackup = 1 << 5; // obsolete
|
||||
const Byte kSecured = 1 << 6;
|
||||
const Byte kDualName = 1 << 7;
|
||||
}
|
||||
|
||||
namespace NHostOS
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kMSDOS = 0, // MS-DOS, OS/2, Win32, pkarj 2.50 (FAT / VFAT / FAT32)
|
||||
kPRIMOS,
|
||||
kUnix,
|
||||
kAMIGA,
|
||||
kMac,
|
||||
kOS_2,
|
||||
kAPPLE_GS,
|
||||
kAtari_ST,
|
||||
kNext,
|
||||
kVAX_VMS,
|
||||
kWIN95
|
||||
};
|
||||
}
|
||||
|
||||
static const char *kHostOS[] =
|
||||
{
|
||||
"MSDOS"
|
||||
, "PRIMOS"
|
||||
, "UNIX"
|
||||
, "AMIGA"
|
||||
, "MAC"
|
||||
, "OS/2"
|
||||
, "APPLE GS"
|
||||
, "ATARI ST"
|
||||
, "NEXT"
|
||||
, "VAX VMS"
|
||||
, "WIN95"
|
||||
};
|
||||
|
||||
struct CArcHeader
|
||||
{
|
||||
// Byte ArchiverVersion;
|
||||
// Byte ExtractVersion;
|
||||
@@ -110,9 +122,9 @@ struct CArchiveHeader
|
||||
UInt32 CTime;
|
||||
UInt32 MTime;
|
||||
UInt32 ArchiveSize;
|
||||
// UInt32 SecurityEnvelopeFilePosition;
|
||||
// UInt16 FilespecPositionInFilename;
|
||||
// UInt16 LengthOfSecurityEnvelopeSata;
|
||||
// UInt32 SecurPos;
|
||||
// UInt16 FilespecPosInFilename;
|
||||
UInt16 SecurSize;
|
||||
// Byte EncryptionVersion;
|
||||
// Byte LastChapter;
|
||||
AString Name;
|
||||
@@ -121,47 +133,71 @@ struct CArchiveHeader
|
||||
HRESULT Parse(const Byte *p, unsigned size);
|
||||
};
|
||||
|
||||
API_FUNC_static_IsArc IsArc_Arj(const Byte *p, size_t size)
|
||||
{
|
||||
if (size < kBlockSizeMin + 4)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
if (p[0] != kSig0 || p[1] != kSig1)
|
||||
return k_IsArc_Res_NO;
|
||||
UInt32 blockSize = Get16(p + 2);
|
||||
if (blockSize < kBlockSizeMin ||
|
||||
blockSize > kBlockSizeMax)
|
||||
return k_IsArc_Res_NO;
|
||||
|
||||
p += 4;
|
||||
size -= 4;
|
||||
|
||||
Byte headerSize = p[0];
|
||||
if (headerSize < kBlockSizeMin ||
|
||||
headerSize > blockSize ||
|
||||
p[6] != NFileType::kArchiveHeader ||
|
||||
p[28] > 8) // EncryptionVersion
|
||||
return k_IsArc_Res_NO;
|
||||
|
||||
if (blockSize + 4 <= size)
|
||||
if (Get32(p + blockSize) != CrcCalc(p, blockSize))
|
||||
return k_IsArc_Res_NO;
|
||||
|
||||
return k_IsArc_Res_YES;
|
||||
}
|
||||
|
||||
static HRESULT ReadString(const Byte *p, unsigned &size, AString &res)
|
||||
{
|
||||
AString s;
|
||||
for (unsigned i = 0; i < size;)
|
||||
{
|
||||
char c = (char)p[i++];
|
||||
if (c == 0)
|
||||
{
|
||||
size = i;
|
||||
res = s;
|
||||
res = (const char *)p;
|
||||
return S_OK;
|
||||
}
|
||||
s += c;
|
||||
}
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT CArchiveHeader::Parse(const Byte *p, unsigned size)
|
||||
HRESULT CArcHeader::Parse(const Byte *p, unsigned size)
|
||||
{
|
||||
if (size < kBlockSizeMin)
|
||||
return S_FALSE;
|
||||
Byte firstHeaderSize = p[0];
|
||||
if (firstHeaderSize > size)
|
||||
Byte headerSize = p[0];
|
||||
if (headerSize < kBlockSizeMin || headerSize > size)
|
||||
return S_FALSE;
|
||||
// ArchiverVersion = p[1];
|
||||
// ExtractVersion = p[2];
|
||||
HostOS = p[3];
|
||||
// Flags = p[4];
|
||||
// SecuryVersion = p[5];
|
||||
if (p[6] != NFileHeader::NFileType::kArchiveHeader)
|
||||
if (p[6] != NFileType::kArchiveHeader)
|
||||
return S_FALSE;
|
||||
// Reserved = p[7];
|
||||
CTime = Get32(p + 8);
|
||||
MTime = Get32(p + 12);
|
||||
ArchiveSize = Get32(p + 16);
|
||||
// SecurityEnvelopeFilePosition = Get32(p + 20);
|
||||
ArchiveSize = Get32(p + 16); // it can be zero. (currently used only for secured archives)
|
||||
// SecurPos = Get32(p + 20);
|
||||
// UInt16 filespecPositionInFilename = Get16(p + 24);
|
||||
// LengthOfSecurityEnvelopeSata = Get16(p + 26);
|
||||
SecurSize = Get16(p + 26);
|
||||
// EncryptionVersion = p[28];
|
||||
// LastChapter = p[29];
|
||||
unsigned pos = firstHeaderSize;
|
||||
unsigned pos = headerSize;
|
||||
unsigned size1 = size - pos;
|
||||
RINOK(ReadString(p + pos, size1, Name));
|
||||
pos += size1;
|
||||
@@ -189,32 +225,30 @@ struct CItem
|
||||
Byte Method;
|
||||
Byte FileType;
|
||||
|
||||
// UInt16 FilespecPositionInFilename;
|
||||
// UInt16 FilespecPosInFilename;
|
||||
UInt16 FileAccessMode;
|
||||
// Byte FirstChapter;
|
||||
// Byte LastChapter;
|
||||
|
||||
UInt64 DataPosition;
|
||||
|
||||
bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kGarbled) != 0; }
|
||||
bool IsDir() const { return (FileType == NFileHeader::NFileType::kDirectory); }
|
||||
bool IsSplitAfter() const { return (Flags & NFileHeader::NFlags::kVolume) != 0; }
|
||||
bool IsSplitBefore() const { return (Flags & NFileHeader::NFlags::kExtFile) != 0; }
|
||||
UInt32 GetWinAttributes() const
|
||||
bool IsEncrypted() const { return (Flags & NFlags::kGarbled) != 0; }
|
||||
bool IsDir() const { return (FileType == NFileType::kDirectory); }
|
||||
bool IsSplitAfter() const { return (Flags & NFlags::kVolume) != 0; }
|
||||
bool IsSplitBefore() const { return (Flags & NFlags::kExtFile) != 0; }
|
||||
UInt32 GetWinAttrib() const
|
||||
{
|
||||
UInt32 winAtrributes;
|
||||
switch(HostOS)
|
||||
UInt32 atrrib = 0;
|
||||
switch (HostOS)
|
||||
{
|
||||
case NFileHeader::NHostOS::kMSDOS:
|
||||
case NFileHeader::NHostOS::kWIN95:
|
||||
winAtrributes = FileAccessMode;
|
||||
case NHostOS::kMSDOS:
|
||||
case NHostOS::kWIN95:
|
||||
atrrib = FileAccessMode;
|
||||
break;
|
||||
default:
|
||||
winAtrributes = 0;
|
||||
}
|
||||
if (IsDir())
|
||||
winAtrributes |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
return winAtrributes;
|
||||
atrrib |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
return atrrib;
|
||||
}
|
||||
|
||||
HRESULT Parse(const Byte *p, unsigned size);
|
||||
@@ -222,11 +256,9 @@ struct CItem
|
||||
|
||||
HRESULT CItem::Parse(const Byte *p, unsigned size)
|
||||
{
|
||||
if (size < kBlockSizeMin)
|
||||
Byte headerSize = p[0];
|
||||
if (headerSize < kBlockSizeMin || headerSize > size)
|
||||
return S_FALSE;
|
||||
|
||||
Byte firstHeaderSize = p[0];
|
||||
|
||||
Version = p[1];
|
||||
ExtractVersion = p[2];
|
||||
HostOS = p[3];
|
||||
@@ -238,16 +270,16 @@ HRESULT CItem::Parse(const Byte *p, unsigned size)
|
||||
PackSize = Get32(p + 12);
|
||||
Size = Get32(p + 16);
|
||||
FileCRC = Get32(p + 20);
|
||||
// FilespecPositionInFilename = Get16(p + 24);
|
||||
// FilespecPosInFilename = Get16(p + 24);
|
||||
FileAccessMode = Get16(p + 26);
|
||||
// FirstChapter = p[28];
|
||||
// FirstChapter = p[29];
|
||||
|
||||
SplitPos = 0;
|
||||
if (IsSplitBefore() && firstHeaderSize >= 34)
|
||||
if (IsSplitBefore() && headerSize >= 34)
|
||||
SplitPos = Get32(p + 30);
|
||||
|
||||
unsigned pos = firstHeaderSize;
|
||||
unsigned pos = headerSize;
|
||||
unsigned size1 = size - pos;
|
||||
RINOK(ReadString(p + pos, size1, Name));
|
||||
pos += size1;
|
||||
@@ -258,180 +290,121 @@ HRESULT CItem::Parse(const Byte *p, unsigned size)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
struct CInArchiveException
|
||||
enum EErrorType
|
||||
{
|
||||
enum CCauseType
|
||||
{
|
||||
kUnexpectedEndOfArchive = 0,
|
||||
kCRCError,
|
||||
kIncorrectArchive
|
||||
}
|
||||
Cause;
|
||||
CInArchiveException(CCauseType cause): Cause(cause) {};
|
||||
k_ErrorType_OK,
|
||||
k_ErrorType_Corrupted,
|
||||
k_ErrorType_UnexpectedEnd,
|
||||
};
|
||||
|
||||
class CInArchive
|
||||
class CArc
|
||||
{
|
||||
UInt32 _blockSize;
|
||||
Byte _block[kBlockSizeMax + 4];
|
||||
|
||||
HRESULT ReadBlock(bool &filled);
|
||||
HRESULT ReadSignatureAndBlock(bool &filled);
|
||||
HRESULT SkipExtendedHeaders();
|
||||
|
||||
HRESULT SafeReadBytes(void *data, UInt32 size);
|
||||
|
||||
public:
|
||||
CArchiveHeader Header;
|
||||
|
||||
UInt64 Processed;
|
||||
EErrorType Error;
|
||||
bool IsArc;
|
||||
IInStream *Stream;
|
||||
IArchiveOpenCallback *Callback;
|
||||
UInt64 NumFiles;
|
||||
UInt64 NumBytes;
|
||||
CArcHeader Header;
|
||||
|
||||
HRESULT Open(const UInt64 *searchHeaderSizeLimit);
|
||||
HRESULT GetNextItem(bool &filled, CItem &item);
|
||||
HRESULT Open();
|
||||
HRESULT GetNextItem(CItem &item, bool &filled);
|
||||
void Close()
|
||||
{
|
||||
IsArc = false;
|
||||
Error = k_ErrorType_OK;
|
||||
}
|
||||
private:
|
||||
UInt32 _blockSize;
|
||||
Byte _block[kBlockSizeMax + 4];
|
||||
|
||||
HRESULT ReadBlock(bool &filled, bool readSignature);
|
||||
HRESULT SkipExtendedHeaders();
|
||||
HRESULT Read(void *data, size_t *size);
|
||||
};
|
||||
|
||||
static inline bool TestMarkerCandidate(const Byte *p, unsigned maxSize)
|
||||
HRESULT CArc::Read(void *data, size_t *size)
|
||||
{
|
||||
if (p[0] != NSignature::kSig0 || p[1] != NSignature::kSig1)
|
||||
return false;
|
||||
UInt32 blockSize = Get16(p + 2);
|
||||
p += 4;
|
||||
if (p[6] != NFileHeader::NFileType::kArchiveHeader ||
|
||||
p[0] > blockSize ||
|
||||
maxSize < 2 + 2 + blockSize + 4 ||
|
||||
blockSize < kBlockSizeMin || blockSize > kBlockSizeMax ||
|
||||
p[28] > 8) // EncryptionVersion
|
||||
return false;
|
||||
// return (Get32(p + blockSize) == CrcCalc(p, blockSize));
|
||||
return true;
|
||||
HRESULT res = ReadStream(Stream, data, size);
|
||||
Processed += *size;
|
||||
return res;
|
||||
}
|
||||
|
||||
static HRESULT FindAndReadMarker(ISequentialInStream *stream, const UInt64 *searchHeaderSizeLimit, UInt64 &position)
|
||||
{
|
||||
position = 0;
|
||||
|
||||
const int kMarkerSizeMin = 2 + 2 + kBlockSizeMin + 4;
|
||||
const int kMarkerSizeMax = 2 + 2 + kBlockSizeMax + 4;
|
||||
|
||||
CByteBuffer byteBuffer;
|
||||
const UInt32 kBufSize = 1 << 16;
|
||||
byteBuffer.SetCapacity(kBufSize);
|
||||
Byte *buf = byteBuffer;
|
||||
|
||||
size_t processedSize = kMarkerSizeMax;
|
||||
RINOK(ReadStream(stream, buf, &processedSize));
|
||||
if (processedSize < kMarkerSizeMin)
|
||||
return S_FALSE;
|
||||
if (TestMarkerCandidate(buf, (unsigned)processedSize))
|
||||
return S_OK;
|
||||
|
||||
UInt32 numBytesPrev = (UInt32)processedSize - 1;
|
||||
memmove(buf, buf + 1, numBytesPrev);
|
||||
UInt64 curTestPos = 1;
|
||||
for (;;)
|
||||
{
|
||||
if (searchHeaderSizeLimit != NULL)
|
||||
if (curTestPos > *searchHeaderSizeLimit)
|
||||
return S_FALSE;
|
||||
processedSize = kBufSize - numBytesPrev;
|
||||
RINOK(ReadStream(stream, buf + numBytesPrev, &processedSize));
|
||||
UInt32 numBytesInBuffer = numBytesPrev + (UInt32)processedSize;
|
||||
if (numBytesInBuffer < kMarkerSizeMin)
|
||||
return S_FALSE;
|
||||
UInt32 numTests = numBytesInBuffer - kMarkerSizeMin + 1;
|
||||
UInt32 pos;
|
||||
for (pos = 0; pos < numTests; pos++)
|
||||
{
|
||||
for (; buf[pos] != NSignature::kSig0 && pos < numTests; pos++);
|
||||
if (pos == numTests)
|
||||
break;
|
||||
if (TestMarkerCandidate(buf + pos, numBytesInBuffer - pos))
|
||||
{
|
||||
position = curTestPos + pos;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
curTestPos += pos;
|
||||
numBytesPrev = numBytesInBuffer - numTests;
|
||||
memmove(buf, buf + numTests, numBytesPrev);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CInArchive::SafeReadBytes(void *data, UInt32 size)
|
||||
{
|
||||
size_t processed = size;
|
||||
RINOK(ReadStream(Stream, data, &processed));
|
||||
if (processed != size)
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadBlock(bool &filled)
|
||||
#define READ_STREAM(_dest_, _size_) \
|
||||
{ size_t _processed_ = (_size_); RINOK(Read(_dest_, &_processed_)); \
|
||||
if (_processed_ != (_size_)) { Error = k_ErrorType_UnexpectedEnd; return S_OK; } }
|
||||
|
||||
HRESULT CArc::ReadBlock(bool &filled, bool readSignature)
|
||||
{
|
||||
Error = k_ErrorType_OK;
|
||||
filled = false;
|
||||
Byte buf[2];
|
||||
RINOK(SafeReadBytes(buf, 2));
|
||||
_blockSize = Get16(buf);
|
||||
if (_blockSize == 0)
|
||||
Byte buf[4];
|
||||
unsigned signSize = readSignature ? 2 : 0;
|
||||
READ_STREAM(buf, signSize + 2)
|
||||
if (readSignature)
|
||||
if (buf[0] != kSig0 || buf[1] != kSig1)
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
return S_OK;
|
||||
}
|
||||
_blockSize = Get16(buf + signSize);
|
||||
if (_blockSize == 0) // end of archive
|
||||
return S_OK;
|
||||
if (_blockSize > kBlockSizeMax)
|
||||
throw CInArchiveException(CInArchiveException::kIncorrectArchive);
|
||||
RINOK(SafeReadBytes(_block, _blockSize + 4));
|
||||
NumBytes += _blockSize + 6;
|
||||
if (_blockSize < kBlockSizeMin ||
|
||||
_blockSize > kBlockSizeMax)
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
return S_OK;
|
||||
}
|
||||
READ_STREAM(_block, _blockSize + 4);
|
||||
if (Get32(_block + _blockSize) != CrcCalc(_block, _blockSize))
|
||||
throw CInArchiveException(CInArchiveException::kCRCError);
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
return S_OK;
|
||||
}
|
||||
filled = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadSignatureAndBlock(bool &filled)
|
||||
{
|
||||
Byte id[2];
|
||||
RINOK(SafeReadBytes(id, 2));
|
||||
if (id[0] != NSignature::kSig0 || id[1] != NSignature::kSig1)
|
||||
throw CInArchiveException(CInArchiveException::kIncorrectArchive);
|
||||
return ReadBlock(filled);
|
||||
}
|
||||
|
||||
HRESULT CInArchive::SkipExtendedHeaders()
|
||||
HRESULT CArc::SkipExtendedHeaders()
|
||||
{
|
||||
for (UInt32 i = 0;; i++)
|
||||
{
|
||||
bool filled;
|
||||
RINOK(ReadBlock(filled));
|
||||
RINOK(ReadBlock(filled, false));
|
||||
if (!filled)
|
||||
return S_OK;
|
||||
if (Callback && (i & 0xFF) == 0)
|
||||
RINOK(Callback->SetCompleted(&NumFiles, &NumBytes));
|
||||
RINOK(Callback->SetCompleted(&NumFiles, &Processed));
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit)
|
||||
HRESULT CArc::Open()
|
||||
{
|
||||
UInt64 position = 0;
|
||||
RINOK(FindAndReadMarker(Stream, searchHeaderSizeLimit, position));
|
||||
RINOK(Stream->Seek(position, STREAM_SEEK_SET, NULL));
|
||||
bool filled;
|
||||
RINOK(ReadSignatureAndBlock(filled));
|
||||
RINOK(ReadBlock(filled, true));
|
||||
if (!filled)
|
||||
return S_FALSE;
|
||||
RINOK(Header.Parse(_block, _blockSize));
|
||||
IsArc = true;
|
||||
return SkipExtendedHeaders();
|
||||
}
|
||||
|
||||
HRESULT CInArchive::GetNextItem(bool &filled, CItem &item)
|
||||
HRESULT CArc::GetNextItem(CItem &item, bool &filled)
|
||||
{
|
||||
RINOK(ReadSignatureAndBlock(filled));
|
||||
RINOK(ReadBlock(filled, true));
|
||||
if (!filled)
|
||||
return S_OK;
|
||||
filled = false;
|
||||
RINOK(item.Parse(_block, _blockSize));
|
||||
if (item.Parse(_block, _blockSize) != S_OK)
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
return S_OK;
|
||||
}
|
||||
/*
|
||||
UInt32 extraData;
|
||||
if ((header.Flags & NFileHeader::NFlags::kExtFile) != 0)
|
||||
if ((header.Flags & NFlags::kExtFile) != 0)
|
||||
extraData = GetUi32(_block + pos);
|
||||
*/
|
||||
|
||||
@@ -444,67 +417,47 @@ class CHandler:
|
||||
public IInArchive,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CObjectVector<CItem> _items;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
UInt64 _phySize;
|
||||
CArc _arc;
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(IInArchive)
|
||||
|
||||
INTERFACE_IInArchive(;)
|
||||
|
||||
HRESULT Open2(IInStream *inStream, const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *callback);
|
||||
private:
|
||||
CInArchive _archive;
|
||||
CObjectVector<CItem> _items;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback);
|
||||
};
|
||||
|
||||
const wchar_t *kHostOS[] =
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
L"MSDOS",
|
||||
L"PRIMOS",
|
||||
L"UNIX",
|
||||
L"AMIGA",
|
||||
L"MAC",
|
||||
L"OS/2",
|
||||
L"APPLE GS",
|
||||
L"ATARI ST",
|
||||
L"NEXT",
|
||||
L"VAX VMS",
|
||||
L"WIN95"
|
||||
kpidName,
|
||||
kpidCTime,
|
||||
kpidMTime,
|
||||
kpidHostOS,
|
||||
kpidComment
|
||||
};
|
||||
|
||||
const wchar_t *kUnknownOS = L"Unknown";
|
||||
|
||||
const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);
|
||||
|
||||
STATPROPSTG kArcProps[] =
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
{ NULL, kpidName, VT_BSTR},
|
||||
{ NULL, kpidCTime, VT_BSTR},
|
||||
{ NULL, kpidMTime, VT_BSTR},
|
||||
{ NULL, kpidHostOS, VT_BSTR},
|
||||
{ NULL, kpidComment, VT_BSTR}
|
||||
};
|
||||
|
||||
STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidIsDir, VT_BOOL},
|
||||
{ NULL, kpidSize, VT_UI4},
|
||||
{ NULL, kpidPosition, VT_UI8},
|
||||
{ NULL, kpidPackSize, VT_UI4},
|
||||
{ NULL, kpidMTime, VT_FILETIME},
|
||||
{ NULL, kpidAttrib, VT_UI4},
|
||||
{ NULL, kpidEncrypted, VT_BOOL},
|
||||
{ NULL, kpidCRC, VT_UI4},
|
||||
{ NULL, kpidMethod, VT_UI1},
|
||||
{ NULL, kpidHostOS, VT_BSTR},
|
||||
{ NULL, kpidComment, VT_BSTR}
|
||||
kpidPath,
|
||||
kpidIsDir,
|
||||
kpidSize,
|
||||
kpidPosition,
|
||||
kpidPackSize,
|
||||
kpidMTime,
|
||||
kpidAttrib,
|
||||
kpidEncrypted,
|
||||
kpidCRC,
|
||||
kpidMethod,
|
||||
kpidHostOS,
|
||||
kpidComment
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
static void SetTime(UInt32 dosTime, NWindows::NCOM::CPropVariant &prop)
|
||||
static void SetTime(UInt32 dosTime, NCOM::CPropVariant &prop)
|
||||
{
|
||||
if (dosTime == 0)
|
||||
return;
|
||||
@@ -519,12 +472,21 @@ static void SetTime(UInt32 dosTime, NWindows::NCOM::CPropVariant &prop)
|
||||
prop = utc;
|
||||
}
|
||||
|
||||
static void SetHostOS(Byte hostOS, NWindows::NCOM::CPropVariant &prop)
|
||||
static void SetHostOS(Byte hostOS, NCOM::CPropVariant &prop)
|
||||
{
|
||||
prop = hostOS < kNumHostOSes ? kHostOS[hostOS] : kUnknownOS;
|
||||
char temp[16];
|
||||
const char *s = NULL;
|
||||
if (hostOS < ARRAY_SIZE(kHostOS))
|
||||
s = kHostOS[hostOS];
|
||||
else
|
||||
{
|
||||
ConvertUInt32ToString(hostOS, temp);
|
||||
s = temp;
|
||||
}
|
||||
prop = s;
|
||||
}
|
||||
|
||||
static void SetUnicodeString(const AString &s, NWindows::NCOM::CPropVariant &prop)
|
||||
static void SetUnicodeString(const AString &s, NCOM::CPropVariant &prop)
|
||||
{
|
||||
if (!s.IsEmpty())
|
||||
prop = MultiByteToUnicodeString(s, CP_OEMCP);
|
||||
@@ -533,14 +495,27 @@ static void SetUnicodeString(const AString &s, NWindows::NCOM::CPropVariant &pro
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidName: SetUnicodeString(_archive.Header.Name, prop); break;
|
||||
case kpidCTime: SetTime(_archive.Header.CTime, prop); break;
|
||||
case kpidMTime: SetTime(_archive.Header.MTime, prop); break;
|
||||
case kpidHostOS: SetHostOS(_archive.Header.HostOS, prop); break;
|
||||
case kpidComment: SetUnicodeString(_archive.Header.Comment, prop); break;
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
case kpidName: SetUnicodeString(_arc.Header.Name, prop); break;
|
||||
case kpidCTime: SetTime(_arc.Header.CTime, prop); break;
|
||||
case kpidMTime: SetTime(_arc.Header.MTime, prop); break;
|
||||
case kpidHostOS: SetHostOS(_arc.Header.HostOS, prop); break;
|
||||
case kpidComment: SetUnicodeString(_arc.Header.Comment, prop); break;
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_arc.IsArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
switch (_arc.Error)
|
||||
{
|
||||
case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break;
|
||||
case k_ErrorType_Corrupted: v |= kpv_ErrorFlags_HeadersError; break;
|
||||
}
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -556,16 +531,16 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
NCOM::CPropVariant prop;
|
||||
const CItem &item = _items[index];
|
||||
switch(propID)
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath: prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;
|
||||
case kpidIsDir: prop = item.IsDir(); break;
|
||||
case kpidSize: prop = item.Size; break;
|
||||
case kpidPackSize: prop = item.PackSize; break;
|
||||
case kpidPosition: if (item.IsSplitBefore() || item.IsSplitAfter()) prop = (UInt64)item.SplitPos; break;
|
||||
case kpidAttrib: prop = item.GetWinAttributes(); break;
|
||||
case kpidAttrib: prop = item.GetWinAttrib(); break;
|
||||
case kpidEncrypted: prop = item.IsEncrypted(); break;
|
||||
case kpidCRC: prop = item.FileCRC; break;
|
||||
case kpidMethod: prop = item.Method; break;
|
||||
@@ -578,75 +553,88 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *inStream, const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *callback)
|
||||
HRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback)
|
||||
{
|
||||
Close();
|
||||
|
||||
UInt64 endPos = 0;
|
||||
if (callback != NULL)
|
||||
{
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
|
||||
_archive.Stream = inStream;
|
||||
_archive.Callback = callback;
|
||||
_archive.NumFiles = _archive.NumBytes = 0;
|
||||
_arc.Stream = inStream;
|
||||
_arc.Callback = callback;
|
||||
_arc.NumFiles = 0;
|
||||
_arc.Processed = 0;
|
||||
|
||||
RINOK(_arc.Open());
|
||||
|
||||
_phySize = _arc.Processed;
|
||||
if (_arc.Header.ArchiveSize != 0)
|
||||
_phySize = (UInt64)_arc.Header.ArchiveSize + _arc.Header.SecurSize;
|
||||
|
||||
RINOK(_archive.Open(maxCheckStartPosition));
|
||||
if (callback != NULL)
|
||||
RINOK(callback->SetTotal(NULL, &endPos));
|
||||
for (;;)
|
||||
{
|
||||
CItem item;
|
||||
bool filled;
|
||||
|
||||
_arc.Error = k_ErrorType_OK;
|
||||
RINOK(_arc.GetNextItem(item, filled));
|
||||
|
||||
RINOK(_archive.GetNextItem(filled, item));
|
||||
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &item.DataPosition));
|
||||
if (_arc.Error != k_ErrorType_OK)
|
||||
break;
|
||||
|
||||
if (!filled)
|
||||
{
|
||||
if (_arc.Error == k_ErrorType_OK)
|
||||
if (_arc.Header.ArchiveSize == 0)
|
||||
_phySize = _arc.Processed;
|
||||
break;
|
||||
}
|
||||
item.DataPosition = _arc.Processed;
|
||||
_items.Add(item);
|
||||
|
||||
if (inStream->Seek(item.PackSize, STREAM_SEEK_CUR, NULL) != S_OK)
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
|
||||
_archive.NumFiles = _items.Size();
|
||||
_archive.NumBytes = item.DataPosition;
|
||||
|
||||
if (callback != NULL && _items.Size() % 100 == 0)
|
||||
UInt64 pos = item.DataPosition + item.PackSize;
|
||||
if (_arc.Header.ArchiveSize == 0)
|
||||
_phySize = pos;
|
||||
if (pos > endPos)
|
||||
{
|
||||
RINOK(callback->SetCompleted(&_archive.NumFiles, &_archive.NumBytes));
|
||||
_arc.Error = k_ErrorType_UnexpectedEnd;
|
||||
break;
|
||||
}
|
||||
|
||||
RINOK(inStream->Seek(pos, STREAM_SEEK_SET, NULL));
|
||||
_arc.NumFiles = _items.Size();
|
||||
_arc.Processed = pos;
|
||||
|
||||
if (callback && (_items.Size() & 0xFF) == 0)
|
||||
{
|
||||
RINOK(callback->SetCompleted(&_arc.NumFiles, &_arc.Processed));
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)
|
||||
const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
HRESULT res;
|
||||
try
|
||||
{
|
||||
res = Open2(inStream, maxCheckStartPosition, callback);
|
||||
res = Open2(inStream, callback);
|
||||
if (res == S_OK)
|
||||
{
|
||||
_stream = inStream;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
catch(const CInArchiveException &) { res = S_FALSE; }
|
||||
Close();
|
||||
return res;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_arc.Close();
|
||||
_phySize = 0;
|
||||
_items.Clear();
|
||||
_stream.Release();
|
||||
return S_OK;
|
||||
@@ -657,7 +645,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
UInt64 totalUnpacked = 0, totalPacked = 0;
|
||||
bool allFilesMode = (numItems == (UInt32)-1);
|
||||
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _items.Size();
|
||||
if (numItems == 0)
|
||||
@@ -736,28 +724,28 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 opRes = NExtract::NOperationResult::kOK;
|
||||
|
||||
if (item.IsEncrypted())
|
||||
opRes = NExtract::NOperationResult::kUnSupportedMethod;
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else
|
||||
{
|
||||
switch(item.Method)
|
||||
switch (item.Method)
|
||||
{
|
||||
case NFileHeader::NCompressionMethod::kStored:
|
||||
case NCompressionMethod::kStored:
|
||||
{
|
||||
result = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
|
||||
if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize)
|
||||
result = S_FALSE;
|
||||
break;
|
||||
}
|
||||
case NFileHeader::NCompressionMethod::kCompressed1a:
|
||||
case NFileHeader::NCompressionMethod::kCompressed1b:
|
||||
case NFileHeader::NCompressionMethod::kCompressed1c:
|
||||
case NCompressionMethod::kCompressed1a:
|
||||
case NCompressionMethod::kCompressed1b:
|
||||
case NCompressionMethod::kCompressed1c:
|
||||
{
|
||||
if (!arj1Decoder)
|
||||
arj1Decoder = new NCompress::NArj::NDecoder1::CCoder;
|
||||
result = arj1Decoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
|
||||
break;
|
||||
}
|
||||
case NFileHeader::NCompressionMethod::kCompressed2:
|
||||
case NCompressionMethod::kCompressed2:
|
||||
{
|
||||
if (!arj2Decoder)
|
||||
arj2Decoder = new NCompress::NArj::NDecoder2::CCoder;
|
||||
@@ -765,7 +753,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
break;
|
||||
}
|
||||
default:
|
||||
opRes = NExtract::NOperationResult::kUnSupportedMethod;
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
}
|
||||
}
|
||||
if (opRes == NExtract::NOperationResult::kOK)
|
||||
@@ -788,10 +776,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static IInArchive *CreateArc() { return new CHandler; }
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"Arj", L"arj", 0, 4, { 0x60, 0xEA }, 2, false, CreateArc, 0 };
|
||||
{ "Arj", "arj", 0, 4,
|
||||
2, { kSig0, kSig1 },
|
||||
0,
|
||||
0,
|
||||
CreateArc, NULL, IsArc_Arj };
|
||||
|
||||
REGISTER_ARC(Arj)
|
||||
|
||||
|
||||
263
CPP/7zip/Archive/Bz2Handler.cpp
Executable file → Normal file
263
CPP/7zip/Archive/Bz2Handler.cpp
Executable file → Normal file
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "../../Common/ComTry.h"
|
||||
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
@@ -29,37 +29,70 @@ class CHandler:
|
||||
{
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CMyComPtr<ISequentialInStream> _seqStream;
|
||||
|
||||
bool _isArc;
|
||||
bool _needSeekToStart;
|
||||
bool _dataAfterEnd;
|
||||
bool _needMoreInput;
|
||||
|
||||
bool _packSize_Defined;
|
||||
bool _unpackSize_Defined;
|
||||
bool _numStreams_Defined;
|
||||
bool _numBlocks_Defined;
|
||||
|
||||
UInt64 _packSize;
|
||||
UInt64 _startPosition;
|
||||
bool _packSizeDefined;
|
||||
UInt64 _unpackSize;
|
||||
UInt64 _numStreams;
|
||||
UInt64 _numBlocks;
|
||||
|
||||
CSingleMethodProps _props;
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
|
||||
|
||||
MY_UNKNOWN_IMP4(
|
||||
IInArchive,
|
||||
IArchiveOpenSeq,
|
||||
IOutArchive,
|
||||
ISetProperties)
|
||||
INTERFACE_IInArchive(;)
|
||||
INTERFACE_IOutArchive(;)
|
||||
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
|
||||
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
|
||||
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
|
||||
|
||||
CHandler() { }
|
||||
};
|
||||
|
||||
static const STATPROPSTG kProps[] =
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
{ NULL, kpidPackSize, VT_UI8}
|
||||
kpidSize,
|
||||
kpidPackSize
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidNumStreams,
|
||||
kpidNumBlocks
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps_NO_Table
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
|
||||
case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;
|
||||
case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;
|
||||
case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;
|
||||
case kpidNumBlocks: if (_numBlocks_Defined) prop = _numBlocks; break;
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;;
|
||||
if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
|
||||
prop = v;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -71,54 +104,75 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
|
||||
case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;
|
||||
case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */)
|
||||
static const unsigned kSignatureCheckSize = 10;
|
||||
|
||||
API_FUNC_static_IsArc IsArc_BZip2(const Byte *p, size_t size)
|
||||
{
|
||||
if (size < kSignatureCheckSize)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
if (p[0] != 'B' || p[1] != 'Z' || p[2] != 'h' || p[3] < '1' || p[3] > '9')
|
||||
return k_IsArc_Res_NO;
|
||||
p += 4;
|
||||
if (NCompress::NBZip2::IsBlockSig(p))
|
||||
return k_IsArc_Res_YES;
|
||||
if (NCompress::NBZip2::IsEndSig(p))
|
||||
return k_IsArc_Res_YES;
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
try
|
||||
Close();
|
||||
{
|
||||
Close();
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPosition));
|
||||
const int kSignatureSize = 3;
|
||||
Byte buf[kSignatureSize];
|
||||
RINOK(ReadStream_FALSE(stream, buf, kSignatureSize));
|
||||
if (buf[0] != 'B' || buf[1] != 'Z' || buf[2] != 'h')
|
||||
Byte buf[kSignatureCheckSize];
|
||||
RINOK(ReadStream_FALSE(stream, buf, kSignatureCheckSize));
|
||||
if (IsArc_BZip2(buf, kSignatureCheckSize) == k_IsArc_Res_NO)
|
||||
return S_FALSE;
|
||||
|
||||
UInt64 endPosition;
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition));
|
||||
_packSize = endPosition - _startPosition;
|
||||
_packSizeDefined = true;
|
||||
_isArc = true;
|
||||
_stream = stream;
|
||||
_seqStream = stream;
|
||||
_needSeekToStart = true;
|
||||
}
|
||||
catch(...) { return S_FALSE; }
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
|
||||
{
|
||||
Close();
|
||||
_isArc = true;
|
||||
_seqStream = stream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_packSizeDefined = false;
|
||||
_isArc = false;
|
||||
_needSeekToStart = false;
|
||||
_dataAfterEnd = false;
|
||||
_needMoreInput = false;
|
||||
|
||||
_packSize_Defined = false;
|
||||
_unpackSize_Defined = false;
|
||||
_numStreams_Defined = false;
|
||||
_numBlocks_Defined = false;
|
||||
|
||||
_packSize = 0;
|
||||
|
||||
_seqStream.Release();
|
||||
_stream.Release();
|
||||
return S_OK;
|
||||
@@ -130,13 +184,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
COM_TRY_BEGIN
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
|
||||
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (_stream)
|
||||
if (_packSize_Defined)
|
||||
extractCallback->SetTotal(_packSize);
|
||||
UInt64 currentTotalPacked = 0;
|
||||
RINOK(extractCallback->SetCompleted(¤tTotalPacked));
|
||||
|
||||
// RINOK(extractCallback->SetCompleted(&packSize));
|
||||
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
@@ -147,14 +202,23 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
extractCallback->PrepareOperation(askMode);
|
||||
|
||||
|
||||
if (_needSeekToStart)
|
||||
{
|
||||
if (!_stream)
|
||||
return E_FAIL;
|
||||
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
else
|
||||
_needSeekToStart = true;
|
||||
|
||||
Int32 opRes;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
NCompress::NBZip2::CDecoder *decoderSpec = new NCompress::NBZip2::CDecoder;
|
||||
CMyComPtr<ICompressCoder> decoder = decoderSpec;
|
||||
|
||||
if (_stream)
|
||||
{
|
||||
RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
|
||||
decoderSpec->SetInStream(_seqStream);
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
@@ -172,43 +236,104 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, true);
|
||||
|
||||
UInt64 packSize = 0;
|
||||
UInt64 unpackedSize = 0;
|
||||
UInt64 numStreams = 0;
|
||||
|
||||
decoderSpec->InitNumBlocks();
|
||||
|
||||
HRESULT result = S_OK;
|
||||
|
||||
bool firstItem = true;
|
||||
for (;;)
|
||||
{
|
||||
lps->InSize = currentTotalPacked;
|
||||
lps->OutSize = outStreamSpec->GetSize();
|
||||
lps->InSize = packSize;
|
||||
lps->OutSize = unpackedSize;
|
||||
|
||||
RINOK(lps->SetCur());
|
||||
|
||||
bool isBz2;
|
||||
result = decoderSpec->CodeResume(outStream, isBz2, progress);
|
||||
result = decoderSpec->CodeResume(outStream, progress);
|
||||
|
||||
if (result != S_FALSE && result != S_OK)
|
||||
return result;
|
||||
|
||||
if (decoderSpec->IsBz)
|
||||
numStreams++;
|
||||
else if (numStreams == 0)
|
||||
{
|
||||
_isArc = false;
|
||||
result = S_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
unpackedSize = outStreamSpec->GetSize();
|
||||
UInt64 streamSize = decoderSpec->GetStreamSize();
|
||||
|
||||
if (streamSize == packSize)
|
||||
{
|
||||
// no new bytes in input stream, So it's good end of archive.
|
||||
result = S_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!decoderSpec->IsBz)
|
||||
{
|
||||
_dataAfterEnd = true;
|
||||
result = S_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (decoderSpec->Base.BitDecoder.ExtraBitsWereRead())
|
||||
{
|
||||
_needMoreInput = true;
|
||||
packSize = streamSize;
|
||||
result = S_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
packSize = decoderSpec->GetInputProcessedSize();
|
||||
|
||||
if (packSize > streamSize)
|
||||
return E_FAIL;
|
||||
|
||||
if (result != S_OK)
|
||||
break;
|
||||
if (!isBz2)
|
||||
{
|
||||
if (firstItem)
|
||||
result = S_FALSE;
|
||||
break;
|
||||
}
|
||||
firstItem = false;
|
||||
|
||||
_packSize = currentTotalPacked = decoderSpec->GetInputProcessedSize();
|
||||
_packSizeDefined = true;
|
||||
}
|
||||
|
||||
if (numStreams != 0)
|
||||
{
|
||||
_packSize = packSize;
|
||||
_unpackSize = unpackedSize;
|
||||
_numStreams = numStreams;
|
||||
_numBlocks = decoderSpec->GetNumBlocks();
|
||||
|
||||
_packSize_Defined = true;
|
||||
_unpackSize_Defined = true;
|
||||
_numStreams_Defined = true;
|
||||
_numBlocks_Defined = true;
|
||||
}
|
||||
|
||||
decoderSpec->ReleaseInStream();
|
||||
outStream.Release();
|
||||
|
||||
Int32 retResult;
|
||||
if (result == S_OK)
|
||||
retResult = NExtract::NOperationResult::kOK;
|
||||
if (!_isArc)
|
||||
opRes = NExtract::NOperationResult::kIsNotArc;
|
||||
else if (_needMoreInput)
|
||||
opRes = NExtract::NOperationResult::kUnexpectedEnd;
|
||||
else if (decoderSpec->CrcError)
|
||||
opRes = NExtract::NOperationResult::kCRCError;
|
||||
else if (_dataAfterEnd)
|
||||
opRes = NExtract::NOperationResult::kDataAfterEnd;
|
||||
else if (result == S_FALSE)
|
||||
retResult = NExtract::NOperationResult::kDataError;
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else if (result == S_OK)
|
||||
opRes = NExtract::NOperationResult::kOK;
|
||||
else
|
||||
return result;
|
||||
return extractCallback->SetOperationResult(retResult);
|
||||
|
||||
}
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
|
||||
return extractCallback->SetOperationResult(opRes);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
@@ -280,24 +405,24 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (indexInArchive != 0)
|
||||
return E_INVALIDARG;
|
||||
if (_stream)
|
||||
RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));
|
||||
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
return NCompress::CopyStream(_stream, outStream, NULL);
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
|
||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
return _props.SetProperties(names, values, numProps);
|
||||
}
|
||||
|
||||
static IInArchive *CreateArc() { return new CHandler; }
|
||||
#ifndef EXTRACT_ONLY
|
||||
static IOutArchive *CreateArcOut() { return new CHandler; }
|
||||
#else
|
||||
#define CreateArcOut 0
|
||||
#endif
|
||||
IMP_CreateArcIn
|
||||
IMP_CreateArcOut
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"bzip2", L"bz2 bzip2 tbz2 tbz", L"* * .tar .tar", 2, { 'B', 'Z', 'h' }, 3, true, CreateArc, CreateArcOut };
|
||||
{ "bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2,
|
||||
3, { 'B', 'Z', 'h' },
|
||||
0,
|
||||
NArcInfoFlags::kKeepName,
|
||||
REF_CreateArc_Pair, IsArc_BZip2 };
|
||||
|
||||
REGISTER_ARC(BZip2)
|
||||
|
||||
|
||||
193
CPP/7zip/Archive/Cab/CabBlockInStream.cpp
Executable file → Normal file
193
CPP/7zip/Archive/Cab/CabBlockInStream.cpp
Executable file → Normal file
@@ -3,8 +3,7 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/Alloc.h"
|
||||
|
||||
#include "Common/Defs.h"
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
@@ -17,173 +16,73 @@ static const UInt32 kBlockSize = (1 << 16);
|
||||
|
||||
bool CCabBlockInStream::Create()
|
||||
{
|
||||
if (!_buffer)
|
||||
_buffer = (Byte *)::MyAlloc(kBlockSize);
|
||||
return (_buffer != 0);
|
||||
if (!_buf)
|
||||
_buf = (Byte *)::MyAlloc(kBlockSize);
|
||||
return _buf != 0;
|
||||
}
|
||||
|
||||
CCabBlockInStream::~CCabBlockInStream()
|
||||
{
|
||||
MyFree(_buffer);
|
||||
::MyFree(_buf);
|
||||
}
|
||||
|
||||
class CCheckSum2
|
||||
static UInt32 CheckSum(const Byte *p, UInt32 size)
|
||||
{
|
||||
UInt32 m_Value;
|
||||
int m_Pos;
|
||||
Byte m_Hist[4];
|
||||
public:
|
||||
CCheckSum2(): m_Value(0){};
|
||||
void Init() { m_Value = 0; m_Pos = 0; }
|
||||
void Update(const void *data, UInt32 size);
|
||||
void FinishDataUpdate()
|
||||
UInt32 sum = 0;
|
||||
for (UInt32 i = size >> 2; i != 0; i--)
|
||||
{
|
||||
for (int i = 0; i < m_Pos; i++)
|
||||
m_Value ^= ((UInt32)(m_Hist[i])) << (8 * (m_Pos - i - 1));
|
||||
sum ^= GetUi32(p);
|
||||
p += 4;
|
||||
}
|
||||
void UpdateUInt32(UInt32 v) { m_Value ^= v; }
|
||||
UInt32 GetResult() const { return m_Value; }
|
||||
};
|
||||
|
||||
void CCheckSum2::Update(const void *data, UInt32 size)
|
||||
{
|
||||
UInt32 checkSum = m_Value;
|
||||
const Byte *dataPointer = (const Byte *)data;
|
||||
|
||||
while (size != 0 && m_Pos != 0)
|
||||
{
|
||||
m_Hist[m_Pos] = *dataPointer++;
|
||||
m_Pos = (m_Pos + 1) & 3;
|
||||
size--;
|
||||
if (m_Pos == 0)
|
||||
for (int i = 0; i < 4; i++)
|
||||
checkSum ^= ((UInt32)m_Hist[i]) << (8 * i);
|
||||
}
|
||||
|
||||
int numWords = size / 4;
|
||||
|
||||
while (numWords-- != 0)
|
||||
{
|
||||
UInt32 temp = *dataPointer++;
|
||||
temp |= ((UInt32)(*dataPointer++)) << 8;
|
||||
temp |= ((UInt32)(*dataPointer++)) << 16;
|
||||
temp |= ((UInt32)(*dataPointer++)) << 24;
|
||||
checkSum ^= temp;
|
||||
}
|
||||
m_Value = checkSum;
|
||||
|
||||
size &= 3;
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
m_Hist[m_Pos] = *dataPointer++;
|
||||
m_Pos = (m_Pos + 1) & 3;
|
||||
size--;
|
||||
}
|
||||
if (size > 2) sum ^= (UInt32)(*p++) << 16;
|
||||
if (size > 1) sum ^= (UInt32)(*p++) << 8;
|
||||
if (size > 0) sum ^= (UInt32)(*p++);
|
||||
return sum;
|
||||
}
|
||||
|
||||
static const UInt32 kDataBlockHeaderSize = 8;
|
||||
|
||||
class CTempCabInBuffer2
|
||||
HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize)
|
||||
{
|
||||
public:
|
||||
Byte Buffer[kDataBlockHeaderSize];
|
||||
UInt32 Pos;
|
||||
Byte ReadByte()
|
||||
{
|
||||
return Buffer[Pos++];
|
||||
}
|
||||
UInt32 ReadUInt32()
|
||||
{
|
||||
UInt32 value = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
value |= (((UInt32)ReadByte()) << (8 * i));
|
||||
return value;
|
||||
}
|
||||
UInt16 ReadUInt16()
|
||||
{
|
||||
UInt16 value = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
value |= (((UInt16)ReadByte()) << (8 * i));
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT CCabBlockInStream::PreRead(UInt32 &packSize, UInt32 &unpackSize)
|
||||
{
|
||||
CTempCabInBuffer2 inBuffer;
|
||||
inBuffer.Pos = 0;
|
||||
RINOK(ReadStream_FALSE(_stream, inBuffer.Buffer, kDataBlockHeaderSize))
|
||||
|
||||
UInt32 checkSum = inBuffer.ReadUInt32();
|
||||
packSize = inBuffer.ReadUInt16();
|
||||
unpackSize = inBuffer.ReadUInt16();
|
||||
if (ReservedSize != 0)
|
||||
{
|
||||
RINOK(ReadStream_FALSE(_stream, _buffer, ReservedSize));
|
||||
}
|
||||
_pos = 0;
|
||||
CCheckSum2 checkSumCalc;
|
||||
checkSumCalc.Init();
|
||||
UInt32 packSize2 = packSize;
|
||||
if (MsZip && _size == 0)
|
||||
{
|
||||
if (packSize < 2)
|
||||
return S_FALSE; // bad block;
|
||||
Byte sig[2];
|
||||
RINOK(ReadStream_FALSE(_stream, sig, 2));
|
||||
if (sig[0] != 0x43 || sig[1] != 0x4B)
|
||||
return S_FALSE;
|
||||
packSize2 -= 2;
|
||||
checkSumCalc.Update(sig, 2);
|
||||
}
|
||||
|
||||
if (kBlockSize - _size < packSize2)
|
||||
const UInt32 kHeaderSize = 8;
|
||||
const UInt32 kReservedMax = 256;
|
||||
Byte header[kHeaderSize + kReservedMax];
|
||||
RINOK(ReadStream_FALSE(stream, header, kHeaderSize + ReservedSize))
|
||||
packSize = GetUi16(header + 4);
|
||||
unpackSize = GetUi16(header + 6);
|
||||
if (packSize > kBlockSize - _size)
|
||||
return S_FALSE;
|
||||
|
||||
UInt32 curSize = packSize2;
|
||||
if (curSize != 0)
|
||||
RINOK(ReadStream_FALSE(stream, _buf + _size, packSize));
|
||||
|
||||
if (MsZip)
|
||||
{
|
||||
size_t processedSizeLoc = curSize;
|
||||
RINOK(ReadStream(_stream, _buffer + _size, &processedSizeLoc));
|
||||
checkSumCalc.Update(_buffer + _size, (UInt32)processedSizeLoc);
|
||||
_size += (UInt32)processedSizeLoc;
|
||||
if (processedSizeLoc != curSize)
|
||||
if (_size == 0)
|
||||
{
|
||||
if (packSize < 2 || _buf[0] != 0x43 || _buf[1] != 0x4B)
|
||||
return S_FALSE;
|
||||
_pos = 2;
|
||||
}
|
||||
if (_size + packSize > ((UInt32)1 << 15) + 12) /* v9.31 fix. MSZIP specification */
|
||||
return S_FALSE;
|
||||
}
|
||||
TotalPackSize = _size;
|
||||
|
||||
checkSumCalc.FinishDataUpdate();
|
||||
|
||||
bool dataError;
|
||||
if (checkSum == 0)
|
||||
dataError = false;
|
||||
else
|
||||
{
|
||||
checkSumCalc.UpdateUInt32(packSize | (((UInt32)unpackSize) << 16));
|
||||
dataError = (checkSumCalc.GetResult() != checkSum);
|
||||
}
|
||||
DataError |= dataError;
|
||||
return dataError ? S_FALSE : S_OK;
|
||||
if (GetUi32(header) != 0) // checkSum
|
||||
if (CheckSum(header, kHeaderSize + ReservedSize) != CheckSum(_buf + _size, packSize))
|
||||
return S_FALSE;
|
||||
|
||||
_size += packSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize != 0)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (_size != 0)
|
||||
{
|
||||
size = MyMin(_size, size);
|
||||
memmove(data, _buffer + _pos, size);
|
||||
_pos += size;
|
||||
_size -= size;
|
||||
if (processedSize != 0)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK; // no blocks data
|
||||
UInt32 rem = _size - _pos;
|
||||
if (size > rem)
|
||||
size = rem;
|
||||
memcpy(data, _buf + _pos, size);
|
||||
_pos += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
33
CPP/7zip/Archive/Cab/CabBlockInStream.h
Executable file → Normal file
33
CPP/7zip/Archive/Cab/CabBlockInStream.h
Executable file → Normal file
@@ -1,9 +1,9 @@
|
||||
// CabBlockInStream.cpp
|
||||
// CabBlockInStream.h
|
||||
|
||||
#ifndef __CABBLOCKINSTREAM_H
|
||||
#define __CABBLOCKINSTREAM_H
|
||||
#ifndef __CAB_BLOCK_IN_STREAM_H
|
||||
#define __CAB_BLOCK_IN_STREAM_H
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../IStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
@@ -13,30 +13,23 @@ class CCabBlockInStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
Byte *_buffer;
|
||||
UInt32 _pos;
|
||||
Byte *_buf;
|
||||
UInt32 _size;
|
||||
UInt32 _pos;
|
||||
|
||||
public:
|
||||
UInt32 TotalPackSize;
|
||||
UInt32 ReservedSize;
|
||||
bool DataError;
|
||||
UInt32 ReservedSize; // < 256
|
||||
bool MsZip;
|
||||
|
||||
CCabBlockInStream(): _buffer(0), ReservedSize(0), MsZip(false), DataError(false), TotalPackSize(0) {}
|
||||
~CCabBlockInStream();
|
||||
bool Create();
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
|
||||
void InitForNewFolder() { TotalPackSize = 0; }
|
||||
void InitForNewBlock() { _size = 0; }
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
CCabBlockInStream(): _buf(0), ReservedSize(0), MsZip(false) {}
|
||||
~CCabBlockInStream();
|
||||
bool Create();
|
||||
void InitForNewBlock() { _size = 0; _pos = 0; }
|
||||
HRESULT PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize);
|
||||
|
||||
HRESULT PreRead(UInt32 &packSize, UInt32 &unpackSize);
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
518
CPP/7zip/Archive/Cab/CabHandler.cpp
Executable file → Normal file
518
CPP/7zip/Archive/Cab/CabHandler.cpp
Executable file → Normal file
@@ -2,15 +2,17 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
#include "../../../../C/Alloc.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/IntToString.h"
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/UTFConvert.h"
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/IntToString.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
#include "../../../Common/UTFConvert.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/Time.h"
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
#include "../../../Windows/TimeUtils.h"
|
||||
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
@@ -39,102 +41,243 @@ enum
|
||||
};
|
||||
#endif
|
||||
|
||||
static STATPROPSTG kProps[] =
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidSize, VT_UI8},
|
||||
{ NULL, kpidMTime, VT_FILETIME},
|
||||
{ NULL, kpidAttrib, VT_UI4},
|
||||
{ NULL, kpidMethod, VT_BSTR},
|
||||
{ NULL, kpidBlock, VT_I4}
|
||||
kpidPath,
|
||||
kpidSize,
|
||||
kpidMTime,
|
||||
kpidAttrib,
|
||||
kpidMethod,
|
||||
kpidBlock
|
||||
#ifdef _CAB_DETAILS
|
||||
,
|
||||
{ L"BlockReal", kpidBlockReal, VT_UI4},
|
||||
{ NULL, kpidOffset, VT_UI4},
|
||||
{ NULL, kpidVolume, VT_UI4}
|
||||
// kpidBlockReal, // L"BlockReal",
|
||||
kpidOffset,
|
||||
kpidVolume
|
||||
#endif
|
||||
};
|
||||
|
||||
static const char *kMethods[] =
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
"None",
|
||||
"MSZip",
|
||||
"Quantum",
|
||||
"LZX"
|
||||
};
|
||||
|
||||
static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
|
||||
static const char *kUnknownMethod = "Unknown";
|
||||
|
||||
static STATPROPSTG kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidMethod, VT_BSTR},
|
||||
// { NULL, kpidSolid, VT_BOOL},
|
||||
{ NULL, kpidNumBlocks, VT_UI4},
|
||||
{ NULL, kpidNumVolumes, VT_UI4}
|
||||
kpidTotalPhySize,
|
||||
kpidMethod,
|
||||
// kpidSolid,
|
||||
kpidNumBlocks,
|
||||
kpidNumVolumes,
|
||||
kpidVolumeIndex,
|
||||
kpidId
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
static const char *kMethods[] =
|
||||
{
|
||||
"None"
|
||||
, "MSZip"
|
||||
, "Quantum"
|
||||
, "LZX"
|
||||
};
|
||||
|
||||
static const unsigned kMethodNameBufSize = 32; // "Quantum:255"
|
||||
|
||||
static void SetMethodName(char *s, unsigned method, unsigned param)
|
||||
{
|
||||
if (method < ARRAY_SIZE(kMethods))
|
||||
{
|
||||
s = MyStpCpy(s, kMethods[method]);
|
||||
if (method != NHeader::NMethod::kLZX &&
|
||||
method != NHeader::NMethod::kQuantum)
|
||||
return;
|
||||
*s++ = ':';
|
||||
method = param;
|
||||
}
|
||||
ConvertUInt32ToString(method, s);
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidMethod:
|
||||
{
|
||||
AString resString;
|
||||
CRecordVector<Byte> ids;
|
||||
int i;
|
||||
for (int v = 0; v < m_Database.Volumes.Size(); v++)
|
||||
UInt32 mask = 0;
|
||||
UInt32 params[2] = { 0, 0 };
|
||||
{
|
||||
const CDatabaseEx &de = m_Database.Volumes[v];
|
||||
for (i = 0; i < de.Folders.Size(); i++)
|
||||
ids.AddToUniqueSorted(de.Folders[i].GetCompressionMethod());
|
||||
FOR_VECTOR (v, m_Database.Volumes)
|
||||
{
|
||||
const CRecordVector<CFolder> &folders = m_Database.Volumes[v].Folders;
|
||||
FOR_VECTOR (i, folders)
|
||||
{
|
||||
const CFolder &folder = folders[i];
|
||||
unsigned method = folder.GetMethod();
|
||||
mask |= ((UInt32)1 << method);
|
||||
if (method == NHeader::NMethod::kLZX ||
|
||||
method == NHeader::NMethod::kQuantum)
|
||||
{
|
||||
unsigned di = (method == NHeader::NMethod::kQuantum) ? 0 : 1;
|
||||
if (params[di] < folder.MethodMinor)
|
||||
params[di] = folder.MethodMinor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ids.Size(); i++)
|
||||
AString s;
|
||||
for (unsigned i = 0; i < kNumMethodsMax; i++)
|
||||
{
|
||||
Byte id = ids[i];
|
||||
AString method = (id < kNumMethods) ? kMethods[id] : kUnknownMethod;
|
||||
if (!resString.IsEmpty())
|
||||
resString += ' ';
|
||||
resString += method;
|
||||
if ((mask & (1 << i)) == 0)
|
||||
continue;
|
||||
if (!s.IsEmpty())
|
||||
s += ' ';
|
||||
char temp[kMethodNameBufSize];
|
||||
SetMethodName(temp, i, params[i == NHeader::NMethod::kQuantum ? 0 : 1]);
|
||||
s += temp;
|
||||
}
|
||||
prop = resString;
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
// case kpidSolid: prop = _database.IsSolid(); break;
|
||||
case kpidNumBlocks:
|
||||
{
|
||||
UInt32 numFolders = 0;
|
||||
for (int v = 0; v < m_Database.Volumes.Size(); v++)
|
||||
FOR_VECTOR (v, m_Database.Volumes)
|
||||
numFolders += m_Database.Volumes[v].Folders.Size();
|
||||
prop = numFolders;
|
||||
break;
|
||||
}
|
||||
case kpidNumVolumes:
|
||||
|
||||
case kpidTotalPhySize:
|
||||
{
|
||||
prop = (UInt32)m_Database.Volumes.Size();
|
||||
if (m_Database.Volumes.Size() > 1)
|
||||
{
|
||||
UInt64 sum = 0;
|
||||
FOR_VECTOR (v, m_Database.Volumes)
|
||||
sum += m_Database.Volumes[v].ArcInfo.Size;
|
||||
prop = sum;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidNumVolumes:
|
||||
prop = (UInt32)m_Database.Volumes.Size();
|
||||
break;
|
||||
|
||||
case kpidVolumeIndex:
|
||||
{
|
||||
if (m_Database.Volumes.Size() == 1)
|
||||
{
|
||||
const CDatabaseEx &db = m_Database.Volumes[0];
|
||||
const CInArcInfo &ai = db.ArcInfo;
|
||||
prop = (UInt32)ai.CabinetNumber;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidId:
|
||||
{
|
||||
if (m_Database.Volumes.Size() != 0)
|
||||
{
|
||||
prop = (UInt32)m_Database.Volumes[0].ArcInfo.SetID;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidOffset:
|
||||
/*
|
||||
if (m_Database.Volumes.Size() == 1)
|
||||
prop = m_Database.Volumes[0].StartPosition;
|
||||
*/
|
||||
prop = _offset;
|
||||
break;
|
||||
|
||||
case kpidPhySize:
|
||||
/*
|
||||
if (m_Database.Volumes.Size() == 1)
|
||||
prop = (UInt64)m_Database.Volumes[0].ArcInfo.Size;
|
||||
*/
|
||||
prop = (UInt64)_phySize;
|
||||
break;
|
||||
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
if (_errorInHeaders) v |= kpv_ErrorFlags_HeadersError;
|
||||
if (_unexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidError:
|
||||
if (!_errorMessage.IsEmpty())
|
||||
prop = _errorMessage;
|
||||
break;
|
||||
|
||||
case kpidName:
|
||||
{
|
||||
if (m_Database.Volumes.Size() == 1)
|
||||
{
|
||||
const CDatabaseEx &db = m_Database.Volumes[0];
|
||||
const CInArcInfo &ai = db.ArcInfo;
|
||||
if (ai.SetID != 0)
|
||||
{
|
||||
AString s;
|
||||
char temp[32];
|
||||
ConvertUInt32ToString(ai.SetID, temp);
|
||||
s += temp;
|
||||
ConvertUInt32ToString(ai.CabinetNumber + 1, temp);
|
||||
s += '_';
|
||||
s += temp;
|
||||
s += ".cab";
|
||||
prop = s;
|
||||
}
|
||||
/*
|
||||
// that code is incomplete. It gcan give accurate name of volume
|
||||
char s[32];
|
||||
ConvertUInt32ToString(ai.CabinetNumber + 2, s);
|
||||
unsigned len = MyStringLen(s);
|
||||
if (ai.IsThereNext())
|
||||
{
|
||||
AString fn = ai.NextArc.FileName;
|
||||
if (fn.Len() > 4 && StringsAreEqualNoCase_Ascii(fn.RightPtr(4), ".cab"))
|
||||
fn.DeleteFrom(fn.Len() - 4);
|
||||
if (len < fn.Len())
|
||||
{
|
||||
if (strcmp(s, fn.RightPtr(len)) == 0)
|
||||
{
|
||||
AString s2 = fn;
|
||||
s2.DeleteFrom(fn.Len() - len);
|
||||
ConvertUInt32ToString(ai.CabinetNumber + 1, s);
|
||||
s2 += s;
|
||||
s2 += ".cab";
|
||||
prop = GetUnicodeString(s2);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// case kpidShortComment:
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
NCOM::CPropVariant prop;
|
||||
|
||||
const CMvItem &mvItem = m_Database.Items[index];
|
||||
const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];
|
||||
int itemIndex = mvItem.ItemIndex;
|
||||
unsigned itemIndex = mvItem.ItemIndex;
|
||||
const CItem &item = db.Items[itemIndex];
|
||||
switch(propID)
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath:
|
||||
{
|
||||
@@ -146,9 +289,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
prop = (const wchar_t *)NItemName::WinNameToOSName(unicodeName);
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidIsDir: prop = item.IsDir(); break;
|
||||
case kpidSize: prop = item.Size; break;
|
||||
case kpidAttrib: prop = item.GetWinAttributes(); break;
|
||||
case kpidAttrib: prop = item.GetWinAttrib(); break;
|
||||
|
||||
case kpidMTime:
|
||||
{
|
||||
@@ -168,24 +312,17 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
{
|
||||
UInt32 realFolderIndex = item.GetFolderIndex(db.Folders.Size());
|
||||
const CFolder &folder = db.Folders[realFolderIndex];
|
||||
int methodIndex = folder.GetCompressionMethod();
|
||||
AString method = (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
|
||||
if (methodIndex == NHeader::NCompressionMethodMajor::kLZX ||
|
||||
methodIndex == NHeader::NCompressionMethodMajor::kQuantum)
|
||||
{
|
||||
method += ':';
|
||||
char temp[32];
|
||||
ConvertUInt64ToString(folder.CompressionTypeMinor, temp);
|
||||
method += temp;
|
||||
}
|
||||
prop = method;
|
||||
char s[kMethodNameBufSize];;
|
||||
SetMethodName(s, folder.GetMethod(), folder.MethodMinor);
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidBlock: prop = (Int32)m_Database.GetFolderIndex(&mvItem); break;
|
||||
|
||||
#ifdef _CAB_DETAILS
|
||||
|
||||
case kpidBlockReal: prop = (UInt32)item.FolderIndex; break;
|
||||
// case kpidBlockReal: prop = (UInt32)item.FolderIndex; break;
|
||||
case kpidOffset: prop = (UInt32)item.Offset; break;
|
||||
case kpidVolume: prop = (UInt32)mvItem.VolumeIndex; break;
|
||||
|
||||
@@ -196,39 +333,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
/*
|
||||
class CProgressImp: public CProgressVirt
|
||||
{
|
||||
CMyComPtr<IArchiveOpenCallback> m_OpenArchiveCallback;
|
||||
public:
|
||||
STDMETHOD(SetTotal)(const UInt64 *numFiles);
|
||||
STDMETHOD(SetCompleted)(const UInt64 *numFiles);
|
||||
void Init(IArchiveOpenCallback *openArchiveCallback)
|
||||
{ m_OpenArchiveCallback = openArchiveCallback; }
|
||||
};
|
||||
|
||||
STDMETHODIMP CProgressImp::SetTotal(const UInt64 *numFiles)
|
||||
{
|
||||
if (m_OpenArchiveCallback)
|
||||
return m_OpenArchiveCallback->SetCompleted(numFiles, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CProgressImp::SetCompleted(const UInt64 *numFiles)
|
||||
{
|
||||
if (m_OpenArchiveCallback)
|
||||
return m_OpenArchiveCallback->SetCompleted(numFiles, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *callback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
HRESULT res = S_FALSE;
|
||||
|
||||
CInArchive archive;
|
||||
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
|
||||
callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
|
||||
@@ -236,96 +347,169 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
CMyComPtr<IInStream> nextStream = inStream;
|
||||
bool prevChecked = false;
|
||||
UInt64 numItems = 0;
|
||||
try
|
||||
unsigned numTempVolumes = 0;
|
||||
// try
|
||||
{
|
||||
while (nextStream != 0)
|
||||
while (nextStream != NULL)
|
||||
{
|
||||
CDatabaseEx db;
|
||||
db.Stream = nextStream;
|
||||
res = archive.Open(maxCheckStartPosition, db);
|
||||
if (res == S_OK)
|
||||
HRESULT res = archive.Open(db, maxCheckStartPosition);
|
||||
_errorInHeaders |= archive.HeaderError;
|
||||
_errorInHeaders |= archive.ErrorInNames;
|
||||
_unexpectedEnd |= archive.UnexpectedEnd;
|
||||
|
||||
if (res == S_OK && !m_Database.Volumes.IsEmpty())
|
||||
{
|
||||
if (!m_Database.Volumes.IsEmpty())
|
||||
const CArchInfo &lastArc = m_Database.Volumes.Back().ArcInfo;
|
||||
unsigned cabNumber = db.ArcInfo.CabinetNumber;
|
||||
if (lastArc.SetID != db.ArcInfo.SetID)
|
||||
res = S_FALSE;
|
||||
else if (prevChecked)
|
||||
{
|
||||
const CDatabaseEx &dbPrev = m_Database.Volumes[prevChecked ? m_Database.Volumes.Size() - 1 : 0];
|
||||
if (dbPrev.ArchiveInfo.SetID != db.ArchiveInfo.SetID ||
|
||||
dbPrev.ArchiveInfo.CabinetNumber + (prevChecked ? 1: - 1) !=
|
||||
db.ArchiveInfo.CabinetNumber)
|
||||
if (cabNumber != lastArc.CabinetNumber + 1)
|
||||
res = S_FALSE;
|
||||
}
|
||||
else if (cabNumber >= lastArc.CabinetNumber)
|
||||
res = S_FALSE;
|
||||
else if (numTempVolumes != 0)
|
||||
{
|
||||
const CArchInfo &prevArc = m_Database.Volumes[numTempVolumes - 1].ArcInfo;
|
||||
if (cabNumber != prevArc.CabinetNumber + 1)
|
||||
res = S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (archive.IsArc || res == S_OK)
|
||||
{
|
||||
_isArc = true;
|
||||
if (m_Database.Volumes.IsEmpty())
|
||||
{
|
||||
_offset = db.StartPosition;
|
||||
_phySize = db.ArcInfo.Size;
|
||||
}
|
||||
}
|
||||
|
||||
if (res == S_OK)
|
||||
m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : 0, db);
|
||||
else if (res != S_FALSE)
|
||||
return res;
|
||||
{
|
||||
numItems += db.Items.Size();
|
||||
m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : numTempVolumes, db);
|
||||
if (!prevChecked && m_Database.Volumes.Size() > 1)
|
||||
{
|
||||
numTempVolumes++;
|
||||
if (db.ArcInfo.CabinetNumber + 1 == m_Database.Volumes[numTempVolumes].ArcInfo.CabinetNumber)
|
||||
numTempVolumes = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (res != S_FALSE)
|
||||
return res;
|
||||
if (m_Database.Volumes.IsEmpty())
|
||||
return S_FALSE;
|
||||
if (prevChecked)
|
||||
break;
|
||||
prevChecked = true;
|
||||
if (numTempVolumes != 0)
|
||||
{
|
||||
m_Database.Volumes.DeleteFrontal(numTempVolumes);
|
||||
numTempVolumes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
numItems += db.Items.Size();
|
||||
RINOK(callback->SetCompleted(&numItems, NULL));
|
||||
|
||||
nextStream = 0;
|
||||
nextStream = NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const COtherArchive *otherArchive = 0;
|
||||
const COtherArc *otherArc = NULL;
|
||||
if (!prevChecked)
|
||||
{
|
||||
const CInArchiveInfo &ai = m_Database.Volumes.Front().ArchiveInfo;
|
||||
if (ai.IsTherePrev())
|
||||
otherArchive = &ai.PrevArc;
|
||||
if (numTempVolumes == 0)
|
||||
{
|
||||
const CInArcInfo &ai = m_Database.Volumes[0].ArcInfo;
|
||||
if (ai.IsTherePrev())
|
||||
otherArc = &ai.PrevArc;
|
||||
else
|
||||
prevChecked = true;
|
||||
}
|
||||
else
|
||||
prevChecked = true;
|
||||
{
|
||||
const CInArcInfo &ai = m_Database.Volumes[numTempVolumes - 1].ArcInfo;
|
||||
if (ai.IsThereNext())
|
||||
otherArc = &ai.NextArc;
|
||||
else
|
||||
{
|
||||
prevChecked = true;
|
||||
m_Database.Volumes.DeleteFrontal(numTempVolumes);
|
||||
numTempVolumes = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (otherArchive == 0)
|
||||
if (!otherArc)
|
||||
{
|
||||
const CInArchiveInfo &ai = m_Database.Volumes.Back().ArchiveInfo;
|
||||
const CInArcInfo &ai = m_Database.Volumes.Back().ArcInfo;
|
||||
if (ai.IsThereNext())
|
||||
otherArchive = &ai.NextArc;
|
||||
otherArc = &ai.NextArc;
|
||||
}
|
||||
if (!otherArchive)
|
||||
if (!otherArc)
|
||||
break;
|
||||
const UString fullName = MultiByteToUnicodeString(otherArchive->FileName, CP_ACP);
|
||||
if (!openVolumeCallback)
|
||||
break;
|
||||
|
||||
// printf("\n%s", otherArc->FileName);
|
||||
const UString fullName = MultiByteToUnicodeString(otherArc->FileName, CP_ACP);
|
||||
HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);
|
||||
if (result == S_OK)
|
||||
break;
|
||||
if (result != S_FALSE)
|
||||
return result;
|
||||
|
||||
if (!_errorMessage.IsEmpty())
|
||||
_errorMessage += L"\n";
|
||||
_errorMessage += L"Can't open volume: ";
|
||||
_errorMessage += fullName;
|
||||
|
||||
if (prevChecked)
|
||||
break;
|
||||
prevChecked = true;
|
||||
if (numTempVolumes != 0)
|
||||
{
|
||||
m_Database.Volumes.DeleteFrontal(numTempVolumes);
|
||||
numTempVolumes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // read nextStream iteration
|
||||
|
||||
if (numTempVolumes != 0)
|
||||
{
|
||||
m_Database.Volumes.DeleteFrontal(numTempVolumes);
|
||||
numTempVolumes = 0;
|
||||
}
|
||||
if (res == S_OK)
|
||||
if (m_Database.Volumes.IsEmpty())
|
||||
return S_FALSE;
|
||||
else
|
||||
{
|
||||
m_Database.FillSortAndShrink();
|
||||
if (!m_Database.Check())
|
||||
res = S_FALSE;
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
res = S_FALSE;
|
||||
}
|
||||
if (res != S_OK)
|
||||
{
|
||||
Close();
|
||||
return res;
|
||||
}
|
||||
COM_TRY_END
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_errorMessage.Empty();
|
||||
_isArc = false;
|
||||
_errorInHeaders = false;
|
||||
_unexpectedEnd = false;
|
||||
// _mainVolIndex = -1;
|
||||
_phySize = 0;
|
||||
_offset = 0;
|
||||
|
||||
m_Database.Clear();
|
||||
return S_OK;
|
||||
}
|
||||
@@ -348,8 +532,8 @@ private:
|
||||
bool TempBufMode;
|
||||
UInt32 m_BufStartFolderOffset;
|
||||
|
||||
int m_StartIndex;
|
||||
int m_CurrentIndex;
|
||||
unsigned m_StartIndex;
|
||||
unsigned m_CurrentIndex;
|
||||
CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;
|
||||
bool m_TestMode;
|
||||
|
||||
@@ -379,7 +563,7 @@ public:
|
||||
void Init(
|
||||
const CMvDatabaseEx *database,
|
||||
const CRecordVector<bool> *extractStatuses,
|
||||
int startIndex,
|
||||
unsigned startIndex,
|
||||
UInt64 folderSize,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
bool testMode);
|
||||
@@ -393,7 +577,7 @@ public:
|
||||
void CFolderOutStream::Init(
|
||||
const CMvDatabaseEx *database,
|
||||
const CRecordVector<bool> *extractStatuses,
|
||||
int startIndex,
|
||||
unsigned startIndex,
|
||||
UInt64 folderSize,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
bool testMode)
|
||||
@@ -436,7 +620,7 @@ HRESULT CFolderOutStream::OpenFile()
|
||||
const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
|
||||
const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
|
||||
int numExtractItems = 0;
|
||||
int curIndex;
|
||||
unsigned curIndex;
|
||||
for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++)
|
||||
{
|
||||
const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex];
|
||||
@@ -559,7 +743,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
|
||||
|
||||
if (!TempBuf && TempBufMode && m_RealOutStream)
|
||||
{
|
||||
RINOK(CloseFileWithResOp(NExtract::NOperationResult::kUnSupportedMethod));
|
||||
RINOK(CloseFileWithResOp(NExtract::NOperationResult::kUnsupportedMethod));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -638,7 +822,7 @@ HRESULT CFolderOutStream::Unsupported()
|
||||
if (result != S_FALSE && result != S_OK)
|
||||
return result;
|
||||
m_RealOutStream.Release();
|
||||
RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
|
||||
RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
|
||||
m_CurrentIndex++;
|
||||
}
|
||||
return S_OK;
|
||||
@@ -649,7 +833,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == (UInt32)-1);
|
||||
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = m_Database.Items.Size();
|
||||
if (numItems == 0)
|
||||
@@ -709,7 +893,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
const CMvItem &mvItem = m_Database.Items[index];
|
||||
const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];
|
||||
int itemIndex = mvItem.ItemIndex;
|
||||
unsigned itemIndex = mvItem.ItemIndex;
|
||||
const CItem &item = db.Items[itemIndex];
|
||||
|
||||
i++;
|
||||
@@ -747,7 +931,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
extractStatuses.Add(true);
|
||||
startIndex++;
|
||||
UInt64 curUnpack = item.GetEndOffset();
|
||||
for(;i < numItems; i++)
|
||||
for (; i < numItems; i++)
|
||||
{
|
||||
int indexNext = allFilesMode ? i : indices[i];
|
||||
const CMvItem &mvItem = m_Database.Items[indexNext];
|
||||
@@ -779,11 +963,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
cabBlockInStreamSpec->MsZip = false;
|
||||
HRESULT res = S_OK;
|
||||
switch(folder.GetCompressionMethod())
|
||||
switch (folder.GetMethod())
|
||||
{
|
||||
case NHeader::NCompressionMethodMajor::kNone:
|
||||
case NHeader::NMethod::kNone:
|
||||
break;
|
||||
case NHeader::NCompressionMethodMajor::kMSZip:
|
||||
case NHeader::NMethod::kMSZip:
|
||||
if (!deflateDecoder)
|
||||
{
|
||||
deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder;
|
||||
@@ -791,21 +975,21 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
}
|
||||
cabBlockInStreamSpec->MsZip = true;
|
||||
break;
|
||||
case NHeader::NCompressionMethodMajor::kLZX:
|
||||
case NHeader::NMethod::kLZX:
|
||||
if (!lzxDecoder)
|
||||
{
|
||||
lzxDecoderSpec = new NCompress::NLzx::CDecoder;
|
||||
lzxDecoder = lzxDecoderSpec;
|
||||
}
|
||||
res = lzxDecoderSpec->SetParams(folder.CompressionTypeMinor);
|
||||
res = lzxDecoderSpec->SetParams(folder.MethodMinor);
|
||||
break;
|
||||
case NHeader::NCompressionMethodMajor::kQuantum:
|
||||
case NHeader::NMethod::kQuantum:
|
||||
if (!quantumDecoder)
|
||||
{
|
||||
quantumDecoderSpec = new NCompress::NQuantum::CDecoder;
|
||||
quantumDecoder = quantumDecoderSpec;
|
||||
}
|
||||
res = quantumDecoderSpec->SetParams(folder.CompressionTypeMinor);
|
||||
res = quantumDecoderSpec->SetParams(folder.MethodMinor);
|
||||
break;
|
||||
default:
|
||||
res = E_INVALIDARG;
|
||||
@@ -820,9 +1004,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
}
|
||||
RINOK(res);
|
||||
|
||||
cabBlockInStreamSpec->InitForNewFolder();
|
||||
{
|
||||
int volIndex = mvItem.VolumeIndex;
|
||||
unsigned volIndex = mvItem.VolumeIndex;
|
||||
int locFolderIndex = item.GetFolderIndex(db.Folders.Size());
|
||||
bool keepHistory = false;
|
||||
bool keepInputBuffer = false;
|
||||
@@ -838,8 +1021,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
const CFolder &folder = db.Folders[locFolderIndex];
|
||||
if (f == 0)
|
||||
{
|
||||
cabBlockInStreamSpec->SetStream(db.Stream);
|
||||
cabBlockInStreamSpec->ReservedSize = db.ArchiveInfo.GetDataBlockReserveSize();
|
||||
cabBlockInStreamSpec->ReservedSize = db.ArcInfo.GetDataBlockReserveSize();
|
||||
RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
if (f == folder.NumDataBlocks)
|
||||
@@ -851,13 +1033,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
}
|
||||
f++;
|
||||
|
||||
cabBlockInStreamSpec->DataError = false;
|
||||
|
||||
if (!keepInputBuffer)
|
||||
cabBlockInStreamSpec->InitForNewBlock();
|
||||
|
||||
UInt32 packSize, unpackSize;
|
||||
res = cabBlockInStreamSpec->PreRead(packSize, unpackSize);
|
||||
res = cabBlockInStreamSpec->PreRead(db.Stream, packSize, unpackSize);
|
||||
if (res == S_FALSE)
|
||||
break;
|
||||
RINOK(res);
|
||||
@@ -878,22 +1058,36 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if (unpackRemain > kBlockSizeMax)
|
||||
unpackRemain = kBlockSizeMax;
|
||||
if (unpackRemain > unpackSize)
|
||||
unpackRemain = unpackSize;
|
||||
unpackRemain = unpackSize;
|
||||
|
||||
switch(folder.GetCompressionMethod())
|
||||
switch (folder.GetMethod())
|
||||
{
|
||||
case NHeader::NCompressionMethodMajor::kNone:
|
||||
case NHeader::NMethod::kNone:
|
||||
res = copyCoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
|
||||
break;
|
||||
case NHeader::NCompressionMethodMajor::kMSZip:
|
||||
deflateDecoderSpec->SetKeepHistory(keepHistory);
|
||||
case NHeader::NMethod::kMSZip:
|
||||
deflateDecoderSpec->Set_KeepHistory(keepHistory);
|
||||
/* v9.31: now we follow MSZIP specification that requires to finish deflate stream at the end of each block.
|
||||
But PyCabArc can create CAB archives that doesn't have finish marker at the end of block.
|
||||
Cabarc probably ignores such errors in cab archives.
|
||||
Maybe we also should ignore that error?
|
||||
Or we should extract full file and show the warning? */
|
||||
deflateDecoderSpec->Set_NeedFinishInput(true);
|
||||
res = deflateDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
|
||||
if (res == S_OK)
|
||||
{
|
||||
if (!deflateDecoderSpec->IsFinished())
|
||||
res = S_FALSE;
|
||||
if (!deflateDecoderSpec->IsFinalBlock())
|
||||
res = S_FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
case NHeader::NCompressionMethodMajor::kLZX:
|
||||
case NHeader::NMethod::kLZX:
|
||||
lzxDecoderSpec->SetKeepHistory(keepHistory);
|
||||
res = lzxDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
|
||||
break;
|
||||
case NHeader::NCompressionMethodMajor::kQuantum:
|
||||
case NHeader::NMethod::kQuantum:
|
||||
quantumDecoderSpec->SetKeepHistory(keepHistory);
|
||||
res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
|
||||
break;
|
||||
|
||||
11
CPP/7zip/Archive/Cab/CabHandler.h
Executable file → Normal file
11
CPP/7zip/Archive/Cab/CabHandler.h
Executable file → Normal file
@@ -3,8 +3,10 @@
|
||||
#ifndef __CAB_HANDLER_H
|
||||
#define __CAB_HANDLER_H
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../IArchive.h"
|
||||
|
||||
#include "CabIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
@@ -21,6 +23,13 @@ public:
|
||||
|
||||
private:
|
||||
CMvDatabaseEx m_Database;
|
||||
UString _errorMessage;
|
||||
bool _isArc;
|
||||
bool _errorInHeaders;
|
||||
bool _unexpectedEnd;
|
||||
// int _mainVolIndex;
|
||||
UInt32 _phySize;
|
||||
UInt64 _offset;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
0
CPP/7zip/Archive/Cab/CabHeader.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Cab/CabHeader.cpp
Executable file → Normal file
23
CPP/7zip/Archive/Cab/CabHeader.h
Executable file → Normal file
23
CPP/7zip/Archive/Cab/CabHeader.h
Executable file → Normal file
@@ -3,7 +3,7 @@
|
||||
#ifndef __ARCHIVE_CAB_HEADER_H
|
||||
#define __ARCHIVE_CAB_HEADER_H
|
||||
|
||||
#include "Common/Types.h"
|
||||
#include "../../../Common/MyTypes.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
@@ -12,17 +12,14 @@ namespace NHeader {
|
||||
const unsigned kMarkerSize = 8;
|
||||
extern Byte kMarker[kMarkerSize];
|
||||
|
||||
namespace NArchive
|
||||
namespace NArcFlags
|
||||
{
|
||||
namespace NFlags
|
||||
{
|
||||
const int kPrevCabinet = 0x0001;
|
||||
const int kNextCabinet = 0x0002;
|
||||
const int kReservePresent = 0x0004;
|
||||
}
|
||||
const unsigned kPrevCabinet = 1;
|
||||
const unsigned kNextCabinet = 2;
|
||||
const unsigned kReservePresent = 4;
|
||||
}
|
||||
|
||||
namespace NCompressionMethodMajor
|
||||
namespace NMethod
|
||||
{
|
||||
const Byte kNone = 0;
|
||||
const Byte kMSZip = 1;
|
||||
@@ -30,13 +27,13 @@ namespace NCompressionMethodMajor
|
||||
const Byte kLZX = 3;
|
||||
}
|
||||
|
||||
const int kFileNameIsUTFAttributeMask = 0x80;
|
||||
const unsigned kFileNameIsUtf8_Mask = 0x80;
|
||||
|
||||
namespace NFolderIndex
|
||||
{
|
||||
const int kContinuedFromPrev = 0xFFFD;
|
||||
const int kContinuedToNext = 0xFFFE;
|
||||
const int kContinuedPrevAndNext = 0xFFFF;
|
||||
const unsigned kContinuedFromPrev = 0xFFFD;
|
||||
const unsigned kContinuedToNext = 0xFFFE;
|
||||
const unsigned kContinuedPrevAndNext = 0xFFFF;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
452
CPP/7zip/Archive/Cab/CabIn.cpp
Executable file → Normal file
452
CPP/7zip/Archive/Cab/CabIn.cpp
Executable file → Normal file
@@ -2,154 +2,353 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../Common/FindSignature.h"
|
||||
// #include <stdio.h>
|
||||
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "CabIn.h"
|
||||
|
||||
#define Get16(p) GetUi16(p)
|
||||
#define Get32(p) GetUi32(p)
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
Byte CInArchive::Read8()
|
||||
struct CUnexpectedEndException {};
|
||||
|
||||
void CInArchive::Skip(unsigned size)
|
||||
{
|
||||
Byte b;
|
||||
if (!inBuffer.ReadByte(b))
|
||||
throw CInArchiveException(CInArchiveException::kUnsupported);
|
||||
return b;
|
||||
if (_inBuffer.Skip(size) != size)
|
||||
throw CUnexpectedEndException();
|
||||
}
|
||||
|
||||
UInt16 CInArchive::Read16()
|
||||
void CInArchive::Read(Byte *data, unsigned size)
|
||||
{
|
||||
UInt16 value = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (_inBuffer.ReadBytes(data, size) != size)
|
||||
throw CUnexpectedEndException();
|
||||
}
|
||||
|
||||
void CInArchive::ReadName(AString &s)
|
||||
{
|
||||
for (size_t i = 0; i < ((size_t)1 << 13); i++)
|
||||
{
|
||||
Byte b = Read8();
|
||||
value |= (UInt16(b) << (8 * i));
|
||||
Byte b;
|
||||
if (!_inBuffer.ReadByte(b))
|
||||
throw CUnexpectedEndException();
|
||||
if (b == 0)
|
||||
{
|
||||
memcpy(s.GetBuffer((unsigned)i), _tempBuf, i);
|
||||
s.ReleaseBuffer((unsigned)i);
|
||||
return;
|
||||
}
|
||||
if (_tempBuf.Size() == i)
|
||||
_tempBuf.ChangeSize_KeepData(i * 2, i);
|
||||
_tempBuf[i] = b;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
UInt32 CInArchive::Read32()
|
||||
{
|
||||
UInt32 value = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Byte b = Read8();
|
||||
value |= (UInt32(b) << (8 * i));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
AString CInArchive::SafeReadName()
|
||||
{
|
||||
AString name;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte b = Read8();
|
||||
Byte b;
|
||||
if (!_inBuffer.ReadByte(b))
|
||||
throw CUnexpectedEndException();
|
||||
if (b == 0)
|
||||
return name;
|
||||
name += (char)b;
|
||||
break;
|
||||
}
|
||||
|
||||
ErrorInNames = true;
|
||||
s = "[ERROR-LONG-PATH]";
|
||||
}
|
||||
|
||||
void CInArchive::ReadOtherArc(COtherArc &oa)
|
||||
{
|
||||
ReadName(oa.FileName);
|
||||
ReadName(oa.DiskName);
|
||||
}
|
||||
|
||||
struct CSignatureFinder
|
||||
{
|
||||
Byte *Buf;
|
||||
UInt32 Pos;
|
||||
UInt32 End;
|
||||
const Byte *Signature;
|
||||
UInt32 SignatureSize;
|
||||
|
||||
UInt32 _HeaderSize;
|
||||
UInt32 _AlignSize;
|
||||
UInt32 _BufUseCapacity;
|
||||
|
||||
ISequentialInStream *Stream;
|
||||
UInt64 Processed; // Global offset of start of Buf
|
||||
|
||||
const UInt64 *SearchLimit;
|
||||
|
||||
UInt32 GetTotalCapacity(UInt32 basicSize, UInt32 headerSize)
|
||||
{
|
||||
_HeaderSize = headerSize;
|
||||
for (_AlignSize = (1 << 5); _AlignSize < _HeaderSize; _AlignSize <<= 1);
|
||||
_BufUseCapacity = basicSize + _AlignSize;
|
||||
return _BufUseCapacity + 16;
|
||||
}
|
||||
|
||||
/*
|
||||
returns:
|
||||
S_OK - signature found (at Pos)
|
||||
S_FALSE - signature not found
|
||||
*/
|
||||
HRESULT Find();
|
||||
};
|
||||
|
||||
HRESULT CSignatureFinder::Find()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
Buf[End] = Signature[0]; // it's for fast search;
|
||||
|
||||
while (End - Pos >= _HeaderSize)
|
||||
{
|
||||
const Byte *p = Buf + Pos;
|
||||
Byte b = Signature[0];
|
||||
for (;;)
|
||||
{
|
||||
if (*p == b) break; p++;
|
||||
if (*p == b) break; p++;
|
||||
}
|
||||
Pos = (UInt32)(p - Buf);
|
||||
if (End - Pos < _HeaderSize)
|
||||
{
|
||||
Pos = End - _HeaderSize + 1;
|
||||
break;
|
||||
}
|
||||
UInt32 i;
|
||||
for (i = 1; i < SignatureSize && p[i] == Signature[i]; i++);
|
||||
if (i == SignatureSize)
|
||||
return S_OK;
|
||||
Pos++;
|
||||
}
|
||||
|
||||
if (Pos >= _AlignSize)
|
||||
{
|
||||
UInt32 num = (Pos & ~(_AlignSize - 1));
|
||||
Processed += num;
|
||||
Pos -= num;
|
||||
End -= num;
|
||||
memmove(Buf, Buf + num, End);
|
||||
}
|
||||
UInt32 rem = _BufUseCapacity - End;
|
||||
if (SearchLimit)
|
||||
{
|
||||
if (Processed + Pos > *SearchLimit)
|
||||
return S_FALSE;
|
||||
UInt64 rem2 = *SearchLimit - (Processed + End) + _HeaderSize;
|
||||
if (rem > rem2)
|
||||
rem = (UInt32)rem2;
|
||||
}
|
||||
|
||||
UInt32 processedSize;
|
||||
if (Processed == 0 && rem == _BufUseCapacity - _HeaderSize)
|
||||
rem -= _AlignSize; // to make reads more aligned.
|
||||
RINOK(Stream->Read(Buf + End, rem, &processedSize));
|
||||
if (processedSize == 0)
|
||||
return S_FALSE;
|
||||
End += processedSize;
|
||||
}
|
||||
}
|
||||
|
||||
void CInArchive::ReadOtherArchive(COtherArchive &oa)
|
||||
bool CInArcInfo::Parse(const Byte *p)
|
||||
{
|
||||
oa.FileName = SafeReadName();
|
||||
oa.DiskName = SafeReadName();
|
||||
if (Get32(p + 0x0C) != 0 ||
|
||||
Get32(p + 0x14) != 0)
|
||||
return false;
|
||||
Size = Get32(p + 8);
|
||||
if (Size < 36)
|
||||
return false;
|
||||
Flags = Get16(p + 0x1E);
|
||||
if (Flags > 7)
|
||||
return false;
|
||||
FileHeadersOffset = Get32(p + 0x10);
|
||||
if (FileHeadersOffset != 0 && FileHeadersOffset > Size)
|
||||
return false;
|
||||
VersionMinor = p[0x18];
|
||||
VersionMajor = p[0x19];
|
||||
NumFolders = Get16(p + 0x1A);
|
||||
NumFiles = Get16(p + 0x1C);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CInArchive::Skip(UInt32 size)
|
||||
|
||||
HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
|
||||
{
|
||||
while (size-- != 0)
|
||||
Read8();
|
||||
}
|
||||
IsArc = false;
|
||||
ErrorInNames = false;
|
||||
UnexpectedEnd = false;
|
||||
HeaderError = false;
|
||||
|
||||
HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit, CDatabaseEx &db)
|
||||
{
|
||||
IInStream *stream = db.Stream;
|
||||
db.Clear();
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_SET, &db.StartPosition));
|
||||
RINOK(db.Stream->Seek(0, STREAM_SEEK_CUR, &db.StartPosition));
|
||||
// UInt64 temp = db.StartPosition;
|
||||
|
||||
RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize,
|
||||
searchHeaderSizeLimit, db.StartPosition));
|
||||
CByteBuffer buffer;
|
||||
CInArcInfo &ai = db.ArcInfo;
|
||||
UInt64 startInBuf = 0;
|
||||
|
||||
RINOK(stream->Seek(db.StartPosition + NHeader::kMarkerSize, STREAM_SEEK_SET, NULL));
|
||||
if (!inBuffer.Create(1 << 17))
|
||||
return E_OUTOFMEMORY;
|
||||
inBuffer.SetStream(stream);
|
||||
inBuffer.Init();
|
||||
CLimitedSequentialInStream *limitedStreamSpec = NULL;
|
||||
CMyComPtr<ISequentialInStream> limitedStream;
|
||||
|
||||
CInArchiveInfo &ai = db.ArchiveInfo;
|
||||
// for (int iii = 0; iii < 10000; iii++)
|
||||
{
|
||||
// db.StartPosition = temp; RINOK(db.Stream->Seek(db.StartPosition, STREAM_SEEK_SET, NULL));
|
||||
|
||||
const UInt32 kMainHeaderSize = 32;
|
||||
Byte header[kMainHeaderSize];
|
||||
const UInt32 kBufSize = 1 << 15;
|
||||
RINOK(ReadStream_FALSE(db.Stream, header, kMainHeaderSize));
|
||||
if (memcmp(header, NHeader::kMarker, NHeader::kMarkerSize) == 0 && ai.Parse(header))
|
||||
{
|
||||
limitedStreamSpec = new CLimitedSequentialInStream;
|
||||
limitedStream = limitedStreamSpec;
|
||||
limitedStreamSpec->SetStream(db.Stream);
|
||||
limitedStreamSpec->Init(ai.Size - NHeader::kMarkerSize);
|
||||
buffer.Alloc(kBufSize);
|
||||
memcpy(buffer, header, kMainHeaderSize);
|
||||
UInt32 numProcessedBytes;
|
||||
RINOK(limitedStream->Read(buffer + kMainHeaderSize, kBufSize - kMainHeaderSize, &numProcessedBytes));
|
||||
_inBuffer.SetBuf(buffer, (UInt32)kBufSize, kMainHeaderSize + numProcessedBytes, kMainHeaderSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)
|
||||
return S_FALSE;
|
||||
|
||||
ai.Size = Read32();
|
||||
if (Read32() != 0)
|
||||
return S_FALSE;
|
||||
ai.FileHeadersOffset = Read32();
|
||||
if (Read32() != 0)
|
||||
return S_FALSE;
|
||||
CSignatureFinder finder;
|
||||
|
||||
ai.VersionMinor = Read8();
|
||||
ai.VersionMajor = Read8();
|
||||
ai.NumFolders = Read16();
|
||||
ai.NumFiles = Read16();
|
||||
ai.Flags = Read16();
|
||||
if (ai.Flags > 7)
|
||||
return S_FALSE;
|
||||
ai.SetID = Read16();
|
||||
ai.CabinetNumber = Read16();
|
||||
finder.Stream = db.Stream;
|
||||
finder.Signature = NHeader::kMarker;
|
||||
finder.SignatureSize = NHeader::kMarkerSize;
|
||||
finder.SearchLimit = searchHeaderSizeLimit;
|
||||
|
||||
buffer.Alloc(finder.GetTotalCapacity(kBufSize, kMainHeaderSize));
|
||||
finder.Buf = buffer;
|
||||
|
||||
memcpy(buffer, header, kMainHeaderSize);
|
||||
finder.Processed = db.StartPosition;
|
||||
finder.End = kMainHeaderSize;
|
||||
finder.Pos = 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
RINOK(finder.Find());
|
||||
if (ai.Parse(finder.Buf + finder.Pos))
|
||||
{
|
||||
db.StartPosition = finder.Processed + finder.Pos;
|
||||
limitedStreamSpec = new CLimitedSequentialInStream;
|
||||
limitedStreamSpec->SetStream(db.Stream);
|
||||
limitedStream = limitedStreamSpec;
|
||||
UInt32 remInFinder = finder.End - finder.Pos;
|
||||
if (ai.Size <= remInFinder)
|
||||
{
|
||||
limitedStreamSpec->Init(0);
|
||||
finder.End = finder.Pos + ai.Size;
|
||||
}
|
||||
else
|
||||
limitedStreamSpec->Init(ai.Size - remInFinder);
|
||||
|
||||
startInBuf = finder.Pos;
|
||||
_inBuffer.SetBuf(buffer, (UInt32)kBufSize, finder.End, finder.Pos + kMainHeaderSize);
|
||||
break;
|
||||
}
|
||||
finder.Pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IsArc = true;
|
||||
|
||||
_inBuffer.SetStream(limitedStream);
|
||||
if (_tempBuf.Size() == 0)
|
||||
_tempBuf.Alloc(1 << 12);
|
||||
|
||||
Byte p[16];
|
||||
unsigned nextSize = 4 + (ai.ReserveBlockPresent() ? 4 : 0);
|
||||
Read(p, nextSize);
|
||||
ai.SetID = Get16(p);
|
||||
ai.CabinetNumber = Get16(p + 2);
|
||||
|
||||
if (ai.ReserveBlockPresent())
|
||||
{
|
||||
ai.PerCabinetAreaSize = Read16();
|
||||
ai.PerFolderAreaSize = Read8();
|
||||
ai.PerDataBlockAreaSize = Read8();
|
||||
|
||||
Skip(ai.PerCabinetAreaSize);
|
||||
ai.PerCabinet_AreaSize = Get16(p + 4);
|
||||
ai.PerFolder_AreaSize = p[6];
|
||||
ai.PerDataBlock_AreaSize = p[7];
|
||||
Skip(ai.PerCabinet_AreaSize);
|
||||
}
|
||||
|
||||
{
|
||||
if (ai.IsTherePrev())
|
||||
ReadOtherArchive(ai.PrevArc);
|
||||
if (ai.IsThereNext())
|
||||
ReadOtherArchive(ai.NextArc);
|
||||
}
|
||||
if (ai.IsTherePrev()) ReadOtherArc(ai.PrevArc);
|
||||
if (ai.IsThereNext()) ReadOtherArc(ai.NextArc);
|
||||
|
||||
int i;
|
||||
UInt32 i;
|
||||
db.Folders.ClearAndReserve(ai.NumFolders);
|
||||
for (i = 0; i < ai.NumFolders; i++)
|
||||
{
|
||||
Read(p, 8);
|
||||
CFolder folder;
|
||||
|
||||
folder.DataStart = Read32();
|
||||
folder.NumDataBlocks = Read16();
|
||||
folder.CompressionTypeMajor = Read8();
|
||||
folder.CompressionTypeMinor = Read8();
|
||||
|
||||
Skip(ai.PerFolderAreaSize);
|
||||
db.Folders.Add(folder);
|
||||
folder.DataStart = Get32(p);
|
||||
folder.NumDataBlocks = Get16(p + 4);
|
||||
folder.MethodMajor = p[6];
|
||||
folder.MethodMinor = p[7];
|
||||
Skip(ai.PerFolder_AreaSize);
|
||||
db.Folders.AddInReserved(folder);
|
||||
}
|
||||
|
||||
RINOK(stream->Seek(db.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL));
|
||||
// for (int iii = 0; iii < 10000; iii++) {
|
||||
|
||||
inBuffer.SetStream(stream);
|
||||
inBuffer.Init();
|
||||
if (_inBuffer.GetProcessedSize() - startInBuf != ai.FileHeadersOffset)
|
||||
{
|
||||
// printf("\n!!! Seek Error !!!!\n");
|
||||
// fflush(stdout);
|
||||
RINOK(db.Stream->Seek(db.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL));
|
||||
limitedStreamSpec->Init(ai.Size - ai.FileHeadersOffset);
|
||||
_inBuffer.Init();
|
||||
}
|
||||
|
||||
db.Items.ClearAndReserve(ai.NumFiles);
|
||||
for (i = 0; i < ai.NumFiles; i++)
|
||||
{
|
||||
CItem item;
|
||||
item.Size = Read32();
|
||||
item.Offset = Read32();
|
||||
item.FolderIndex = Read16();
|
||||
UInt16 pureDate = Read16();
|
||||
UInt16 pureTime = Read16();
|
||||
item.Time = ((UInt32(pureDate) << 16)) | pureTime;
|
||||
item.Attributes = Read16();
|
||||
item.Name = SafeReadName();
|
||||
int folderIndex = item.GetFolderIndex(db.Folders.Size());
|
||||
if (folderIndex >= db.Folders.Size())
|
||||
Read(p, 16);
|
||||
CItem &item = db.Items.AddNewInReserved();
|
||||
item.Size = Get32(p);
|
||||
item.Offset = Get32(p + 4);
|
||||
item.FolderIndex = Get16(p + 8);
|
||||
UInt16 pureDate = Get16(p + 10);
|
||||
UInt16 pureTime = Get16(p + 12);
|
||||
item.Time = (((UInt32)pureDate << 16)) | pureTime;
|
||||
item.Attributes = Get16(p + 14);
|
||||
|
||||
ReadName(item.Name);
|
||||
if (item.GetFolderIndex(db.Folders.Size()) >= (int)db.Folders.Size())
|
||||
{
|
||||
HeaderError = true;
|
||||
return S_FALSE;
|
||||
db.Items.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Open2(db, searchHeaderSizeLimit);
|
||||
}
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
catch(CUnexpectedEndException &) { UnexpectedEnd = true; return S_FALSE; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
||||
|
||||
static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
|
||||
@@ -161,10 +360,8 @@ static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
|
||||
const CItem &item2 = db2.Items[p2->ItemIndex];;
|
||||
bool isDir1 = item1.IsDir();
|
||||
bool isDir2 = item2.IsDir();
|
||||
if (isDir1 && !isDir2)
|
||||
return -1;
|
||||
if (isDir2 && !isDir1)
|
||||
return 1;
|
||||
if (isDir1 && !isDir2) return -1;
|
||||
if (isDir2 && !isDir1) return 1;
|
||||
int f1 = mvDb.GetFolderIndex(p1);
|
||||
int f2 = mvDb.GetFolderIndex(p2);
|
||||
RINOZ(MyCompare(f1, f2));
|
||||
@@ -174,7 +371,7 @@ static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
|
||||
return MyCompare(p1->ItemIndex, p2->ItemIndex);
|
||||
}
|
||||
|
||||
bool CMvDatabaseEx::AreItemsEqual(int i1, int i2)
|
||||
bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2)
|
||||
{
|
||||
const CMvItem *p1 = &Items[i1];
|
||||
const CMvItem *p2 = &Items[i2];
|
||||
@@ -182,10 +379,10 @@ bool CMvDatabaseEx::AreItemsEqual(int i1, int i2)
|
||||
const CDatabaseEx &db2 = Volumes[p2->VolumeIndex];
|
||||
const CItem &item1 = db1.Items[p1->ItemIndex];
|
||||
const CItem &item2 = db2.Items[p2->ItemIndex];;
|
||||
return GetFolderIndex(p1) == GetFolderIndex(p2) &&
|
||||
item1.Offset == item2.Offset &&
|
||||
item1.Size == item2.Size &&
|
||||
item1.Name == item2.Name;
|
||||
return GetFolderIndex(p1) == GetFolderIndex(p2)
|
||||
&& item1.Offset == item2.Offset
|
||||
&& item1.Size == item2.Size
|
||||
&& item1.Name == item2.Name;
|
||||
}
|
||||
|
||||
void CMvDatabaseEx::FillSortAndShrink()
|
||||
@@ -194,7 +391,7 @@ void CMvDatabaseEx::FillSortAndShrink()
|
||||
StartFolderOfVol.Clear();
|
||||
FolderStartFileIndex.Clear();
|
||||
int offset = 0;
|
||||
for (int v = 0; v < Volumes.Size(); v++)
|
||||
FOR_VECTOR (v, Volumes)
|
||||
{
|
||||
const CDatabaseEx &db = Volumes[v];
|
||||
int curOffset = offset;
|
||||
@@ -205,32 +402,35 @@ void CMvDatabaseEx::FillSortAndShrink()
|
||||
|
||||
CMvItem mvItem;
|
||||
mvItem.VolumeIndex = v;
|
||||
for (int i = 0 ; i < db.Items.Size(); i++)
|
||||
FOR_VECTOR (i, db.Items)
|
||||
{
|
||||
mvItem.ItemIndex = i;
|
||||
Items.Add(mvItem);
|
||||
}
|
||||
}
|
||||
|
||||
Items.Sort(CompareMvItems, (void *)this);
|
||||
int j = 1;
|
||||
int i;
|
||||
for (i = 1; i < Items.Size(); i++)
|
||||
if (!AreItemsEqual(i, i -1))
|
||||
Items[j++] = Items[i];
|
||||
Items.DeleteFrom(j);
|
||||
if (Items.Size() > 1)
|
||||
{
|
||||
Items.Sort(CompareMvItems, (void *)this);
|
||||
unsigned j = 1;
|
||||
unsigned i = 1;
|
||||
for (; i < Items.Size(); i++)
|
||||
if (!AreItemsEqual(i, i - 1))
|
||||
Items[j++] = Items[i];
|
||||
Items.DeleteFrom(j);
|
||||
}
|
||||
|
||||
for (i = 0; i < Items.Size(); i++)
|
||||
FOR_VECTOR (i, Items)
|
||||
{
|
||||
int folderIndex = GetFolderIndex(&Items[i]);
|
||||
if (folderIndex >= FolderStartFileIndex.Size())
|
||||
if (folderIndex >= (int)FolderStartFileIndex.Size())
|
||||
FolderStartFileIndex.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
bool CMvDatabaseEx::Check()
|
||||
{
|
||||
for (int v = 1; v < Volumes.Size(); v++)
|
||||
for (unsigned v = 1; v < Volumes.Size(); v++)
|
||||
{
|
||||
const CDatabaseEx &db1 = Volumes[v];
|
||||
if (db1.IsTherePrevFolder())
|
||||
@@ -240,19 +440,19 @@ bool CMvDatabaseEx::Check()
|
||||
return false;
|
||||
const CFolder &f0 = db0.Folders.Back();
|
||||
const CFolder &f1 = db1.Folders.Front();
|
||||
if (f0.CompressionTypeMajor != f1.CompressionTypeMajor ||
|
||||
f0.CompressionTypeMinor != f1.CompressionTypeMinor)
|
||||
if (f0.MethodMajor != f1.MethodMajor ||
|
||||
f0.MethodMinor != f1.MethodMinor)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
UInt32 beginPos = 0;
|
||||
UInt64 endPos = 0;
|
||||
int prevFolder = -2;
|
||||
for (int i = 0; i < Items.Size(); i++)
|
||||
FOR_VECTOR (i, Items)
|
||||
{
|
||||
const CMvItem &mvItem = Items[i];
|
||||
int fIndex = GetFolderIndex(&mvItem);
|
||||
if (fIndex >= FolderStartFileIndex.Size())
|
||||
if (fIndex >= (int)FolderStartFileIndex.Size())
|
||||
return false;
|
||||
const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
|
||||
if (item.IsDir())
|
||||
|
||||
121
CPP/7zip/Archive/Cab/CabIn.h
Executable file → Normal file
121
CPP/7zip/Archive/Cab/CabIn.h
Executable file → Normal file
@@ -3,96 +3,88 @@
|
||||
#ifndef __ARCHIVE_CAB_IN_H
|
||||
#define __ARCHIVE_CAB_IN_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../Common/InBuffer.h"
|
||||
#include "CabHeader.h"
|
||||
|
||||
#include "CabItem.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
class CInArchiveException
|
||||
{
|
||||
public:
|
||||
enum CCauseType
|
||||
{
|
||||
kUnexpectedEndOfArchive = 0,
|
||||
kIncorrectArchive,
|
||||
kUnsupported
|
||||
} Cause;
|
||||
CInArchiveException(CCauseType cause) : Cause(cause) {}
|
||||
};
|
||||
|
||||
struct COtherArchive
|
||||
struct COtherArc
|
||||
{
|
||||
AString FileName;
|
||||
AString DiskName;
|
||||
};
|
||||
|
||||
struct CArchiveInfo
|
||||
struct CArchInfo
|
||||
{
|
||||
Byte VersionMinor; /* cabinet file format version, minor */
|
||||
Byte VersionMajor; /* cabinet file format version, major */
|
||||
UInt16 NumFolders; /* number of CFFOLDER entries in this cabinet */
|
||||
UInt16 NumFiles; /* number of CFFILE entries in this cabinet */
|
||||
UInt16 Flags; /* cabinet file option indicators */
|
||||
UInt16 SetID; /* must be the same for all cabinets in a set */
|
||||
UInt16 CabinetNumber; /* number of this cabinet file in a set */
|
||||
Byte VersionMinor; // cabinet file format version, minor
|
||||
Byte VersionMajor; // cabinet file format version, major
|
||||
UInt32 NumFolders; // number of CFFOLDER entries in this cabinet
|
||||
UInt32 NumFiles; // number of CFFILE entries in this cabinet
|
||||
UInt32 Flags; // cabinet file option indicators
|
||||
UInt32 SetID; // must be the same for all cabinets in a set
|
||||
UInt32 CabinetNumber; // number of this cabinet file in a set
|
||||
|
||||
bool ReserveBlockPresent() const { return (Flags & NHeader::NArchive::NFlags::kReservePresent) != 0; }
|
||||
UInt16 PerCabinet_AreaSize; // (optional) size of per-cabinet reserved area
|
||||
Byte PerFolder_AreaSize; // (optional) size of per-folder reserved area
|
||||
Byte PerDataBlock_AreaSize; // (optional) size of per-datablock reserved area
|
||||
|
||||
bool IsTherePrev() const { return (Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0; }
|
||||
bool IsThereNext() const { return (Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0; }
|
||||
COtherArc PrevArc; // prev link can skip some volumes !!!
|
||||
COtherArc NextArc;
|
||||
|
||||
UInt16 PerCabinetAreaSize; // (optional) size of per-cabinet reserved area
|
||||
Byte PerFolderAreaSize; // (optional) size of per-folder reserved area
|
||||
Byte PerDataBlockAreaSize; // (optional) size of per-datablock reserved area
|
||||
bool ReserveBlockPresent() const { return (Flags & NHeader::NArcFlags::kReservePresent) != 0; }
|
||||
bool IsTherePrev() const { return (Flags & NHeader::NArcFlags::kPrevCabinet) != 0; }
|
||||
bool IsThereNext() const { return (Flags & NHeader::NArcFlags::kNextCabinet) != 0; }
|
||||
Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlock_AreaSize : 0); }
|
||||
|
||||
Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlockAreaSize : 0); }
|
||||
|
||||
COtherArchive PrevArc;
|
||||
COtherArchive NextArc;
|
||||
|
||||
CArchiveInfo()
|
||||
CArchInfo()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
PerCabinetAreaSize = 0;
|
||||
PerFolderAreaSize = 0;
|
||||
PerDataBlockAreaSize = 0;
|
||||
PerCabinet_AreaSize = 0;
|
||||
PerFolder_AreaSize = 0;
|
||||
PerDataBlock_AreaSize = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct CInArchiveInfo: public CArchiveInfo
|
||||
struct CInArcInfo: public CArchInfo
|
||||
{
|
||||
UInt32 Size; /* size of this cabinet file in bytes */
|
||||
UInt32 Size; // size of this cabinet file in bytes
|
||||
UInt32 FileHeadersOffset; // offset of the first CFFILE entry
|
||||
|
||||
bool Parse(const Byte *p);
|
||||
};
|
||||
|
||||
|
||||
struct CDatabase
|
||||
{
|
||||
UInt64 StartPosition;
|
||||
CInArchiveInfo ArchiveInfo;
|
||||
CObjectVector<CFolder> Folders;
|
||||
CRecordVector<CFolder> Folders;
|
||||
CObjectVector<CItem> Items;
|
||||
UInt64 StartPosition;
|
||||
CInArcInfo ArcInfo;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
ArchiveInfo.Clear();
|
||||
ArcInfo.Clear();
|
||||
Folders.Clear();
|
||||
Items.Clear();
|
||||
}
|
||||
|
||||
bool IsTherePrevFolder() const
|
||||
{
|
||||
for (int i = 0; i < Items.Size(); i++)
|
||||
FOR_VECTOR (i, Items)
|
||||
if (Items[i].ContinuedFromPrev())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int GetNumberOfNewFolders() const
|
||||
{
|
||||
int res = Folders.Size();
|
||||
@@ -100,8 +92,6 @@ struct CDatabase
|
||||
res--;
|
||||
return res;
|
||||
}
|
||||
UInt32 GetFileOffset(int index) const { return Items[index].Offset; }
|
||||
UInt32 GetFileSize(int index) const { return Items[index].Size; }
|
||||
};
|
||||
|
||||
struct CDatabaseEx: public CDatabase
|
||||
@@ -111,25 +101,27 @@ struct CDatabaseEx: public CDatabase
|
||||
|
||||
struct CMvItem
|
||||
{
|
||||
int VolumeIndex;
|
||||
int ItemIndex;
|
||||
unsigned VolumeIndex;
|
||||
unsigned ItemIndex;
|
||||
};
|
||||
|
||||
class CMvDatabaseEx
|
||||
{
|
||||
bool AreItemsEqual(int i1, int i2);
|
||||
bool AreItemsEqual(unsigned i1, unsigned i2);
|
||||
|
||||
public:
|
||||
CObjectVector<CDatabaseEx> Volumes;
|
||||
CRecordVector<CMvItem> Items;
|
||||
CRecordVector<int> StartFolderOfVol;
|
||||
CRecordVector<int> FolderStartFileIndex;
|
||||
|
||||
CRecordVector<int> StartFolderOfVol; // can be negative
|
||||
CRecordVector<unsigned> FolderStartFileIndex;
|
||||
|
||||
int GetFolderIndex(const CMvItem *mvi) const
|
||||
{
|
||||
const CDatabaseEx &db = Volumes[mvi->VolumeIndex];
|
||||
return StartFolderOfVol[mvi->VolumeIndex] +
|
||||
db.Items[mvi->ItemIndex].GetFolderIndex(db.Folders.Size());
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Volumes.Clear();
|
||||
@@ -137,23 +129,30 @@ public:
|
||||
StartFolderOfVol.Clear();
|
||||
FolderStartFileIndex.Clear();
|
||||
}
|
||||
|
||||
void FillSortAndShrink();
|
||||
bool Check();
|
||||
};
|
||||
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
CInBuffer inBuffer;
|
||||
CInBufferBase _inBuffer;
|
||||
CByteBuffer _tempBuf;
|
||||
|
||||
Byte Read8();
|
||||
UInt16 Read16();
|
||||
UInt32 Read32();
|
||||
AString SafeReadName();
|
||||
void Skip(UInt32 size);
|
||||
void ReadOtherArchive(COtherArchive &oa);
|
||||
void Skip(unsigned size);
|
||||
void Read(Byte *data, unsigned size);
|
||||
void ReadName(AString &s);
|
||||
void ReadOtherArc(COtherArc &oa);
|
||||
HRESULT Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit);
|
||||
|
||||
public:
|
||||
HRESULT Open(const UInt64 *searchHeaderSizeLimit, CDatabaseEx &db);
|
||||
bool IsArc;
|
||||
bool ErrorInNames;
|
||||
bool UnexpectedEnd;
|
||||
bool HeaderError;
|
||||
|
||||
HRESULT Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
29
CPP/7zip/Archive/Cab/CabItem.h
Executable file → Normal file
29
CPP/7zip/Archive/Cab/CabItem.h
Executable file → Normal file
@@ -3,20 +3,23 @@
|
||||
#ifndef __ARCHIVE_CAB_ITEM_H
|
||||
#define __ARCHIVE_CAB_ITEM_H
|
||||
|
||||
#include "Common/Types.h"
|
||||
#include "Common/MyString.h"
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "CabHeader.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
const unsigned kNumMethodsMax = 16;
|
||||
|
||||
struct CFolder
|
||||
{
|
||||
UInt32 DataStart; // offset of the first CFDATA block in this folder
|
||||
UInt16 NumDataBlocks; // number of CFDATA blocks in this folder
|
||||
Byte CompressionTypeMajor;
|
||||
Byte CompressionTypeMinor;
|
||||
Byte GetCompressionMethod() const { return (Byte)(CompressionTypeMajor & 0xF); }
|
||||
Byte MethodMajor;
|
||||
Byte MethodMinor;
|
||||
|
||||
Byte GetMethod() const { return (Byte)(MethodMajor & 0xF); }
|
||||
};
|
||||
|
||||
struct CItem
|
||||
@@ -25,27 +28,27 @@ struct CItem
|
||||
UInt32 Offset;
|
||||
UInt32 Size;
|
||||
UInt32 Time;
|
||||
UInt16 FolderIndex;
|
||||
UInt32 FolderIndex;
|
||||
UInt16 Flags;
|
||||
UInt16 Attributes;
|
||||
|
||||
UInt64 GetEndOffset() const { return (UInt64)Offset + Size; }
|
||||
UInt32 GetWinAttributes() const { return (Attributes & ~NHeader::kFileNameIsUTFAttributeMask); }
|
||||
bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUTFAttributeMask) != 0; }
|
||||
UInt32 GetWinAttrib() const { return (UInt32)Attributes & ~(UInt32)NHeader::kFileNameIsUtf8_Mask; }
|
||||
bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUtf8_Mask) != 0; }
|
||||
bool IsDir() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; }
|
||||
|
||||
bool ContinuedFromPrev() const
|
||||
{
|
||||
return
|
||||
(FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev) ||
|
||||
(FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext);
|
||||
FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev ||
|
||||
FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;
|
||||
}
|
||||
|
||||
bool ContinuedToNext() const
|
||||
{
|
||||
return
|
||||
(FolderIndex == NHeader::NFolderIndex::kContinuedToNext) ||
|
||||
(FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext);
|
||||
FolderIndex == NHeader::NFolderIndex::kContinuedToNext ||
|
||||
FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;
|
||||
}
|
||||
|
||||
int GetFolderIndex(int numFolders) const
|
||||
@@ -53,7 +56,7 @@ struct CItem
|
||||
if (ContinuedFromPrev())
|
||||
return 0;
|
||||
if (ContinuedToNext())
|
||||
return (numFolders - 1);
|
||||
return numFolders - 1;
|
||||
return FolderIndex;
|
||||
}
|
||||
};
|
||||
|
||||
14
CPP/7zip/Archive/Cab/CabRegister.cpp
Executable file → Normal file
14
CPP/7zip/Archive/Cab/CabRegister.cpp
Executable file → Normal file
@@ -5,9 +5,19 @@
|
||||
#include "../../Common/RegisterArc.h"
|
||||
|
||||
#include "CabHandler.h"
|
||||
static IInArchive *CreateArc() { return new NArchive::NCab::CHandler; }
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"Cab", L"cab", 0, 8, { 0x4D, 0x53, 0x43, 0x46 }, 4, false, CreateArc, 0 };
|
||||
{ "Cab", "cab", 0, 8,
|
||||
8, { 'M', 'S', 'C', 'F', 0, 0, 0, 0 },
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Cab)
|
||||
|
||||
}}
|
||||
|
||||
2
CPP/7zip/Archive/Cab/StdAfx.h
Executable file → Normal file
2
CPP/7zip/Archive/Cab/StdAfx.h
Executable file → Normal file
@@ -3,6 +3,6 @@
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
|
||||
118
CPP/7zip/Archive/Chm/ChmHandler.cpp
Executable file → Normal file
118
CPP/7zip/Archive/Chm/ChmHandler.cpp
Executable file → Normal file
@@ -2,17 +2,17 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/Defs.h"
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/UTFConvert.h"
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
#include "../../../Common/UTFConvert.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/Time.h"
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
#include "../../../Windows/TimeUtils.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
#include "../../Common/RegisterArc.h"
|
||||
|
||||
#include "../../Compress/CopyCoder.h"
|
||||
#include "../../Compress/LzxDecoder.h"
|
||||
@@ -38,44 +38,45 @@ enum
|
||||
|
||||
#endif
|
||||
|
||||
STATPROPSTG kProps[] =
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidSize, VT_UI8},
|
||||
{ NULL, kpidMethod, VT_BSTR},
|
||||
{ NULL, kpidBlock, VT_UI4}
|
||||
kpidPath,
|
||||
kpidSize,
|
||||
kpidMethod,
|
||||
kpidBlock
|
||||
|
||||
#ifdef _CHM_DETAILS
|
||||
,
|
||||
{ L"Section", kpidSection, VT_UI4},
|
||||
{ NULL, kpidOffset, VT_UI4}
|
||||
L"Section", kpidSection,
|
||||
kpidOffset
|
||||
#endif
|
||||
};
|
||||
|
||||
STATPROPSTG kArcProps[] =
|
||||
/*
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidNumBlocks, VT_UI8}
|
||||
// kpidNumBlocks,
|
||||
};
|
||||
*/
|
||||
|
||||
IMP_IInArchive_Props
|
||||
|
||||
IMP_IInArchive_ArcProps_NO
|
||||
/*
|
||||
IMP_IInArchive_ArcProps
|
||||
IMP_IInArchive_ArcProps_NO_Table
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
// COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
/*
|
||||
case kpidNumBlocks:
|
||||
{
|
||||
UInt64 numBlocks = 0;
|
||||
for (int i = 0; i < m_Database.Sections.Size(); i++)
|
||||
FOR_VECTOR(i, m_Database.Sections)
|
||||
{
|
||||
const CSectionInfo &s = m_Database.Sections[i];
|
||||
for (int j = 0; j < s.Methods.Size(); j++)
|
||||
FOR_VECTOR(j, s.Methods)
|
||||
{
|
||||
const CMethodInfo &m = s.Methods[j];
|
||||
if (m.IsLzx())
|
||||
@@ -85,23 +86,27 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
prop = numBlocks;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case kpidOffset: prop = m_Database.StartPosition; break;
|
||||
case kpidPhySize: prop = m_Database.PhySize; break;
|
||||
|
||||
case kpidErrorFlags: prop = m_ErrorFlags; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
// COM_TRY_END
|
||||
}
|
||||
*/
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
NCOM::CPropVariant prop;
|
||||
if (m_Database.NewFormat)
|
||||
{
|
||||
switch(propID)
|
||||
{
|
||||
case kpidSize:
|
||||
prop = (UInt64)m_Database.NewFormatString.Length();
|
||||
prop = (UInt64)m_Database.NewFormatString.Len();
|
||||
break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
@@ -113,7 +118,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
else
|
||||
entryIndex = m_Database.Indices[index];
|
||||
const CItem &item = m_Database.Items[entryIndex];
|
||||
switch(propID)
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath:
|
||||
{
|
||||
@@ -122,7 +127,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
{
|
||||
if (!m_Database.LowLevel)
|
||||
{
|
||||
if (us.Length() > 1)
|
||||
if (us.Len() > 1)
|
||||
if (us[0] == L'/')
|
||||
us.Delete(0);
|
||||
}
|
||||
@@ -160,6 +165,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
/*
|
||||
class CProgressImp: public CProgressVirt
|
||||
{
|
||||
CMyComPtr<IArchiveOpenCallback> _callback;
|
||||
@@ -182,18 +188,25 @@ STDMETHODIMP CProgressImp::SetCompleted(const UInt64 *numFiles)
|
||||
return _callback->SetCompleted(numFiles, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
m_Stream.Release();
|
||||
Close();
|
||||
try
|
||||
{
|
||||
CInArchive archive;
|
||||
CInArchive archive(_help2);
|
||||
// CProgressImp progressImp(openArchiveCallback);
|
||||
RINOK(archive.Open(inStream, maxCheckStartPosition, m_Database));
|
||||
HRESULT res = archive.Open(inStream, maxCheckStartPosition, m_Database);
|
||||
if (!archive.IsArc) m_ErrorFlags |= kpv_ErrorFlags_IsNotArc;
|
||||
if (archive.HeadersError) m_ErrorFlags |= kpv_ErrorFlags_HeadersError;
|
||||
if (archive.UnexpectedEnd) m_ErrorFlags |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
if (archive.UnsupportedFeature) m_ErrorFlags |= kpv_ErrorFlags_UnsupportedFeature;
|
||||
|
||||
RINOK(res);
|
||||
/*
|
||||
if (m_Database.LowLevel)
|
||||
return S_FALSE;
|
||||
@@ -210,6 +223,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
m_ErrorFlags = 0;
|
||||
m_Database.Clear();
|
||||
m_Stream.Release();
|
||||
return S_OK;
|
||||
@@ -402,7 +416,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == (UInt32)-1);
|
||||
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
|
||||
if (allFilesMode)
|
||||
numItems = m_Database.NewFormat ? 1:
|
||||
@@ -432,7 +446,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
UInt64 currentItemSize = 0;
|
||||
UInt64 totalSize = 0;
|
||||
if (m_Database.NewFormat)
|
||||
totalSize = m_Database.NewFormatString.Length();
|
||||
totalSize = m_Database.NewFormatString.Len();
|
||||
else
|
||||
for (i = 0; i < numItems; i++)
|
||||
totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size;
|
||||
@@ -460,7 +474,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
continue;
|
||||
if (!testMode)
|
||||
{
|
||||
UInt32 size = m_Database.NewFormatString.Length();
|
||||
UInt32 size = m_Database.NewFormatString.Len();
|
||||
RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size));
|
||||
}
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
|
||||
@@ -475,7 +489,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
if (item.Section != 0)
|
||||
{
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -589,7 +603,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -718,4 +732,32 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
namespace NChm {
|
||||
|
||||
IMP_CreateArcIn_2(CHandler(false))
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Chm", "chm chi chq chw", 0, 0xE9,
|
||||
12, { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0, 0, 0 },
|
||||
0,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Chm)
|
||||
}
|
||||
|
||||
namespace NHxs {
|
||||
|
||||
IMP_CreateArcIn_2(CHandler(true))
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Hxs", "hxs hxi hxr hxq hxw lit", 0, 0xCE,
|
||||
16, { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 },
|
||||
0,
|
||||
NArcInfoFlags::kFindSignature,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Hxs)
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
8
CPP/7zip/Archive/Chm/ChmHandler.h
Executable file → Normal file
8
CPP/7zip/Archive/Chm/ChmHandler.h
Executable file → Normal file
@@ -3,8 +3,10 @@
|
||||
#ifndef __ARCHIVE_CHM_HANDLER_H
|
||||
#define __ARCHIVE_CHM_HANDLER_H
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../IArchive.h"
|
||||
|
||||
#include "ChmIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
@@ -19,9 +21,13 @@ public:
|
||||
|
||||
INTERFACE_IInArchive(;)
|
||||
|
||||
bool _help2;
|
||||
CHandler(bool help2): _help2(help2) {}
|
||||
|
||||
private:
|
||||
CFilesDatabase m_Database;
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
UInt32 m_ErrorFlags;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
// Archive/Chm/Header.h
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ChmHeader.h"
|
||||
|
||||
namespace NArchive{
|
||||
namespace NChm{
|
||||
namespace NHeader{
|
||||
|
||||
UInt32 kItsfSignature = 0x46535449 + 1;
|
||||
UInt32 kItolSignature = 0x4C4F5449 + 1;
|
||||
static class CSignatureInitializer
|
||||
{
|
||||
public:
|
||||
CSignatureInitializer()
|
||||
{
|
||||
kItsfSignature--;
|
||||
kItolSignature--;
|
||||
}
|
||||
}g_SignatureInitializer;
|
||||
|
||||
|
||||
}}}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Archive/Chm/Header.h
|
||||
|
||||
#ifndef __ARCHIVE_CHM_HEADER_H
|
||||
#define __ARCHIVE_CHM_HEADER_H
|
||||
|
||||
#include "Common/Types.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NChm {
|
||||
namespace NHeader{
|
||||
|
||||
const UInt32 kItspSignature = 0x50535449;
|
||||
const UInt32 kPmglSignature = 0x4C474D50;
|
||||
const UInt32 kLzxcSignature = 0x43585A4C;
|
||||
|
||||
const UInt32 kIfcmSignature = 0x4D434649;
|
||||
const UInt32 kAollSignature = 0x4C4C4F41;
|
||||
const UInt32 kCaolSignature = 0x4C4F4143;
|
||||
|
||||
extern UInt32 kItsfSignature;
|
||||
|
||||
extern UInt32 kItolSignature;
|
||||
const UInt32 kItlsSignature = 0x534C5449;
|
||||
UInt64 inline GetHxsSignature() { return ((UInt64)kItlsSignature << 32) | kItolSignature; }
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
277
CPP/7zip/Archive/Chm/ChmIn.cpp
Executable file → Normal file
277
CPP/7zip/Archive/Chm/ChmIn.cpp
Executable file → Normal file
@@ -2,8 +2,10 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/IntToString.h"
|
||||
#include "Common/UTFConvert.h"
|
||||
// #include <stdio.h>
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
#include "../../../Common/UTFConvert.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
|
||||
@@ -12,6 +14,21 @@
|
||||
namespace NArchive {
|
||||
namespace NChm {
|
||||
|
||||
static const UInt32 kSignature_ITSP = 0x50535449;
|
||||
static const UInt32 kSignature_PMGL = 0x4C474D50;
|
||||
static const UInt32 kSignature_LZXC = 0x43585A4C;
|
||||
|
||||
static const UInt32 kSignature_IFCM = 0x4D434649;
|
||||
static const UInt32 kSignature_AOLL = 0x4C4C4F41;
|
||||
static const UInt32 kSignature_CAOL = 0x4C4F4143;
|
||||
|
||||
static const UInt32 kSignature_ITSF = 0x46535449;
|
||||
static const UInt32 kSignature_ITOL = 0x4C4F5449;
|
||||
static const UInt32 kSignature_ITLS = 0x534C5449;
|
||||
|
||||
struct CEnexpectedEndException {};
|
||||
struct CHeaderErrorException {};
|
||||
|
||||
// define CHM_LOW, if you want to see low level items
|
||||
// #define CHM_LOW
|
||||
|
||||
@@ -31,9 +48,9 @@ static bool AreGuidsEqual(REFGUID g1, REFGUID g2)
|
||||
return true;
|
||||
}
|
||||
|
||||
static char GetHex(Byte value)
|
||||
static char GetHex(unsigned v)
|
||||
{
|
||||
return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
|
||||
return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10)));
|
||||
}
|
||||
|
||||
static void PrintByte(Byte b, AString &s)
|
||||
@@ -103,10 +120,10 @@ UString CMethodInfo::GetName() const
|
||||
else
|
||||
{
|
||||
s2 = GetGuidString();
|
||||
if (ControlData.GetCapacity() > 0)
|
||||
if (ControlData.Size() > 0)
|
||||
{
|
||||
s2 += ':';
|
||||
for (size_t i = 0; i < ControlData.GetCapacity(); i++)
|
||||
for (size_t i = 0; i < ControlData.Size(); i++)
|
||||
PrintByte(ControlData[i], s2);
|
||||
}
|
||||
}
|
||||
@@ -132,7 +149,7 @@ UString CSectionInfo::GetMethodName() const
|
||||
s += temp;
|
||||
s += L": ";
|
||||
}
|
||||
for (int i = 0; i < Methods.Size(); i++)
|
||||
FOR_VECTOR (i, Methods)
|
||||
{
|
||||
if (i != 0)
|
||||
s += L' ';
|
||||
@@ -145,7 +162,7 @@ Byte CInArchive::ReadByte()
|
||||
{
|
||||
Byte b;
|
||||
if (!_inBuffer.ReadByte(b))
|
||||
throw 1;
|
||||
throw CEnexpectedEndException();
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -163,32 +180,32 @@ void CInArchive::ReadBytes(Byte *data, UInt32 size)
|
||||
|
||||
UInt16 CInArchive::ReadUInt16()
|
||||
{
|
||||
UInt16 value = 0;
|
||||
UInt16 val = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
value |= ((UInt16)(ReadByte()) << (8 * i));
|
||||
return value;
|
||||
val |= ((UInt16)(ReadByte()) << (8 * i));
|
||||
return val;
|
||||
}
|
||||
|
||||
UInt32 CInArchive::ReadUInt32()
|
||||
{
|
||||
UInt32 value = 0;
|
||||
UInt32 val = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
value |= ((UInt32)(ReadByte()) << (8 * i));
|
||||
return value;
|
||||
val |= ((UInt32)(ReadByte()) << (8 * i));
|
||||
return val;
|
||||
}
|
||||
|
||||
UInt64 CInArchive::ReadUInt64()
|
||||
{
|
||||
UInt64 value = 0;
|
||||
UInt64 val = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
value |= ((UInt64)(ReadByte()) << (8 * i));
|
||||
return value;
|
||||
val |= ((UInt64)(ReadByte()) << (8 * i));
|
||||
return val;
|
||||
}
|
||||
|
||||
UInt64 CInArchive::ReadEncInt()
|
||||
{
|
||||
UInt64 val = 0;;
|
||||
for (int i = 0; i < 10; i++)
|
||||
UInt64 val = 0;
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
Byte b = ReadByte();
|
||||
val |= (b & 0x7F);
|
||||
@@ -196,7 +213,7 @@ UInt64 CInArchive::ReadEncInt()
|
||||
return val;
|
||||
val <<= 7;
|
||||
}
|
||||
throw 1;
|
||||
throw CHeaderErrorException();
|
||||
}
|
||||
|
||||
void CInArchive::ReadGUID(GUID &g)
|
||||
@@ -207,10 +224,10 @@ void CInArchive::ReadGUID(GUID &g)
|
||||
ReadBytes(g.Data4, 8);
|
||||
}
|
||||
|
||||
void CInArchive::ReadString(int size, AString &s)
|
||||
void CInArchive::ReadString(unsigned size, AString &s)
|
||||
{
|
||||
s.Empty();
|
||||
while(size-- != 0)
|
||||
while (size-- != 0)
|
||||
{
|
||||
char c = (char)ReadByte();
|
||||
if (c == 0)
|
||||
@@ -222,10 +239,10 @@ void CInArchive::ReadString(int size, AString &s)
|
||||
}
|
||||
}
|
||||
|
||||
void CInArchive::ReadUString(int size, UString &s)
|
||||
void CInArchive::ReadUString(unsigned size, UString &s)
|
||||
{
|
||||
s.Empty();
|
||||
while(size-- != 0)
|
||||
while (size-- != 0)
|
||||
{
|
||||
wchar_t c = ReadUInt16();
|
||||
if (c == 0)
|
||||
@@ -244,6 +261,7 @@ HRESULT CInArchive::ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size)
|
||||
CMyComPtr<ISequentialInStream> limitedStream(streamSpec);
|
||||
streamSpec->SetStream(inStream);
|
||||
streamSpec->Init(size);
|
||||
m_InStreamRef = limitedStream;
|
||||
_inBuffer.SetStream(limitedStream);
|
||||
_inBuffer.Init();
|
||||
return S_OK;
|
||||
@@ -252,10 +270,10 @@ HRESULT CInArchive::ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size)
|
||||
HRESULT CInArchive::ReadDirEntry(CDatabase &database)
|
||||
{
|
||||
CItem item;
|
||||
UInt64 nameLength = ReadEncInt();
|
||||
if (nameLength == 0 || nameLength >= 0x10000000)
|
||||
UInt64 nameLen = ReadEncInt();
|
||||
if (nameLen == 0 || nameLen > (1 << 13))
|
||||
return S_FALSE;
|
||||
ReadString((int)nameLength, item.Name);
|
||||
ReadString((unsigned)nameLen, item.Name);
|
||||
item.Section = ReadEncInt();
|
||||
item.Offset = ReadEncInt();
|
||||
item.Size = ReadEncInt();
|
||||
@@ -268,9 +286,14 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
|
||||
UInt32 headerSize = ReadUInt32();
|
||||
if (headerSize != 0x60)
|
||||
return S_FALSE;
|
||||
database.PhySize = headerSize;
|
||||
|
||||
UInt32 unknown1 = ReadUInt32();
|
||||
if (unknown1 != 0 && unknown1 != 1) // it's 0 in one .sll file
|
||||
return S_FALSE;
|
||||
|
||||
IsArc = true;
|
||||
|
||||
/* UInt32 timeStamp = */ ReadUInt32();
|
||||
// Considered as a big-endian DWORD, it appears to contain seconds (MSB) and
|
||||
// fractional seconds (second byte).
|
||||
@@ -280,37 +303,39 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
|
||||
GUID g;
|
||||
ReadGUID(g); // {7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC}
|
||||
ReadGUID(g); // {7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC}
|
||||
const int kNumSections = 2;
|
||||
const unsigned kNumSections = 2;
|
||||
UInt64 sectionOffsets[kNumSections];
|
||||
UInt64 sectionSizes[kNumSections];
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 0; i < kNumSections; i++)
|
||||
{
|
||||
sectionOffsets[i] = ReadUInt64();
|
||||
sectionSizes[i] = ReadUInt64();
|
||||
UInt64 end = sectionOffsets[i] + sectionSizes[i];
|
||||
database.UpdatePhySize(end);
|
||||
}
|
||||
// if (chmVersion == 3)
|
||||
database.ContentOffset = ReadUInt64();
|
||||
/*
|
||||
else
|
||||
database.ContentOffset = _startPosition + 0x58
|
||||
database.ContentOffset = database.StartPosition + 0x58
|
||||
*/
|
||||
|
||||
/*
|
||||
// Section 0
|
||||
ReadChunk(inStream, sectionOffsets[0], sectionSizes[0]);
|
||||
if (sectionSizes[0] != 0x18)
|
||||
if (sectionSizes[0] < 0x18)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 0x01FE)
|
||||
return S_FALSE;
|
||||
ReadUInt32(); // unknown: 01FE
|
||||
ReadUInt32(); // unknown: 0
|
||||
UInt64 fileSize = ReadUInt64();
|
||||
database.UpdatePhySize(fileSize);
|
||||
ReadUInt32(); // unknown: 0
|
||||
ReadUInt32(); // unknown: 0
|
||||
*/
|
||||
|
||||
// Section 1: The Directory Listing
|
||||
ReadChunk(inStream, sectionOffsets[1], sectionSizes[1]);
|
||||
if (ReadUInt32() != NHeader::kItspSignature)
|
||||
if (ReadUInt32() != kSignature_ITSP)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 1) // version
|
||||
return S_FALSE;
|
||||
@@ -340,13 +365,13 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
|
||||
for (UInt32 ci = 0; ci < numDirChunks; ci++)
|
||||
{
|
||||
UInt64 chunkPos = _inBuffer.GetProcessedSize();
|
||||
if (ReadUInt32() == NHeader::kPmglSignature)
|
||||
if (ReadUInt32() == kSignature_PMGL)
|
||||
{
|
||||
// The quickref area is written backwards from the end of the chunk.
|
||||
// One quickref entry exists for every n entries in the file, where n
|
||||
// is calculated as 1 + (1 << quickref density). So for density = 2, n = 5.
|
||||
|
||||
UInt32 quickrefLength = ReadUInt32(); // Length of free space and/or quickref area at end of directory chunk
|
||||
UInt32 quickrefLength = ReadUInt32(); // Len of free space and/or quickref area at end of directory chunk
|
||||
if (quickrefLength > dirChunkSize || quickrefLength < 2)
|
||||
return S_FALSE;
|
||||
ReadUInt32(); // Always 0
|
||||
@@ -354,7 +379,7 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
|
||||
// directory in sequence (-1 if this is the first listing chunk)
|
||||
ReadUInt32(); // Chunk number of next listing chunk when reading
|
||||
// directory in sequence (-1 if this is the last listing chunk)
|
||||
int numItems = 0;
|
||||
unsigned numItems = 0;
|
||||
for (;;)
|
||||
{
|
||||
UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;
|
||||
@@ -383,10 +408,13 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
if (ReadUInt32() != 0x28) // Location of header section table
|
||||
return S_FALSE;
|
||||
UInt32 numHeaderSections = ReadUInt32();
|
||||
const int kNumHeaderSectionsMax = 5;
|
||||
const unsigned kNumHeaderSectionsMax = 5;
|
||||
if (numHeaderSections != kNumHeaderSectionsMax)
|
||||
return S_FALSE;
|
||||
ReadUInt32(); // Length of post-header table
|
||||
|
||||
IsArc = true;
|
||||
|
||||
ReadUInt32(); // Len of post-header table
|
||||
GUID g;
|
||||
ReadGUID(g); // {0A9007C1-4076-11D3-8789-0000F8105754}
|
||||
|
||||
@@ -398,6 +426,8 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
{
|
||||
sectionOffsets[i] = ReadUInt64();
|
||||
sectionSizes[i] = ReadUInt64();
|
||||
UInt64 end = sectionOffsets[i] + sectionSizes[i];
|
||||
database.UpdatePhySize(end);
|
||||
}
|
||||
|
||||
// Post-Header
|
||||
@@ -436,11 +466,11 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
ReadUInt32(); // $20000 (Same as field following chunk size in directory index)
|
||||
|
||||
ReadUInt64(); // 0 (unknown)
|
||||
if (ReadUInt32() != NHeader::kCaolSignature)
|
||||
if (ReadUInt32() != kSignature_CAOL)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 2) // (Most likely a version number)
|
||||
return S_FALSE;
|
||||
UInt32 caolLength = ReadUInt32(); // $50 (Length of the CAOL section, which includes the ITSF section)
|
||||
UInt32 caolLength = ReadUInt32(); // $50 (Len of the CAOL section, which includes the ITSF section)
|
||||
if (caolLength >= 0x2C)
|
||||
{
|
||||
/* UInt32 c7 = */ ReadUInt16(); // Unknown. Remains the same when identical files are built.
|
||||
@@ -458,13 +488,15 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
ReadUInt32(); // 0 (Unknown)
|
||||
if (caolLength == 0x2C)
|
||||
{
|
||||
database.ContentOffset = 0;
|
||||
// fprintf(stdout, "\n !!!NewFormat\n");
|
||||
// fflush(stdout);
|
||||
database.ContentOffset = 0; // maybe we must add database.StartPosition here?
|
||||
database.NewFormat = true;
|
||||
}
|
||||
else if (caolLength == 0x50)
|
||||
{
|
||||
ReadUInt32(); // 0 (Unknown)
|
||||
if (ReadUInt32() != NHeader::kItsfSignature)
|
||||
if (ReadUInt32() != kSignature_ITSF)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 4) // $4 (Version number -- CHM uses 3)
|
||||
return S_FALSE;
|
||||
@@ -473,7 +505,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
UInt32 unknown = ReadUInt32();
|
||||
if (unknown != 0 && unknown != 1) // = 0 for some HxW files, 1 in other cases;
|
||||
return S_FALSE;
|
||||
database.ContentOffset = _startPosition + ReadUInt64();
|
||||
database.ContentOffset = database.StartPosition + ReadUInt64();
|
||||
/* UInt32 timeStamp = */ ReadUInt32();
|
||||
// A timestamp of some sort.
|
||||
// Considered as a big-endian DWORD, it appears to contain
|
||||
@@ -486,21 +518,21 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
// Section 0
|
||||
ReadChunk(inStream, _startPosition + sectionOffsets[0], sectionSizes[0]);
|
||||
if (sectionSizes[0] != 0x18)
|
||||
ReadChunk(inStream, database.StartPosition + sectionOffsets[0], sectionSizes[0]);
|
||||
if (sectionSizes[0] < 0x18)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 0x01FE)
|
||||
return S_FALSE;
|
||||
ReadUInt32(); // unknown: 01FE
|
||||
ReadUInt32(); // unknown: 0
|
||||
UInt64 fileSize = ReadUInt64();
|
||||
database.UpdatePhySize(fileSize);
|
||||
ReadUInt32(); // unknown: 0
|
||||
ReadUInt32(); // unknown: 0
|
||||
*/
|
||||
|
||||
// Section 1: The Directory Listing
|
||||
ReadChunk(inStream, _startPosition + sectionOffsets[1], sectionSizes[1]);
|
||||
if (ReadUInt32() != NHeader::kIfcmSignature)
|
||||
ReadChunk(inStream, database.StartPosition + sectionOffsets[1], sectionSizes[1]);
|
||||
if (ReadUInt32() != kSignature_IFCM)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 1) // (probably a version number)
|
||||
return S_FALSE;
|
||||
@@ -516,9 +548,9 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
for (UInt32 ci = 0; ci < numDirChunks; ci++)
|
||||
{
|
||||
UInt64 chunkPos = _inBuffer.GetProcessedSize();
|
||||
if (ReadUInt32() == NHeader::kAollSignature)
|
||||
if (ReadUInt32() == kSignature_AOLL)
|
||||
{
|
||||
UInt32 quickrefLength = ReadUInt32(); // Length of quickref area at end of directory chunk
|
||||
UInt32 quickrefLength = ReadUInt32(); // Len of quickref area at end of directory chunk
|
||||
if (quickrefLength > dirChunkSize || quickrefLength < 2)
|
||||
return S_FALSE;
|
||||
ReadUInt64(); // Directory chunk number
|
||||
@@ -533,7 +565,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
ReadUInt32(); // 1 (unknown -- other values have also been seen here)
|
||||
ReadUInt32(); // 0 (unknown)
|
||||
|
||||
int numItems = 0;
|
||||
unsigned numItems = 0;
|
||||
for (;;)
|
||||
{
|
||||
UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;
|
||||
@@ -544,11 +576,11 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
break;
|
||||
if (database.NewFormat)
|
||||
{
|
||||
UInt16 nameLength = ReadUInt16();
|
||||
if (nameLength == 0)
|
||||
UInt16 nameLen = ReadUInt16();
|
||||
if (nameLen == 0)
|
||||
return S_FALSE;
|
||||
UString name;
|
||||
ReadUString((int)nameLength, name);
|
||||
ReadUString((unsigned)nameLen, name);
|
||||
AString s;
|
||||
ConvertUnicodeToUTF8(name, s);
|
||||
Byte b = ReadByte();
|
||||
@@ -637,10 +669,10 @@ static int CompareFiles(const int *p1, const int *p2, void *param)
|
||||
|
||||
void CFilesDatabase::SetIndices()
|
||||
{
|
||||
for (int i = 0; i < Items.Size(); i++)
|
||||
FOR_VECTOR (i, Items)
|
||||
{
|
||||
const CItem &item = Items[i];
|
||||
if (item.IsUserItem() && item.Name.Length() != 1)
|
||||
if (item.IsUserItem() && item.Name.Len() != 1)
|
||||
Indices.Add(i);
|
||||
}
|
||||
}
|
||||
@@ -654,7 +686,7 @@ bool CFilesDatabase::Check()
|
||||
{
|
||||
UInt64 maxPos = 0;
|
||||
UInt64 prevSection = 0;
|
||||
for(int i = 0; i < Indices.Size(); i++)
|
||||
FOR_VECTOR (i, Indices)
|
||||
{
|
||||
const CItem &item = Items[Indices[i]];
|
||||
if (item.Section == 0 || item.IsDir())
|
||||
@@ -684,9 +716,9 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
|
||||
for (int i = 0; i < numSections; i++)
|
||||
{
|
||||
CSectionInfo section;
|
||||
UInt16 nameLength = ReadUInt16();
|
||||
UInt16 nameLen = ReadUInt16();
|
||||
UString name;
|
||||
ReadUString(nameLength, name);
|
||||
ReadUString(nameLen, name);
|
||||
if (ReadUInt16() != 0)
|
||||
return S_FALSE;
|
||||
if (!ConvertUnicodeToUTF8(name, section.Name))
|
||||
@@ -695,7 +727,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
|
||||
}
|
||||
}
|
||||
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 1; i < database.Sections.Size(); i++)
|
||||
{
|
||||
CSectionInfo §ion = database.Sections[i];
|
||||
@@ -736,7 +768,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
|
||||
{
|
||||
// Control Data
|
||||
RINOK(DecompressStream(inStream, database, sectionPrefix + kControlData));
|
||||
for (int mi = 0; mi < section.Methods.Size(); mi++)
|
||||
FOR_VECTOR (mi, section.Methods)
|
||||
{
|
||||
CMethodInfo &method = section.Methods[mi];
|
||||
UInt32 numDWORDS = ReadUInt32();
|
||||
@@ -744,7 +776,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
|
||||
{
|
||||
if (numDWORDS < 5)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != NHeader::kLzxcSignature)
|
||||
if (ReadUInt32() != kSignature_LZXC)
|
||||
return S_FALSE;
|
||||
CLzxInfo &li = method.LzxInfo;
|
||||
li.Version = ReadUInt32();
|
||||
@@ -778,7 +810,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
|
||||
else
|
||||
{
|
||||
UInt32 numBytes = numDWORDS * 4;
|
||||
method.ControlData.SetCapacity(numBytes);
|
||||
method.ControlData.Alloc(numBytes);
|
||||
ReadBytes(method.ControlData, numBytes);
|
||||
}
|
||||
}
|
||||
@@ -791,7 +823,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
|
||||
}
|
||||
|
||||
// read ResetTable for LZX
|
||||
for (int mi = 0; mi < section.Methods.Size(); mi++)
|
||||
FOR_VECTOR (mi, section.Methods)
|
||||
{
|
||||
CMethodInfo &method = section.Methods[mi];
|
||||
if (method.IsLzx())
|
||||
@@ -819,16 +851,16 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
|
||||
UInt32 numEntries = ReadUInt32();
|
||||
if (ReadUInt32() != 8) // Size of table entry (bytes)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 0x28) // Length of table header
|
||||
if (ReadUInt32() != 0x28) // Len of table header
|
||||
return S_FALSE;
|
||||
rt.UncompressedSize = ReadUInt64();
|
||||
rt.CompressedSize = ReadUInt64();
|
||||
rt.BlockSize = ReadUInt64(); // 0x8000 block size for locations below
|
||||
if (rt.BlockSize != 0x8000)
|
||||
return S_FALSE;
|
||||
rt.ResetOffsets.Reserve(numEntries);
|
||||
rt.ResetOffsets.ClearAndReserve(numEntries);
|
||||
for (UInt32 i = 0; i < numEntries; i++)
|
||||
rt.ResetOffsets.Add(ReadUInt64());
|
||||
rt.ResetOffsets.AddInReserved(ReadUInt64());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -843,77 +875,91 @@ HRESULT CInArchive::Open2(IInStream *inStream,
|
||||
const UInt64 *searchHeaderSizeLimit,
|
||||
CFilesDatabase &database)
|
||||
{
|
||||
IsArc = false;
|
||||
HeadersError = false;
|
||||
UnexpectedEnd = false;
|
||||
UnsupportedFeature = false;
|
||||
|
||||
database.Clear();
|
||||
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition));
|
||||
|
||||
database.Help2Format = false;
|
||||
database.Help2Format = _help2;
|
||||
const UInt32 chmVersion = 3;
|
||||
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &database.StartPosition));
|
||||
|
||||
if (!_inBuffer.Create(1 << 14))
|
||||
return E_OUTOFMEMORY;
|
||||
_inBuffer.SetStream(inStream);
|
||||
_inBuffer.Init();
|
||||
|
||||
if (_help2)
|
||||
{
|
||||
if (!_inBuffer.Create(1 << 14))
|
||||
return E_OUTOFMEMORY;
|
||||
_inBuffer.SetStream(inStream);
|
||||
_inBuffer.Init();
|
||||
UInt64 value = 0;
|
||||
const int kSignatureSize = 8;
|
||||
UInt64 hxsSignature = NHeader::GetHxsSignature();
|
||||
UInt64 chmSignature = ((UInt64)chmVersion << 32)| NHeader::kItsfSignature;
|
||||
UInt64 signature = ((UInt64)kSignature_ITLS << 32)| kSignature_ITOL;
|
||||
UInt64 limit = 1 << 18;
|
||||
if (searchHeaderSizeLimit)
|
||||
if (limit > *searchHeaderSizeLimit)
|
||||
limit = *searchHeaderSizeLimit;
|
||||
|
||||
UInt64 val = 0;
|
||||
for (;;)
|
||||
{
|
||||
Byte b;
|
||||
if (!_inBuffer.ReadByte(b))
|
||||
return S_FALSE;
|
||||
value >>= 8;
|
||||
value |= ((UInt64)b) << ((kSignatureSize - 1) * 8);
|
||||
val >>= 8;
|
||||
val |= ((UInt64)b) << ((kSignatureSize - 1) * 8);
|
||||
if (_inBuffer.GetProcessedSize() >= kSignatureSize)
|
||||
{
|
||||
if (value == chmSignature)
|
||||
if (val == signature)
|
||||
break;
|
||||
if (value == hxsSignature)
|
||||
{
|
||||
database.Help2Format = true;
|
||||
break;
|
||||
}
|
||||
if (_inBuffer.GetProcessedSize() > limit)
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
_startPosition += _inBuffer.GetProcessedSize() - kSignatureSize;
|
||||
}
|
||||
|
||||
if (database.Help2Format)
|
||||
{
|
||||
database.StartPosition += _inBuffer.GetProcessedSize() - kSignatureSize;
|
||||
RINOK(OpenHelp2(inStream, database));
|
||||
if (database.NewFormat)
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ReadUInt32() != kSignature_ITSF)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != chmVersion)
|
||||
return S_FALSE;
|
||||
RINOK(OpenChm(inStream, database));
|
||||
}
|
||||
|
||||
|
||||
#ifndef CHM_LOW
|
||||
|
||||
try
|
||||
{
|
||||
HRESULT res = OpenHighLevel(inStream, database);
|
||||
if (res == S_FALSE)
|
||||
try
|
||||
{
|
||||
HRESULT res = OpenHighLevel(inStream, database);
|
||||
if (res == S_FALSE)
|
||||
{
|
||||
UnsupportedFeature = true;
|
||||
database.HighLevelClear();
|
||||
return S_OK;
|
||||
}
|
||||
RINOK(res);
|
||||
database.LowLevel = false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
database.HighLevelClear();
|
||||
return S_OK;
|
||||
throw;
|
||||
}
|
||||
RINOK(res);
|
||||
database.LowLevel = false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
// catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
catch(CEnexpectedEndException &) { UnexpectedEnd = true; }
|
||||
catch(CHeaderErrorException &) { HeadersError = true; }
|
||||
catch(...) { throw; }
|
||||
|
||||
#endif
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -923,15 +969,22 @@ HRESULT CInArchive::Open(IInStream *inStream,
|
||||
{
|
||||
try
|
||||
{
|
||||
HRESULT res = Open2(inStream, searchHeaderSizeLimit, database);
|
||||
_inBuffer.ReleaseStream();
|
||||
return res;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
_inBuffer.ReleaseStream();
|
||||
throw;
|
||||
try
|
||||
{
|
||||
HRESULT res = Open2(inStream, searchHeaderSizeLimit, database);
|
||||
m_InStreamRef.Release();
|
||||
return res;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
m_InStreamRef.Release();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
catch(CEnexpectedEndException &) { UnexpectedEnd = true; }
|
||||
catch(CHeaderErrorException &) { HeadersError = true; }
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
46
CPP/7zip/Archive/Chm/ChmIn.h
Executable file → Normal file
46
CPP/7zip/Archive/Chm/ChmIn.h
Executable file → Normal file
@@ -3,13 +3,12 @@
|
||||
#ifndef __ARCHIVE_CHM_IN_H
|
||||
#define __ARCHIVE_CHM_IN_H
|
||||
|
||||
#include "Common/Buffer.h"
|
||||
#include "Common/MyString.h"
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "../../Common/InBuffer.h"
|
||||
|
||||
#include "ChmHeader.h"
|
||||
#include "../../Common/InBuffer.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NChm {
|
||||
@@ -23,21 +22,21 @@ struct CItem
|
||||
|
||||
bool IsFormatRelatedItem() const
|
||||
{
|
||||
if (Name.Length() < 2)
|
||||
if (Name.Len() < 2)
|
||||
return false;
|
||||
return Name[0] == ':' && Name[1] == ':';
|
||||
}
|
||||
|
||||
bool IsUserItem() const
|
||||
{
|
||||
if (Name.Length() < 2)
|
||||
if (Name.Len() < 2)
|
||||
return false;
|
||||
return Name[0] == '/';
|
||||
}
|
||||
|
||||
bool IsDir() const
|
||||
{
|
||||
if (Name.Length() == 0)
|
||||
if (Name.Len() == 0)
|
||||
return false;
|
||||
return (Name.Back() == '/');
|
||||
}
|
||||
@@ -45,15 +44,19 @@ struct CItem
|
||||
|
||||
struct CDatabase
|
||||
{
|
||||
UInt64 StartPosition;
|
||||
UInt64 ContentOffset;
|
||||
CObjectVector<CItem> Items;
|
||||
AString NewFormatString;
|
||||
bool Help2Format;
|
||||
bool NewFormat;
|
||||
UInt64 PhySize;
|
||||
|
||||
void UpdatePhySize(UInt64 v) { if (PhySize < v) PhySize = v; }
|
||||
|
||||
int FindItem(const AString &name) const
|
||||
{
|
||||
for (int i = 0; i < Items.Size(); i++)
|
||||
FOR_VECTOR (i, Items)
|
||||
if (Items[i].Name == name)
|
||||
return i;
|
||||
return -1;
|
||||
@@ -65,6 +68,8 @@ struct CDatabase
|
||||
NewFormatString.Empty();
|
||||
Help2Format = false;
|
||||
Items.Clear();
|
||||
StartPosition = 0;
|
||||
PhySize = 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -74,15 +79,16 @@ struct CResetTable
|
||||
UInt64 CompressedSize;
|
||||
UInt64 BlockSize;
|
||||
CRecordVector<UInt64> ResetOffsets;
|
||||
|
||||
bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const
|
||||
{
|
||||
if (blockIndex >= ResetOffsets.Size())
|
||||
return false;
|
||||
UInt64 startPos = ResetOffsets[(int)blockIndex];
|
||||
UInt64 startPos = ResetOffsets[(unsigned)blockIndex];
|
||||
if (blockIndex + numBlocks >= ResetOffsets.Size())
|
||||
size = CompressedSize - startPos;
|
||||
else
|
||||
size = ResetOffsets[(int)(blockIndex + numBlocks)] - startPos;
|
||||
size = ResetOffsets[(unsigned)(blockIndex + numBlocks)] - startPos;
|
||||
return true;
|
||||
}
|
||||
bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const
|
||||
@@ -107,7 +113,7 @@ struct CLzxInfo
|
||||
{
|
||||
if (Version == 2 || Version == 3)
|
||||
{
|
||||
for (int i = 0; i <= 31; i++)
|
||||
for (unsigned i = 0; i <= 31; i++)
|
||||
if (((UInt32)1 << i) >= WindowSize)
|
||||
return 15 + i;
|
||||
}
|
||||
@@ -123,7 +129,7 @@ struct CLzxInfo
|
||||
UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
|
||||
if (blockIndex >= ResetTable.ResetOffsets.Size())
|
||||
return false;
|
||||
offset = ResetTable.ResetOffsets[(int)blockIndex];
|
||||
offset = ResetTable.ResetOffsets[(unsigned)blockIndex];
|
||||
return true;
|
||||
}
|
||||
bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const
|
||||
@@ -202,18 +208,21 @@ public:
|
||||
bool Check();
|
||||
};
|
||||
|
||||
/*
|
||||
class CProgressVirt
|
||||
{
|
||||
public:
|
||||
STDMETHOD(SetTotal)(const UInt64 *numFiles) PURE;
|
||||
STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE;
|
||||
};
|
||||
*/
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
UInt64 _startPosition;
|
||||
CMyComPtr<ISequentialInStream> m_InStreamRef;
|
||||
::CInBuffer _inBuffer;
|
||||
UInt64 _chunkSize;
|
||||
bool _help2;
|
||||
|
||||
Byte ReadByte();
|
||||
void ReadBytes(Byte *data, UInt32 size);
|
||||
@@ -222,8 +231,8 @@ class CInArchive
|
||||
UInt32 ReadUInt32();
|
||||
UInt64 ReadUInt64();
|
||||
UInt64 ReadEncInt();
|
||||
void ReadString(int size, AString &s);
|
||||
void ReadUString(int size, UString &s);
|
||||
void ReadString(unsigned size, AString &s);
|
||||
void ReadUString(unsigned size, UString &s);
|
||||
void ReadGUID(GUID &g);
|
||||
|
||||
HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size);
|
||||
@@ -232,6 +241,13 @@ class CInArchive
|
||||
HRESULT DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name);
|
||||
|
||||
public:
|
||||
bool IsArc;
|
||||
bool HeadersError;
|
||||
bool UnexpectedEnd;
|
||||
bool UnsupportedFeature;
|
||||
|
||||
CInArchive(bool help2) { _help2 = help2; }
|
||||
|
||||
HRESULT OpenChm(IInStream *inStream, CDatabase &database);
|
||||
HRESULT OpenHelp2(IInStream *inStream, CDatabase &database);
|
||||
HRESULT OpenHighLevel(IInStream *inStream, CFilesDatabase &database);
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
// ChmRegister.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/RegisterArc.h"
|
||||
|
||||
#include "ChmHandler.h"
|
||||
static IInArchive *CreateArc() { return new NArchive::NChm::CHandler; }
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"Chm", L"chm chi chq chw hxs hxi hxr hxq hxw lit", 0, 0xE9, { 'I', 'T', 'S', 'F' }, 4, false, CreateArc, 0 };
|
||||
|
||||
REGISTER_ARC(Chm)
|
||||
2
CPP/7zip/Archive/Chm/StdAfx.h
Executable file → Normal file
2
CPP/7zip/Archive/Chm/StdAfx.h
Executable file → Normal file
@@ -3,6 +3,6 @@
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,239 +0,0 @@
|
||||
// ComHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "../../Compress/CopyCoder.h"
|
||||
|
||||
#include "ComHandler.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCom {
|
||||
|
||||
STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidIsDir, VT_BOOL},
|
||||
{ NULL, kpidSize, VT_UI8},
|
||||
{ NULL, kpidPackSize, VT_UI8},
|
||||
{ NULL, kpidCTime, VT_FILETIME},
|
||||
{ NULL, kpidMTime, VT_FILETIME}
|
||||
};
|
||||
|
||||
STATPROPSTG kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidClusterSize, VT_UI4},
|
||||
{ NULL, kpidSectorSize, VT_UI4}
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
{
|
||||
case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break;
|
||||
case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break;
|
||||
case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
const CRef &ref = _db.Refs[index];
|
||||
const CItem &item = _db.Items[ref.Did];
|
||||
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPath: prop = _db.GetItemPath(index); break;
|
||||
case kpidIsDir: prop = item.IsDir(); break;
|
||||
case kpidCTime: prop = item.CTime; break;
|
||||
case kpidMTime: prop = item.MTime; break;
|
||||
case kpidPackSize: if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break;
|
||||
case kpidSize: if (!item.IsDir()) prop = item.Size; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
try
|
||||
{
|
||||
if (_db.Open(inStream) != S_OK)
|
||||
return S_FALSE;
|
||||
_stream = inStream;
|
||||
}
|
||||
catch(...) { return S_FALSE; }
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_db.Clear();
|
||||
_stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == (UInt32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _db.Refs.Size();
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
UInt32 i;
|
||||
UInt64 totalSize = 0;
|
||||
for(i = 0; i < numItems; i++)
|
||||
{
|
||||
const CItem &item = _db.Items[_db.Refs[allFilesMode ? i : indices[i]].Did];
|
||||
if (!item.IsDir())
|
||||
totalSize += item.Size;
|
||||
}
|
||||
RINOK(extractCallback->SetTotal(totalSize));
|
||||
|
||||
UInt64 totalPackSize;
|
||||
totalSize = totalPackSize = 0;
|
||||
|
||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
|
||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
lps->InSize = totalPackSize;
|
||||
lps->OutSize = totalSize;
|
||||
RINOK(lps->SetCur());
|
||||
Int32 index = allFilesMode ? i : indices[i];
|
||||
const CItem &item = _db.Items[_db.Refs[index].Did];
|
||||
|
||||
CMyComPtr<ISequentialOutStream> outStream;
|
||||
Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
RINOK(extractCallback->GetStream(index, &outStream, askMode));
|
||||
|
||||
if (item.IsDir())
|
||||
{
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
|
||||
continue;
|
||||
}
|
||||
|
||||
totalPackSize += _db.GetItemPackSize(item.Size);
|
||||
totalSize += item.Size;
|
||||
|
||||
if (!testMode && !outStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
Int32 res = NExtract::NOperationResult::kDataError;
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
HRESULT hres = GetStream(index, &inStream);
|
||||
if (hres == S_FALSE)
|
||||
res = NExtract::NOperationResult::kDataError;
|
||||
else if (hres == E_NOTIMPL)
|
||||
res = NExtract::NOperationResult::kUnSupportedMethod;
|
||||
else
|
||||
{
|
||||
RINOK(hres);
|
||||
if (inStream)
|
||||
{
|
||||
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
|
||||
if (copyCoderSpec->TotalSize == item.Size)
|
||||
res = NExtract::NOperationResult::kOK;
|
||||
}
|
||||
}
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(res));
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
*numItems = _db.Refs.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*stream = 0;
|
||||
const CItem &item = _db.Items[_db.Refs[index].Did];
|
||||
CClusterInStream *streamSpec = new CClusterInStream;
|
||||
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
|
||||
streamSpec->Stream = _stream;
|
||||
streamSpec->StartOffset = 0;
|
||||
|
||||
bool isLargeStream = _db.IsLargeStream(item.Size);
|
||||
int bsLog = isLargeStream ? _db.SectorSizeBits : _db.MiniSectorSizeBits;
|
||||
streamSpec->BlockSizeLog = bsLog;
|
||||
streamSpec->Size = item.Size;
|
||||
|
||||
UInt32 clusterSize = (UInt32)1 << bsLog;
|
||||
UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog;
|
||||
if (numClusters64 >= ((UInt32)1 << 31))
|
||||
return E_NOTIMPL;
|
||||
streamSpec->Vector.Reserve((int)numClusters64);
|
||||
UInt32 sid = item.Sid;
|
||||
UInt64 size = item.Size;
|
||||
|
||||
if (size != 0)
|
||||
{
|
||||
for (;; size -= clusterSize)
|
||||
{
|
||||
if (isLargeStream)
|
||||
{
|
||||
if (sid >= _db.FatSize)
|
||||
return S_FALSE;
|
||||
streamSpec->Vector.Add(sid + 1);
|
||||
sid = _db.Fat[sid];
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt64 val;
|
||||
if (sid >= _db.MatSize || !_db.GetMiniCluster(sid, val) || val >= (UInt64)1 << 32)
|
||||
return S_FALSE;
|
||||
streamSpec->Vector.Add((UInt32)val);
|
||||
sid = _db.Mat[sid];
|
||||
}
|
||||
if (size <= clusterSize)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sid != NFatID::kEndOfChain)
|
||||
return S_FALSE;
|
||||
RINOK(streamSpec->InitAndSeek());
|
||||
*stream = streamTemp.Detach();
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,28 +0,0 @@
|
||||
// ComHandler.h
|
||||
|
||||
#ifndef __ARCHIVE_COM_HANDLER_H
|
||||
#define __ARCHIVE_COM_HANDLER_H
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "../IArchive.h"
|
||||
#include "ComIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCom {
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IInArchiveGetStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CDatabase _db;
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -1,389 +0,0 @@
|
||||
// Archive/ComIn.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/Alloc.h"
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "Common/IntToString.h"
|
||||
#include "Common/MyCom.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "ComIn.h"
|
||||
|
||||
#define Get16(p) GetUi16(p)
|
||||
#define Get32(p) GetUi32(p)
|
||||
|
||||
namespace NArchive{
|
||||
namespace NCom{
|
||||
|
||||
static const UInt32 kSignatureSize = 8;
|
||||
static const Byte kSignature[kSignatureSize] = { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
|
||||
|
||||
void CUInt32Buf::Free()
|
||||
{
|
||||
MyFree(_buf);
|
||||
_buf = 0;
|
||||
}
|
||||
|
||||
bool CUInt32Buf::Allocate(UInt32 numItems)
|
||||
{
|
||||
Free();
|
||||
if (numItems == 0)
|
||||
return true;
|
||||
size_t newSize = (size_t)numItems * sizeof(UInt32);
|
||||
if (newSize / sizeof(UInt32) != numItems)
|
||||
return false;
|
||||
_buf = (UInt32 *)MyAlloc(newSize);
|
||||
return (_buf != 0);
|
||||
}
|
||||
|
||||
static HRESULT ReadSector(IInStream *inStream, Byte *buf, int sectorSizeBits, UInt32 sid)
|
||||
{
|
||||
RINOK(inStream->Seek((((UInt64)sid + 1) << sectorSizeBits), STREAM_SEEK_SET, NULL));
|
||||
return ReadStream_FALSE(inStream, buf, (UInt32)1 << sectorSizeBits);
|
||||
}
|
||||
|
||||
static HRESULT ReadIDs(IInStream *inStream, Byte *buf, int sectorSizeBits, UInt32 sid, UInt32 *dest)
|
||||
{
|
||||
RINOK(ReadSector(inStream, buf, sectorSizeBits, sid));
|
||||
UInt32 sectorSize = (UInt32)1 << sectorSizeBits;
|
||||
for (UInt32 t = 0; t < sectorSize; t += 4)
|
||||
*dest++ = Get32(buf + t);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
|
||||
{
|
||||
ft->dwLowDateTime = Get32(p);
|
||||
ft->dwHighDateTime = Get32(p + 4);
|
||||
}
|
||||
|
||||
void CItem::Parse(const Byte *p, bool mode64bit)
|
||||
{
|
||||
memcpy(Name, p, kNameSizeMax);
|
||||
// NameSize = Get16(p + 64);
|
||||
Type = p[66];
|
||||
LeftDid = Get32(p + 68);
|
||||
RightDid = Get32(p + 72);
|
||||
SonDid = Get32(p + 76);
|
||||
// Flags = Get32(p + 96);
|
||||
GetFileTimeFromMem(p + 100, &CTime);
|
||||
GetFileTimeFromMem(p + 108, &MTime);
|
||||
Sid = Get32(p + 116);
|
||||
Size = Get32(p + 120);
|
||||
if (mode64bit)
|
||||
Size |= ((UInt64)Get32(p + 124) << 32);
|
||||
}
|
||||
|
||||
void CDatabase::Clear()
|
||||
{
|
||||
Fat.Free();
|
||||
MiniSids.Free();
|
||||
Mat.Free();
|
||||
Items.Clear();
|
||||
Refs.Clear();
|
||||
}
|
||||
|
||||
static const UInt32 kNoDid = 0xFFFFFFFF;
|
||||
|
||||
HRESULT CDatabase::AddNode(int parent, UInt32 did)
|
||||
{
|
||||
if (did == kNoDid)
|
||||
return S_OK;
|
||||
if (did >= (UInt32)Items.Size())
|
||||
return S_FALSE;
|
||||
const CItem &item = Items[did];
|
||||
if (item.IsEmpty())
|
||||
return S_FALSE;
|
||||
CRef ref;
|
||||
ref.Parent = parent;
|
||||
ref.Did = did;
|
||||
int index = Refs.Add(ref);
|
||||
if (Refs.Size() > Items.Size())
|
||||
return S_FALSE;
|
||||
RINOK(AddNode(parent, item.LeftDid));
|
||||
RINOK(AddNode(parent, item.RightDid));
|
||||
if (item.IsDir())
|
||||
{
|
||||
RINOK(AddNode(index, item.SonDid));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const char kCharOpenBracket = '[';
|
||||
static const char kCharCloseBracket = ']';
|
||||
|
||||
static UString CompoundNameToFileName(const UString &s)
|
||||
{
|
||||
UString res;
|
||||
for (int i = 0; i < s.Length(); i++)
|
||||
{
|
||||
wchar_t c = s[i];
|
||||
if (c < 0x20)
|
||||
{
|
||||
res += kCharOpenBracket;
|
||||
wchar_t buf[32];
|
||||
ConvertUInt32ToString(c, buf);
|
||||
res += buf;
|
||||
res += kCharCloseBracket;
|
||||
}
|
||||
else
|
||||
res += c;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static char g_MsiChars[] =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._";
|
||||
|
||||
static const wchar_t *kMsi_ID = L""; // L"{msi}";
|
||||
|
||||
static const int kMsiNumBits = 6;
|
||||
static const UInt32 kMsiNumChars = 1 << kMsiNumBits;
|
||||
static const UInt32 kMsiCharMask = kMsiNumChars - 1;
|
||||
static const UInt32 kMsiStartUnicodeChar = 0x3800;
|
||||
static const UInt32 kMsiUnicodeRange = kMsiNumChars * (kMsiNumChars + 1);
|
||||
|
||||
bool CompoundMsiNameToFileName(const UString &name, UString &resultName)
|
||||
{
|
||||
resultName.Empty();
|
||||
for (int i = 0; i < name.Length(); i++)
|
||||
{
|
||||
wchar_t c = name[i];
|
||||
if (c < kMsiStartUnicodeChar || c > kMsiStartUnicodeChar + kMsiUnicodeRange)
|
||||
return false;
|
||||
if (i == 0)
|
||||
resultName += kMsi_ID;
|
||||
c -= kMsiStartUnicodeChar;
|
||||
|
||||
UInt32 c0 = c & kMsiCharMask;
|
||||
UInt32 c1 = c >> kMsiNumBits;
|
||||
|
||||
if (c1 <= kMsiNumChars)
|
||||
{
|
||||
resultName += (wchar_t)g_MsiChars[c0];
|
||||
if (c1 == kMsiNumChars)
|
||||
break;
|
||||
resultName += (wchar_t)g_MsiChars[c1];
|
||||
}
|
||||
else
|
||||
resultName += L'!';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static UString ConvertName(const Byte *p, bool &isMsi)
|
||||
{
|
||||
isMsi = false;
|
||||
UString s;
|
||||
for (int i = 0; i < kNameSizeMax; i += 2)
|
||||
{
|
||||
wchar_t c = (p[i] | (wchar_t)p[i + 1] << 8);
|
||||
if (c == 0)
|
||||
break;
|
||||
s += c;
|
||||
}
|
||||
UString msiName;
|
||||
if (CompoundMsiNameToFileName(s, msiName))
|
||||
{
|
||||
isMsi = true;
|
||||
return msiName;
|
||||
}
|
||||
return CompoundNameToFileName(s);
|
||||
}
|
||||
|
||||
static UString ConvertName(const Byte *p)
|
||||
{
|
||||
bool isMsi;
|
||||
return ConvertName(p, isMsi);
|
||||
}
|
||||
|
||||
UString CDatabase::GetItemPath(UInt32 index) const
|
||||
{
|
||||
UString s;
|
||||
while (index != kNoDid)
|
||||
{
|
||||
const CRef &ref = Refs[index];
|
||||
const CItem &item = Items[ref.Did];
|
||||
if (!s.IsEmpty())
|
||||
s = (UString)WCHAR_PATH_SEPARATOR + s;
|
||||
s = ConvertName(item.Name) + s;
|
||||
index = ref.Parent;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
HRESULT CDatabase::Open(IInStream *inStream)
|
||||
{
|
||||
MainSubfile = -1;
|
||||
static const UInt32 kHeaderSize = 512;
|
||||
Byte p[kHeaderSize];
|
||||
RINOK(ReadStream_FALSE(inStream, p, kHeaderSize));
|
||||
if (memcmp(p, kSignature, kSignatureSize) != 0)
|
||||
return S_FALSE;
|
||||
if (Get16(p + 0x1A) > 4) // majorVer
|
||||
return S_FALSE;
|
||||
if (Get16(p + 0x1C) != 0xFFFE)
|
||||
return S_FALSE;
|
||||
int sectorSizeBits = Get16(p + 0x1E);
|
||||
bool mode64bit = (sectorSizeBits >= 12);
|
||||
int miniSectorSizeBits = Get16(p + 0x20);
|
||||
SectorSizeBits = sectorSizeBits;
|
||||
MiniSectorSizeBits = miniSectorSizeBits;
|
||||
|
||||
if (sectorSizeBits > 28 || miniSectorSizeBits > 28 ||
|
||||
sectorSizeBits < 7 || miniSectorSizeBits < 2 || miniSectorSizeBits > sectorSizeBits)
|
||||
return S_FALSE;
|
||||
UInt32 numSectorsForFAT = Get32(p + 0x2C);
|
||||
LongStreamMinSize = Get32(p + 0x38);
|
||||
|
||||
UInt32 sectSize = (UInt32)1 << (int)sectorSizeBits;
|
||||
|
||||
CByteBuffer sect;
|
||||
sect.SetCapacity(sectSize);
|
||||
|
||||
int ssb2 = (int)(sectorSizeBits - 2);
|
||||
UInt32 numSidsInSec = (UInt32)1 << ssb2;
|
||||
UInt32 numFatItems = numSectorsForFAT << ssb2;
|
||||
if ((numFatItems >> ssb2) != numSectorsForFAT)
|
||||
return S_FALSE;
|
||||
FatSize = numFatItems;
|
||||
|
||||
{
|
||||
CUInt32Buf bat;
|
||||
UInt32 numSectorsForBat = Get32(p + 0x48);
|
||||
const UInt32 kNumHeaderBatItems = 109;
|
||||
UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2);
|
||||
if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat)
|
||||
return S_FALSE;
|
||||
if (!bat.Allocate(numBatItems))
|
||||
return S_FALSE;
|
||||
UInt32 i;
|
||||
for (i = 0; i < kNumHeaderBatItems; i++)
|
||||
bat[i] = Get32(p + 0x4c + i * 4);
|
||||
UInt32 sid = Get32(p + 0x44);
|
||||
for (UInt32 s = 0; s < numSectorsForBat; s++)
|
||||
{
|
||||
RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, bat + i));
|
||||
i += numSidsInSec - 1;
|
||||
sid = bat[i];
|
||||
}
|
||||
numBatItems = i;
|
||||
|
||||
if (!Fat.Allocate(numFatItems))
|
||||
return S_FALSE;
|
||||
UInt32 j = 0;
|
||||
|
||||
for (i = 0; i < numFatItems; j++, i += numSidsInSec)
|
||||
{
|
||||
if (j >= numBatItems)
|
||||
return S_FALSE;
|
||||
RINOK(ReadIDs(inStream, sect, sectorSizeBits, bat[j], Fat + i));
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 numMatItems;
|
||||
{
|
||||
UInt32 numSectorsForMat = Get32(p + 0x40);
|
||||
numMatItems = (UInt32)numSectorsForMat << ssb2;
|
||||
if ((numMatItems >> ssb2) != numSectorsForMat)
|
||||
return S_FALSE;
|
||||
if (!Mat.Allocate(numMatItems))
|
||||
return S_FALSE;
|
||||
UInt32 i;
|
||||
UInt32 sid = Get32(p + 0x3C);
|
||||
for (i = 0; i < numMatItems; i += numSidsInSec)
|
||||
{
|
||||
RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, Mat + i));
|
||||
if (sid >= numFatItems)
|
||||
return S_FALSE;
|
||||
sid = Fat[sid];
|
||||
}
|
||||
if (sid != NFatID::kEndOfChain)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
{
|
||||
UInt32 sid = Get32(p + 0x30);
|
||||
for (;;)
|
||||
{
|
||||
if (sid >= numFatItems)
|
||||
return S_FALSE;
|
||||
RINOK(ReadSector(inStream, sect, sectorSizeBits, sid));
|
||||
for (UInt32 i = 0; i < sectSize; i += 128)
|
||||
{
|
||||
CItem item;
|
||||
item.Parse(sect + i, mode64bit);
|
||||
Items.Add(item);
|
||||
}
|
||||
sid = Fat[sid];
|
||||
if (sid == NFatID::kEndOfChain)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CItem root = Items[0];
|
||||
|
||||
{
|
||||
UInt32 numSectorsInMiniStream;
|
||||
{
|
||||
UInt64 numSatSects64 = (root.Size + sectSize - 1) >> sectorSizeBits;
|
||||
if (numSatSects64 > NFatID::kMaxValue)
|
||||
return S_FALSE;
|
||||
numSectorsInMiniStream = (UInt32)numSatSects64;
|
||||
}
|
||||
NumSectorsInMiniStream = numSectorsInMiniStream;
|
||||
if (!MiniSids.Allocate(numSectorsInMiniStream))
|
||||
return S_FALSE;
|
||||
{
|
||||
UInt64 matSize64 = (root.Size + ((UInt64)1 << miniSectorSizeBits) - 1) >> miniSectorSizeBits;
|
||||
if (matSize64 > NFatID::kMaxValue)
|
||||
return S_FALSE;
|
||||
MatSize = (UInt32)matSize64;
|
||||
if (numMatItems < MatSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
UInt32 sid = root.Sid;
|
||||
for (UInt32 i = 0; ; i++)
|
||||
{
|
||||
if (sid == NFatID::kEndOfChain)
|
||||
{
|
||||
if (i != numSectorsInMiniStream)
|
||||
return S_FALSE;
|
||||
break;
|
||||
}
|
||||
if (i >= numSectorsInMiniStream)
|
||||
return S_FALSE;
|
||||
MiniSids[i] = sid;
|
||||
if (sid >= numFatItems)
|
||||
return S_FALSE;
|
||||
sid = Fat[sid];
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(AddNode(-1, root.SonDid));
|
||||
|
||||
unsigned numCabs = 0;
|
||||
for (int i = 0; i < Refs.Size(); i++)
|
||||
{
|
||||
const CItem &item = Items[Refs[i].Did];
|
||||
if (item.IsDir() || numCabs > 1)
|
||||
continue;
|
||||
bool isMsiName;
|
||||
UString msiName = ConvertName(item.Name, isMsiName);
|
||||
if (isMsiName && msiName.Right(4).CompareNoCase(L".cab") == 0)
|
||||
{
|
||||
numCabs++;
|
||||
MainSubfile = i;
|
||||
}
|
||||
}
|
||||
if (numCabs > 1)
|
||||
MainSubfile = -1;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,119 +0,0 @@
|
||||
// Archive/ComIn.h
|
||||
|
||||
#ifndef __ARCHIVE_COM_IN_H
|
||||
#define __ARCHIVE_COM_IN_H
|
||||
|
||||
#include "Common/MyString.h"
|
||||
#include "Common/Buffer.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCom {
|
||||
|
||||
struct CUInt32Buf
|
||||
{
|
||||
UInt32 *_buf;
|
||||
public:
|
||||
CUInt32Buf(): _buf(0) {}
|
||||
~CUInt32Buf() { Free(); }
|
||||
void Free();
|
||||
bool Allocate(UInt32 numItems);
|
||||
operator UInt32 *() const { return _buf; };
|
||||
};
|
||||
|
||||
namespace NFatID
|
||||
{
|
||||
const UInt32 kFree = 0xFFFFFFFF;
|
||||
const UInt32 kEndOfChain = 0xFFFFFFFE;
|
||||
const UInt32 kFatSector = 0xFFFFFFFD;
|
||||
const UInt32 kMatSector = 0xFFFFFFFC;
|
||||
const UInt32 kMaxValue = 0xFFFFFFFA;
|
||||
}
|
||||
|
||||
namespace NItemType
|
||||
{
|
||||
const Byte kEmpty = 0;
|
||||
const Byte kStorage = 1;
|
||||
const Byte kStream = 2;
|
||||
const Byte kLockBytes = 3;
|
||||
const Byte kProperty = 4;
|
||||
const Byte kRootStorage = 5;
|
||||
}
|
||||
|
||||
const UInt32 kNameSizeMax = 64;
|
||||
|
||||
struct CItem
|
||||
{
|
||||
Byte Name[kNameSizeMax];
|
||||
// UInt16 NameSize;
|
||||
// UInt32 Flags;
|
||||
FILETIME CTime;
|
||||
FILETIME MTime;
|
||||
UInt64 Size;
|
||||
UInt32 LeftDid;
|
||||
UInt32 RightDid;
|
||||
UInt32 SonDid;
|
||||
UInt32 Sid;
|
||||
Byte Type;
|
||||
|
||||
bool IsEmpty() const { return Type == NItemType::kEmpty; }
|
||||
bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; }
|
||||
|
||||
void Parse(const Byte *p, bool mode64bit);
|
||||
};
|
||||
|
||||
struct CRef
|
||||
{
|
||||
int Parent;
|
||||
UInt32 Did;
|
||||
};
|
||||
|
||||
class CDatabase
|
||||
{
|
||||
UInt32 NumSectorsInMiniStream;
|
||||
CUInt32Buf MiniSids;
|
||||
|
||||
HRESULT AddNode(int parent, UInt32 did);
|
||||
public:
|
||||
|
||||
CUInt32Buf Fat;
|
||||
UInt32 FatSize;
|
||||
|
||||
CUInt32Buf Mat;
|
||||
UInt32 MatSize;
|
||||
|
||||
CObjectVector<CItem> Items;
|
||||
CRecordVector<CRef> Refs;
|
||||
|
||||
UInt32 LongStreamMinSize;
|
||||
int SectorSizeBits;
|
||||
int MiniSectorSizeBits;
|
||||
|
||||
Int32 MainSubfile;
|
||||
|
||||
void Clear();
|
||||
bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; }
|
||||
UString GetItemPath(UInt32 index) const;
|
||||
|
||||
UInt64 GetItemPackSize(UInt64 size) const
|
||||
{
|
||||
UInt64 mask = ((UInt64)1 << (IsLargeStream(size) ? SectorSizeBits : MiniSectorSizeBits)) - 1;
|
||||
return (size + mask) & ~mask;
|
||||
}
|
||||
|
||||
bool GetMiniCluster(UInt32 sid, UInt64 &res) const
|
||||
{
|
||||
int subBits = SectorSizeBits - MiniSectorSizeBits;
|
||||
UInt32 fid = sid >> subBits;
|
||||
if (fid >= NumSectorsInMiniStream)
|
||||
return false;
|
||||
res = (((UInt64)MiniSids[fid] + 1) << subBits) + (sid & ((1 << subBits) - 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
HRESULT Open(IInStream *inStream);
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -1,13 +0,0 @@
|
||||
// ComRegister.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../Common/RegisterArc.h"
|
||||
|
||||
#include "ComHandler.h"
|
||||
static IInArchive *CreateArc() { return new NArchive::NCom::CHandler; }
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"Compound", L"msi msp doc xls ppt", 0, 0xE5, { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }, 8, false, CreateArc, 0 };
|
||||
|
||||
REGISTER_ARC(Com)
|
||||
875
CPP/7zip/Archive/ComHandler.cpp
Normal file
875
CPP/7zip/Archive/ComHandler.cpp
Normal file
@@ -0,0 +1,875 @@
|
||||
// ComHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/IntToString.h"
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyString.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "../Compress/CopyCoder.h"
|
||||
|
||||
#define Get16(p) GetUi16(p)
|
||||
#define Get32(p) GetUi32(p)
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCom {
|
||||
|
||||
#define SIGNATURE { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }
|
||||
static const UInt32 kSignatureSize = 8;
|
||||
static const Byte kSignature[kSignatureSize] = SIGNATURE;
|
||||
|
||||
enum EType
|
||||
{
|
||||
k_Type_Common,
|
||||
k_Type_Msi,
|
||||
k_Type_Msp,
|
||||
k_Type_Doc,
|
||||
k_Type_Ppt,
|
||||
k_Type_Xls,
|
||||
};
|
||||
|
||||
static const char *kExtensions[] =
|
||||
{
|
||||
"compound"
|
||||
, "msi"
|
||||
, "msp"
|
||||
, "doc"
|
||||
, "ppt"
|
||||
, "xls"
|
||||
};
|
||||
|
||||
namespace NFatID
|
||||
{
|
||||
static const UInt32 kFree = 0xFFFFFFFF;
|
||||
static const UInt32 kEndOfChain = 0xFFFFFFFE;
|
||||
static const UInt32 kFatSector = 0xFFFFFFFD;
|
||||
static const UInt32 kMatSector = 0xFFFFFFFC;
|
||||
static const UInt32 kMaxValue = 0xFFFFFFFA;
|
||||
}
|
||||
|
||||
namespace NItemType
|
||||
{
|
||||
static const Byte kEmpty = 0;
|
||||
static const Byte kStorage = 1;
|
||||
static const Byte kStream = 2;
|
||||
static const Byte kLockBytes = 3;
|
||||
static const Byte kProperty = 4;
|
||||
static const Byte kRootStorage = 5;
|
||||
}
|
||||
|
||||
static const UInt32 kNameSizeMax = 64;
|
||||
|
||||
struct CItem
|
||||
{
|
||||
Byte Name[kNameSizeMax];
|
||||
// UInt16 NameSize;
|
||||
// UInt32 Flags;
|
||||
FILETIME CTime;
|
||||
FILETIME MTime;
|
||||
UInt64 Size;
|
||||
UInt32 LeftDid;
|
||||
UInt32 RightDid;
|
||||
UInt32 SonDid;
|
||||
UInt32 Sid;
|
||||
Byte Type;
|
||||
|
||||
bool IsEmpty() const { return Type == NItemType::kEmpty; }
|
||||
bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; }
|
||||
|
||||
void Parse(const Byte *p, bool mode64bit);
|
||||
};
|
||||
|
||||
struct CRef
|
||||
{
|
||||
int Parent;
|
||||
UInt32 Did;
|
||||
};
|
||||
|
||||
class CDatabase
|
||||
{
|
||||
UInt32 NumSectorsInMiniStream;
|
||||
CObjArray<UInt32> MiniSids;
|
||||
|
||||
HRESULT AddNode(int parent, UInt32 did);
|
||||
public:
|
||||
|
||||
CObjArray<UInt32> Fat;
|
||||
UInt32 FatSize;
|
||||
|
||||
CObjArray<UInt32> Mat;
|
||||
UInt32 MatSize;
|
||||
|
||||
CObjectVector<CItem> Items;
|
||||
CRecordVector<CRef> Refs;
|
||||
|
||||
UInt32 LongStreamMinSize;
|
||||
unsigned SectorSizeBits;
|
||||
unsigned MiniSectorSizeBits;
|
||||
|
||||
Int32 MainSubfile;
|
||||
|
||||
UInt64 PhySize;
|
||||
EType Type;
|
||||
|
||||
bool IsNotArcType() const
|
||||
{
|
||||
return
|
||||
Type != k_Type_Msi &&
|
||||
Type != k_Type_Msp;
|
||||
}
|
||||
|
||||
void UpdatePhySize(UInt64 val)
|
||||
{
|
||||
if (PhySize < val)
|
||||
PhySize = val;
|
||||
}
|
||||
HRESULT ReadSector(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid);
|
||||
HRESULT ReadIDs(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid, UInt32 *dest);
|
||||
|
||||
HRESULT Update_PhySize_WithItem(unsigned index);
|
||||
|
||||
void Clear();
|
||||
bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; }
|
||||
UString GetItemPath(UInt32 index) const;
|
||||
|
||||
UInt64 GetItemPackSize(UInt64 size) const
|
||||
{
|
||||
UInt64 mask = ((UInt64)1 << (IsLargeStream(size) ? SectorSizeBits : MiniSectorSizeBits)) - 1;
|
||||
return (size + mask) & ~mask;
|
||||
}
|
||||
|
||||
bool GetMiniCluster(UInt32 sid, UInt64 &res) const
|
||||
{
|
||||
unsigned subBits = SectorSizeBits - MiniSectorSizeBits;
|
||||
UInt32 fid = sid >> subBits;
|
||||
if (fid >= NumSectorsInMiniStream)
|
||||
return false;
|
||||
res = (((UInt64)MiniSids[fid] + 1) << subBits) + (sid & ((1 << subBits) - 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
HRESULT Open(IInStream *inStream);
|
||||
};
|
||||
|
||||
|
||||
HRESULT CDatabase::ReadSector(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid)
|
||||
{
|
||||
UpdatePhySize(((UInt64)sid + 2) << sectorSizeBits);
|
||||
RINOK(inStream->Seek((((UInt64)sid + 1) << sectorSizeBits), STREAM_SEEK_SET, NULL));
|
||||
return ReadStream_FALSE(inStream, buf, (UInt32)1 << sectorSizeBits);
|
||||
}
|
||||
|
||||
HRESULT CDatabase::ReadIDs(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid, UInt32 *dest)
|
||||
{
|
||||
RINOK(ReadSector(inStream, buf, sectorSizeBits, sid));
|
||||
UInt32 sectorSize = (UInt32)1 << sectorSizeBits;
|
||||
for (UInt32 t = 0; t < sectorSize; t += 4)
|
||||
*dest++ = Get32(buf + t);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
|
||||
{
|
||||
ft->dwLowDateTime = Get32(p);
|
||||
ft->dwHighDateTime = Get32(p + 4);
|
||||
}
|
||||
|
||||
void CItem::Parse(const Byte *p, bool mode64bit)
|
||||
{
|
||||
memcpy(Name, p, kNameSizeMax);
|
||||
// NameSize = Get16(p + 64);
|
||||
Type = p[66];
|
||||
LeftDid = Get32(p + 68);
|
||||
RightDid = Get32(p + 72);
|
||||
SonDid = Get32(p + 76);
|
||||
// Flags = Get32(p + 96);
|
||||
GetFileTimeFromMem(p + 100, &CTime);
|
||||
GetFileTimeFromMem(p + 108, &MTime);
|
||||
Sid = Get32(p + 116);
|
||||
Size = Get32(p + 120);
|
||||
if (mode64bit)
|
||||
Size |= ((UInt64)Get32(p + 124) << 32);
|
||||
}
|
||||
|
||||
void CDatabase::Clear()
|
||||
{
|
||||
PhySize = 0;
|
||||
|
||||
Fat.Free();
|
||||
MiniSids.Free();
|
||||
Mat.Free();
|
||||
Items.Clear();
|
||||
Refs.Clear();
|
||||
}
|
||||
|
||||
static const UInt32 kNoDid = 0xFFFFFFFF;
|
||||
|
||||
HRESULT CDatabase::AddNode(int parent, UInt32 did)
|
||||
{
|
||||
if (did == kNoDid)
|
||||
return S_OK;
|
||||
if (did >= (UInt32)Items.Size())
|
||||
return S_FALSE;
|
||||
const CItem &item = Items[did];
|
||||
if (item.IsEmpty())
|
||||
return S_FALSE;
|
||||
CRef ref;
|
||||
ref.Parent = parent;
|
||||
ref.Did = did;
|
||||
int index = Refs.Add(ref);
|
||||
if (Refs.Size() > Items.Size())
|
||||
return S_FALSE;
|
||||
RINOK(AddNode(parent, item.LeftDid));
|
||||
RINOK(AddNode(parent, item.RightDid));
|
||||
if (item.IsDir())
|
||||
{
|
||||
RINOK(AddNode(index, item.SonDid));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const char kCharOpenBracket = '[';
|
||||
static const char kCharCloseBracket = ']';
|
||||
|
||||
static UString CompoundNameToFileName(const UString &s)
|
||||
{
|
||||
UString res;
|
||||
for (unsigned i = 0; i < s.Len(); i++)
|
||||
{
|
||||
wchar_t c = s[i];
|
||||
if (c < 0x20)
|
||||
{
|
||||
res += kCharOpenBracket;
|
||||
wchar_t buf[32];
|
||||
ConvertUInt32ToString(c, buf);
|
||||
res += buf;
|
||||
res += kCharCloseBracket;
|
||||
}
|
||||
else
|
||||
res += c;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static char g_MsiChars[] =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._";
|
||||
|
||||
static const wchar_t *kMsi_ID = L""; // L"{msi}";
|
||||
|
||||
static const unsigned kMsiNumBits = 6;
|
||||
static const UInt32 kMsiNumChars = 1 << kMsiNumBits;
|
||||
static const UInt32 kMsiCharMask = kMsiNumChars - 1;
|
||||
static const UInt32 kMsiStartUnicodeChar = 0x3800;
|
||||
static const UInt32 kMsiUnicodeRange = kMsiNumChars * (kMsiNumChars + 1);
|
||||
|
||||
static bool IsMsiName(const Byte *p)
|
||||
{
|
||||
UInt32 c = Get16(p);
|
||||
return
|
||||
c >= kMsiStartUnicodeChar &&
|
||||
c <= kMsiStartUnicodeChar + kMsiUnicodeRange;
|
||||
}
|
||||
|
||||
static bool AreEqualNames(const Byte *rawName, const char *asciiName)
|
||||
{
|
||||
for (unsigned i = 0; i < kNameSizeMax / 2; i++)
|
||||
{
|
||||
wchar_t c = Get16(rawName + i * 2);
|
||||
wchar_t c2 = (Byte)asciiName[i];
|
||||
if (c != c2)
|
||||
return false;
|
||||
if (c == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CompoundMsiNameToFileName(const UString &name, UString &resultName)
|
||||
{
|
||||
resultName.Empty();
|
||||
for (unsigned i = 0; i < name.Len(); i++)
|
||||
{
|
||||
wchar_t c = name[i];
|
||||
if (c < kMsiStartUnicodeChar || c > kMsiStartUnicodeChar + kMsiUnicodeRange)
|
||||
return false;
|
||||
if (i == 0)
|
||||
resultName += kMsi_ID;
|
||||
c -= kMsiStartUnicodeChar;
|
||||
|
||||
UInt32 c0 = c & kMsiCharMask;
|
||||
UInt32 c1 = c >> kMsiNumBits;
|
||||
|
||||
if (c1 <= kMsiNumChars)
|
||||
{
|
||||
resultName += (wchar_t)g_MsiChars[c0];
|
||||
if (c1 == kMsiNumChars)
|
||||
break;
|
||||
resultName += (wchar_t)g_MsiChars[c1];
|
||||
}
|
||||
else
|
||||
resultName += L'!';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static UString ConvertName(const Byte *p, bool &isMsi)
|
||||
{
|
||||
isMsi = false;
|
||||
UString s;
|
||||
for (unsigned i = 0; i < kNameSizeMax; i += 2)
|
||||
{
|
||||
wchar_t c = Get16(p + i);
|
||||
if (c == 0)
|
||||
break;
|
||||
s += c;
|
||||
}
|
||||
UString msiName;
|
||||
if (CompoundMsiNameToFileName(s, msiName))
|
||||
{
|
||||
isMsi = true;
|
||||
return msiName;
|
||||
}
|
||||
return CompoundNameToFileName(s);
|
||||
}
|
||||
|
||||
static UString ConvertName(const Byte *p)
|
||||
{
|
||||
bool isMsi;
|
||||
return ConvertName(p, isMsi);
|
||||
}
|
||||
|
||||
UString CDatabase::GetItemPath(UInt32 index) const
|
||||
{
|
||||
UString s;
|
||||
while (index != kNoDid)
|
||||
{
|
||||
const CRef &ref = Refs[index];
|
||||
const CItem &item = Items[ref.Did];
|
||||
if (!s.IsEmpty())
|
||||
s.InsertAtFront(WCHAR_PATH_SEPARATOR);
|
||||
s.Insert(0, ConvertName(item.Name));
|
||||
index = ref.Parent;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
HRESULT CDatabase::Update_PhySize_WithItem(unsigned index)
|
||||
{
|
||||
const CItem &item = Items[index];
|
||||
bool isLargeStream = (index == 0 || IsLargeStream(item.Size));
|
||||
if (!isLargeStream)
|
||||
return S_OK;
|
||||
unsigned bsLog = isLargeStream ? SectorSizeBits : MiniSectorSizeBits;
|
||||
// streamSpec->Size = item.Size;
|
||||
|
||||
UInt32 clusterSize = (UInt32)1 << bsLog;
|
||||
UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog;
|
||||
if (numClusters64 >= ((UInt32)1 << 31))
|
||||
return S_FALSE;
|
||||
UInt32 sid = item.Sid;
|
||||
UInt64 size = item.Size;
|
||||
|
||||
if (size != 0)
|
||||
{
|
||||
for (;; size -= clusterSize)
|
||||
{
|
||||
// if (isLargeStream)
|
||||
{
|
||||
if (sid >= FatSize)
|
||||
return S_FALSE;
|
||||
UpdatePhySize(((UInt64)sid + 2) << bsLog);
|
||||
sid = Fat[sid];
|
||||
}
|
||||
if (size <= clusterSize)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sid != NFatID::kEndOfChain)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// There is name "[!]MsiPatchSequence" in msp files
|
||||
static const unsigned kMspSequence_Size = 18;
|
||||
static const Byte kMspSequence[kMspSequence_Size] =
|
||||
{ 0x40, 0x48, 0x96, 0x45, 0x6C, 0x3E, 0xE4, 0x45,
|
||||
0xE6, 0x42, 0x16, 0x42, 0x37, 0x41, 0x27, 0x41,
|
||||
0x37, 0x41 };
|
||||
|
||||
HRESULT CDatabase::Open(IInStream *inStream)
|
||||
{
|
||||
MainSubfile = -1;
|
||||
Type = k_Type_Common;
|
||||
const UInt32 kHeaderSize = 512;
|
||||
Byte p[kHeaderSize];
|
||||
PhySize = kHeaderSize;
|
||||
RINOK(ReadStream_FALSE(inStream, p, kHeaderSize));
|
||||
if (memcmp(p, kSignature, kSignatureSize) != 0)
|
||||
return S_FALSE;
|
||||
if (Get16(p + 0x1A) > 4) // majorVer
|
||||
return S_FALSE;
|
||||
if (Get16(p + 0x1C) != 0xFFFE) // Little-endian
|
||||
return S_FALSE;
|
||||
unsigned sectorSizeBits = Get16(p + 0x1E);
|
||||
bool mode64bit = (sectorSizeBits >= 12);
|
||||
unsigned miniSectorSizeBits = Get16(p + 0x20);
|
||||
SectorSizeBits = sectorSizeBits;
|
||||
MiniSectorSizeBits = miniSectorSizeBits;
|
||||
|
||||
if (sectorSizeBits > 28 ||
|
||||
sectorSizeBits < 7 ||
|
||||
miniSectorSizeBits > 28 ||
|
||||
miniSectorSizeBits < 2 ||
|
||||
miniSectorSizeBits > sectorSizeBits)
|
||||
return S_FALSE;
|
||||
UInt32 numSectorsForFAT = Get32(p + 0x2C); // SAT
|
||||
LongStreamMinSize = Get32(p + 0x38);
|
||||
|
||||
UInt32 sectSize = (UInt32)1 << sectorSizeBits;
|
||||
|
||||
CByteBuffer sect(sectSize);
|
||||
|
||||
unsigned ssb2 = sectorSizeBits - 2;
|
||||
UInt32 numSidsInSec = (UInt32)1 << ssb2;
|
||||
UInt32 numFatItems = numSectorsForFAT << ssb2;
|
||||
if ((numFatItems >> ssb2) != numSectorsForFAT)
|
||||
return S_FALSE;
|
||||
FatSize = numFatItems;
|
||||
|
||||
{
|
||||
UInt32 numSectorsForBat = Get32(p + 0x48); // master sector allocation table
|
||||
const UInt32 kNumHeaderBatItems = 109;
|
||||
UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2);
|
||||
if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat)
|
||||
return S_FALSE;
|
||||
CObjArray<UInt32> bat(numBatItems);
|
||||
UInt32 i;
|
||||
for (i = 0; i < kNumHeaderBatItems; i++)
|
||||
bat[i] = Get32(p + 0x4c + i * 4);
|
||||
UInt32 sid = Get32(p + 0x44);
|
||||
for (UInt32 s = 0; s < numSectorsForBat; s++)
|
||||
{
|
||||
RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, bat + i));
|
||||
i += numSidsInSec - 1;
|
||||
sid = bat[i];
|
||||
}
|
||||
numBatItems = i;
|
||||
|
||||
Fat.Alloc(numFatItems);
|
||||
UInt32 j = 0;
|
||||
|
||||
for (i = 0; i < numFatItems; j++, i += numSidsInSec)
|
||||
{
|
||||
if (j >= numBatItems)
|
||||
return S_FALSE;
|
||||
RINOK(ReadIDs(inStream, sect, sectorSizeBits, bat[j], Fat + i));
|
||||
}
|
||||
FatSize = numFatItems = i;
|
||||
}
|
||||
|
||||
UInt32 numMatItems;
|
||||
{
|
||||
UInt32 numSectorsForMat = Get32(p + 0x40);
|
||||
numMatItems = (UInt32)numSectorsForMat << ssb2;
|
||||
if ((numMatItems >> ssb2) != numSectorsForMat)
|
||||
return S_FALSE;
|
||||
Mat.Alloc(numMatItems);
|
||||
UInt32 i;
|
||||
UInt32 sid = Get32(p + 0x3C); // short-sector table SID
|
||||
for (i = 0; i < numMatItems; i += numSidsInSec)
|
||||
{
|
||||
RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, Mat + i));
|
||||
if (sid >= numFatItems)
|
||||
return S_FALSE;
|
||||
sid = Fat[sid];
|
||||
}
|
||||
if (sid != NFatID::kEndOfChain)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
{
|
||||
CByteBuffer used(numFatItems);
|
||||
for (UInt32 i = 0; i < numFatItems; i++)
|
||||
used[i] = 0;
|
||||
UInt32 sid = Get32(p + 0x30); // directory stream SID
|
||||
for (;;)
|
||||
{
|
||||
if (sid >= numFatItems)
|
||||
return S_FALSE;
|
||||
if (used[sid])
|
||||
return S_FALSE;
|
||||
used[sid] = 1;
|
||||
RINOK(ReadSector(inStream, sect, sectorSizeBits, sid));
|
||||
for (UInt32 i = 0; i < sectSize; i += 128)
|
||||
{
|
||||
CItem item;
|
||||
item.Parse(sect + i, mode64bit);
|
||||
Items.Add(item);
|
||||
}
|
||||
sid = Fat[sid];
|
||||
if (sid == NFatID::kEndOfChain)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const CItem &root = Items[0];
|
||||
|
||||
{
|
||||
UInt32 numSectorsInMiniStream;
|
||||
{
|
||||
UInt64 numSatSects64 = (root.Size + sectSize - 1) >> sectorSizeBits;
|
||||
if (numSatSects64 > NFatID::kMaxValue)
|
||||
return S_FALSE;
|
||||
numSectorsInMiniStream = (UInt32)numSatSects64;
|
||||
}
|
||||
NumSectorsInMiniStream = numSectorsInMiniStream;
|
||||
MiniSids.Alloc(numSectorsInMiniStream);
|
||||
{
|
||||
UInt64 matSize64 = (root.Size + ((UInt64)1 << miniSectorSizeBits) - 1) >> miniSectorSizeBits;
|
||||
if (matSize64 > NFatID::kMaxValue)
|
||||
return S_FALSE;
|
||||
MatSize = (UInt32)matSize64;
|
||||
if (numMatItems < MatSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
UInt32 sid = root.Sid;
|
||||
for (UInt32 i = 0; ; i++)
|
||||
{
|
||||
if (sid == NFatID::kEndOfChain)
|
||||
{
|
||||
if (i != numSectorsInMiniStream)
|
||||
return S_FALSE;
|
||||
break;
|
||||
}
|
||||
if (i >= numSectorsInMiniStream)
|
||||
return S_FALSE;
|
||||
MiniSids[i] = sid;
|
||||
if (sid >= numFatItems)
|
||||
return S_FALSE;
|
||||
sid = Fat[sid];
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(AddNode(-1, root.SonDid));
|
||||
|
||||
unsigned numCabs = 0;
|
||||
FOR_VECTOR (i, Refs)
|
||||
{
|
||||
const CItem &item = Items[Refs[i].Did];
|
||||
if (item.IsDir() || numCabs > 1)
|
||||
continue;
|
||||
bool isMsiName;
|
||||
UString msiName = ConvertName(item.Name, isMsiName);
|
||||
if (isMsiName && msiName.Len() >= 4 &&
|
||||
MyStringCompareNoCase(msiName.RightPtr(4), L".cab") == 0)
|
||||
{
|
||||
numCabs++;
|
||||
MainSubfile = i;
|
||||
}
|
||||
}
|
||||
if (numCabs > 1)
|
||||
MainSubfile = -1;
|
||||
|
||||
{
|
||||
FOR_VECTOR(t, Items)
|
||||
{
|
||||
Update_PhySize_WithItem(t);
|
||||
}
|
||||
}
|
||||
{
|
||||
FOR_VECTOR(t, Items)
|
||||
{
|
||||
const CItem &item = Items[t];
|
||||
|
||||
if (IsMsiName(item.Name))
|
||||
{
|
||||
Type = k_Type_Msi;
|
||||
if (memcmp(item.Name, kMspSequence, kMspSequence_Size) == 0)
|
||||
{
|
||||
Type = k_Type_Msp;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (AreEqualNames(item.Name, "WordDocument"))
|
||||
{
|
||||
Type = k_Type_Doc;
|
||||
break;
|
||||
}
|
||||
if (AreEqualNames(item.Name, "PowerPoint Document"))
|
||||
{
|
||||
Type = k_Type_Ppt;
|
||||
break;
|
||||
}
|
||||
if (AreEqualNames(item.Name, "Workbook"))
|
||||
{
|
||||
Type = k_Type_Xls;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IInArchiveGetStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CDatabase _db;
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidPath,
|
||||
kpidSize,
|
||||
kpidPackSize,
|
||||
kpidCTime,
|
||||
kpidMTime
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidExtension,
|
||||
kpidClusterSize,
|
||||
kpidSectorSize
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidExtension: prop = kExtensions[_db.Type]; break;
|
||||
case kpidPhySize: prop = _db.PhySize; break;
|
||||
case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break;
|
||||
case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break;
|
||||
case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break;
|
||||
case kpidIsNotArcType: if (_db.IsNotArcType()) prop = true; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
const CRef &ref = _db.Refs[index];
|
||||
const CItem &item = _db.Items[ref.Did];
|
||||
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPath: prop = _db.GetItemPath(index); break;
|
||||
case kpidIsDir: prop = item.IsDir(); break;
|
||||
case kpidCTime: prop = item.CTime; break;
|
||||
case kpidMTime: prop = item.MTime; break;
|
||||
case kpidPackSize: if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break;
|
||||
case kpidSize: if (!item.IsDir()) prop = item.Size; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback * /* openArchiveCallback */)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
try
|
||||
{
|
||||
if (_db.Open(inStream) != S_OK)
|
||||
return S_FALSE;
|
||||
_stream = inStream;
|
||||
}
|
||||
catch(...) { return S_FALSE; }
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_db.Clear();
|
||||
_stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _db.Refs.Size();
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
UInt32 i;
|
||||
UInt64 totalSize = 0;
|
||||
for(i = 0; i < numItems; i++)
|
||||
{
|
||||
const CItem &item = _db.Items[_db.Refs[allFilesMode ? i : indices[i]].Did];
|
||||
if (!item.IsDir())
|
||||
totalSize += item.Size;
|
||||
}
|
||||
RINOK(extractCallback->SetTotal(totalSize));
|
||||
|
||||
UInt64 totalPackSize;
|
||||
totalSize = totalPackSize = 0;
|
||||
|
||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
|
||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
lps->InSize = totalPackSize;
|
||||
lps->OutSize = totalSize;
|
||||
RINOK(lps->SetCur());
|
||||
Int32 index = allFilesMode ? i : indices[i];
|
||||
const CItem &item = _db.Items[_db.Refs[index].Did];
|
||||
|
||||
CMyComPtr<ISequentialOutStream> outStream;
|
||||
Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
RINOK(extractCallback->GetStream(index, &outStream, askMode));
|
||||
|
||||
if (item.IsDir())
|
||||
{
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
|
||||
continue;
|
||||
}
|
||||
|
||||
totalPackSize += _db.GetItemPackSize(item.Size);
|
||||
totalSize += item.Size;
|
||||
|
||||
if (!testMode && !outStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
Int32 res = NExtract::NOperationResult::kDataError;
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
HRESULT hres = GetStream(index, &inStream);
|
||||
if (hres == S_FALSE)
|
||||
res = NExtract::NOperationResult::kDataError;
|
||||
else if (hres == E_NOTIMPL)
|
||||
res = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else
|
||||
{
|
||||
RINOK(hres);
|
||||
if (inStream)
|
||||
{
|
||||
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
|
||||
if (copyCoderSpec->TotalSize == item.Size)
|
||||
res = NExtract::NOperationResult::kOK;
|
||||
}
|
||||
}
|
||||
outStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(res));
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
*numItems = _db.Refs.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*stream = 0;
|
||||
UInt32 itemIndex = _db.Refs[index].Did;
|
||||
const CItem &item = _db.Items[itemIndex];
|
||||
CClusterInStream *streamSpec = new CClusterInStream;
|
||||
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
|
||||
streamSpec->Stream = _stream;
|
||||
streamSpec->StartOffset = 0;
|
||||
|
||||
bool isLargeStream = (itemIndex == 0 || _db.IsLargeStream(item.Size));
|
||||
int bsLog = isLargeStream ? _db.SectorSizeBits : _db.MiniSectorSizeBits;
|
||||
streamSpec->BlockSizeLog = bsLog;
|
||||
streamSpec->Size = item.Size;
|
||||
|
||||
UInt32 clusterSize = (UInt32)1 << bsLog;
|
||||
UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog;
|
||||
if (numClusters64 >= ((UInt32)1 << 31))
|
||||
return E_NOTIMPL;
|
||||
streamSpec->Vector.ClearAndReserve((unsigned)numClusters64);
|
||||
UInt32 sid = item.Sid;
|
||||
UInt64 size = item.Size;
|
||||
|
||||
if (size != 0)
|
||||
{
|
||||
for (;; size -= clusterSize)
|
||||
{
|
||||
if (isLargeStream)
|
||||
{
|
||||
if (sid >= _db.FatSize)
|
||||
return S_FALSE;
|
||||
streamSpec->Vector.AddInReserved(sid + 1);
|
||||
sid = _db.Fat[sid];
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt64 val = 0;
|
||||
if (sid >= _db.MatSize || !_db.GetMiniCluster(sid, val) || val >= (UInt64)1 << 32)
|
||||
return S_FALSE;
|
||||
streamSpec->Vector.AddInReserved((UInt32)val);
|
||||
sid = _db.Mat[sid];
|
||||
}
|
||||
if (size <= clusterSize)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sid != NFatID::kEndOfChain)
|
||||
return S_FALSE;
|
||||
RINOK(streamSpec->InitAndSeek());
|
||||
*stream = streamTemp.Detach();
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ "Compound", "msi msp doc xls ppt", 0, 0xE5,
|
||||
kSignatureSize, SIGNATURE,
|
||||
0,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Com)
|
||||
|
||||
}}
|
||||
0
CPP/7zip/Archive/Common/CoderMixer.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Common/CoderMixer.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Common/CoderMixer.h
Executable file → Normal file
0
CPP/7zip/Archive/Common/CoderMixer.h
Executable file → Normal file
70
CPP/7zip/Archive/Common/CoderMixer2.cpp
Executable file → Normal file
70
CPP/7zip/Archive/Common/CoderMixer2.cpp
Executable file → Normal file
@@ -11,16 +11,23 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
|
||||
{
|
||||
srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);
|
||||
|
||||
UInt32 j;
|
||||
UInt32 j;
|
||||
_srcInToDestOutMap.ClearAndSetSize(NumSrcInStreams);
|
||||
DestOutToSrcInMap.ClearAndSetSize(NumSrcInStreams);
|
||||
|
||||
for (j = 0; j < NumSrcInStreams; j++)
|
||||
{
|
||||
_srcInToDestOutMap.Add(0);
|
||||
DestOutToSrcInMap.Add(0);
|
||||
_srcInToDestOutMap[j] = 0;
|
||||
DestOutToSrcInMap[j] = 0;
|
||||
}
|
||||
|
||||
_srcOutToDestInMap.ClearAndSetSize(_numSrcOutStreams);
|
||||
_destInToSrcOutMap.ClearAndSetSize(_numSrcOutStreams);
|
||||
|
||||
for (j = 0; j < _numSrcOutStreams; j++)
|
||||
{
|
||||
_srcOutToDestInMap.Add(0);
|
||||
_destInToSrcOutMap.Add(0);
|
||||
_srcOutToDestInMap[j] = 0;
|
||||
_destInToSrcOutMap[j] = 0;
|
||||
}
|
||||
|
||||
UInt32 destInOffset = 0;
|
||||
@@ -53,66 +60,57 @@ CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
|
||||
|
||||
void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)
|
||||
{
|
||||
destBindInfo.Coders.Clear();
|
||||
destBindInfo.BindPairs.Clear();
|
||||
destBindInfo.InStreams.Clear();
|
||||
destBindInfo.OutStreams.Clear();
|
||||
destBindInfo.Coders.ClearAndReserve(_srcBindInfo.Coders.Size());
|
||||
destBindInfo.BindPairs.ClearAndReserve(_srcBindInfo.BindPairs.Size());
|
||||
destBindInfo.InStreams.ClearAndReserve(_srcBindInfo.OutStreams.Size());
|
||||
destBindInfo.OutStreams.ClearAndReserve(_srcBindInfo.InStreams.Size());
|
||||
|
||||
int i;
|
||||
for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--)
|
||||
unsigned i;
|
||||
for (i = _srcBindInfo.Coders.Size(); i != 0;)
|
||||
{
|
||||
i--;
|
||||
const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i];
|
||||
CCoderStreamsInfo destCoderInfo;
|
||||
destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams;
|
||||
destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams;
|
||||
destBindInfo.Coders.Add(destCoderInfo);
|
||||
destBindInfo.Coders.AddInReserved(destCoderInfo);
|
||||
}
|
||||
for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--)
|
||||
for (i = _srcBindInfo.BindPairs.Size(); i != 0;)
|
||||
{
|
||||
i--;
|
||||
const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i];
|
||||
CBindPair destBindPair;
|
||||
destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex];
|
||||
destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex];
|
||||
destBindInfo.BindPairs.Add(destBindPair);
|
||||
destBindInfo.BindPairs.AddInReserved(destBindPair);
|
||||
}
|
||||
for (i = 0; i < _srcBindInfo.InStreams.Size(); i++)
|
||||
destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);
|
||||
destBindInfo.OutStreams.AddInReserved(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);
|
||||
for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++)
|
||||
destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);
|
||||
destBindInfo.InStreams.AddInReserved(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);
|
||||
}
|
||||
|
||||
CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
NumInStreams(numInStreams),
|
||||
NumOutStreams(numOutStreams)
|
||||
{
|
||||
InSizes.Reserve(NumInStreams);
|
||||
InSizePointers.Reserve(NumInStreams);
|
||||
OutSizes.Reserve(NumOutStreams);
|
||||
OutSizePointers.Reserve(NumOutStreams);
|
||||
}
|
||||
|
||||
static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
|
||||
void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
|
||||
CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
|
||||
{
|
||||
sizes.Clear();
|
||||
sizePointers.Clear();
|
||||
sizes.ClearAndSetSize(numItems);
|
||||
sizePointers.ClearAndSetSize(numItems);
|
||||
for(UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
if (srcSizes == 0 || srcSizes[i] == NULL)
|
||||
if (!srcSizes || !srcSizes[i])
|
||||
{
|
||||
sizes.Add(0);
|
||||
sizePointers.Add(NULL);
|
||||
sizes[i] = 0;
|
||||
sizePointers[i] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sizes.Add(*srcSizes[i]);
|
||||
sizePointers.Add(&sizes.Back());
|
||||
sizes[i] = *(srcSizes[i]);
|
||||
sizePointers[i] = &sizes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes,
|
||||
const UInt64 **outSizes)
|
||||
void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
|
||||
{
|
||||
SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
|
||||
SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
|
||||
|
||||
19
CPP/7zip/Archive/Common/CoderMixer2.h
Executable file → Normal file
19
CPP/7zip/Archive/Common/CoderMixer2.h
Executable file → Normal file
@@ -3,9 +3,9 @@
|
||||
#ifndef __CODER_MIXER2_H
|
||||
#define __CODER_MIXER2_H
|
||||
|
||||
#include "../../../Common/MyVector.h"
|
||||
#include "../../../Common/Types.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/MyVector.h"
|
||||
|
||||
#include "../../ICoder.h"
|
||||
|
||||
namespace NCoderMixer {
|
||||
@@ -52,7 +52,7 @@ struct CBindInfo
|
||||
{
|
||||
numInStreams = 0;
|
||||
numOutStreams = 0;
|
||||
for (int i = 0; i < Coders.Size(); i++)
|
||||
FOR_VECTOR (i, Coders)
|
||||
{
|
||||
const CCoderStreamsInfo &coderStreamsInfo = Coders[i];
|
||||
numInStreams += coderStreamsInfo.NumInStreams;
|
||||
@@ -62,14 +62,14 @@ struct CBindInfo
|
||||
|
||||
int FindBinderForInStream(UInt32 inStream) const
|
||||
{
|
||||
for (int i = 0; i < BindPairs.Size(); i++)
|
||||
FOR_VECTOR (i, BindPairs)
|
||||
if (BindPairs[i].InIndex == inStream)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
int FindBinderForOutStream(UInt32 outStream) const
|
||||
{
|
||||
for (int i = 0; i < BindPairs.Size(); i++)
|
||||
FOR_VECTOR (i, BindPairs)
|
||||
if (BindPairs[i].OutIndex == outStream)
|
||||
return i;
|
||||
return -1;
|
||||
@@ -139,6 +139,9 @@ public:
|
||||
void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo);
|
||||
};
|
||||
|
||||
void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
|
||||
CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems);
|
||||
|
||||
struct CCoderInfo2
|
||||
{
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
@@ -151,7 +154,9 @@ struct CCoderInfo2
|
||||
CRecordVector<const UInt64 *> InSizePointers;
|
||||
CRecordVector<const UInt64 *> OutSizePointers;
|
||||
|
||||
CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams);
|
||||
CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
NumInStreams(numInStreams),
|
||||
NumOutStreams(numOutStreams) {}
|
||||
void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
|
||||
|
||||
HRESULT QueryInterface(REFGUID iid, void** pp) const
|
||||
@@ -170,5 +175,5 @@ public:
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
56
CPP/7zip/Archive/Common/CoderMixer2MT.cpp
Executable file → Normal file
56
CPP/7zip/Archive/Common/CoderMixer2MT.cpp
Executable file → Normal file
@@ -9,30 +9,28 @@ namespace NCoderMixer {
|
||||
CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams):
|
||||
CCoderInfo2(numInStreams, numOutStreams)
|
||||
{
|
||||
InStreams.Reserve(NumInStreams);
|
||||
InStreamPointers.Reserve(NumInStreams);
|
||||
OutStreams.Reserve(NumOutStreams);
|
||||
OutStreamPointers.Reserve(NumOutStreams);
|
||||
InStreams.ClearAndReserve(NumInStreams);
|
||||
OutStreams.ClearAndReserve(NumOutStreams);
|
||||
}
|
||||
|
||||
void CCoder2::Execute() { Code(NULL); }
|
||||
|
||||
void CCoder2::Code(ICompressProgressInfo *progress)
|
||||
{
|
||||
InStreamPointers.Clear();
|
||||
OutStreamPointers.Clear();
|
||||
InStreamPointers.ClearAndReserve(NumInStreams);
|
||||
OutStreamPointers.ClearAndReserve(NumOutStreams);
|
||||
UInt32 i;
|
||||
for (i = 0; i < NumInStreams; i++)
|
||||
{
|
||||
if (InSizePointers[i] != NULL)
|
||||
if (InSizePointers[i])
|
||||
InSizePointers[i] = &InSizes[i];
|
||||
InStreamPointers.Add((ISequentialInStream *)InStreams[i]);
|
||||
InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
|
||||
}
|
||||
for (i = 0; i < NumOutStreams; i++)
|
||||
{
|
||||
if (OutSizePointers[i] != NULL)
|
||||
if (OutSizePointers[i])
|
||||
OutSizePointers[i] = &OutSizes[i];
|
||||
OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]);
|
||||
OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
|
||||
}
|
||||
if (Coder)
|
||||
Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
|
||||
@@ -41,7 +39,7 @@ void CCoder2::Code(ICompressProgressInfo *progress)
|
||||
Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,
|
||||
&OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);
|
||||
{
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 0; i < InStreams.Size(); i++)
|
||||
InStreams[i].Release();
|
||||
for (i = 0; i < OutStreams.Size(); i++)
|
||||
@@ -49,32 +47,13 @@ void CCoder2::Code(ICompressProgressInfo *progress)
|
||||
}
|
||||
}
|
||||
|
||||
static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
|
||||
CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
|
||||
{
|
||||
sizes.Clear();
|
||||
sizePointers.Clear();
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
if (srcSizes == 0 || srcSizes[i] == NULL)
|
||||
{
|
||||
sizes.Add(0);
|
||||
sizePointers.Add(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
sizes.Add(*srcSizes[i]);
|
||||
sizePointers.Add(&sizes.Back());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
|
||||
{
|
||||
SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
|
||||
SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
|
||||
}
|
||||
*/
|
||||
|
||||
//////////////////////////////////////
|
||||
// CCoderMixer2MT
|
||||
@@ -83,10 +62,9 @@ HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
|
||||
{
|
||||
_bindInfo = bindInfo;
|
||||
_streamBinders.Clear();
|
||||
for (int i = 0; i < _bindInfo.BindPairs.Size(); i++)
|
||||
FOR_VECTOR (i, _bindInfo.BindPairs)
|
||||
{
|
||||
_streamBinders.Add(CStreamBinder());
|
||||
RINOK(_streamBinders.Back().CreateEvents());
|
||||
RINOK(_streamBinders.AddNew().CreateEvents());
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -113,7 +91,7 @@ void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
|
||||
|
||||
void CCoderMixer2MT::ReInit()
|
||||
{
|
||||
for (int i = 0; i < _streamBinders.Size(); i++)
|
||||
FOR_VECTOR (i, _streamBinders)
|
||||
_streamBinders[i].ReInit();
|
||||
}
|
||||
|
||||
@@ -124,7 +102,7 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre
|
||||
if (_coders.Size() != _bindInfo.Coders.Size())
|
||||
throw 0;
|
||||
*/
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
{
|
||||
CCoder2 &coderInfo = _coders[i];
|
||||
@@ -179,7 +157,7 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre
|
||||
|
||||
HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)
|
||||
{
|
||||
for (int i = 0; i < _coders.Size(); i++)
|
||||
FOR_VECTOR (i, _coders)
|
||||
if (_coders[i].Result == code)
|
||||
return code;
|
||||
return S_OK;
|
||||
@@ -199,7 +177,7 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
|
||||
|
||||
Init(inStreams, outStreams);
|
||||
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != _progressCoderIndex)
|
||||
{
|
||||
|
||||
14
CPP/7zip/Archive/Common/CoderMixer2MT.h
Executable file → Normal file
14
CPP/7zip/Archive/Common/CoderMixer2MT.h
Executable file → Normal file
@@ -12,15 +12,17 @@ namespace NCoderMixer {
|
||||
|
||||
struct CCoder2: public CCoderInfo2, public CVirtThread
|
||||
{
|
||||
HRESULT Result;
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
|
||||
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
|
||||
CRecordVector<ISequentialInStream*> InStreamPointers;
|
||||
CRecordVector<ISequentialOutStream*> OutStreamPointers;
|
||||
|
||||
public:
|
||||
HRESULT Result;
|
||||
CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
|
||||
CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
|
||||
|
||||
CCoder2(UInt32 numInStreams, UInt32 numOutStreams);
|
||||
~CCoder2() { CVirtThread::WaitThreadFinish(); }
|
||||
void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
|
||||
// void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
|
||||
virtual void Execute();
|
||||
void Code(ICompressProgressInfo *progress);
|
||||
};
|
||||
@@ -48,7 +50,7 @@ class CCoderMixer2MT:
|
||||
{
|
||||
CBindInfo _bindInfo;
|
||||
CObjectVector<CStreamBinder> _streamBinders;
|
||||
int _progressCoderIndex;
|
||||
unsigned _progressCoderIndex;
|
||||
|
||||
void AddCoderCommon();
|
||||
HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams);
|
||||
@@ -68,7 +70,7 @@ public:
|
||||
HRESULT SetBindInfo(const CBindInfo &bindInfo);
|
||||
void AddCoder(ICompressCoder *coder);
|
||||
void AddCoder2(ICompressCoder2 *coder);
|
||||
void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; }
|
||||
void SetProgressCoderIndex(unsigned coderIndex) { _progressCoderIndex = coderIndex; }
|
||||
|
||||
void ReInit();
|
||||
void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
|
||||
|
||||
4
CPP/7zip/Archive/Common/CoderMixer2ST.cpp
Executable file → Normal file
4
CPP/7zip/Archive/Common/CoderMixer2ST.cpp
Executable file → Normal file
@@ -47,7 +47,7 @@ HRESULT CCoderMixer2ST::GetInStream(
|
||||
{
|
||||
seqInStream = inStreams[i];
|
||||
*inStreamRes = seqInStream.Detach();
|
||||
return S_OK;
|
||||
return S_OK;
|
||||
}
|
||||
int binderIndex = _bindInfo.FindBinderForInStream(streamIndex);
|
||||
if (binderIndex < 0)
|
||||
@@ -96,7 +96,7 @@ HRESULT CCoderMixer2ST::GetOutStream(
|
||||
{
|
||||
seqOutStream = outStreams[i];
|
||||
*outStreamRes = seqOutStream.Detach();
|
||||
return S_OK;
|
||||
return S_OK;
|
||||
}
|
||||
int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex);
|
||||
if (binderIndex < 0)
|
||||
|
||||
0
CPP/7zip/Archive/Common/CoderMixer2ST.h
Executable file → Normal file
0
CPP/7zip/Archive/Common/CoderMixer2ST.h
Executable file → Normal file
0
CPP/7zip/Archive/Common/CoderMixerMT.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Common/CoderMixerMT.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Common/CoderMixerMT.h
Executable file → Normal file
0
CPP/7zip/Archive/Common/CoderMixerMT.h
Executable file → Normal file
0
CPP/7zip/Archive/Common/CrossThreadProgress.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Common/CrossThreadProgress.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Common/CrossThreadProgress.h
Executable file → Normal file
0
CPP/7zip/Archive/Common/CrossThreadProgress.h
Executable file → Normal file
19
CPP/7zip/Archive/Common/DummyOutStream.cpp
Executable file → Normal file
19
CPP/7zip/Archive/Common/DummyOutStream.cpp
Executable file → Normal file
@@ -4,19 +4,14 @@
|
||||
|
||||
#include "DummyOutStream.h"
|
||||
|
||||
STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result;
|
||||
if(!_stream)
|
||||
{
|
||||
realProcessedSize = size;
|
||||
result = S_OK;
|
||||
}
|
||||
else
|
||||
result = _stream->Write(data, size, &realProcessedSize);
|
||||
UInt32 realProcessedSize = size;
|
||||
HRESULT res = S_OK;
|
||||
if (_stream)
|
||||
res = _stream->Write(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
if(processedSize != NULL)
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
return res;
|
||||
}
|
||||
|
||||
7
CPP/7zip/Archive/Common/DummyOutStream.h
Executable file → Normal file
7
CPP/7zip/Archive/Common/DummyOutStream.h
Executable file → Normal file
@@ -1,10 +1,11 @@
|
||||
// DummyOutStream.h
|
||||
|
||||
#ifndef __DUMMYOUTSTREAM_H
|
||||
#define __DUMMYOUTSTREAM_H
|
||||
#ifndef __DUMMY_OUT_STREAM_H
|
||||
#define __DUMMY_OUT_STREAM_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "Common/MyCom.h"
|
||||
|
||||
class CDummyOutStream:
|
||||
public ISequentialOutStream,
|
||||
|
||||
12
CPP/7zip/Archive/Common/FindSignature.cpp
Executable file → Normal file
12
CPP/7zip/Archive/Common/FindSignature.cpp
Executable file → Normal file
@@ -2,27 +2,25 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/Buffer.h"
|
||||
|
||||
#include "FindSignature.h"
|
||||
#include "../../../Common/MyBuffer.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "FindSignature.h"
|
||||
|
||||
HRESULT FindSignatureInStream(ISequentialInStream *stream,
|
||||
const Byte *signature, unsigned signatureSize,
|
||||
const UInt64 *limit, UInt64 &resPos)
|
||||
{
|
||||
resPos = 0;
|
||||
CByteBuffer byteBuffer2;
|
||||
byteBuffer2.SetCapacity(signatureSize);
|
||||
CByteBuffer byteBuffer2(signatureSize);
|
||||
RINOK(ReadStream_FALSE(stream, byteBuffer2, signatureSize));
|
||||
|
||||
if (memcmp(byteBuffer2, signature, signatureSize) == 0)
|
||||
return S_OK;
|
||||
|
||||
const UInt32 kBufferSize = (1 << 16);
|
||||
CByteBuffer byteBuffer;
|
||||
byteBuffer.SetCapacity(kBufferSize);
|
||||
CByteBuffer byteBuffer(kBufferSize);
|
||||
Byte *buffer = byteBuffer;
|
||||
UInt32 numPrevBytes = signatureSize - 1;
|
||||
memcpy(buffer, (const Byte *)byteBuffer2 + 1, numPrevBytes);
|
||||
|
||||
0
CPP/7zip/Archive/Common/FindSignature.h
Executable file → Normal file
0
CPP/7zip/Archive/Common/FindSignature.h
Executable file → Normal file
36
CPP/7zip/Archive/Common/HandlerOut.cpp
Executable file → Normal file
36
CPP/7zip/Archive/Common/HandlerOut.cpp
Executable file → Normal file
@@ -27,7 +27,7 @@ void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo
|
||||
)
|
||||
{
|
||||
UInt32 level = _level;
|
||||
if (level != (UInt32)(UInt32)-1)
|
||||
if (level != (UInt32)(Int32)-1)
|
||||
SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
|
||||
#ifndef _7ZIP_ST
|
||||
SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
|
||||
@@ -40,7 +40,7 @@ void CMultiMethodProps::Init()
|
||||
_numProcessors = _numThreads = NSystem::GetNumberOfProcessors();
|
||||
#endif
|
||||
|
||||
_level = (UInt32)(UInt32)-1;
|
||||
_level = (UInt32)(Int32)-1;
|
||||
_autoFilter = true;
|
||||
_crcSize = 4;
|
||||
_filterMethod.Clear();
|
||||
@@ -50,18 +50,18 @@ void CMultiMethodProps::Init()
|
||||
HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
|
||||
{
|
||||
UString name = nameSpec;
|
||||
name.MakeUpper();
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (name[0] == 'X')
|
||||
if (name[0] == 'x')
|
||||
{
|
||||
name.Delete(0);
|
||||
_level = 9;
|
||||
return ParsePropToUInt32(name, value, _level);
|
||||
}
|
||||
|
||||
if (name == L"CRC")
|
||||
if (name == L"crc")
|
||||
{
|
||||
name.Delete(0, 3);
|
||||
_crcSize = 4;
|
||||
@@ -70,17 +70,17 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
|
||||
|
||||
UInt32 number;
|
||||
int index = ParseStringToUInt32(name, number);
|
||||
UString realName = name.Mid(index);
|
||||
UString realName = name.Ptr(index);
|
||||
if (index == 0)
|
||||
{
|
||||
if (name.Left(2).CompareNoCase(L"MT") == 0)
|
||||
if (name.IsPrefixedBy(L"mt"))
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
RINOK(ParseMtProp(name.Mid(2), value, _numProcessors, _numThreads));
|
||||
RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));
|
||||
#endif
|
||||
return S_OK;
|
||||
}
|
||||
if (name.CompareNoCase(L"F") == 0)
|
||||
if (name.IsEqualTo("f"))
|
||||
{
|
||||
HRESULT res = PROPVARIANT_to_bool(value, _autoFilter);
|
||||
if (res == S_OK)
|
||||
@@ -105,35 +105,35 @@ void CSingleMethodProps::Init()
|
||||
_numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors();
|
||||
AddNumThreadsProp(_numThreads);
|
||||
#endif
|
||||
_level = (UInt32)(UInt32)-1;
|
||||
_level = (UInt32)(Int32)-1;
|
||||
}
|
||||
|
||||
HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
|
||||
HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
|
||||
{
|
||||
Init();
|
||||
for (int i = 0; i < numProps; i++)
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
UString name = names[i];
|
||||
name.MakeUpper();
|
||||
name.MakeLower_Ascii();
|
||||
if (name.IsEmpty())
|
||||
return E_INVALIDARG;
|
||||
const PROPVARIANT &value = values[i];
|
||||
if (name[0] == L'X')
|
||||
if (name[0] == L'x')
|
||||
{
|
||||
UInt32 a = 9;
|
||||
RINOK(ParsePropToUInt32(name.Mid(1), value, a));
|
||||
RINOK(ParsePropToUInt32(name.Ptr(1), value, a));
|
||||
_level = a;
|
||||
AddLevelProp(a);
|
||||
}
|
||||
else if (name.Left(2).CompareNoCase(L"MT") == 0)
|
||||
else if (name.IsPrefixedBy(L"mt"))
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
RINOK(ParseMtProp(name.Mid(2), value, _numProcessors, _numThreads));
|
||||
RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads));
|
||||
AddNumThreadsProp(_numThreads);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return ParseParamsFromPROPVARIANT(name, value);
|
||||
return ParseMethodFromPROPVARIANT(names[i], value);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
14
CPP/7zip/Archive/Common/HandlerOut.h
Executable file → Normal file
14
CPP/7zip/Archive/Common/HandlerOut.h
Executable file → Normal file
@@ -27,16 +27,16 @@ public:
|
||||
#endif
|
||||
);
|
||||
|
||||
int GetNumEmptyMethods() const
|
||||
unsigned GetNumEmptyMethods() const
|
||||
{
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 0; i < _methods.Size(); i++)
|
||||
if (!_methods[i].IsEmpty())
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
|
||||
int GetLevel() const { return _level == (UInt32)(UInt32)-1 ? 5 : (int)_level; }
|
||||
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
|
||||
|
||||
void Init();
|
||||
|
||||
@@ -44,20 +44,20 @@ public:
|
||||
HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
|
||||
};
|
||||
|
||||
class CSingleMethodProps: public CMethodProps
|
||||
class CSingleMethodProps: public COneMethodInfo
|
||||
{
|
||||
UInt32 _level;
|
||||
|
||||
void Init();
|
||||
public:
|
||||
#ifndef _7ZIP_ST
|
||||
UInt32 _numThreads;
|
||||
UInt32 _numProcessors;
|
||||
#endif
|
||||
|
||||
void Init();
|
||||
CSingleMethodProps() { Init(); }
|
||||
int GetLevel() const { return _level == (UInt32)(UInt32)-1 ? 5 : (int)_level; }
|
||||
HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
|
||||
int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }
|
||||
HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
32
CPP/7zip/Archive/Common/InStreamWithCRC.cpp
Executable file → Normal file
32
CPP/7zip/Archive/Common/InStreamWithCRC.cpp
Executable file → Normal file
@@ -6,29 +6,33 @@
|
||||
|
||||
STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->Read(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
if (size > 0 && realProcessedSize == 0)
|
||||
UInt32 realProcessed = 0;
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
_stream->Read(data, size, &realProcessed);
|
||||
_size += realProcessed;
|
||||
if (size > 0 && realProcessed == 0)
|
||||
_wasFinished = true;
|
||||
_crc = CrcUpdate(_crc, data, realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
_crc = CrcUpdate(_crc, data, realProcessed);
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->Read(data, size, &realProcessedSize);
|
||||
UInt32 realProcessed = 0;
|
||||
HRESULT result = S_OK;
|
||||
if (_stream)
|
||||
result = _stream->Read(data, size, &realProcessed);
|
||||
_size += realProcessed;
|
||||
/*
|
||||
if (size > 0 && realProcessedSize == 0)
|
||||
if (size > 0 && realProcessed == 0)
|
||||
_wasFinished = true;
|
||||
*/
|
||||
_size += realProcessedSize;
|
||||
_crc = CrcUpdate(_crc, data, realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
_crc = CrcUpdate(_crc, data, realProcessed);
|
||||
if (processedSize)
|
||||
*processedSize = realProcessed;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
0
CPP/7zip/Archive/Common/InStreamWithCRC.h
Executable file → Normal file
0
CPP/7zip/Archive/Common/InStreamWithCRC.h
Executable file → Normal file
37
CPP/7zip/Archive/Common/ItemNameUtils.cpp
Executable file → Normal file
37
CPP/7zip/Archive/Common/ItemNameUtils.cpp
Executable file → Normal file
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/Types.h"
|
||||
|
||||
#include "ItemNameUtils.h"
|
||||
|
||||
namespace NArchive {
|
||||
@@ -12,6 +10,21 @@ namespace NItemName {
|
||||
static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR;
|
||||
static const wchar_t kDirDelimiter = L'/';
|
||||
|
||||
void ReplaceToOsPathSeparator(wchar_t *s)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = *s;
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c == kDirDelimiter)
|
||||
*s = kOSDirDelimiter;
|
||||
s++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
UString MakeLegalName(const UString &name)
|
||||
{
|
||||
UString zipName = name;
|
||||
@@ -36,15 +49,29 @@ UString GetOSName2(const UString &name)
|
||||
return newName;
|
||||
}
|
||||
|
||||
bool HasTailSlash(const AString &name, UINT codePage)
|
||||
void ConvertToOSName2(UString &name)
|
||||
{
|
||||
if (!name.IsEmpty())
|
||||
{
|
||||
name.Replace(kDirDelimiter, kOSDirDelimiter);
|
||||
if (name.Back() == kOSDirDelimiter)
|
||||
name.DeleteBack();
|
||||
}
|
||||
}
|
||||
|
||||
bool HasTailSlash(const AString &name, UINT
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
codePage
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (name.IsEmpty())
|
||||
return false;
|
||||
LPCSTR prev =
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
CharPrevExA((WORD)codePage, name, &name[name.Length()], 0);
|
||||
CharPrevExA((WORD)codePage, name, &name[name.Len()], 0);
|
||||
#else
|
||||
(LPCSTR)(name) + (name.Length() - 1);
|
||||
(LPCSTR)(name) + (name.Len() - 1);
|
||||
#endif
|
||||
return (*prev == '/');
|
||||
}
|
||||
|
||||
7
CPP/7zip/Archive/Common/ItemNameUtils.h
Executable file → Normal file
7
CPP/7zip/Archive/Common/ItemNameUtils.h
Executable file → Normal file
@@ -1,16 +1,19 @@
|
||||
// Archive/Common/ItemNameUtils.h
|
||||
|
||||
#ifndef __ARCHIVE_ITEMNAMEUTILS_H
|
||||
#define __ARCHIVE_ITEMNAMEUTILS_H
|
||||
#ifndef __ARCHIVE_ITEM_NAME_UTILS_H
|
||||
#define __ARCHIVE_ITEM_NAME_UTILS_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NItemName {
|
||||
|
||||
void ReplaceToOsPathSeparator(wchar_t *s);
|
||||
|
||||
UString MakeLegalName(const UString &name);
|
||||
UString GetOSName(const UString &name);
|
||||
UString GetOSName2(const UString &name);
|
||||
void ConvertToOSName2(UString &name);
|
||||
bool HasTailSlash(const AString &name, UINT codePage);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
43
CPP/7zip/Archive/Common/MultiStream.cpp
Executable file → Normal file
43
CPP/7zip/Archive/Common/MultiStream.cpp
Executable file → Normal file
@@ -11,10 +11,10 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (_pos >= _totalLength)
|
||||
return (_pos == _totalLength) ? S_OK : E_FAIL;
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
int left = 0, mid = _streamIndex, right = Streams.Size();
|
||||
unsigned left = 0, mid = _streamIndex, right = Streams.Size();
|
||||
for (;;)
|
||||
{
|
||||
CSubStreamInfo &m = Streams[mid];
|
||||
@@ -51,15 +51,18 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
|
||||
STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
switch(seekOrigin)
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET: _pos = offset; break;
|
||||
case STREAM_SEEK_CUR: _pos = _pos + offset; break;
|
||||
case STREAM_SEEK_END: _pos = _totalLength + offset; break;
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _pos; break;
|
||||
case STREAM_SEEK_END: offset += _totalLength; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (newPosition != 0)
|
||||
*newPosition = _pos;
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_pos = offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -69,7 +72,7 @@ class COutVolumeStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
int _volIndex;
|
||||
unsigned _volIndex;
|
||||
UInt64 _volSize;
|
||||
UInt64 _curPos;
|
||||
CMyComPtr<ISequentialOutStream> _volumeStream;
|
||||
@@ -169,22 +172,20 @@ STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *proce
|
||||
|
||||
STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if(seekOrigin >= 3)
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
switch(seekOrigin)
|
||||
switch (seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET:
|
||||
_absPos = offset;
|
||||
break;
|
||||
case STREAM_SEEK_CUR:
|
||||
_absPos += offset;
|
||||
break;
|
||||
case STREAM_SEEK_END:
|
||||
_absPos = _length + offset;
|
||||
break;
|
||||
case STREAM_SEEK_SET: break;
|
||||
case STREAM_SEEK_CUR: offset += _absPos; break;
|
||||
case STREAM_SEEK_END: offset += _length; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_absPos = offset;
|
||||
_offsetPos = _absPos;
|
||||
_streamIndex = 0;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
6
CPP/7zip/Archive/Common/MultiStream.h
Executable file → Normal file
6
CPP/7zip/Archive/Common/MultiStream.h
Executable file → Normal file
@@ -14,7 +14,7 @@ class CMultiStream:
|
||||
{
|
||||
UInt64 _pos;
|
||||
UInt64 _totalLength;
|
||||
int _streamIndex;
|
||||
unsigned _streamIndex;
|
||||
public:
|
||||
struct CSubStreamInfo
|
||||
{
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
HRESULT Init()
|
||||
{
|
||||
UInt64 total = 0;
|
||||
for (int i = 0; i < Streams.Size(); i++)
|
||||
FOR_VECTOR (i, Streams)
|
||||
{
|
||||
CSubStreamInfo &s = Streams[i];
|
||||
s.GlobalOffset = total;
|
||||
@@ -52,7 +52,7 @@ class COutMultiStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
int _streamIndex; // required stream
|
||||
unsigned _streamIndex; // required stream
|
||||
UInt64 _offsetPos; // offset from start of _streamIndex index
|
||||
UInt64 _absPos;
|
||||
UInt64 _length;
|
||||
|
||||
0
CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
Executable file → Normal file
1
CPP/7zip/Archive/Common/OutStreamWithCRC.h
Executable file → Normal file
1
CPP/7zip/Archive/Common/OutStreamWithCRC.h
Executable file → Normal file
@@ -28,6 +28,7 @@ public:
|
||||
_calculate = calculate;
|
||||
_crc = CRC_INIT_VAL;
|
||||
}
|
||||
void EnableCalc(bool calculate) { _calculate = calculate; }
|
||||
void InitCRC() { _crc = CRC_INIT_VAL; }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
|
||||
|
||||
0
CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Common/OutStreamWithSha1.h
Executable file → Normal file
0
CPP/7zip/Archive/Common/OutStreamWithSha1.h
Executable file → Normal file
0
CPP/7zip/Archive/Common/ParseProperties.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Common/ParseProperties.cpp
Executable file → Normal file
0
CPP/7zip/Archive/Common/ParseProperties.h
Executable file → Normal file
0
CPP/7zip/Archive/Common/ParseProperties.h
Executable file → Normal file
3
CPP/7zip/Archive/Common/StdAfx.h
Executable file → Normal file
3
CPP/7zip/Archive/Common/StdAfx.h
Executable file → Normal file
@@ -3,7 +3,6 @@
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
#include "../../../Common/NewHandler.h"
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
|
||||
864
CPP/7zip/Archive/CpioHandler.cpp
Executable file → Normal file
864
CPP/7zip/Archive/CpioHandler.cpp
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
287
CPP/7zip/Archive/CramfsHandler.cpp
Executable file → Normal file
287
CPP/7zip/Archive/CramfsHandler.cpp
Executable file → Normal file
@@ -3,13 +3,14 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/7zCrc.h"
|
||||
#include "../../../C/CpuArch.h"
|
||||
#include "../../../C/Alloc.h"
|
||||
#include "../../../C/CpuArch.h"
|
||||
#include "../../../C/LzmaDec.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/StringConvert.h"
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/StringConvert.h"
|
||||
|
||||
#include "Windows/PropVariantUtils.h"
|
||||
#include "../../Windows/PropVariantUtils.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
@@ -38,6 +39,30 @@ static const UInt32 kNodeSize = 12;
|
||||
|
||||
static const UInt32 kFlag_FsVer2 = (1 << 0);
|
||||
|
||||
static const unsigned k_Flags_BlockSize_Shift = 11;
|
||||
static const unsigned k_Flags_BlockSize_Mask = 7;
|
||||
static const unsigned k_Flags_Method_Shift = 14;
|
||||
static const unsigned k_Flags_Method_Mask = 3;
|
||||
|
||||
/*
|
||||
There is possible collision in flags:
|
||||
- Original CramFS writes 0 in method field. But it uses ZLIB.
|
||||
- Modified CramFS writes 0 in method field for "NONE" compression?
|
||||
How to solve that collision?
|
||||
*/
|
||||
|
||||
#define k_Flags_Method_NONE 0
|
||||
#define k_Flags_Method_ZLIB 1
|
||||
#define k_Flags_Method_LZMA 2
|
||||
|
||||
static const char *k_Methods[] =
|
||||
{
|
||||
"Copy"
|
||||
, "ZLIB"
|
||||
, "LZMA"
|
||||
, "Unknown"
|
||||
};
|
||||
|
||||
static const CUInt32PCharPair k_Flags[] =
|
||||
{
|
||||
{ 0, "Ver2" },
|
||||
@@ -48,7 +73,6 @@ static const CUInt32PCharPair k_Flags[] =
|
||||
};
|
||||
|
||||
static const unsigned kBlockSizeLog = 12;
|
||||
static const UInt32 kBlockSize = 1 << kBlockSizeLog;
|
||||
|
||||
/*
|
||||
struct CNode
|
||||
@@ -141,6 +165,8 @@ struct CHeader
|
||||
}
|
||||
|
||||
bool IsVer2() const { return (Flags & kFlag_FsVer2) != 0; }
|
||||
unsigned GetBlockSizeShift() const { return (unsigned)(Flags >> k_Flags_BlockSize_Shift) & k_Flags_BlockSize_Mask; }
|
||||
unsigned GetMethod() const { return (unsigned)(Flags >> k_Flags_Method_Shift) & k_Flags_Method_Mask; }
|
||||
};
|
||||
|
||||
class CHandler:
|
||||
@@ -153,14 +179,21 @@ class CHandler:
|
||||
Byte *_data;
|
||||
UInt32 _size;
|
||||
UInt32 _headersSize;
|
||||
AString _errorMessage;
|
||||
|
||||
UInt32 _errorFlags;
|
||||
bool _isArc;
|
||||
|
||||
CHeader _h;
|
||||
UInt32 _phySize;
|
||||
|
||||
unsigned _method;
|
||||
unsigned _blockSizeLog;
|
||||
|
||||
// Current file
|
||||
|
||||
NCompress::NZlib::CDecoder *_zlibDecoderSpec;
|
||||
CMyComPtr<ICompressCoder> _zlibDecoder;
|
||||
|
||||
|
||||
CBufInStream *_inStreamSpec;
|
||||
CMyComPtr<ISequentialInStream> _inStream;
|
||||
|
||||
@@ -175,6 +208,18 @@ class CHandler:
|
||||
AString GetPath(int index) const;
|
||||
bool GetPackSize(int index, UInt32 &res) const;
|
||||
void Free();
|
||||
|
||||
UInt32 GetNumBlocks(UInt32 size) const
|
||||
{
|
||||
return (size + ((UInt32)1 << _blockSizeLog) - 1) >> _blockSizeLog;
|
||||
}
|
||||
|
||||
void UpdatePhySize(UInt32 s)
|
||||
{
|
||||
if (_phySize < s)
|
||||
_phySize = s;
|
||||
}
|
||||
|
||||
public:
|
||||
CHandler(): _data(0) {}
|
||||
~CHandler() { Free(); }
|
||||
@@ -184,25 +229,26 @@ public:
|
||||
HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);
|
||||
};
|
||||
|
||||
static const STATPROPSTG kProps[] =
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidIsDir, VT_BOOL},
|
||||
{ NULL, kpidSize, VT_UI4},
|
||||
{ NULL, kpidPackSize, VT_UI4},
|
||||
{ NULL, kpidPosixAttrib, VT_UI4}
|
||||
// { NULL, kpidOffset, VT_UI4}
|
||||
kpidPath,
|
||||
kpidIsDir,
|
||||
kpidSize,
|
||||
kpidPackSize,
|
||||
kpidPosixAttrib
|
||||
// kpidOffset
|
||||
};
|
||||
|
||||
static const STATPROPSTG kArcProps[] =
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidName, VT_BSTR},
|
||||
{ NULL, kpidBigEndian, VT_BOOL},
|
||||
{ NULL, kpidCharacts, VT_BSTR},
|
||||
{ NULL, kpidPhySize, VT_UI4},
|
||||
{ NULL, kpidHeadersSize, VT_UI4},
|
||||
{ NULL, kpidNumSubFiles, VT_UI4},
|
||||
{ NULL, kpidNumBlocks, VT_UI4}
|
||||
kpidVolumeName,
|
||||
kpidBigEndian,
|
||||
kpidCharacts,
|
||||
kpidClusterSize,
|
||||
kpidMethod,
|
||||
kpidHeadersSize,
|
||||
kpidNumSubFiles,
|
||||
kpidNumBlocks
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
@@ -221,10 +267,11 @@ HRESULT CHandler::OpenDir(int parent, UInt32 baseOffset, unsigned level)
|
||||
UInt32 end = offset + size;
|
||||
if (offset < kHeaderSize || end > _size || level > kNumDirLevelsMax)
|
||||
return S_FALSE;
|
||||
UpdatePhySize(end);
|
||||
if (end > _headersSize)
|
||||
_headersSize = end;
|
||||
|
||||
int startIndex = _items.Size();
|
||||
unsigned startIndex = _items.Size();
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
@@ -241,8 +288,8 @@ HRESULT CHandler::OpenDir(int parent, UInt32 baseOffset, unsigned level)
|
||||
size -= nodeLen;
|
||||
}
|
||||
|
||||
int endIndex = _items.Size();
|
||||
for (int i = startIndex; i < endIndex; i++)
|
||||
unsigned endIndex = _items.Size();
|
||||
for (unsigned i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
RINOK(OpenDir(i, _items[i].Offset, level + 1));
|
||||
}
|
||||
@@ -255,17 +302,26 @@ HRESULT CHandler::Open2(IInStream *inStream)
|
||||
RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize));
|
||||
if (!_h.Parse(buf))
|
||||
return S_FALSE;
|
||||
_method = k_Flags_Method_ZLIB;
|
||||
_blockSizeLog = kBlockSizeLog;
|
||||
_phySize = kHeaderSize;
|
||||
if (_h.IsVer2())
|
||||
{
|
||||
_method = _h.GetMethod();
|
||||
// FIT IT. Now we don't know correct way to work with collision in method field.
|
||||
if (_method == k_Flags_Method_NONE)
|
||||
_method = k_Flags_Method_ZLIB;
|
||||
_blockSizeLog = kBlockSizeLog + _h.GetBlockSizeShift();
|
||||
if (_h.Size < kHeaderSize || _h.Size > kArcSizeMax || _h.NumFiles > kNumFilesMax)
|
||||
return S_FALSE;
|
||||
_phySize = _h.Size;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt64 size;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_END, &size));
|
||||
if (size > kArcSizeMax)
|
||||
return S_FALSE;
|
||||
size = kArcSizeMax;
|
||||
_h.Size = (UInt32)size;
|
||||
RINOK(inStream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
@@ -278,18 +334,59 @@ HRESULT CHandler::Open2(IInStream *inStream)
|
||||
if (processed < kNodeSize)
|
||||
return S_FALSE;
|
||||
_size = kHeaderSize + (UInt32)processed;
|
||||
if (_size != _h.Size)
|
||||
_errorMessage = "Unexpected end of archive";
|
||||
else
|
||||
{
|
||||
SetUi32(_data + 0x20, 0);
|
||||
if (_h.IsVer2())
|
||||
if (CrcCalc(_data, _h.Size) != _h.Crc)
|
||||
_errorMessage = "CRC error";
|
||||
}
|
||||
if (_h.IsVer2())
|
||||
_items.Reserve(_h.NumFiles - 1);
|
||||
return OpenDir(-1, kHeaderSize, 0);
|
||||
{
|
||||
if (_size != _h.Size)
|
||||
_errorFlags = kpv_ErrorFlags_UnexpectedEnd;
|
||||
else
|
||||
{
|
||||
SetUi32(_data + 0x20, 0);
|
||||
if (CrcCalc(_data, _h.Size) != _h.Crc)
|
||||
{
|
||||
_errorFlags = kpv_ErrorFlags_HeadersError;
|
||||
// _errorMessage = "CRC error";
|
||||
}
|
||||
}
|
||||
if (_h.NumFiles >= 1)
|
||||
_items.ClearAndReserve(_h.NumFiles - 1);
|
||||
}
|
||||
|
||||
RINOK(OpenDir(-1, kHeaderSize, 0));
|
||||
|
||||
if (!_h.IsVer2())
|
||||
{
|
||||
FOR_VECTOR(i, _items)
|
||||
{
|
||||
const CItem &item = _items[i];
|
||||
const Byte *p = _data + item.Offset;
|
||||
bool be = _h.be;
|
||||
if (IsDir(p, be))
|
||||
continue;
|
||||
UInt32 offset = GetOffset(p, be);
|
||||
if (offset < kHeaderSize)
|
||||
continue;
|
||||
UInt32 numBlocks = GetNumBlocks(GetSize(p, be));
|
||||
if (numBlocks == 0)
|
||||
continue;
|
||||
UInt32 start = offset + numBlocks * 4;
|
||||
if (start > _size)
|
||||
continue;
|
||||
UInt32 end = Get32(_data + start - 4);
|
||||
if (end >= start)
|
||||
UpdatePhySize(end);
|
||||
}
|
||||
|
||||
// Read tailing zeros. Most cramfs archives use 4096-bytes aligned zeros
|
||||
const UInt32 kTailSize_MAX = 1 << 12;
|
||||
UInt32 endPos = (_phySize + kTailSize_MAX - 1) & ~(kTailSize_MAX - 1);
|
||||
if (endPos > _size)
|
||||
endPos = _size;
|
||||
UInt32 pos;
|
||||
for (pos = _phySize; pos < endPos && _data[pos] == 0; pos++);
|
||||
if (pos == endPos)
|
||||
_phySize = endPos;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
AString CHandler::GetPath(int index) const
|
||||
@@ -334,13 +431,16 @@ AString CHandler::GetPath(int index) const
|
||||
|
||||
bool CHandler::GetPackSize(int index, UInt32 &res) const
|
||||
{
|
||||
res = 0;
|
||||
const CItem &item = _items[index];
|
||||
const Byte *p = _data + item.Offset;
|
||||
bool be = _h.be;
|
||||
UInt32 offset = GetOffset(p, be);
|
||||
if (offset < kHeaderSize)
|
||||
return false;
|
||||
UInt32 numBlocks = (GetSize(p, be) + kBlockSize - 1) >> kBlockSizeLog;
|
||||
UInt32 numBlocks = GetNumBlocks(GetSize(p, be));
|
||||
if (numBlocks == 0)
|
||||
return true;
|
||||
UInt32 start = offset + numBlocks * 4;
|
||||
if (start > _size)
|
||||
return false;
|
||||
@@ -357,6 +457,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
|
||||
{
|
||||
Close();
|
||||
RINOK(Open2(stream));
|
||||
_isArc = true;
|
||||
_stream = stream;
|
||||
}
|
||||
return S_OK;
|
||||
@@ -371,10 +472,12 @@ void CHandler::Free()
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_isArc = false;
|
||||
_phySize = 0;
|
||||
_errorFlags = 0;
|
||||
_headersSize = 0;
|
||||
_items.Clear();
|
||||
_stream.Release();
|
||||
_errorMessage.Empty();
|
||||
Free();
|
||||
return S_OK;
|
||||
}
|
||||
@@ -389,9 +492,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
switch (propID)
|
||||
{
|
||||
case kpidName:
|
||||
case kpidVolumeName:
|
||||
{
|
||||
char dest[kHeaderNameSize + 4];
|
||||
memcpy(dest, _h.Name, kHeaderNameSize);
|
||||
@@ -401,11 +504,20 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
}
|
||||
case kpidBigEndian: prop = _h.be; break;
|
||||
case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break;
|
||||
case kpidMethod: prop = k_Methods[_method]; break;
|
||||
case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break;
|
||||
case kpidNumBlocks: if (_h.IsVer2()) prop = _h.NumBlocks; break;
|
||||
case kpidNumSubFiles: if (_h.IsVer2()) prop = _h.NumFiles; break;
|
||||
case kpidPhySize: if (_h.IsVer2()) prop = _h.Size; break;
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
case kpidHeadersSize: prop = _headersSize; break;
|
||||
case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = _errorFlags;
|
||||
if (!_isArc)
|
||||
v |= kpv_ErrorFlags_IsNotArc;
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -453,13 +565,60 @@ HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSi
|
||||
return Handler->ReadBlock(blockIndex, dest, blockSize);
|
||||
}
|
||||
|
||||
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
|
||||
{
|
||||
if (!_zlibDecoder)
|
||||
if (_method == k_Flags_Method_ZLIB)
|
||||
{
|
||||
_zlibDecoderSpec = new NCompress::NZlib::CDecoder();
|
||||
_zlibDecoder = _zlibDecoderSpec;
|
||||
if (!_zlibDecoder)
|
||||
{
|
||||
_zlibDecoderSpec = new NCompress::NZlib::CDecoder();
|
||||
_zlibDecoder = _zlibDecoderSpec;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_method != k_Flags_Method_LZMA)
|
||||
{
|
||||
// probably we must support no-compression archives here.
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
}
|
||||
|
||||
bool be = _h.be;
|
||||
const Byte *p = _data + (_curBlocksOffset + (UInt32)blockIndex * 4);
|
||||
UInt32 start = (blockIndex == 0 ? _curBlocksOffset + _curNumBlocks * 4: Get32(p - 4));
|
||||
UInt32 end = Get32(p);
|
||||
if (end < start || end > _size)
|
||||
return S_FALSE;
|
||||
UInt32 inSize = end - start;
|
||||
|
||||
if (_method == k_Flags_Method_LZMA)
|
||||
{
|
||||
const unsigned kLzmaHeaderSize = LZMA_PROPS_SIZE + 4;
|
||||
if (inSize < kLzmaHeaderSize)
|
||||
return S_FALSE;
|
||||
const Byte *p = _data + start;
|
||||
UInt32 destSize32 = GetUi32(p + LZMA_PROPS_SIZE);
|
||||
if (destSize32 > blockSize)
|
||||
return S_FALSE;
|
||||
SizeT destLen = destSize32;
|
||||
SizeT srcLen = inSize - kLzmaHeaderSize;
|
||||
ELzmaStatus status;
|
||||
SRes res = LzmaDecode(dest, &destLen, p + kLzmaHeaderSize, &srcLen,
|
||||
p, LZMA_PROPS_SIZE, LZMA_FINISH_END, &status, &g_Alloc);
|
||||
if (res != SZ_OK
|
||||
|| (status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
||||
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
|| destLen != destSize32
|
||||
|| srcLen != inSize - kLzmaHeaderSize)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!_inStream)
|
||||
{
|
||||
_inStreamSpec = new CBufInStream();
|
||||
@@ -470,17 +629,10 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
|
||||
_outStreamSpec = new CBufPtrSeqOutStream();
|
||||
_outStream = _outStreamSpec;
|
||||
}
|
||||
bool be = _h.be;
|
||||
const Byte *p = _data + (_curBlocksOffset + (UInt32)blockIndex * 4);
|
||||
UInt32 start = (blockIndex == 0 ? _curBlocksOffset + _curNumBlocks * 4: Get32(p - 4));
|
||||
UInt32 end = Get32(p);
|
||||
if (end < start || end > _size)
|
||||
return S_FALSE;
|
||||
UInt32 inSize = end - start;
|
||||
_inStreamSpec->Init(_data + start, inSize);
|
||||
_outStreamSpec->Init(dest, blockSize);
|
||||
RINOK(_zlibDecoder->Code(_inStream, _outStream, NULL, NULL, NULL));
|
||||
return (_zlibDecoderSpec->GetInputProcessedSize() == inSize &&
|
||||
return (inSize == _zlibDecoderSpec->GetInputProcessedSize() &&
|
||||
_outStreamSpec->GetPos() == blockSize) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
@@ -488,7 +640,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == (UInt32)-1);
|
||||
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _items.Size();
|
||||
if (numItems == 0)
|
||||
@@ -562,19 +714,22 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if (hres == E_OUTOFMEMORY)
|
||||
return E_OUTOFMEMORY;
|
||||
if (hres == S_FALSE || !inStream)
|
||||
res = NExtract::NOperationResult::kUnSupportedMethod;
|
||||
res = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else
|
||||
{
|
||||
RINOK(hres);
|
||||
if (inStream)
|
||||
{
|
||||
HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
|
||||
if (hres != S_OK && hres != S_FALSE)
|
||||
if (hres == S_OK)
|
||||
{
|
||||
RINOK(hres);
|
||||
if (copyCoderSpec->TotalSize == curSize)
|
||||
res = NExtract::NOperationResult::kOK;
|
||||
}
|
||||
if (copyCoderSpec->TotalSize == curSize && hres == S_OK)
|
||||
res = NExtract::NOperationResult::kOK;
|
||||
else if (hres == E_NOTIMPL)
|
||||
res = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else if (hres != S_FALSE)
|
||||
return hres;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -596,7 +751,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
return E_FAIL;
|
||||
|
||||
UInt32 size = GetSize(p, be);
|
||||
UInt32 numBlocks = (size + kBlockSize - 1) >> kBlockSizeLog;
|
||||
UInt32 numBlocks = GetNumBlocks(size);
|
||||
UInt32 offset = GetOffset(p, be);
|
||||
if (offset < kHeaderSize)
|
||||
{
|
||||
@@ -625,7 +780,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
_curNumBlocks = numBlocks;
|
||||
_curBlocksOffset = offset;
|
||||
streamSpec->Handler = this;
|
||||
if (!streamSpec->Alloc(kBlockSizeLog, 21 - kBlockSizeLog))
|
||||
if (!streamSpec->Alloc(_blockSizeLog, 21 - _blockSizeLog))
|
||||
return E_OUTOFMEMORY;
|
||||
streamSpec->Init(size);
|
||||
*stream = streamTemp.Detach();
|
||||
@@ -634,10 +789,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static IInArchive *CreateArc() { return new NArchive::NCramfs::CHandler; }
|
||||
IMP_CreateArcIn
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"CramFS", L"cramfs", 0, 0xD3, SIGNATURE, kSignatureSize, false, CreateArc, 0 };
|
||||
{ "CramFS", "cramfs", 0, 0xD3,
|
||||
kSignatureSize, SIGNATURE,
|
||||
16,
|
||||
0,
|
||||
CreateArc };
|
||||
|
||||
REGISTER_ARC(Cramfs)
|
||||
|
||||
|
||||
@@ -1,413 +0,0 @@
|
||||
// DebHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/StringToInt.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/Time.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "../Compress/CopyCoder.h"
|
||||
|
||||
#include "Common/ItemNameUtils.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NTime;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NDeb {
|
||||
|
||||
namespace NHeader
|
||||
{
|
||||
const int kSignatureLen = 8;
|
||||
|
||||
const char *kSignature = "!<arch>\n";
|
||||
|
||||
const int kNameSize = 16;
|
||||
const int kTimeSize = 12;
|
||||
const int kModeSize = 8;
|
||||
const int kSizeSize = 10;
|
||||
|
||||
/*
|
||||
struct CHeader
|
||||
{
|
||||
char Name[kNameSize];
|
||||
char MTime[kTimeSize];
|
||||
char Number0[6];
|
||||
char Number1[6];
|
||||
char Mode[kModeSize];
|
||||
char Size[kSizeSize];
|
||||
char Quote;
|
||||
char NewLine;
|
||||
};
|
||||
*/
|
||||
const int kHeaderSize = kNameSize + kTimeSize + 6 + 6 + kModeSize + kSizeSize + 1 + 1;
|
||||
}
|
||||
|
||||
struct CItem
|
||||
{
|
||||
AString Name;
|
||||
UInt64 Size;
|
||||
UInt32 MTime;
|
||||
UInt32 Mode;
|
||||
|
||||
UInt64 HeaderPos;
|
||||
UInt64 GetDataPos() const { return HeaderPos + NHeader::kHeaderSize; };
|
||||
// UInt64 GetFullSize() const { return NFileHeader::kRecordSize + Size; };
|
||||
};
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
|
||||
HRESULT GetNextItemReal(bool &filled, CItem &itemInfo);
|
||||
public:
|
||||
UInt64 m_Position;
|
||||
HRESULT Open(IInStream *inStream);
|
||||
HRESULT GetNextItem(bool &filled, CItem &itemInfo);
|
||||
HRESULT SkipData(UInt64 dataSize);
|
||||
};
|
||||
|
||||
HRESULT CInArchive::Open(IInStream *inStream)
|
||||
{
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
|
||||
char signature[NHeader::kSignatureLen];
|
||||
RINOK(ReadStream_FALSE(inStream, signature, NHeader::kSignatureLen));
|
||||
m_Position += NHeader::kSignatureLen;
|
||||
if (memcmp(signature, NHeader::kSignature, NHeader::kSignatureLen) != 0)
|
||||
return S_FALSE;
|
||||
m_Stream = inStream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void MyStrNCpy(char *dest, const char *src, int size)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
char c = src[i];
|
||||
dest[i] = c;
|
||||
if (c == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool OctalToNumber(const char *s, int size, UInt64 &res)
|
||||
{
|
||||
char sz[32];
|
||||
MyStrNCpy(sz, s, size);
|
||||
sz[size] = 0;
|
||||
const char *end;
|
||||
int i;
|
||||
for (i = 0; sz[i] == ' '; i++);
|
||||
res = ConvertOctStringToUInt64(sz + i, &end);
|
||||
return (*end == ' ' || *end == 0);
|
||||
}
|
||||
|
||||
static bool OctalToNumber32(const char *s, int size, UInt32 &res)
|
||||
{
|
||||
UInt64 res64;
|
||||
if (!OctalToNumber(s, size, res64))
|
||||
return false;
|
||||
res = (UInt32)res64;
|
||||
return (res64 <= 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
static bool DecimalToNumber(const char *s, int size, UInt64 &res)
|
||||
{
|
||||
char sz[32];
|
||||
MyStrNCpy(sz, s, size);
|
||||
sz[size] = 0;
|
||||
const char *end;
|
||||
int i;
|
||||
for (i = 0; sz[i] == ' '; i++);
|
||||
res = ConvertStringToUInt64(sz + i, &end);
|
||||
return (*end == ' ' || *end == 0);
|
||||
}
|
||||
|
||||
static bool DecimalToNumber32(const char *s, int size, UInt32 &res)
|
||||
{
|
||||
UInt64 res64;
|
||||
if (!DecimalToNumber(s, size, res64))
|
||||
return false;
|
||||
res = (UInt32)res64;
|
||||
return (res64 <= 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
#define RIF(x) { if (!(x)) return S_FALSE; }
|
||||
|
||||
|
||||
HRESULT CInArchive::GetNextItemReal(bool &filled, CItem &item)
|
||||
{
|
||||
filled = false;
|
||||
|
||||
char header[NHeader::kHeaderSize];
|
||||
const char *cur = header;
|
||||
|
||||
size_t processedSize = sizeof(header);
|
||||
item.HeaderPos = m_Position;
|
||||
RINOK(ReadStream(m_Stream, header, &processedSize));
|
||||
if (processedSize != sizeof(header))
|
||||
return S_OK;
|
||||
m_Position += processedSize;
|
||||
|
||||
char tempString[NHeader::kNameSize + 1];
|
||||
MyStrNCpy(tempString, cur, NHeader::kNameSize);
|
||||
cur += NHeader::kNameSize;
|
||||
tempString[NHeader::kNameSize] = '\0';
|
||||
item.Name = tempString;
|
||||
item.Name.Trim();
|
||||
|
||||
for (int i = 0; i < item.Name.Length(); i++)
|
||||
if (((Byte)item.Name[i]) < 0x20)
|
||||
return S_FALSE;
|
||||
|
||||
RIF(DecimalToNumber32(cur, NHeader::kTimeSize, item.MTime));
|
||||
cur += NHeader::kTimeSize;
|
||||
|
||||
cur += 6 + 6;
|
||||
|
||||
RIF(OctalToNumber32(cur, NHeader::kModeSize, item.Mode));
|
||||
cur += NHeader::kModeSize;
|
||||
|
||||
RIF(DecimalToNumber(cur, NHeader::kSizeSize, item.Size));
|
||||
cur += NHeader::kSizeSize;
|
||||
|
||||
filled = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::GetNextItem(bool &filled, CItem &item)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
RINOK(GetNextItemReal(filled, item));
|
||||
if (!filled)
|
||||
return S_OK;
|
||||
if (item.Name.Compare("debian-binary") != 0)
|
||||
return S_OK;
|
||||
if (item.Size != 4)
|
||||
return S_OK;
|
||||
SkipData(item.Size);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CInArchive::SkipData(UInt64 dataSize)
|
||||
{
|
||||
return m_Stream->Seek((dataSize + 1) & (~((UInt64)0x1)), STREAM_SEEK_CUR, &m_Position);
|
||||
}
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IInArchiveGetStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CObjectVector<CItem> _items;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
Int32 _mainSubfile;
|
||||
UInt64 _phySize;
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
};
|
||||
|
||||
static STATPROPSTG kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidPhySize, VT_UI8}
|
||||
};
|
||||
|
||||
static STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidSize, VT_UI8},
|
||||
{ NULL, kpidMTime, VT_FILETIME}
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
{
|
||||
_mainSubfile = -1;
|
||||
CInArchive archive;
|
||||
if (archive.Open(stream) != S_OK)
|
||||
return S_FALSE;
|
||||
_items.Clear();
|
||||
|
||||
if (openArchiveCallback != NULL)
|
||||
{
|
||||
RINOK(openArchiveCallback->SetTotal(NULL, NULL));
|
||||
UInt64 numFiles = _items.Size();
|
||||
RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
CItem item;
|
||||
bool filled;
|
||||
HRESULT result = archive.GetNextItem(filled, item);
|
||||
if (result == S_FALSE)
|
||||
return S_FALSE;
|
||||
if (result != S_OK)
|
||||
return S_FALSE;
|
||||
if (!filled)
|
||||
break;
|
||||
if (item.Name.Left(5) == "data.")
|
||||
_mainSubfile = _items.Size();
|
||||
_items.Add(item);
|
||||
archive.SkipData(item.Size);
|
||||
if (openArchiveCallback != NULL)
|
||||
{
|
||||
UInt64 numFiles = _items.Size();
|
||||
RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
|
||||
}
|
||||
}
|
||||
_stream = stream;
|
||||
_phySize = archive.m_Position;
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_stream.Release();
|
||||
_items.Clear();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
*numItems = _items.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPhySize: prop = _phySize; break;
|
||||
case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
const CItem &item = _items[index];
|
||||
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPath: prop = (const wchar_t *)NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;
|
||||
case kpidSize:
|
||||
case kpidPackSize:
|
||||
prop = item.Size;
|
||||
break;
|
||||
case kpidMTime:
|
||||
{
|
||||
if (item.MTime != 0)
|
||||
{
|
||||
FILETIME fileTime;
|
||||
NTime::UnixTimeToFileTime(item.MTime, fileTime);
|
||||
prop = fileTime;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == (UInt32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _items.Size();
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
UInt64 totalSize = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
totalSize += _items[allFilesMode ? i : indices[i]].Size;
|
||||
extractCallback->SetTotal(totalSize);
|
||||
|
||||
UInt64 currentTotalSize = 0;
|
||||
|
||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
|
||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
streamSpec->SetStream(_stream);
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
lps->InSize = lps->OutSize = currentTotalSize;
|
||||
RINOK(lps->SetCur());
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
Int32 index = allFilesMode ? i : indices[i];
|
||||
const CItem &item = _items[index];
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
||||
currentTotalSize += item.Size;
|
||||
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
if (testMode)
|
||||
{
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
|
||||
continue;
|
||||
}
|
||||
RINOK(_stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(item.Size);
|
||||
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
|
||||
realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
|
||||
NExtract::NOperationResult::kOK:
|
||||
NExtract::NOperationResult::kDataError));
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const CItem &item = _items[index];
|
||||
return CreateLimitedInStream(_stream, item.GetDataPos(), item.Size, stream);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static IInArchive *CreateArc() { return new NArchive::NDeb::CHandler; }
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"Deb", L"deb", 0, 0xEC, { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' }, 8, false, CreateArc, 0 };
|
||||
|
||||
REGISTER_ARC(Deb)
|
||||
|
||||
}}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user