diff options
Diffstat (limited to 'src/libs/7zip/unix/CPP/7zip/Archive/7z')
27 files changed, 3606 insertions, 1908 deletions
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7z.pri b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7z.pri new file mode 100644 index 000000000..60211faae --- /dev/null +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7z.pri @@ -0,0 +1,29 @@ +HEADERS += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zCompressionMode.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zDecode.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zEncode.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zFolderInStream.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zFolderOutStream.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHandler.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHeader.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zIn.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zItem.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zOut.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zProperties.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zSpecStream.h \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zUpdate.h + +SOURCES += $$7ZIP_BASE/CPP/7zip/Archive/7z/7zDecode.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zEncode.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zExtract.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zFolderInStream.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zFolderOutStream.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHandler.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHandlerOut.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zHeader.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zIn.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zOut.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zProperties.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zRegister.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zSpecStream.cpp \ + $$7ZIP_BASE/CPP/7zip/Archive/7z/7zUpdate.cpp + diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.cpp deleted file mode 100644 index 6774fc482..000000000 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// CompressionMethod.cpp - -#include "StdAfx.h" diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h index 55bbc68ee..5cde97c38 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zCompressionMode.h @@ -3,19 +3,18 @@ #ifndef __7Z_COMPRESSION_MODE_H #define __7Z_COMPRESSION_MODE_H -#include "../../../Common/MyString.h" - -#include "../../../Windows/PropVariant.h" - +#include "../../Common/MethodId.h" #include "../../Common/MethodProps.h" namespace NArchive { namespace N7z { -struct CMethodFull: public CMethod +struct CMethodFull: public CProps { + CMethodId Id; UInt32 NumInStreams; UInt32 NumOutStreams; + bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp index 425a34157..973966bd3 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.cpp @@ -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,46 +94,50 @@ 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); bool createNewCoders; @@ -139,10 +147,10 @@ HRESULT CDecoder::Decode( createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { - int i; + unsigned i; _decoders.Clear(); // _decoders2.Clear(); - + _mixerCoder.Release(); if (_multiThread) @@ -160,12 +168,12 @@ HRESULT CDecoder::Decode( #endif } RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); - + for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; - + CMyComPtr<ICompressCoder> decoder; CMyComPtr<ICompressCoder2> decoder2; RINOK(CreateCoder( @@ -178,7 +186,7 @@ HRESULT CDecoder::Decode( return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder; - + if (_multiThread) _mixerCoderMTSpec->AddCoder(decoder); #ifdef _ST_MODE @@ -204,32 +212,34 @@ 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; - + for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; - + { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); 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,56 +267,55 @@ 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 coderIndex++; - + 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); @@ -317,16 +326,18 @@ HRESULT CDecoder::Decode( else _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; */ - + 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); } }} diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h index d8a424a36..54e9d2b52 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zDecode.h @@ -14,7 +14,7 @@ #include "../../Common/CreateCoder.h" -#include "7zItem.h" +#include "7zIn.h" namespace NArchive { namespace N7z { @@ -33,14 +33,14 @@ class CDecoder { bool _bindInfoExPrevIsDefined; CBindInfoEx _bindInfoExPrev; - + bool _multiThread; #ifdef _ST_MODE NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; #endif NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec; NCoderMixer::CCoderMixer2 *_mixerCoderCommon; - + CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CMyComPtr<IUnknown> > _decoders; // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2; @@ -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 diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp index 87996bc0e..5f1436fc7 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.cpp @@ -23,30 +23,39 @@ 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) +{ + CMyComPtr<ICompressSetCoderProperties> setCoderProperties; + coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); + if (setCoderProperties) + return props.SetCoderProps(setCoderProperties, dataSizeReduce); + return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK; } HRESULT CEncoder::CreateMixerCoder( @@ -56,15 +65,14 @@ 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; - + RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS @@ -74,7 +82,7 @@ HRESULT CEncoder::CreateMixerCoder( return E_FAIL; CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; - + #ifndef _7ZIP_ST { CMyComPtr<ICompressSetCoderMt> setCoderMt; @@ -85,14 +93,13 @@ HRESULT CEncoder::CreateMixerCoder( } } #endif - - RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); + RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr<ICryptoResetSalt> resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); - if (resetSalt != NULL) + if (resetSalt) { resetSalt->ResetSalt(); } @@ -103,19 +110,18 @@ HRESULT CEncoder::CreateMixerCoder( encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { - RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); } #endif - + CMyComPtr<ICryptoSetPassword> cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); 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; @@ -137,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)); } @@ -153,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++) { @@ -177,8 +185,8 @@ HRESULT CEncoder::Encode( return E_FAIL; 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++) @@ -189,40 +197,47 @@ HRESULT CEncoder::Encode( _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); } - + // UInt64 outStreamStartPos; // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); - + 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]); for (i = 0; i < _codersInfo.Size(); i++) { CCoderInfo &encodingInfo = _codersInfo[i]; - + 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); @@ -242,33 +257,38 @@ HRESULT CEncoder::Encode( } _mixerCoderSpec->SetProgressCoderIndex(progressIndex); - + RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); - + 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++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; 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; } @@ -298,16 +318,16 @@ HRESULT CEncoder::EncoderConstr() throw 1; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; - + method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = 1; coderStreamsInfo.NumOutStreams = 1; method.Id = k_AES; - + _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); - + _bindInfo.InStreams.Add(0); _bindInfo.OutStreams.Add(0); } @@ -315,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]; @@ -331,12 +351,12 @@ 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); } - + numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; @@ -390,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++) { diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h index 4909a6e89..8e20bdb5f 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zEncode.h @@ -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); diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp index d55f38e13..bb350455c 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zExtract.cpp @@ -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 @@ -60,17 +60,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, _db.Files.Size(); #endif - if(numItems == 0) + if (numItems == 0) return S_OK; /* - if(_volumes.Size() != 1) + 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; */ - + CObjectVector<CExtractFolderInfo> extractFolderInfoVector; for (UInt32 ii = 0; ii < numItems; ii++) { @@ -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,14 +115,13 @@ 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; } - + CExtractFolderInfo &efi = extractFolderInfoVector.Back(); - + // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; CNum startIndex = db.FolderStartFileIndex[folderIndex]; for (CNum index = efi.ExtractStatuses.Size(); @@ -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; @@ -164,7 +163,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, if (i >= extractFolderInfoVector.Size()) break; - + const CExtractFolderInfo &efi = extractFolderInfoVector[i]; curUnpacked = efi.UnpackSize; curPacked = 0; @@ -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) diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp index edd276bc1..3f420a513 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.cpp @@ -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()) { diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h index 6df3672a1..4ed4b2dd2 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderInStream.h @@ -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; } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp index 22c4600ec..847f65bf2 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.cpp @@ -14,7 +14,7 @@ CFolderOutStream::CFolderOutStream() } HRESULT CFolderOutStream::Init( - const CArchiveDatabaseEx *db, + const CDbEx *db, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h index f9bb1af42..cc2d77343 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zFolderOutStream.h @@ -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, diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp index 4ab7afa87..ed65dc20c 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.cpp @@ -23,26 +23,23 @@ #endif using namespace NWindows; - -extern UString ConvertMethodIdToString(UInt64 id); +using namespace NCOM; namespace NArchive { namespace N7z { CHandler::CHandler() { - _crcSize = 4; - #ifndef _NO_CRYPTO + _isEncrypted = false; _passwordIsDefined = false; #endif #ifdef EXTRACT_ONLY + _crcSize = 4; #ifdef __7Z_SET_PROPERTIES _numThreads = NSystem::GetNumberOfProcessors(); #endif - #else - Init(); #endif } @@ -54,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 */, @@ -67,162 +65,502 @@ STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, return E_NOTIMPL; } - #else -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 }; +IMP_IInArchive_ArcProps + +static inline char GetHex(unsigned value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id) +{ + 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 void ConvertMethodIdToString(AString &res, UInt64 id) +{ + 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 char *AddProp32(char *s, const char *name, UInt32 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 + STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { + #ifndef _SFX COM_TRY_BEGIN + #endif NCOM::CPropVariant prop; - switch(propID) + switch (propID) { + #ifndef _SFX 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++) + AString s; + const CParsedMethods &pm = _db.ParsedMethods; + FOR_VECTOR (i, pm.IDs) { - 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; + 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 = resString; + prop = s; break; } case kpidSolid: prop = _db.IsSolid(); break; - case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break; + case kpidNumBlocks: prop = (UInt32)_db.NumFolders; 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; + 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 } -IMP_IInArchive_ArcProps - -#endif - -static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop) +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--) { - FILETIME ft; - ft.dwLowDateTime = (DWORD)value; - ft.dwHighDateTime = (DWORD)(value >> 32); - prop = ft; + 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; } -#ifndef _SFX +STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps) +{ + *numProps = 0; + return S_OK; +} -static UString ConvertUInt32ToString(UInt32 value) +STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID) { - wchar_t buffer[32]; - ConvertUInt64ToString(value, buffer); - return buffer; + *name = NULL; + *propID = kpidNtSecure; + return S_OK; } -static UString GetStringForSizeValue(UInt32 value) +STDMETHODIMP CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType) { - 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) + /* + 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) { - result += ConvertUInt32ToString(value >> 10); - result += L"k"; + if (_db.NameOffsets && _db.NamesBuf) + { + size_t offset = _db.NameOffsets[index]; + size_t size = (_db.NameOffsets[index + 1] - offset) * 2; + if (size < ((UInt32)1 << 31)) + { + *data = (const void *)(_db.NamesBuf + offset * 2); + *dataSize = (UInt32)size; + *propType = NPropDataType::kUtf16z; + } + } + return S_OK; } - else + /* + if (propID == kpidNtSecure) { - result += ConvertUInt32ToString(value); - result += L"b"; + 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 result; + */ + return S_OK; } -static const UInt64 k_Copy = 0x0; -static const UInt64 k_Delta = 3; -static const UInt64 k_LZMA2 = 0x21; -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_PPMD = 0x030401; +#ifndef _SFX -static wchar_t GetHex(Byte value) -{ - return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); -} -static inline void AddHexToString(UString &res, Byte value) +HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const { - res += GetHex((Byte)(value >> 4)); - res += GetHex((Byte)(value & 0xF)); + 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); + + if ((mainByte & 0x10) != 0) + { + inByte.ReadNum(); // NumInStreams + inByte.ReadNum(); // NumOutStreams + } + + 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 -bool CHandler::IsEncrypted(UInt32 index2) const +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { - CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; - if (folderIndex != kNumNoIndex) - return _db.Folders[folderIndex].IsEncrypted(); - return false; -} + PropVariant_Clear(value); + // COM_TRY_BEGIN + // NCOM::CPropVariant prop; -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) -{ - COM_TRY_BEGIN - NCOM::CPropVariant prop; - /* const CRef2 &ref2 = _refs[index]; if (ref2.Refs.IsEmpty()) return E_FAIL; const CRef &ref = ref2.Refs.Front(); */ - + const CFileItem &item = _db.Files[index]; UInt32 index2 = index; 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; } @@ -234,122 +572,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); - } - 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_Prop(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: @@ -358,6 +623,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va case kpidPackedSize3: case kpidPackedSize4: { + /* CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { @@ -372,13 +638,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, @@ -390,6 +657,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, #ifndef _SFX _fileInfoPopIDs.Clear(); #endif + try { CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback; @@ -397,31 +665,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; @@ -437,6 +704,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 } @@ -444,16 +715,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]; @@ -461,9 +732,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 diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h index 56062d464..677a3e10a 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandler.h @@ -18,6 +18,16 @@ namespace NArchive { namespace N7z { +const UInt32 k_Copy = 0x0; +const UInt32 k_Delta = 3; +const UInt32 k_LZMA2 = 0x21; +const UInt32 k_LZMA = 0x030101; +const UInt32 k_PPMD = 0x030401; +const UInt32 k_BCJ = 0x03030103; +const UInt32 k_BCJ2 = 0x0303011B; +const UInt32 k_Deflate = 0x040108; +const UInt32 k_BZip2 = 0x040202; + #ifndef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY @@ -31,11 +41,53 @@ namespace N7z { #endif +#ifndef EXTRACT_ONLY + +class COutHandler: public CMultiMethodProps +{ + HRESULT SetSolidFromString(const UString &s); + HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value); +public: + bool _removeSfxBlock; + + UInt64 _numSolidFiles; + UInt64 _numSolidBytes; + bool _numSolidBytesDefined; + bool _solidExtension; + + bool _compressHeaders; + bool _encryptHeadersSpecified; + bool _encryptHeaders; + // bool _useParents; 9.26 + + CBoolPair Write_CTime; + CBoolPair Write_ATime; + CBoolPair Write_MTime; + + bool _volumeMode; + + void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } + void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } + void InitSolid() + { + InitSolidFiles(); + InitSolidSize(); + _solidExtension = false; + _numSolidBytesDefined = false; + } + + void InitProps(); + + COutHandler() { InitProps(); } + + HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); +}; + +#endif + class CHandler: - #ifndef EXTRACT_ONLY - public NArchive::COutHandler, - #endif public IInArchive, + public IArchiveGetRawProps, #ifdef __7Z_SET_PROPERTIES public ISetProperties, #endif @@ -44,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 @@ -58,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 @@ -73,13 +130,14 @@ public: private: CMyComPtr<IInStream> _inStream; - NArchive::N7z::CArchiveDatabaseEx _db; + NArchive::N7z::CDbEx _db; #ifndef _NO_CRYPTO + bool _isEncrypted; bool _passwordIsDefined; #endif #ifdef EXTRACT_ONLY - + #ifdef __7Z_SET_PROPERTIES UInt32 _numThreads; #endif @@ -87,27 +145,29 @@ private: UInt32 _crcSize; #else - + CRecordVector<CBind> _binds; - HRESULT SetCompressionMethod(CCompressionMethodMode &method, + HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m); + HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod); + void AddDefaultMethod(); + HRESULT SetMainMethod(CCompressionMethodMode &method, CObjectVector<COneMethodInfo> &methodsInfo #ifndef _7ZIP_ST , UInt32 numThreads #endif ); - HRESULT SetCompressionMethod( - CCompressionMethodMode &method, - CCompressionMethodMode &headerMethod); #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 diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp index a8ccab6df..7de5b8140 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -2,12 +2,9 @@ #include "StdAfx.h" -#include "../../../Windows/PropVariant.h" - #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" - -#include "../../ICoder.h" +#include "../../../Common/Wildcard.h" #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" @@ -21,24 +18,19 @@ using namespace NWindows; namespace NArchive { namespace N7z { -static const wchar_t *kLZMAMethodName = L"LZMA"; -static const wchar_t *kCopyMethod = L"Copy"; -static const wchar_t *kDefaultMethodName = kLZMAMethodName; +static const wchar_t *k_LZMA_Name = L"LZMA"; +static const wchar_t *kDefaultMethodName = L"LZMA2"; +static const wchar_t *k_Copy_Name = L"Copy"; -static const UInt32 kLzmaAlgorithmX5 = 1; -static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; -static const UInt32 kDictionaryForHeaders = +static const wchar_t *k_MatchFinder_ForHeaders = L"BT2"; +static const UInt32 k_NumFastBytes_ForHeaders = 273; +static const UInt32 k_Level_ForHeaders = 5; +static const UInt32 k_Dictionary_ForHeaders = #ifdef UNDER_CE - 1 << 18 + 1 << 18; #else - 1 << 20 + 1 << 20; #endif -; -static const UInt32 kNumFastBytesForHeaders = 273; -static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; - -static inline bool IsCopyMethod(const UString &methodName) - { return (methodName.CompareNoCase(kCopyMethod) == 0); } STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { @@ -46,132 +38,112 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) return S_OK; } -HRESULT CHandler::SetCompressionMethod( - CCompressionMethodMode &methodMode, - CCompressionMethodMode &headerMethod) +HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m) { - HRESULT res = SetCompressionMethod(methodMode, _methods - #ifndef _7ZIP_ST - , _numThreads - #endif - ); - RINOK(res); - methodMode.Binds = _binds; + if (!FindMethod( + EXTERNAL_CODECS_VARS + m.MethodName, dest.Id, dest.NumInStreams, dest.NumOutStreams)) + return E_INVALIDARG; + (CProps &)dest = (CProps &)m; + return S_OK; +} - if (_compressHeaders) - { - // headerMethod.Methods.Add(methodMode.Methods.Back()); +HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod) +{ + if (!_compressHeaders) + return S_OK; + COneMethodInfo m; + m.MethodName = k_LZMA_Name; + m.AddPropString(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders); + m.AddProp32(NCoderPropID::kLevel, k_Level_ForHeaders); + m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders); + m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders); + m.AddNumThreadsProp(1); + + CMethodFull methodFull; + RINOK(PropsMethod_To_FullMethod(methodFull, m)); + headerMethod.Methods.Add(methodFull); + return S_OK; +} - CObjectVector<COneMethodInfo> headerMethodInfoVector; - COneMethodInfo oneMethodInfo; - oneMethodInfo.MethodName = kLZMAMethodName; - { - CProp prop; - prop.Id = NCoderPropID::kMatchFinder; - prop.Value = kLzmaMatchFinderForHeaders; - oneMethodInfo.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kAlgorithm; - prop.Value = kAlgorithmForHeaders; - oneMethodInfo.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kNumFastBytes; - prop.Value = (UInt32)kNumFastBytesForHeaders; - oneMethodInfo.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kDictionarySize; - prop.Value = (UInt32)kDictionaryForHeaders; - oneMethodInfo.Props.Add(prop); - } - headerMethodInfoVector.Add(oneMethodInfo); - HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector - #ifndef _7ZIP_ST - , 1 - #endif - ); - RINOK(res); +void CHandler::AddDefaultMethod() +{ + FOR_VECTOR (i, _methods) + { + UString &methodName = _methods[i].MethodName; + if (methodName.IsEmpty()) + methodName = kDefaultMethodName; + } + if (_methods.IsEmpty()) + { + COneMethodInfo m; + m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName); + _methods.Add(m); } - return S_OK; } -HRESULT CHandler::SetCompressionMethod( +HRESULT CHandler::SetMainMethod( CCompressionMethodMode &methodMode, - CObjectVector<COneMethodInfo> &methodsInfo + CObjectVector<COneMethodInfo> &methods #ifndef _7ZIP_ST , UInt32 numThreads #endif ) { - UInt32 level = _level; - - if (methodsInfo.IsEmpty()) - { - COneMethodInfo oneMethodInfo; - oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); - methodsInfo.Add(oneMethodInfo); - } + AddDefaultMethod(); + + const UInt64 kSolidBytes_Min = (1 << 24); + const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1; bool needSolid = false; - for(int i = 0; i < methodsInfo.Size(); i++) + FOR_VECTOR (i, methods) { - COneMethodInfo &oneMethodInfo = methodsInfo[i]; - SetCompressionMethod2(oneMethodInfo + COneMethodInfo &oneMethodInfo = methods[i]; + SetGlobalLevelAndThreads(oneMethodInfo #ifndef _7ZIP_ST , numThreads #endif ); - if (!IsCopyMethod(oneMethodInfo.MethodName)) - needSolid = true; - CMethodFull methodFull; - - if (!FindMethod( - EXTERNAL_CODECS_VARS - oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams)) - return E_INVALIDARG; - methodFull.Props = oneMethodInfo.Props; + RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo)); methodMode.Methods.Add(methodFull); - if (!_numSolidBytesDefined) + if (methodFull.Id != k_Copy) + needSolid = true; + + if (_numSolidBytesDefined) + continue; + + UInt32 dicSize; + switch (methodFull.Id) { - for (int j = 0; j < methodFull.Props.Size(); j++) - { - const CProp &prop = methodFull.Props[j]; - if ((prop.Id == NCoderPropID::kDictionarySize || - prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) - { - _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; - const UInt64 kMinSize = (1 << 24); - if (_numSolidBytes < kMinSize) - _numSolidBytes = kMinSize; - _numSolidBytesDefined = true; - break; - } - } + case k_LZMA: + case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break; + case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break; + case k_Deflate: dicSize = (UInt32)1 << 15; break; + case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break; + default: continue; } - } - - if (!needSolid && !_numSolidBytesDefined) - { + _numSolidBytes = (UInt64)dicSize << 7; + if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min; + if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max; _numSolidBytesDefined = true; - _numSolidBytes = 0; } + + if (!_numSolidBytesDefined) + if (needSolid) + _numSolidBytes = kSolidBytes_Max; + else + _numSolidBytes = 0; + _numSolidBytesDefined = true; 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) @@ -181,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; @@ -204,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; @@ -221,24 +292,32 @@ 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) + { + _db.GetPath(ui.IndexInArchive, name); + } 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; @@ -253,23 +332,37 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.AttribDefined = true; } } - + // 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); } } { @@ -297,6 +390,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; @@ -304,13 +410,87 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt ui.CTimeDefined = false; ui.ATimeDefined = false; ui.MTimeDefined = false; - + ui.Size = 0; } 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) { @@ -325,8 +505,27 @@ 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; - RINOK(SetCompressionMethod(methodMode, headerMethod)); + + HRESULT res = SetMainMethod(methodMode, _methods + #ifndef _7ZIP_ST + , _numThreads + #endif + ); + RINOK(res); + methodMode.Binds = _binds; + + RINOK(SetHeaderMethod(headerMethod)); #ifndef _7ZIP_ST methodMode.NumThreads = _numThreads; headerMethod.NumThreads = 1; @@ -335,17 +534,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 @@ -373,14 +572,17 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt CUpdateOptions options; options.Method = &methodMode; options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0; - options.UseFilters = _level != 0 && _autoFilter; - options.MaxFilter = _level >= 8; + int level = GetLevel(); + options.UseFilters = level != 0 && _autoFilter; + 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; options.SolidExtension = _solidExtension; @@ -388,12 +590,24 @@ 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); - - HRESULT res = Update( + + /* + 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 volume ? volume->Stream: 0, @@ -403,6 +617,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt db, #endif updateItems, + // treeFolders, + // secureBlocks, archive, newDatabase, outStream, updateCallback, options #ifndef _NO_CRYPTO , getPassword @@ -426,7 +642,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); @@ -437,38 +653,173 @@ static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream return S_OK; } -static HRESULT GetBindInfo(UString &srcString, CBind &bind) +void COutHandler::InitProps() { - RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream)); - if (srcString[0] != ':') - return E_INVALIDARG; - srcString.Delete(0); - RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream)); - if (!srcString.IsEmpty()) - return E_INVALIDARG; + CMultiMethodProps::Init(); + + _removeSfxBlock = false; + _compressHeaders = true; + _encryptHeadersSpecified = false; + _encryptHeaders = false; + // _useParents = false; + + Write_CTime.Init(); + Write_ATime.Init(); + Write_MTime.Init(); + + _volumeMode = false; + InitSolid(); +} + +HRESULT COutHandler::SetSolidFromString(const UString &s) +{ + UString s2 = s; + 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') + return E_INVALIDARG; + _solidExtension = true; + continue; + } + i += (int)(end - start); + if (i == s2.Len()) + return E_INVALIDARG; + wchar_t c = s2[i++]; + if (c == 'f') + { + if (v < 1) + v = 1; + _numSolidFiles = v; + } + else + { + 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 't': numBits = 40; break; + default: return E_INVALIDARG; + } + _numSolidBytes = (v << numBits); + _numSolidBytesDefined = true; + } + } return S_OK; } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) +HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value) +{ + bool isSolid; + switch (value.vt) + { + case VT_EMPTY: isSolid = true; break; + case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; + case VT_BSTR: + if (StringToBool(value.bstrVal, isSolid)) + break; + return SetSolidFromString(value.bstrVal); + default: return E_INVALIDARG; + } + if (isSolid) + InitSolid(); + else + _numSolidFiles = 1; + 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.MakeLower_Ascii(); + if (name.IsEmpty()) + return E_INVALIDARG; + + if (name[0] == L's') + { + name.Delete(0); + if (name.IsEmpty()) + return SetSolidFromPROPVARIANT(value); + if (value.vt != VT_EMPTY) + return E_INVALIDARG; + return SetSolidFromString(name); + } + + UInt32 number; + int index = ParseStringToUInt32(name, number); + UString realName = name.Ptr(index); + if (index == 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.IsEqualTo("he")) + { + RINOK(PROPVARIANT_to_bool(value, _encryptHeaders)); + _encryptHeadersSpecified = true; + return S_OK; + } + + 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, UInt32 numProps) { COM_TRY_BEGIN _binds.Clear(); - BeforeSetProperty(); + InitProps(); - 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]; - if (name[0] == 'B') + if (name[0] == 'b') { + if (value.vt != VT_EMPTY) + return E_INVALIDARG; name.Delete(0); CBind bind; - RINOK(GetBindInfo(name, bind)); + RINOK(GetBindInfoPart(name, bind.OutCoder, bind.OutStream)); + if (name[0] != ':') + return E_INVALIDARG; + name.Delete(0); + RINOK(GetBindInfoPart(name, bind.InCoder, bind.InStream)); + if (!name.IsEmpty()) + return E_INVALIDARG; _binds.Add(bind); continue; } @@ -476,6 +827,47 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v RINOK(SetProperty(name, value)); } + unsigned numEmptyMethods = GetNumEmptyMethods(); + if (numEmptyMethods > 0) + { + unsigned k; + for (k = 0; k < _binds.Size(); k++) + { + const CBind &bind = _binds[k]; + if (bind.InCoder < (UInt32)numEmptyMethods || + bind.OutCoder < (UInt32)numEmptyMethods) + return E_INVALIDARG; + } + for (k = 0; k < _binds.Size(); k++) + { + CBind &bind = _binds[k]; + bind.InCoder -= (UInt32)numEmptyMethods; + bind.OutCoder -= (UInt32)numEmptyMethods; + } + _methods.DeleteFrontal(numEmptyMethods); + } + + AddDefaultMethod(); + + if (!_filterMethod.MethodName.IsEmpty()) + { + FOR_VECTOR (k, _binds) + { + CBind &bind = _binds[k]; + bind.InCoder++; + bind.OutCoder++; + } + _methods.Insert(0, _filterMethod); + } + + FOR_VECTOR (k, _binds) + { + const CBind &bind = _binds[k]; + if (bind.InCoder >= (UInt32)_methods.Size() || + bind.OutCoder >= (UInt32)_methods.Size()) + return E_INVALIDARG; + } + return S_OK; COM_TRY_END } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp index 5b5f2fb37..acff2fdd8 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.cpp @@ -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; + }} diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h index 30622b90e..61dad655d 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zHeader.h @@ -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 @@ -57,11 +57,11 @@ namespace NID kHeader, kArchiveProperties, - + kAdditionalStreamsInfo, kMainStreamsInfo, kFilesInfo, - + kPackInfo, kUnpackInfo, kSubStreamsInfo, @@ -82,13 +82,17 @@ namespace NID kCTime, kATime, kMTime, - kWinAttributes, + kWinAttrib, kComment, kEncodedHeader, kStartPos, kDummy + + // kNtSecure, + // kParent, + // kIsAux }; } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp index b11819616..28ec5e083 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.cpp @@ -2,6 +2,12 @@ #include "StdAfx.h" +#ifdef _WIN32 +#include <wchar.h> +#else +#include <ctype.h> +#endif + #include "../../../../C/7zCrc.h" #include "../../../../C/CpuArch.h" @@ -20,15 +26,21 @@ #define FORMAT_7Z_RECOVERY #endif +using namespace NWindows; +using namespace NCOM; + namespace NArchive { namespace N7z { -static void BoolVector_Fill_False(CBoolVector &v, int size) +static const UInt32 k_LZMA2 = 0x21; +static const UInt32 k_LZMA = 0x030101; + +static void BoolVector_Fill_False(CBoolVector &v, unsigned size) { - v.Clear(); - v.Reserve(size); - for (int i = 0; i < size; i++) - v.Add(false); + v.ClearAndSetSize(size); + bool *p = &v[0]; + for (unsigned i = 0; i < size; i++) + p[i] = false; } static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) @@ -40,11 +52,11 @@ static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) return res; } -bool CFolder::CheckStructure() const +bool CFolder::CheckStructure(unsigned numUnpackSizes) const { - const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it - const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax - const int kNumBindsMax = 32; + const unsigned kNumCodersMax = sizeof(UInt32) * 8; // don't change it + const unsigned kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax + const unsigned kNumBindsMax = 32; if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) return false; @@ -52,28 +64,28 @@ bool CFolder::CheckStructure() const { CBoolVector v; BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); - - int i; + + unsigned i; for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) return false; for (i = 0; i < PackStreams.Size(); i++) if (BoolVector_GetAndSet(v, PackStreams[i])) return false; - - BoolVector_Fill_False(v, UnpackSizes.Size()); + + BoolVector_Fill_False(v, numUnpackSizes); for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) return false; } - + UInt32 mask[kMaskSize]; - int i; + unsigned i; for (i = 0; i < kMaskSize; i++) mask[i] = 0; { - CIntVector inStreamToCoder, outStreamToCoder; + CUIntVector inStreamToCoder, outStreamToCoder; for (i = 0; i < Coders.Size(); i++) { CNum j; @@ -83,16 +95,16 @@ bool CFolder::CheckStructure() const for (j = 0; j < coder.NumOutStreams; j++) outStreamToCoder.Add(i); } - + for (i = 0; i < BindPairs.Size(); i++) { const CBindPair &bp = BindPairs[i]; mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]); } } - + for (i = 0; i < kMaskSize; i++) - for (int j = 0; j < kMaskSize; j++) + for (unsigned j = 0; j < kMaskSize; j++) if (((1 << j) & mask[i]) != 0) mask[i] |= mask[j]; @@ -104,43 +116,23 @@ bool CFolder::CheckStructure() const } class CInArchiveException {}; +class CUnsupportedFeatureException: public CInArchiveException {}; static void ThrowException() { throw CInArchiveException(); } static inline void ThrowEndOfData() { ThrowException(); } -static inline void ThrowUnsupported() { ThrowException(); } +static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); } static inline void ThrowIncorrect() { ThrowException(); } -static inline void ThrowUnsupportedVersion() { ThrowException(); } - -/* -class CInArchiveException -{ -public: - enum CCauseType - { - kUnsupportedVersion = 0, - kUnsupported, - kIncorrect, - kEndOfData - } Cause; - CInArchiveException(CCauseType cause): Cause(cause) {}; -}; - -static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } -static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } -static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } -static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } -static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } -*/ class CStreamSwitch { CInArchive *_archive; bool _needRemove; + bool _needUpdatePos; public: - CStreamSwitch(): _needRemove(false) {} + CStreamSwitch(): _needRemove(false), _needUpdatePos(false) {} ~CStreamSwitch() { Remove(); } void Remove(); - void Set(CInArchive *archive, const Byte *data, size_t size); + void Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos); void Set(CInArchive *archive, const CByteBuffer &byteBuffer); void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector); }; @@ -149,22 +141,25 @@ void CStreamSwitch::Remove() { if (_needRemove) { - _archive->DeleteByteStream(); + if (_archive->_inByteBack->GetRem() != 0) + _archive->ThereIsHeaderError = true; + _archive->DeleteByteStream(_needUpdatePos); _needRemove = false; } } -void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) +void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos) { Remove(); _archive = archive; _archive->AddByteStream(data, size); _needRemove = true; + _needUpdatePos = needUpdatePos; } void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) { - Set(archive, byteBuffer, byteBuffer.GetCapacity()); + Set(archive, byteBuffer, byteBuffer.Size(), false); } void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector) @@ -173,13 +168,22 @@ void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *d Byte external = archive->ReadByte(); if (external != 0) { - int dataIndex = (int)archive->ReadNum(); - if (dataIndex < 0 || dataIndex >= dataVector->Size()) + CNum dataIndex = archive->ReadNum(); + if (dataIndex >= dataVector->Size()) ThrowIncorrect(); Set(archive, (*dataVector)[dataIndex]); } } +void CInArchive::AddByteStream(const Byte *buf, size_t size) +{ + if (_numInByteBufs == kNumBufLevelsMax) + ThrowIncorrect(); + _inByteBack = &_inByteVector[_numInByteBufs++]; + _inByteBack->Init(buf, size); +} + + Byte CInByte2::ReadByte() { if (_pos >= _size) @@ -191,8 +195,8 @@ void CInByte2::ReadBytes(Byte *data, size_t size) { if (size > _size - _pos) ThrowEndOfData(); - for (size_t i = 0; i < size; i++) - data[i] = _buffer[_pos++]; + memcpy(data, _buffer + _pos, size); + _pos += size; } void CInByte2::SkipData(UInt64 size) @@ -207,31 +211,75 @@ void CInByte2::SkipData() SkipData(ReadNumber()); } -UInt64 CInByte2::ReadNumber() +static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed) { - if (_pos >= _size) - ThrowEndOfData(); - Byte firstByte = _buffer[_pos++]; - Byte mask = 0x80; - UInt64 value = 0; - for (int i = 0; i < 8; i++) + if (size == 0) + { + processed = 0; + return 0; + } + Byte firstByte = *p++; + size--; + if ((firstByte & 0x80) == 0) + { + processed = 1; + return firstByte; + } + Byte mask = 0x40; + if (size == 0) + { + processed = 0; + return 0; + } + UInt64 value = (UInt64)*p; + p++; + size--; + for (unsigned i = 1; i < 8; i++) { if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); value += (highPart << (i * 8)); + processed = i + 1; return value; } - if (_pos >= _size) - ThrowEndOfData(); - value |= ((UInt64)_buffer[_pos++] << (8 * i)); + if (size == 0) + { + processed = 0; + return 0; + } + value |= ((UInt64)*p << (i * 8)); + p++; + size--; mask >>= 1; } + processed = 9; return value; } +UInt64 CInByte2::ReadNumber() +{ + size_t processed; + UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed); + if (processed == 0) + ThrowEndOfData(); + _pos += processed; + return res; +} + CNum CInByte2::ReadNum() { + /* + if (_pos < _size) + { + Byte val = _buffer[_pos]; + if ((unsigned)val < 0x80) + { + _pos++; + return (unsigned)val; + } + } + */ UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); @@ -256,48 +304,21 @@ UInt64 CInByte2::ReadUInt64() return res; } -void CInByte2::ReadString(UString &s) -{ - const Byte *buf = _buffer + _pos; - size_t rem = (_size - _pos) / 2 * 2; - { - size_t i; - for (i = 0; i < rem; i += 2) - if (buf[i] == 0 && buf[i + 1] == 0) - break; - if (i == rem) - ThrowEndOfData(); - rem = i; - } - int len = (int)(rem / 2); - if (len < 0 || (size_t)len * 2 != rem) - ThrowUnsupported(); - wchar_t *p = s.GetBuffer(len); - int i; - for (i = 0; i < len; i++, buf += 2) - p[i] = (wchar_t)Get16(buf); - s.ReleaseBuffer(len); - _pos += rem + 2; -} +#define CHECK_SIGNATURE if (p[0] != '7' || p[1] != 'z' || p[2] != 0xBC || p[3] != 0xAF || p[4] != 0x27 || p[5] != 0x1C) return false; static inline bool TestSignature(const Byte *p) { - for (int i = 0; i < kSignatureSize; i++) - if (p[i] != kSignature[i]) - return false; - return CrcCalc(p + 12, 20) == GetUi32(p + 8); + CHECK_SIGNATURE + return CrcCalc(p + 12, 20) == Get32(p + 8); } #ifdef FORMAT_7Z_RECOVERY static inline bool TestSignature2(const Byte *p) { - int i; - for (i = 0; i < kSignatureSize; i++) - if (p[i] != kSignature[i]) - return false; - if (CrcCalc(p + 12, 20) == GetUi32(p + 8)) + CHECK_SIGNATURE; + if (CrcCalc(p + 12, 20) == Get32(p + 8)) return true; - for (i = 8; i < kHeaderSize; i++) + for (unsigned i = 8; i < kHeaderSize; i++) if (p[i] != 0) return false; return (p[6] != 0 || p[7] != 0); @@ -312,48 +333,52 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search if (TestSignature2(_header)) return S_OK; + if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0) + return S_FALSE; + + const UInt32 kBufSize = 1 << 15; + CByteArr buf(kBufSize); + memcpy(buf, _header, kHeaderSize); + UInt64 offset = 0; - CByteBuffer byteBuffer; - const UInt32 kBufferSize = (1 << 16); - byteBuffer.SetCapacity(kBufferSize); - Byte *buffer = byteBuffer; - UInt32 numPrevBytes = kHeaderSize; - memcpy(buffer, _header, kHeaderSize); - UInt64 curTestPos = _arhiveBeginStreamPosition; for (;;) { - if (searchHeaderSizeLimit != NULL) - if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) - break; - do + UInt32 readSize = kBufSize - kHeaderSize; { - UInt32 numReadBytes = kBufferSize - numPrevBytes; - UInt32 processedSize; - RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); - numPrevBytes += processedSize; - if (processedSize == 0) + UInt64 rem = *searchHeaderSizeLimit - offset; + if (readSize > rem) + readSize = (UInt32)rem; + if (readSize == 0) return S_FALSE; } - while (numPrevBytes <= kHeaderSize); - UInt32 numTests = numPrevBytes - kHeaderSize; - for (UInt32 pos = 0; pos < numTests; pos++) + UInt32 processed = 0; + RINOK(stream->Read(buf + kHeaderSize, readSize, &processed)); + if (processed == 0) + return S_FALSE; + for (UInt32 pos = 0;;) { - for (; buffer[pos] != '7' && pos < numTests; pos++) {} - if (pos == numTests) + const Byte *p = buf + pos + 1; + const Byte *lim = buf + processed; + for (; p <= lim; p += 4) + { + if (p[0] == '7') break; + if (p[1] == '7') { p += 1; break; } + if (p[2] == '7') { p += 2; break; } + if (p[3] == '7') { p += 3; break; } + }; + if (p > lim) break; - if (TestSignature(buffer + pos)) + pos = (UInt32)(p - buf); + if (TestSignature(p)) { - memcpy(_header, buffer + pos, kHeaderSize); - curTestPos += pos; - _arhiveBeginStreamPosition = curTestPos; - return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); + memcpy(_header, p, kHeaderSize); + _arhiveBeginStreamPosition += offset + pos; + return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL); } } - curTestPos += numTests; - numPrevBytes -= numTests; - memmove(buffer, buffer + numTests, numPrevBytes); + offset += processed; + memmove(buf, buf + processed, kHeaderSize); } - return S_FALSE; } // S_FALSE means that file is not archive @@ -362,14 +387,18 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) HeadersSize = 0; Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) + RINOK(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition)) + RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; } - + void CInArchive::Close() { + _numInByteBufs = 0; _stream.Release(); + ThereIsHeaderError = false; } void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) @@ -382,30 +411,32 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) } } -void CInArchive::GetNextFolderItem(CFolder &folder) +// CFolder &folder can be non empty. So we must set all fields + +void CInByte2::ParseFolder(CFolder &folder) { CNum numCoders = ReadNum(); - folder.Coders.Clear(); - folder.Coders.Reserve((int)numCoders); + folder.Coders.SetSize(numCoders); + CNum numInStreams = 0; CNum numOutStreams = 0; CNum i; for (i = 0; i < numCoders; i++) { - folder.Coders.Add(CCoderInfo()); - CCoderInfo &coder = folder.Coders.Back(); - + CCoderInfo &coder = folder.Coders[i]; { Byte mainByte = ReadByte(); - int idSize = (mainByte & 0xF); - Byte longID[15]; - ReadBytes(longID, idSize); - if (idSize > 8) + if ((mainByte & 0xC0) != 0) ThrowUnsupported(); + unsigned idSize = (mainByte & 0xF); + if (idSize > 8 || idSize > GetRem()) + ThrowUnsupported(); + const Byte *longID = GetPtr(); UInt64 id = 0; - for (int j = 0; j < idSize; j++) - id |= (UInt64)longID[idSize - 1 - j] << (8 * j); + for (unsigned j = 0; j < idSize; j++) + id = ((id << 8) | longID[j]); + SkipDataNoCheck(idSize); coder.MethodID = id; if ((mainByte & 0x10) != 0) @@ -421,53 +452,171 @@ void CInArchive::GetNextFolderItem(CFolder &folder) if ((mainByte & 0x20) != 0) { CNum propsSize = ReadNum(); - coder.Props.SetCapacity((size_t)propsSize); + coder.Props.Alloc((size_t)propsSize); ReadBytes((Byte *)coder.Props, (size_t)propsSize); } - if ((mainByte & 0x80) != 0) - ThrowUnsupported(); + else + coder.Props.Free(); } numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } CNum numBindPairs = numOutStreams - 1; - folder.BindPairs.Clear(); - folder.BindPairs.Reserve(numBindPairs); + folder.BindPairs.SetSize(numBindPairs); for (i = 0; i < numBindPairs; i++) { - CBindPair bp; + CBindPair &bp = folder.BindPairs[i]; bp.InIndex = ReadNum(); bp.OutIndex = ReadNum(); - folder.BindPairs.Add(bp); } if (numInStreams < numBindPairs) ThrowUnsupported(); CNum numPackStreams = numInStreams - numBindPairs; - folder.PackStreams.Reserve(numPackStreams); + folder.PackStreams.SetSize(numPackStreams); if (numPackStreams == 1) { for (i = 0; i < numInStreams; i++) if (folder.FindBindPairForInStream(i) < 0) { - folder.PackStreams.Add(i); + folder.PackStreams[0] = i; break; } - if (folder.PackStreams.Size() != 1) + if (i == numInStreams) ThrowUnsupported(); } else for (i = 0; i < numPackStreams; i++) - folder.PackStreams.Add(ReadNum()); + folder.PackStreams[i] = ReadNum(); +} + +void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const +{ + size_t startPos = FoCodersDataOffset[folderIndex]; + CInByte2 inByte; + inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos); + inByte.ParseFolder(folder); + if (inByte.GetRem() != 0) + throw 20120424; +} + + +void CDatabase::GetPath(unsigned index, UString &path) const +{ + path.Empty(); + if (!NameOffsets || !NamesBuf) + return; + + size_t offset = NameOffsets[index]; + size_t size = NameOffsets[index + 1] - offset - 1; + + if (size >= (1 << 20)) + return; + + wchar_t *s = path.GetBuffer((unsigned)size); + + const Byte *p = ((const Byte *)NamesBuf + offset * 2); + + #if defined(_WIN32) && defined(MY_CPU_LE) + + wmemcpy(s, (const wchar_t *)p, size); + + #else + + for (size_t i = 0; i < size; i++) + { + *s = Get16(p); + p += 2; + s++; + } + + #endif + + path.ReleaseBuffer((unsigned)size); +} + +HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw() +{ + PropVariant_Clear(path); + if (!NameOffsets || !NamesBuf) + return S_OK; + + size_t offset = NameOffsets[index]; + size_t size = NameOffsets[index + 1] - offset; + + if (size >= (1 << 14)) + return S_OK; + + RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1)); + wchar_t *s = path->bstrVal; + + const Byte *p = ((const Byte *)NamesBuf + offset * 2); + + for (size_t i = 0; i < size; i++) + { + wchar_t c = Get16(p); + p += 2; + #if WCHAR_PATH_SEPARATOR != L'/' + if (c == L'/') + c = WCHAR_PATH_SEPARATOR; + #endif + *s++ = c; + } + + return S_OK; + + /* + unsigned cur = index; + unsigned size = 0; + + for (int i = 0;; i++) + { + size_t len = NameOffsets[cur + 1] - NameOffsets[cur]; + size += (unsigned)len; + if (i > 256 || len > (1 << 14) || size > (1 << 14)) + return PropVarEm_Set_Str(path, "[TOO-LONG]"); + cur = Files[cur].Parent; + if (cur < 0) + break; + } + size--; + + RINOK(PropVarEm_Alloc_Bstr(path, size)); + wchar_t *s = path->bstrVal; + s += size; + *s = 0; + cur = index; + + for (;;) + { + unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1); + const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2; + do + { + p -= 2; + --s; + wchar_t c = Get16(p); + if (c == '/') + c = WCHAR_PATH_SEPARATOR; + *s = c; + } + while (--len); + const CFileItem &file = Files[cur]; + cur = file.Parent; + if (cur < 0) + return S_OK; + *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR); + } + */ } -void CInArchive::WaitAttribute(UInt64 attribute) +void CInArchive::WaitId(UInt64 id) { for (;;) { UInt64 type = ReadID(); - if (type == attribute) + if (type == id) return; if (type == NID::kEnd) ThrowIncorrect(); @@ -475,91 +624,210 @@ void CInArchive::WaitAttribute(UInt64 attribute) } } -void CInArchive::ReadHashDigests(int numItems, - CBoolVector &digestsDefined, - CRecordVector<UInt32> &digests) +void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs) { - ReadBoolVector2(numItems, digestsDefined); - digests.Clear(); - digests.Reserve(numItems); - for (int i = 0; i < numItems; i++) + ReadBoolVector2(numItems, crcs.Defs); + crcs.Vals.ClearAndSetSize(numItems); + UInt32 *p = &crcs.Vals[0]; + const bool *defs = &crcs.Defs[0]; + for (unsigned i = 0; i < numItems; i++) { UInt32 crc = 0; - if (digestsDefined[i]) + if (defs[i]) crc = ReadUInt32(); - digests.Add(crc); + p[i] = crc; } } -void CInArchive::ReadPackInfo( - UInt64 &dataOffset, - CRecordVector<UInt64> &packSizes, - CBoolVector &packCRCsDefined, - CRecordVector<UInt32> &packCRCs) +void CInArchive::ReadPackInfo(CFolders &f) { - dataOffset = ReadNumber(); CNum numPackStreams = ReadNum(); - WaitAttribute(NID::kSize); - packSizes.Clear(); - packSizes.Reserve(numPackStreams); + WaitId(NID::kSize); + f.PackPositions.Alloc(numPackStreams + 1); + f.NumPackStreams = numPackStreams; + UInt64 sum = 0; for (CNum i = 0; i < numPackStreams; i++) - packSizes.Add(ReadNumber()); + { + f.PackPositions[i] = sum; + UInt64 packSize = ReadNumber(); + sum += packSize; + if (sum < packSize) + ThrowIncorrect(); + } + f.PackPositions[numPackStreams] = sum; UInt64 type; for (;;) { type = ReadID(); if (type == NID::kEnd) - break; + return; if (type == NID::kCRC) { - ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); + CUInt32DefVector PackCRCs; + ReadHashDigests(numPackStreams, PackCRCs); continue; } SkipData(); } - if (packCRCsDefined.IsEmpty()) - { - BoolVector_Fill_False(packCRCsDefined, numPackStreams); - packCRCs.Reserve(numPackStreams); - packCRCs.Clear(); - for (CNum i = 0; i < numPackStreams; i++) - packCRCs.Add(0); - } } void CInArchive::ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, - CObjectVector<CFolder> &folders) + CFolders &folders) { - WaitAttribute(NID::kFolder); + WaitId(NID::kFolder); CNum numFolders = ReadNum(); + CNum numCodersOutStreams = 0; { CStreamSwitch streamSwitch; streamSwitch.Set(this, dataVector); - folders.Clear(); - folders.Reserve(numFolders); - for (CNum i = 0; i < numFolders; i++) + const Byte *startBufPtr = _inByteBack->GetPtr(); + folders.NumFolders = numFolders; + + folders.FoStartPackStreamIndex.Alloc(numFolders + 1); + folders.FoToMainUnpackSizeIndex.Alloc(numFolders); + folders.FoCodersDataOffset.Alloc(numFolders + 1); + folders.FoToCoderUnpackSizes.Alloc(numFolders + 1); + + CRecordVector<bool> InStreamUsed; + CRecordVector<bool> OutStreamUsed; + + CNum packStreamIndex = 0; + CNum fo; + CInByte2 *inByte = _inByteBack; + for (fo = 0; fo < numFolders; fo++) { - folders.Add(CFolder()); - GetNextFolderItem(folders.Back()); - } - } + UInt32 numOutStreams = 0; + UInt32 indexOfMainStream = 0; + UInt32 numPackStreams = 0; + folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; + + numOutStreams = 0; + CNum numInStreams = 0; + CNum numCoders = inByte->ReadNum(); + for (CNum ci = 0; ci < numCoders; ci++) + { + Byte mainByte = inByte->ReadByte(); + if ((mainByte & 0xC0) != 0) + ThrowUnsupported(); + unsigned idSize = (mainByte & 0xF); + if (idSize > 8) + ThrowUnsupported(); + if (idSize > inByte->GetRem()) + ThrowEndOfData(); + const Byte *longID = inByte->GetPtr(); + UInt64 id = 0; + for (unsigned j = 0; j < idSize; j++) + id = ((id << 8) | longID[j]); + inByte->SkipDataNoCheck(idSize); + if (folders.ParsedMethods.IDs.Size() < 128) + folders.ParsedMethods.IDs.AddToUniqueSorted(id); + CNum coderInStreams = 1; + CNum coderOutStreams = 1; + if ((mainByte & 0x10) != 0) + { + coderInStreams = inByte->ReadNum(); + coderOutStreams = inByte->ReadNum(); + } + numInStreams += coderInStreams; + if (numInStreams < coderInStreams) + ThrowUnsupported(); + numOutStreams += coderOutStreams; + if (numOutStreams < coderOutStreams) + ThrowUnsupported(); + if ((mainByte & 0x20) != 0) + { + CNum propsSize = inByte->ReadNum(); + if (propsSize > inByte->GetRem()) + ThrowEndOfData(); + if (id == k_LZMA2 && propsSize == 1) + { + Byte v = *_inByteBack->GetPtr(); + if (folders.ParsedMethods.Lzma2Prop < v) + folders.ParsedMethods.Lzma2Prop = v; + } + else if (id == k_LZMA && propsSize == 5) + { + UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1); + if (folders.ParsedMethods.LzmaDic < dicSize) + folders.ParsedMethods.LzmaDic = dicSize; + } + inByte->SkipDataNoCheck((size_t)propsSize); + } + } + + if (numOutStreams == 1 && numInStreams == 1) + { + indexOfMainStream = 0; + numPackStreams = 1; + } + else + { + UInt32 i; + if (numOutStreams == 0) + ThrowUnsupported(); + CNum numBindPairs = numOutStreams - 1; + if (numInStreams < numBindPairs) + ThrowUnsupported(); + if (numInStreams >= 256 || numOutStreams >= 256) + ThrowUnsupported(); + + InStreamUsed.ClearAndSetSize(numInStreams); + for (i = 0; i < numInStreams; i++) + InStreamUsed[i] = false; + + OutStreamUsed.ClearAndSetSize(numOutStreams); + for (i = 0; i < numOutStreams; i++) + OutStreamUsed[i] = false; + + for (i = 0; i < numBindPairs; i++) + { + CNum index = ReadNum(); + if (index >= numInStreams || InStreamUsed[index]) + ThrowUnsupported(); + InStreamUsed[index] = true; + index = ReadNum(); + if (index >= numOutStreams || OutStreamUsed[index]) + ThrowUnsupported(); + OutStreamUsed[index] = true; + } - WaitAttribute(NID::kCodersUnpackSize); + numPackStreams = numInStreams - numBindPairs; - CNum i; - for (i = 0; i < numFolders; i++) - { - CFolder &folder = folders[i]; - CNum numOutStreams = folder.GetNumOutStreams(); - folder.UnpackSizes.Reserve(numOutStreams); - for (CNum j = 0; j < numOutStreams; j++) - folder.UnpackSizes.Add(ReadNumber()); + if (numPackStreams != 1) + for (i = 0; i < numPackStreams; i++) + inByte->ReadNum(); // PackStreams + + for (i = 0; i < numOutStreams; i++) + if (!OutStreamUsed[i]) + { + indexOfMainStream = i; + break; + } + if (i == numOutStreams) + ThrowUnsupported(); + } + folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; + numCodersOutStreams += numOutStreams; + folders.FoStartPackStreamIndex[fo] = packStreamIndex; + packStreamIndex += numPackStreams; + folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; + } + size_t dataSize = _inByteBack->GetPtr() - startBufPtr; + folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; + folders.FoStartPackStreamIndex[fo] = packStreamIndex; + folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr; + folders.CodersData.CopyFrom(startBufPtr, dataSize); } + WaitId(NID::kCodersUnpackSize); + folders.CoderUnpackSizes.Alloc(numCodersOutStreams); + for (CNum i = 0; i < numCodersOutStreams; i++) + folders.CoderUnpackSizes[i] = ReadNumber(); + for (;;) { UInt64 type = ReadID(); @@ -567,15 +835,7 @@ void CInArchive::ReadUnpackInfo( return; if (type == NID::kCRC) { - CBoolVector crcsDefined; - CRecordVector<UInt32> crcs; - ReadHashDigests(numFolders, crcsDefined, crcs); - for (i = 0; i < numFolders; i++) - { - CFolder &folder = folders[i]; - folder.UnpackCRCDefined = crcsDefined[i]; - folder.UnpackCRC = crcs[i]; - } + ReadHashDigests(numFolders, folders.FolderCRCs); continue; } SkipData(); @@ -583,170 +843,217 @@ void CInArchive::ReadUnpackInfo( } void CInArchive::ReadSubStreamsInfo( - const CObjectVector<CFolder> &folders, - CRecordVector<CNum> &numUnpackStreamsInFolders, + CFolders &folders, CRecordVector<UInt64> &unpackSizes, - CBoolVector &digestsDefined, - CRecordVector<UInt32> &digests) + CUInt32DefVector &digests) { - numUnpackStreamsInFolders.Clear(); - numUnpackStreamsInFolders.Reserve(folders.Size()); + folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); + CNum i; + for (i = 0; i < folders.NumFolders; i++) + folders.NumUnpackStreamsVector[i] = 1; + UInt64 type; + for (;;) { type = ReadID(); if (type == NID::kNumUnpackStream) { - for (int i = 0; i < folders.Size(); i++) - numUnpackStreamsInFolders.Add(ReadNum()); + for (i = 0; i < folders.NumFolders; i++) + folders.NumUnpackStreamsVector[i] = ReadNum(); continue; } - if (type == NID::kCRC || type == NID::kSize) - break; - if (type == NID::kEnd) + if (type == NID::kCRC || type == NID::kSize || type == NID::kEnd) break; SkipData(); } - if (numUnpackStreamsInFolders.IsEmpty()) - for (int i = 0; i < folders.Size(); i++) - numUnpackStreamsInFolders.Add(1); - - int i; - for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) + if (type == NID::kSize) { - // v3.13 incorrectly worked with empty folders - // v4.07: we check that folder is empty - CNum numSubstreams = numUnpackStreamsInFolders[i]; - if (numSubstreams == 0) - continue; - UInt64 sum = 0; - for (CNum j = 1; j < numSubstreams; j++) - if (type == NID::kSize) + for (i = 0; i < folders.NumFolders; i++) + { + // v3.13 incorrectly worked with empty folders + // v4.07: we check that folder is empty + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams == 0) + continue; + UInt64 sum = 0; + for (CNum j = 1; j < numSubstreams; j++) { UInt64 size = ReadNumber(); unpackSizes.Add(size); sum += size; + if (sum < size) + ThrowIncorrect(); } - unpackSizes.Add(folders[i].GetUnpackSize() - sum); - } - if (type == NID::kSize) + UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i); + if (folderUnpackSize < sum) + ThrowIncorrect(); + unpackSizes.Add(folderUnpackSize - sum); + } type = ReadID(); + } + else + { + for (i = 0; i < folders.NumFolders; i++) + { + /* v9.26 - v9.29 incorrectly worked: + if (folders.NumUnpackStreamsVector[i] == 0), it threw error */ + CNum val = folders.NumUnpackStreamsVector[i]; + if (val > 1) + ThrowIncorrect(); + if (val == 1) + unpackSizes.Add(folders.GetFolderUnpackSize(i)); + } + } - int numDigests = 0; - int numDigestsTotal = 0; - for (i = 0; i < folders.Size(); i++) + unsigned numDigests = 0; + for (i = 0; i < folders.NumFolders; i++) { - CNum numSubstreams = numUnpackStreamsInFolders[i]; - if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i)) numDigests += numSubstreams; - numDigestsTotal += numSubstreams; } for (;;) { + if (type == NID::kEnd) + break; if (type == NID::kCRC) { - CBoolVector digestsDefined2; - CRecordVector<UInt32> digests2; - ReadHashDigests(numDigests, digestsDefined2, digests2); - int digestIndex = 0; - for (i = 0; i < folders.Size(); i++) + // CUInt32DefVector digests2; + // ReadHashDigests(numDigests, digests2); + CBoolVector digests2; + ReadBoolVector2(numDigests, digests2); + + digests.ClearAndSetSize(unpackSizes.Size()); + + unsigned k = 0; + unsigned k2 = 0; + + for (i = 0; i < folders.NumFolders; i++) { - CNum numSubstreams = numUnpackStreamsInFolders[i]; - const CFolder &folder = folders[i]; - if (numSubstreams == 1 && folder.UnpackCRCDefined) + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i)) { - digestsDefined.Add(true); - digests.Add(folder.UnpackCRC); + digests.Defs[k] = true; + digests.Vals[k] = folders.FolderCRCs.Vals[i]; + k++; + } + else for (CNum j = 0; j < numSubstreams; j++) + { + bool defined = digests2[k2++]; + digests.Defs[k] = defined; + UInt32 crc = 0; + if (defined) + crc = ReadUInt32(); + digests.Vals[k] = crc; + k++; } - else - for (CNum j = 0; j < numSubstreams; j++, digestIndex++) - { - digestsDefined.Add(digestsDefined2[digestIndex]); - digests.Add(digests2[digestIndex]); - } } + // if (k != unpackSizes.Size()) throw 1234567; } - else if (type == NID::kEnd) + else + SkipData(); + + type = ReadID(); + } + + if (digests.Defs.Size() != unpackSizes.Size()) + { + digests.ClearAndSetSize(unpackSizes.Size()); + unsigned k = 0; + for (i = 0; i < folders.NumFolders; i++) { - if (digestsDefined.IsEmpty()) + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i)) { - BoolVector_Fill_False(digestsDefined, numDigestsTotal); - digests.Clear(); - for (int i = 0; i < numDigestsTotal; i++) - digests.Add(0); + digests.Defs[k] = true; + digests.Vals[k] = folders.FolderCRCs.Vals[i]; + k++; + } + else for (CNum j = 0; j < numSubstreams; j++) + { + digests.Defs[k] = false; + digests.Vals[k] = 0; + k++; } - return; } - else - SkipData(); - type = ReadID(); } } void CInArchive::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) { - for (;;) + UInt64 type = ReadID(); + + if (type == NID::kPackInfo) { - UInt64 type = ReadID(); - if (type > ((UInt32)1 << 30)) - ThrowIncorrect(); - switch((UInt32)type) + dataOffset = ReadNumber(); + ReadPackInfo(folders); + type = ReadID(); + } + + if (type == NID::kUnpackInfo) + { + ReadUnpackInfo(dataVector, folders); + type = ReadID(); + } + + if (folders.NumFolders != 0 && !folders.PackPositions) + { + // if there are folders, we need PackPositions also + folders.PackPositions.Alloc(1); + folders.PackPositions[0] = 0; + } + + if (type == NID::kSubStreamsInfo) + { + ReadSubStreamsInfo(folders, unpackSizes, digests); + type = ReadID(); + } + else + { + folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); + /* If digests.Defs.Size() == 0, it means that there are no crcs. + So we don't need to fill digests with values. */ + // digests.Vals.ClearAndSetSize(folders.NumFolders); + // BoolVector_Fill_False(digests.Defs, folders.NumFolders); + for (CNum i = 0; i < folders.NumFolders; i++) { - case NID::kEnd: - return; - case NID::kPackInfo: - { - ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); - break; - } - case NID::kUnpackInfo: - { - ReadUnpackInfo(dataVector, folders); - break; - } - case NID::kSubStreamsInfo: - { - ReadSubStreamsInfo(folders, numUnpackStreamsInFolders, - unpackSizes, digestsDefined, digests); - break; - } - default: - ThrowIncorrect(); + folders.NumUnpackStreamsVector[i] = 1; + unpackSizes.Add(folders.GetFolderUnpackSize(i)); + // digests.Vals[i] = 0; } } + + if (type != NID::kEnd) + ThrowIncorrect(); } -void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) +void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v) { - v.Clear(); - v.Reserve(numItems); + v.ClearAndSetSize(numItems); Byte b = 0; Byte mask = 0; - for (int i = 0; i < numItems; i++) + bool *p = &v[0]; + for (unsigned i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } - v.Add((b & mask) != 0); + p[i] = ((b & mask) != 0); mask >>= 1; } } -void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) +void CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v) { Byte allAreDefined = ReadByte(); if (allAreDefined == 0) @@ -754,27 +1061,30 @@ void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) ReadBoolVector(numItems, v); return; } - v.Clear(); - v.Reserve(numItems); - for (int i = 0; i < numItems; i++) - v.Add(true); + v.ClearAndSetSize(numItems); + bool *p = &v[0]; + for (unsigned i = 0; i < numItems; i++) + p[i] = true; } void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, - CUInt64DefVector &v, int numFiles) + CUInt64DefVector &v, unsigned numItems) { - ReadBoolVector2(numFiles, v.Defined); + ReadBoolVector2(numItems, v.Defs); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); - v.Values.Reserve(numFiles); - for (int i = 0; i < numFiles; i++) + v.Vals.ClearAndSetSize(numItems); + UInt64 *p = &v.Vals[0]; + const bool *defs = &v.Defs[0]; + + for (unsigned i = 0; i < numItems; i++) { UInt64 t = 0; - if (v.Defined[i]) + if (defs[i]) t = ReadUInt64(); - v.Values.Add(t); + p[i] = t; } } @@ -782,35 +1092,19 @@ HRESULT CInArchive::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 ) { - 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; + ReadStreamsInfo(NULL, dataOffset, - packSizes, - packCRCsDefined, - packCRCs, folders, - numUnpackStreamsInFolders, unpackSizes, - digestsDefined, digests); - - // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; - - CNum packIndex = 0; + CDecoder decoder( #ifdef _ST_MODE false @@ -818,134 +1112,107 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( true #endif ); - UInt64 dataStartPos = baseOffset + dataOffset; - for (int i = 0; i < folders.Size(); i++) + + for (CNum i = 0; i < folders.NumFolders; i++) { - const CFolder &folder = folders[i]; - dataVector.Add(CByteBuffer()); - CByteBuffer &data = dataVector.Back(); - UInt64 unpackSize64 = folder.GetUnpackSize(); + CByteBuffer &data = dataVector.AddNew(); + UInt64 unpackSize64 = folders.GetFolderUnpackSize(i); size_t unpackSize = (size_t)unpackSize64; if (unpackSize != unpackSize64) ThrowUnsupported(); - data.SetCapacity(unpackSize); - + data.Alloc(unpackSize); + CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->Init(data, unpackSize); - + HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS - _stream, dataStartPos, - &packSizes[packIndex], folder, outStream, NULL - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _stream, baseOffset + dataOffset, + folders, i, + outStream, NULL + _7Z_DECODER_CRYPRO_VARS #if !defined(_7ZIP_ST) && !defined(_SFX) , false, 1 #endif ); RINOK(result); - - if (folder.UnpackCRCDefined) - if (CrcCalc(data, unpackSize) != folder.UnpackCRC) + + if (folders.FolderCRCs.ValidAndDefined(i)) + if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i]) ThrowIncorrect(); - for (int j = 0; j < folder.PackStreams.Size(); j++) - { - UInt64 packSize = packSizes[packIndex++]; - dataStartPos += packSize; - HeadersSize += packSize; - } } + HeadersSize += folders.PackPositions[folders.NumPackStreams]; return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ) { UInt64 type = ReadID(); if (type == NID::kArchiveProperties) { - ReadArchiveProperties(db.ArchiveInfo); + ReadArchiveProperties(db.ArcInfo); type = ReadID(); } - + CObjectVector<CByteBuffer> dataVector; - + if (type == NID::kAdditionalStreamsInfo) { HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS - db.ArchiveInfo.StartPositionAfterHeader, - db.ArchiveInfo.DataStartPosition2, + db.ArcInfo.StartPositionAfterHeader, + db.ArcInfo.DataStartPosition2, dataVector - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS ); RINOK(result); - db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; + db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader; type = ReadID(); } CRecordVector<UInt64> unpackSizes; - CBoolVector digestsDefined; - CRecordVector<UInt32> digests; - + CUInt32DefVector digests; + if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, - db.ArchiveInfo.DataStartPosition, - db.PackSizes, - db.PackCRCsDefined, - db.PackCRCs, - db.Folders, - db.NumUnpackStreamsVector, + db.ArcInfo.DataStartPosition, + (CFolders &)db, unpackSizes, - digestsDefined, digests); - db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; + db.ArcInfo.DataStartPosition += db.ArcInfo.StartPositionAfterHeader; type = ReadID(); } - else - { - for (int i = 0; i < db.Folders.Size(); i++) - { - db.NumUnpackStreamsVector.Add(1); - CFolder &folder = db.Folders[i]; - unpackSizes.Add(folder.GetUnpackSize()); - digestsDefined.Add(folder.UnpackCRCDefined); - digests.Add(folder.UnpackCRC); - } - } db.Files.Clear(); - if (type == NID::kEnd) - return S_OK; - if (type != NID::kFilesInfo) - ThrowIncorrect(); - + if (type == NID::kFilesInfo) + { + CNum numFiles = ReadNum(); + db.Files.ClearAndSetSize(numFiles); + CNum i; + /* db.Files.Reserve(numFiles); CNum i; for (i = 0; i < numFiles; i++) db.Files.Add(CFileItem()); + */ - db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); - if (!db.PackSizes.IsEmpty()) - db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); - if (numFiles > 0 && !digests.IsEmpty()) - db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); + db.ArcInfo.FileInfoPopIDs.Add(NID::kSize); + // if (!db.PackSizes.IsEmpty()) + db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo); + if (numFiles > 0 && !digests.Defs.IsEmpty()) + db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; - BoolVector_Fill_False(emptyStreamVector, (int)numFiles); + BoolVector_Fill_False(emptyStreamVector, (unsigned)numFiles); CBoolVector emptyFileVector; CBoolVector antiFileVector; CNum numEmptyStreams = 0; @@ -956,7 +1223,10 @@ HRESULT CInArchive::ReadHeader( if (type == NID::kEnd) break; UInt64 size = ReadNumber(); - size_t ppp = _inByteBack->_pos; + if (size > _inByteBack->GetRem()) + ThrowIncorrect(); + CStreamSwitch switchProp; + switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true); bool addPropIdToList = true; bool isKnownType = true; if (type > ((UInt32)1 << 30)) @@ -967,11 +1237,29 @@ HRESULT CInArchive::ReadHeader( { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); - for (int i = 0; i < db.Files.Size(); i++) - _inByteBack->ReadString(db.Files[i].Name); + size_t rem = _inByteBack->GetRem(); + db.NamesBuf.Alloc(rem); + ReadBytes(db.NamesBuf, rem); + db.NameOffsets.Alloc(db.Files.Size() + 1); + size_t pos = 0; + unsigned i; + for (i = 0; i < db.Files.Size(); i++) + { + size_t curRem = (rem - pos) / 2; + const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos); + size_t j; + for (j = 0; j < curRem && buf[j] != 0; j++); + if (j == curRem) + ThrowEndOfData(); + db.NameOffsets[i] = pos / 2; + pos += j * 2 + 2; + } + db.NameOffsets[i] = pos / 2; + if (pos != rem) + ThereIsHeaderError = true; break; } - case NID::kWinAttributes: + case NID::kWinAttrib: { CBoolVector boolVector; ReadBoolVector2(db.Files.Size(), boolVector); @@ -986,9 +1274,40 @@ HRESULT CInArchive::ReadHeader( } break; } + /* + case NID::kIsAux: + { + ReadBoolVector(db.Files.Size(), db.IsAux); + break; + } + case NID::kParent: + { + db.IsTree = true; + // CBoolVector boolVector; + // ReadBoolVector2(db.Files.Size(), boolVector); + // CStreamSwitch streamSwitch; + // streamSwitch.Set(this, &dataVector); + CBoolVector boolVector; + ReadBoolVector2(db.Files.Size(), boolVector); + + db.ThereAreAltStreams = false; + for (i = 0; i < numFiles; i++) + { + CFileItem &file = db.Files[i]; + // file.Parent = -1; + // if (boolVector[i]) + file.Parent = (int)ReadUInt32(); + file.IsAltStream = !boolVector[i]; + if (file.IsAltStream) + db.ThereAreAltStreams = true; + } + break; + } + */ case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); + numEmptyStreams = 0; for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) if (emptyStreamVector[i]) numEmptyStreams++; @@ -1000,34 +1319,83 @@ HRESULT CInArchive::ReadHeader( } case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; - case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break; - case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break; - case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break; - case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break; + case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (unsigned)numFiles); break; + case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (unsigned)numFiles); break; + case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (unsigned)numFiles); break; + case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (unsigned)numFiles); break; case NID::kDummy: { for (UInt64 j = 0; j < size; j++) if (ReadByte() != 0) - ThrowIncorrect(); + ThereIsHeaderError = true; addPropIdToList = false; break; } + /* + case NID::kNtSecure: + { + try + { + { + CStreamSwitch streamSwitch; + streamSwitch.Set(this, &dataVector); + UInt32 numDescriptors = ReadUInt32(); + size_t offset = 0; + db.SecureOffsets.Clear(); + for (i = 0; i < numDescriptors; i++) + { + UInt32 size = ReadUInt32(); + db.SecureOffsets.Add(offset); + offset += size; + } + // ThrowIncorrect();; + db.SecureOffsets.Add(offset); + db.SecureBuf.SetCapacity(offset); + for (i = 0; i < numDescriptors; i++) + { + offset = db.SecureOffsets[i]; + ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset); + } + db.SecureIDs.Clear(); + for (unsigned i = 0; i < db.Files.Size(); i++) + { + db.SecureIDs.Add(ReadNum()); + // db.SecureIDs.Add(ReadUInt32()); + } + // ReadUInt32(); + if (_inByteBack->GetRem() != 0) + ThrowIncorrect();; + } + } + catch(CInArchiveException &) + { + ThereIsHeaderError = true; + addPropIdToList = isKnownType = false; + db.ClearSecure(); + } + break; + } + */ default: addPropIdToList = isKnownType = false; } if (isKnownType) { - if(addPropIdToList) - db.ArchiveInfo.FileInfoPopIDs.Add(type); + if (addPropIdToList) + db.ArcInfo.FileInfoPopIDs.Add(type); } else - SkipData(size); - bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || - db.ArchiveInfo.Version.Minor > 2); - if (checkRecordsSize && _inByteBack->_pos - ppp != size) + { + db.UnsupportedFeatureWarning = true; + _inByteBack->SkipRem(); + } + // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 00.02) + if (_inByteBack->GetRem() != 0) ThrowIncorrect(); } + type = ReadID(); // Read (NID::kEnd) end of headers + CNum emptyFileIndex = 0; CNum sizeIndex = 0; @@ -1035,19 +1403,21 @@ HRESULT CInArchive::ReadHeader( for (i = 0; i < numEmptyStreams; i++) if (antiFileVector[i]) numAntiItems++; - + for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; bool isAnti; file.HasStream = !emptyStreamVector[i]; + file.Crc = 0; if (file.HasStream) { file.IsDir = false; isAnti = false; file.Size = unpackSizes[sizeIndex]; - file.Crc = digests[sizeIndex]; - file.CrcDefined = digestsDefined[sizeIndex]; + file.CrcDefined = digests.ValidAndDefined(sizeIndex); + if (file.CrcDefined) + file.Crc = digests.Vals[sizeIndex]; sizeIndex++; } else @@ -1061,162 +1431,187 @@ HRESULT CInArchive::ReadHeader( if (numAntiItems != 0) db.IsAnti.Add(isAnti); } + } + db.FillLinks(); + /* + if (type != NID::kEnd) + ThrowIncorrect(); + if (_inByteBack->GetRem() != 0) + ThrowIncorrect(); + */ return S_OK; } - -void CArchiveDatabaseEx::FillFolderStartPackStream() +void CDbEx::FillLinks() { - FolderStartPackStreamIndex.Clear(); - FolderStartPackStreamIndex.Reserve(Folders.Size()); - CNum startPos = 0; - for (int i = 0; i < Folders.Size(); i++) - { - FolderStartPackStreamIndex.Add(startPos); - startPos += (CNum)Folders[i].PackStreams.Size(); - } -} + FolderStartFileIndex.ClearAndSetSize(NumFolders); -void CArchiveDatabaseEx::FillStartPos() -{ - PackStreamStartPositions.Clear(); - PackStreamStartPositions.Reserve(PackSizes.Size()); - UInt64 startPos = 0; - for (int i = 0; i < PackSizes.Size(); i++) - { - PackStreamStartPositions.Add(startPos); - startPos += PackSizes[i]; - } -} + FileIndexToFolderIndexMap.ClearAndSetSize(Files.Size()); -void CArchiveDatabaseEx::FillFolderStartFileIndex() -{ - FolderStartFileIndex.Clear(); - FolderStartFileIndex.Reserve(Folders.Size()); - FileIndexToFolderIndexMap.Clear(); - FileIndexToFolderIndexMap.Reserve(Files.Size()); - - int folderIndex = 0; + CNum folderIndex = 0; CNum indexInFolder = 0; - for (int i = 0; i < Files.Size(); i++) + unsigned i; + for (i = 0; i < Files.Size(); i++) { - const CFileItem &file = Files[i]; - bool emptyStream = !file.HasStream; - if (emptyStream && indexInFolder == 0) - { - FileIndexToFolderIndexMap.Add(kNumNoIndex); - continue; - } + bool emptyStream = !Files[i].HasStream; if (indexInFolder == 0) { + if (emptyStream) + { + FileIndexToFolderIndexMap[i] = kNumNoIndex; + continue; + } // v3.13 incorrectly worked with empty folders - // v4.07: Loop for skipping empty folders + // v4.07: we skip empty folders for (;;) { - if (folderIndex >= Folders.Size()) + if (folderIndex >= NumFolders) ThrowIncorrect(); - FolderStartFileIndex.Add(i); // check it + FolderStartFileIndex[folderIndex] = i; if (NumUnpackStreamsVector[folderIndex] != 0) break; folderIndex++; } } - FileIndexToFolderIndexMap.Add(folderIndex); + FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; - indexInFolder++; - if (indexInFolder >= NumUnpackStreamsVector[folderIndex]) + if (++indexInFolder >= NumUnpackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; } } + + if (indexInFolder != 0) + folderIndex++; + /* + if (indexInFolder != 0) + ThrowIncorrect(); + */ + for (;;) + { + if (folderIndex >= NumFolders) + return; + FolderStartFileIndex[folderIndex] = i; + /* + if (NumUnpackStreamsVector[folderIndex] != 0) + ThrowIncorrect();; + */ + folderIndex++; + } } HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ) { db.Clear(); - db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; + db.ArcInfo.StartPosition = _arhiveBeginStreamPosition; - db.ArchiveInfo.Version.Major = _header[6]; - db.ArchiveInfo.Version.Minor = _header[7]; + db.ArcInfo.Version.Major = _header[6]; + db.ArcInfo.Version.Minor = _header[7]; - if (db.ArchiveInfo.Version.Major != kMajorVersion) - ThrowUnsupportedVersion(); + if (db.ArcInfo.Version.Major != kMajorVersion) + { + // db.UnsupportedVersion = true; + return S_FALSE; + } - UInt32 crcFromArchive = Get32(_header + 8); - UInt64 nextHeaderOffset = Get64(_header + 0xC); - UInt64 nextHeaderSize = Get64(_header + 0x14); - UInt32 nextHeaderCRC = Get32(_header + 0x1C); - UInt32 crc = CrcCalc(_header + 0xC, 20); + UInt64 nextHeaderOffset = Get64(_header + 12); + UInt64 nextHeaderSize = Get64(_header + 20); + UInt32 nextHeaderCRC = Get32(_header + 28); #ifdef FORMAT_7Z_RECOVERY - if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) + UInt32 crcFromArc = Get32(_header + 8); + if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { - UInt64 cur, cur2; + UInt64 cur, fileSize; RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); - const int kCheckSize = 500; + const unsigned kCheckSize = 512; Byte buf[kCheckSize]; - RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); - int checkSize = kCheckSize; - if (cur2 - cur < kCheckSize) - checkSize = (int)(cur2 - cur); - RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); - + RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); + UInt64 rem = fileSize - cur; + unsigned checkSize = kCheckSize; + if (rem < kCheckSize) + checkSize = (unsigned)(rem); + if (checkSize < 3) + return S_FALSE; + RINOK(_stream->Seek(fileSize - checkSize, STREAM_SEEK_SET, NULL)); RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); - int i; - for (i = (int)checkSize - 2; i >= 0; i--) - if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) - break; - if (i < 0) + if (buf[checkSize - 1] != 0) return S_FALSE; + + unsigned i; + for (i = checkSize - 2;; i--) + { + if (buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo || + buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo) + break; + if (i == 0) + return S_FALSE; + } nextHeaderSize = checkSize - i; - nextHeaderOffset = cur2 - cur + i; + nextHeaderOffset = rem - nextHeaderSize; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); + db.StartHeaderWasRecovered = true; } else #endif { - if (crc != crcFromArchive) - ThrowIncorrect(); + // Crc was tested already at signature check + // if (CrcCalc(_header + 12, 20) != crcFromArchive) ThrowIncorrect(); } - db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; + db.ArcInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; + db.PhySize = kHeaderSize; + db.IsArc = false; + if ((Int64)nextHeaderOffset < 0 || + nextHeaderSize > ((UInt64)1 << 62)) + return S_FALSE; if (nextHeaderSize == 0) + { + if (nextHeaderOffset != 0) + return S_FALSE; + db.IsArc = true; return S_OK; + } - if (nextHeaderSize > (UInt64)0xFFFFFFFF) - return S_FALSE; + if (!db.StartHeaderWasRecovered) + db.IsArc = true; - if ((Int64)nextHeaderOffset < 0) + HeadersSize += kHeaderSize + nextHeaderSize; + db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; + if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize) + { + db.UnexpectedEnd = true; return S_FALSE; - + } RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); - CByteBuffer buffer2; - buffer2.SetCapacity((size_t)nextHeaderSize); + size_t nextHeaderSize_t = (size_t)nextHeaderSize; + if (nextHeaderSize_t != nextHeaderSize) + return E_OUTOFMEMORY; + CByteBuffer buffer2(nextHeaderSize_t); - RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); - HeadersSize += kHeaderSize + nextHeaderSize; - db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; + RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t)); - if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) + if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC) ThrowIncorrect(); - + + if (!db.StartHeaderWasRecovered) + db.PhySizeWasConfirmed = true; + CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); - + CObjectVector<CByteBuffer> dataVector; - + UInt64 type = ReadID(); if (type != NID::kHeader) { @@ -1224,12 +1619,10 @@ HRESULT CInArchive::ReadDatabase2( ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS - db.ArchiveInfo.StartPositionAfterHeader, - db.ArchiveInfo.DataStartPosition2, + db.ArcInfo.StartPositionAfterHeader, + db.ArcInfo.DataStartPosition2, dataVector - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS ); RINOK(result); if (dataVector.Size() == 0) @@ -1242,35 +1635,45 @@ HRESULT CInArchive::ReadDatabase2( ThrowIncorrect(); } + db.IsArc = true; + db.HeadersSize = HeadersSize; return ReadHeader( EXTERNAL_CODECS_LOC_VARS db - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS - CArchiveDatabaseEx &db - #ifndef _NO_CRYPTO - , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined - #endif + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL ) { try { - return ReadDatabase2( + HRESULT res = ReadDatabase2( EXTERNAL_CODECS_LOC_VARS db - #ifndef _NO_CRYPTO - , getTextPassword, passwordIsDefined - #endif + _7Z_DECODER_CRYPRO_VARS ); + if (ThereIsHeaderError) + db.ThereIsHeaderError = true; + if (res == E_NOTIMPL) + ThrowUnsupported(); + return res; + } + catch(CUnsupportedFeatureException &) + { + db.UnsupportedFeatureError = true; + return S_FALSE; + } + catch(CInArchiveException &) + { + db.ThereIsHeaderError = true; + return S_FALSE; } - catch(CInArchiveException &) { return S_FALSE; } } }} diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.h index 971f27b2a..98f61c81e 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zIn.h @@ -5,6 +5,8 @@ #include "../../../Common/MyCom.h" +#include "../../../Windows/PropVariant.h" + #include "../../IPassword.h" #include "../../IStream.h" @@ -12,10 +14,151 @@ #include "../../Common/InBuffer.h" #include "7zItem.h" - + 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, offsets of utf-16 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 void * GetName(unsigned index) const + { + if (!NameOffsets || !NamesBuf) + return NULL; + return (const void *)((const Byte *)NamesBuf + NameOffsets[index] * 2); + }; + + void GetPath(unsigned index, UString &path) const; + HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw(); +}; + struct CInArchiveInfo { CArchiveVersion Version; @@ -24,29 +167,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 +241,25 @@ struct CArchiveDatabaseEx: public CArchiveDatabase PhySize = 0; } - void FillFolderStartPackStream(); - void FillStartPos(); - void FillFolderStartFileIndex(); + void FillLinks(); - void Fill() - { - FillFolderStartPackStream(); - FillStartPos(); - FillFolderStartFileIndex(); - } - - UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const + UInt64 GetFolderStreamPos(unsigned folderIndex, unsigned indexInFolder) const { - return ArchiveInfo.DataStartPosition + - PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder]; + return ArcInfo.DataStartPosition + + PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; } - - UInt64 GetFolderFullPackSize(int folderIndex) const + + UInt64 GetFolderFullPackSize(unsigned folderIndex) 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; + return + PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - + PackPositions[FoStartPackStreamIndex[folderIndex]]; } - - UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const + + UInt64 GetFolderPackStreamSize(unsigned folderIndex, unsigned 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 +272,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 +291,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,32 +314,35 @@ class CInArchive CMyComPtr<IInStream> _stream; - CObjectVector<CInByte2> _inByteVector; + unsigned _numInByteBufs; + CInByte2 _inByteVector[kNumBufLevelsMax]; + CInByte2 *_inByteBack; - + bool ThereIsHeaderError; + UInt64 _arhiveBeginStreamPosition; + UInt64 _fileEndPosition; Byte _header[kHeaderSize]; UInt64 HeadersSize; - void AddByteStream(const Byte *buffer, size_t size) - { - _inByteVector.Add(CInByte2()); - _inByteBack = &_inByteVector.Back(); - _inByteBack->Init(buffer, size); - } - - void DeleteByteStream() + void AddByteStream(const Byte *buffer, size_t size); + + 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: HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); - + void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } Byte ReadByte() { return _inByteBack->ReadByte(); } UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } @@ -164,82 +352,61 @@ 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 ReadPackInfo( - UInt64 &dataOffset, - CRecordVector<UInt64> &packSizes, - CBoolVector &packCRCsDefined, - CRecordVector<UInt32> &packCRCs); - + void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs); + + 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 ); }; - + }} - + #endif diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zItem.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zItem.h index 34f10775c..c112f83fd 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zItem.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zItem.h @@ -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; - } - bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; } + void SetItem(unsigned index, bool defined, UInt64 value); + + 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 diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp index 0c8aa7e8c..e20858ea7 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.cpp @@ -4,41 +4,19 @@ #include "../../../../C/7zCrc.h" -#include "../../../Common/AutoPtr.h" - #include "../../Common/StreamObjects.h" #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 +123,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 +251,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 +301,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 +317,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 +360,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 +379,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]); - } + FOR_VECTOR (i, outFolders.CoderUnpackSizes) + WriteNumber(outFolders.CoderUnpackSizes[i]); - 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); + 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 +409,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 +466,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,49 +487,54 @@ 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); - - for (i = 0; i < v.Defined.Size(); i++) - if (v.Defined[i]) - WriteUInt64(v.Values[i]); + WriteAlignedBoolHeader(v.Defs, numDefined, type, 8); + + 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++) packedSize += db.PackSizes[i]; @@ -580,31 +548,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 +577,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++) + if (db.Files[i].HasStream) + emptyStreamVector[i] = false; + else + { + emptyStreamVector[i] = true; + numEmptyStreams++; + } + if (numEmptyStreams != 0) { - const CFileItem &file = db.Files[i]; - if (!file.HasStream) + 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++) { - emptyFileVector.Add(!file.IsDir); + const CFileItem &file = db.Files[i]; + if (file.HasStream) + continue; + emptyFileVector[cur] = !file.IsDir; if (!file.IsDir) - numEmptyFiles++; + thereAreEmptyFiles = true; bool isAnti = db.IsItemAnti(i); - antiVector.Add(isAnti); + antiVector[cur] = isAnti; if (isAnti) - numAntiItems++; + thereAreAntiItems = true; + cur++; } - } - if (numEmptyFiles > 0) - { - WriteByte(NID::kEmptyFile); - WriteNumber(Bv_GetSizeInBytes(emptyFileVector)); - WriteBoolVector(emptyFileVector); - } - - if (numAntiItems > 0) - { - WriteByte(NID::kAnti); - WriteNumber(Bv_GetSizeInBytes(antiVector)); - WriteBoolVector(antiVector); + if (thereAreEmptyFiles) + WritePropBoolVector(NID::kEmptyFile, emptyFileVector); + if (thereAreAntiItems) + WritePropBoolVector(NID::kAnti, 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 +655,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 +684,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,18 +804,17 @@ 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,22 +824,23 @@ 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; - + if (folders.Size() == 0) 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 +873,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); } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.h index 7b1b528e6..391ca9d02 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zOut.h @@ -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,38 +240,38 @@ 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; bool _writeToStream; size_t _countSize; @@ -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); diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp index fd4af49c7..a29f8abe9 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zProperties.cpp @@ -17,12 +17,12 @@ struct CPropMap STATPROPSTG StatPROPSTG; }; -CPropMap kPropMap[] = +static const CPropMap kPropMap[] = { { NID::kName, { NULL, kpidPath, VT_BSTR } }, { NID::kSize, { NULL, kpidSize, VT_UI8 } }, { NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } }, - + #ifdef _MULTI_PACK { 100, { L"Pack0", kpidPackedSize0, VT_UI8 } }, { 101, { L"Pack1", kpidPackedSize1, 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,34 +91,41 @@ 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(); #ifdef _7Z_VOL - if(_volumes.Size() < 1) + if (_volumes.Size() < 1) return; const CVolume &volume = _volumes.Front(); 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 _fileInfoPopIDs.Add(97); _fileInfoPopIDs.Add(98); @@ -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; } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp index 6e9bf6b99..37ea29d30 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zRegister.cpp @@ -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_DEC_SIG(7z) +// REGISTER_ARC(7z) -REGISTER_ARC(7z) +}} diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp index 06969636d..8e45d9875 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zSpecStream.cpp @@ -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); } - diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp index f07efc178..c745e32f0 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -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" @@ -28,15 +29,6 @@ namespace NArchive { namespace N7z { -static const UInt64 k_LZMA = 0x030101; -static const UInt64 k_BCJ = 0x03030103; -static const UInt64 k_BCJ2 = 0x0303011B; - -static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; -static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; -static const UInt32 kAlgorithmForBCJ2_LZMA = 1; -static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; - #ifdef MY_CPU_X86_OR_AMD64 #define USE_86_FILTER #endif @@ -71,19 +63,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(); @@ -123,11 +116,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); } */ @@ -138,15 +132,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( @@ -160,25 +158,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]; + // NonAnti < Anti + if (u1.IsAnti != u2.IsAnti) + return (u1.IsAnti ? 1 : -1); if (u1.IsDir != u2.IsDir) - return (u1.IsDir) ? 1 : -1; - if (u1.IsDir) { - if (u1.IsAnti != u2.IsAnti) + // Dir.NonAnti < File < Dir.Anti + if (u1.IsDir) return (u1.IsAnti ? 1 : -1); - int n = MyStringCompareNoCase(u1.Name, u2.Name); - return -n; + return (u2.IsAnti ? -1 : 1); } - if (u1.IsAnti != u2.IsAnti) - return (u1.IsAnti ? 1 : -1); - return MyStringCompareNoCase(u1.Name, u2.Name); + int n = CompareFileNames(u1.Name, u2.Name); + return (u1.IsDir && u1.IsAnti) ? -n : n; } static const char *g_Exts = @@ -211,7 +215,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; @@ -250,7 +254,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), @@ -261,64 +267,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 @@ -327,19 +403,19 @@ struct CSolidGroup }; #ifdef _WIN32 -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; } @@ -361,7 +437,7 @@ static bool IsExeFile(const CUpdateItem &ui) { for(UInt32 i = 0; i < processedSize ; i++) { - if (buffer[i] == 0) + if (buffer[i] == 0) { return true; // this file is not a text (ascii, utf8, ...) ! } @@ -369,112 +445,97 @@ static bool IsExeFile(const CUpdateItem &ui) } } } - } + } return false; } #endif -#ifdef USE_86_FILTER -static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) +static inline void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &m) +{ + m.Id = methodID; + m.NumInStreams = numInStreams; + m.NumOutStreams = 1; +} + +static void AddBcj2Methods(CCompressionMethodMode &mode) { - methodResult.Id = methodID; - methodResult.NumInStreams = numInStreams; - methodResult.NumOutStreams = 1; + CMethodFull m; + GetMethodFull(k_LZMA, 1, m); + + m.AddProp32(NCoderPropID::kDictionarySize, 1 << 20); + m.AddProp32(NCoderPropID::kNumFastBytes, 128); + m.AddProp32(NCoderPropID::kNumThreads, 1); + m.AddProp32(NCoderPropID::kLitPosBits, 2); + m.AddProp32(NCoderPropID::kLitContextBits, 0); + // m.AddPropString(NCoderPropID::kMatchFinder, L"BT2"); + + mode.Methods.Add(m); + mode.Methods.Add(m); + + CBind bind; + bind.OutCoder = 0; + bind.InStream = 0; + bind.InCoder = 1; bind.OutStream = 0; mode.Binds.Add(bind); + bind.InCoder = 2; bind.OutStream = 1; mode.Binds.Add(bind); + bind.InCoder = 3; bind.OutStream = 2; mode.Binds.Add(bind); } -static void MakeExeMethod(const CCompressionMethodMode &method, - bool bcj2Filter, CCompressionMethodMode &exeMethod) +static void MakeExeMethod(CCompressionMethodMode &mode, + bool useFilters, bool addFilter, bool bcj2Filter) { - exeMethod = method; + if (!mode.Binds.IsEmpty() || !useFilters || mode.Methods.Size() > 2) + return; + if (mode.Methods.Size() == 2) + { + if (mode.Methods[0].Id == k_BCJ2) + AddBcj2Methods(mode); + return; + } + if (!addFilter) + return; + bcj2Filter = bcj2Filter; + #ifdef USE_86_FILTER if (bcj2Filter) { - CMethodFull methodFull; - GetMethodFull(k_BCJ2, 4, methodFull); - exeMethod.Methods.Insert(0, methodFull); - GetMethodFull(k_LZMA, 1, methodFull); - { - CProp prop; - prop.Id = NCoderPropID::kAlgorithm; - prop.Value = kAlgorithmForBCJ2_LZMA; - methodFull.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kMatchFinder; - prop.Value = kMatchFinderForBCJ2_LZMA; - methodFull.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kDictionarySize; - prop.Value = kDictionaryForBCJ2_LZMA; - methodFull.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kNumFastBytes; - prop.Value = kNumFastBytesForBCJ2_LZMA; - methodFull.Props.Add(prop); - } - { - CProp prop; - prop.Id = NCoderPropID::kNumThreads; - prop.Value = (UInt32)1; - methodFull.Props.Add(prop); - } - - exeMethod.Methods.Add(methodFull); - exeMethod.Methods.Add(methodFull); - CBind bind; - - bind.OutCoder = 0; - bind.InStream = 0; - - bind.InCoder = 1; - bind.OutStream = 0; - exeMethod.Binds.Add(bind); - - bind.InCoder = 2; - bind.OutStream = 1; - exeMethod.Binds.Add(bind); - - bind.InCoder = 3; - bind.OutStream = 2; - exeMethod.Binds.Add(bind); + CMethodFull m; + GetMethodFull(k_BCJ2, 4, m); + mode.Methods.Insert(0, m); + AddBcj2Methods(mode); } else { - CMethodFull methodFull; - GetMethodFull(k_BCJ, 1, methodFull); - exeMethod.Methods.Insert(0, methodFull); + CMethodFull m; + GetMethodFull(k_BCJ, 1, m); + mode.Methods.Insert(0, m); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; - exeMethod.Binds.Add(bind); + mode.Binds.Add(bind); } + #endif } -#endif static void FromUpdateItemToFileItem(const CUpdateItem &ui, CFileItem &file, CFileItem2 &file2) { - file.Name = NItemName::MakeLegalName(ui.Name); if (ui.AttribDefined) file.SetAttrib(ui.Attrib); - + file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined; 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: @@ -483,11 +544,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; @@ -497,14 +558,14 @@ class CFolderOutStream2: HRESULT ProcessEmptyFiles(); public: MY_UNKNOWN_IMP - + CFolderOutStream2() { _crcStreamSpec = new COutStreamWithCRC; _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; } @@ -512,7 +573,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; @@ -611,13 +672,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 @@ -636,6 +697,7 @@ public: Fos = FosSpec; Result = E_FAIL; } + ~CThreadDecoder() { CVirtThread::WaitThreadFinish(); } virtual void Execute(); }; @@ -644,21 +706,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 ); } @@ -673,7 +734,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) @@ -704,20 +765,31 @@ STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password) static const int kNumGroupsMax = 4; -#ifdef USE_86_FILTER static bool Is86Group(int group) { return (group & 1) != 0; } -#endif 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 @@ -729,6 +801,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)); @@ -736,23 +811,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++) { @@ -761,7 +836,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; @@ -788,7 +863,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); @@ -807,7 +883,7 @@ HRESULT Update( } UInt64 inSizeForReduce = 0; - int i; + unsigned i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; @@ -824,32 +900,30 @@ HRESULT Update( if (inSizeForReduce2 > inSizeForReduce) inSizeForReduce = inSizeForReduce2; - const UInt32 kMinReduceSize = (1 << 16); - if (inSizeForReduce < kMinReduceSize) - inSizeForReduce = kMinReduceSize; - RINOK(updateCallback->SetTotal(complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); + CStreamBinder sb; + RINOK(sb.CreateEvents()); + CThreadDecoder threadDecoder; 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; @@ -866,7 +940,7 @@ HRESULT Update( #ifdef _WIN32 int dotPos = ui.Name.ReverseFind(L'.'); if (dotPos >= 0) - filteredGroup = IsExeExt(ui.Name.Mid(dotPos + 1)); + filteredGroup = IsExeExt(ui.Name.Ptr(dotPos + 1)); #else filteredGroup = IsExeFile(ui); #endif @@ -881,7 +955,7 @@ HRESULT Update( if (needEncryptedRepack) { getPasswordSpec = new CCryptoGetTextPassword; - threadDecoder.GetTextPassword = getPasswordSpec; + threadDecoder.getTextPassword = getPasswordSpec; if (options.Method->PasswordIsDefined) getPasswordSpec->Password = options.Method->Password; @@ -891,31 +965,119 @@ 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); + db->GetPath(ui.IndexInArchive, name); + } + + /* + 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++) { const CSolidGroup &group = groups[groupIndex]; - CCompressionMethodMode method; - #ifdef USE_86_FILTER - if (Is86Group(groupIndex)) - MakeExeMethod(*options.Method, options.MaxFilter, method); - else - #endif - method = *options.Method; + CCompressionMethodMode method = *options.Method; + MakeExeMethod(method, options.UseFilters, Is86Group(groupIndex), options.MaxFilter); if (IsEncryptedGroup(groupIndex)) { @@ -942,36 +1104,36 @@ HRESULT Update( if (rep.Group != groupIndex) break; int folderIndex = rep.FolderIndex; - + if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex]) { UInt64 packSize = db->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, 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 { - CStreamBinder sb; - RINOK(sb.CreateEvents()); - CMyComPtr<ISequentialOutStream> sbOutStream; - CMyComPtr<ISequentialInStream> sbInStream; - sb.CreateStreams(&sbInStream, &sbOutStream); CBoolVector extractStatuses; - + CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; CNum indexInFolder = 0; - + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { bool needExtract = false; @@ -985,44 +1147,52 @@ HRESULT Update( extractStatuses.Add(needExtract); } - RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream)); - sbOutStream.Release(); - - threadDecoder.InStream = inStream; - threadDecoder.Folder = &db->Folders[folderIndex]; - threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0); - threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]]; - - threadDecoder.Start(); - - int startPackIndex = newDatabase.PackSizes.Size(); - CFolder newFolder; - RINOK(encoder.Encode( - EXTERNAL_CODECS_LOC_VARS - sbInStream, NULL, &inSizeForReduce, newFolder, - archive.SeqStream, newDatabase.PackSizes, progress)); - - threadDecoder.WaitFinish(); + unsigned startPackIndex = newDatabase.PackSizes.Size(); + UInt64 curUnpackSize; + { + CMyComPtr<ISequentialInStream> sbInStream; + { + CMyComPtr<ISequentialOutStream> sbOutStream; + sb.CreateStreams(&sbInStream, &sbOutStream); + sb.ReInit(); + RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream)); + } + + threadDecoder.InStream = inStream; + 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, + newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize, + archive.SeqStream, newDatabase.PackSizes, progress)); + + threadDecoder.WaitExecuteFinish(); + } RINOK(threadDecoder.Result); 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); - + CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; - + CNum indexInFolder = 0; for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { CFileItem file; CFileItem2 file2; - db->GetFile(fi, file, file2); + GetFile(*db, fi, file, file2); + UString name; + db->GetPath(fi, name); if (file.HasStream) { indexInFolder++; @@ -1041,30 +1211,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); - - CRecordVector<UInt32> indices; - indices.Reserve(numFiles); + refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType); + CSortParam sortParam; + // sortParam.TreeFolders = &treeFolders; + sortParam.SortByType = sortByType; + refItems.Sort(CompareUpdateItems, (void *)&sortParam); + + 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; @@ -1077,7 +1257,7 @@ HRESULT Update( newDatabase.Files.Add(file); */ } - + for (i = 0; i < numFiles;) { UInt64 totalSize = 0; @@ -1096,7 +1276,7 @@ HRESULT Update( if (numSubFiles == 0) prevExtension = ext; else - if (ext.CompareNoCase(prevExtension) != 0) + if (!ext.IsEqualToNoCase(prevExtension)) break; } } @@ -1106,38 +1286,43 @@ HRESULT Update( CFolderInStream *inStreamSpec = new CFolderInStream; 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); + db->GetPath(ui.IndexInArchive, name); + } if (file2.IsAnti || file.IsDir) return E_FAIL; - + /* CFileItem &file = newDatabase.Files[ startFileIndexInDatabase + i + subIndex]; @@ -1161,7 +1346,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. @@ -1173,42 +1365,36 @@ HRESULT Update( if (folderRefIndex != folderRefs.Size()) return E_FAIL; + RINOK(lps->SetCur()); + /* folderRefs.ClearAndFree(); fileIndexToUpdateIndexMap.ClearAndFree(); 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++) + 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 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); + 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; } diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h index 31e362246..aee2d5ed3 100644 --- a/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h +++ b/src/libs/7zip/unix/CPP/7zip/Archive/7z/7zUpdate.h @@ -3,29 +3,54 @@ #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; int IndexInClient; - + UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 Size; UString Name; + /* + bool IsAltStream; + int ParentFolderIndex; + int TreeFolderIndex; + */ + + // that code is not used in 9.26 + // int ParentSortIndex; + // int ParentSortIndexEnd; UInt32 Attrib; - + bool NewData; bool NewProps; @@ -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 |