This commit is contained in:
Igor Pavlov
2014-11-23 00:00:00 +00:00
committed by Kornel Lesiński
parent 83f8ddcc5b
commit f08f4dcc3c
1158 changed files with 76451 additions and 35082 deletions

16
CPP/7zip/Archive/7z/7z.dsp Executable file → Normal file
View 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
View File

0
CPP/7zip/Archive/7z/7zCompressionMode.cpp Executable file → Normal file
View File

0
CPP/7zip/Archive/7z/7zCompressionMode.h Executable file → Normal file
View File

123
CPP/7zip/Archive/7z/7zDecode.cpp Executable file → Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

File diff suppressed because it is too large Load Diff

335
CPP/7zip/Archive/7z/7zIn.h Executable file → Normal file
View 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
View 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
View 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
View 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
View 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
View File

23
CPP/7zip/Archive/7z/7zRegister.cpp Executable file → Normal file
View 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
View 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
View File

509
CPP/7zip/Archive/7z/7zUpdate.cpp Executable file → Normal file
View 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
View 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
View File

3
CPP/7zip/Archive/7z/StdAfx.h Executable file → Normal file
View 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
View 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
View File

113
CPP/7zip/Archive/ApmHandler.cpp Executable file → Normal file
View 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)

View 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
View File

4
CPP/7zip/Archive/Archive2.def Executable file → Normal file
View 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
View 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
View 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
View 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(&currentTotalPacked));
// 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
View 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
View 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
View 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
View 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
View File

23
CPP/7zip/Archive/Cab/CabHeader.h Executable file → Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
};
}}

View File

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

View File

@@ -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
View 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 &section = 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
View 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);

View File

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

@@ -3,6 +3,6 @@
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#include "../../../Common/Common.h"
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View 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
View File

0
CPP/7zip/Archive/Common/CoderMixer.h Executable file → Normal file
View File

70
CPP/7zip/Archive/Common/CoderMixer2.cpp Executable file → Normal file
View 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
View 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
View 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
View 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
View 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
View File

0
CPP/7zip/Archive/Common/CoderMixerMT.cpp Executable file → Normal file
View File

0
CPP/7zip/Archive/Common/CoderMixerMT.h Executable file → Normal file
View File

0
CPP/7zip/Archive/Common/CrossThreadProgress.cpp Executable file → Normal file
View File

0
CPP/7zip/Archive/Common/CrossThreadProgress.h Executable file → Normal file
View File

19
CPP/7zip/Archive/Common/DummyOutStream.cpp Executable file → Normal file
View 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
View 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
View 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
View File

36
CPP/7zip/Archive/Common/HandlerOut.cpp Executable file → Normal file
View 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
View 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
View 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
View File

37
CPP/7zip/Archive/Common/ItemNameUtils.cpp Executable file → Normal file
View 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
View 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
View 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
View 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
View File

1
CPP/7zip/Archive/Common/OutStreamWithCRC.h Executable file → Normal file
View 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
View File

0
CPP/7zip/Archive/Common/OutStreamWithSha1.h Executable file → Normal file
View File

0
CPP/7zip/Archive/Common/ParseProperties.cpp Executable file → Normal file
View File

0
CPP/7zip/Archive/Common/ParseProperties.h Executable file → Normal file
View File

3
CPP/7zip/Archive/Common/StdAfx.h Executable file → Normal file
View 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
View File

File diff suppressed because it is too large Load Diff

287
CPP/7zip/Archive/CramfsHandler.cpp Executable file → Normal file
View 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)

View File

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