diff options
Diffstat (limited to 'CPP/7zip/Archive/Zip')
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipAddCommon.cpp | 101 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipCompressionMode.h | 56 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipHandler.cpp | 44 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipHandler.h | 41 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipHandlerOut.cpp | 298 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipIn.cpp | 4 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipItem.cpp | 62 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipItem.h | 13 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipUpdate.cpp | 69 |
9 files changed, 262 insertions, 426 deletions
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index 4c5fd38d..da42f3bd 100755 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -33,6 +33,7 @@ static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize; class CLzmaEncoder: public ICompressCoder, + public ICompressSetCoderProperties, public CMyUnknownImp { NCompress::NLzma::CEncoder *EncoderSpec; @@ -41,12 +42,12 @@ class CLzmaEncoder: public: STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); - HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); - MY_UNKNOWN_IMP + MY_UNKNOWN_IMP1(ICompressSetCoderProperties) }; -HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +STDMETHODIMP CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) { if (!Encoder) { @@ -67,7 +68,7 @@ HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIAN return S_OK; } -HRESULT CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, +STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { RINOK(WriteStream(outStream, Header, kLzmaHeaderSize)); @@ -210,52 +211,12 @@ HRESULT CAddCommon::Compress( _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_LZMA; CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder(); _compressEncoder = _lzmaEncoder; - NWindows::NCOM::CPropVariant props[] = - { - #ifndef _7ZIP_ST - _options.NumThreads, - #endif - _options.Algo, - _options.DicSize, - _options.NumFastBytes, - const_cast<BSTR>((const wchar_t *)_options.MatchFinder), - _options.NumMatchFinderCycles - }; - PROPID propIDs[] = - { - #ifndef _7ZIP_ST - NCoderPropID::kNumThreads, - #endif - NCoderPropID::kAlgorithm, - NCoderPropID::kDictionarySize, - NCoderPropID::kNumFastBytes, - NCoderPropID::kMatchFinder, - NCoderPropID::kMatchFinderCycles - }; - int numProps = sizeof(propIDs) / sizeof(propIDs[0]); - if (!_options.NumMatchFinderCyclesDefined) - numProps--; - RINOK(_lzmaEncoder->SetCoderProperties(propIDs, props, numProps)); } else if (method == NFileHeader::NCompressionMethod::kPPMd) { _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd; NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder(); _compressEncoder = encoder; - NWindows::NCOM::CPropVariant props[] = - { - _options.Algo, - _options.MemSize, - _options.Order - - }; - PROPID propIDs[] = - { - NCoderPropID::kAlgorithm, - NCoderPropID::kUsedMemorySize, - NCoderPropID::kOrder - }; - RINOK(encoder->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0]))); } else { @@ -282,56 +243,20 @@ HRESULT CAddCommon::Compress( if (method == NFileHeader::NCompressionMethod::kDeflated || method == NFileHeader::NCompressionMethod::kDeflated64) { - NWindows::NCOM::CPropVariant props[] = - { - _options.Algo, - _options.NumPasses, - _options.NumFastBytes, - _options.NumMatchFinderCycles - }; - PROPID propIDs[] = - { - NCoderPropID::kAlgorithm, - NCoderPropID::kNumPasses, - NCoderPropID::kNumFastBytes, - NCoderPropID::kMatchFinderCycles - }; - int numProps = sizeof(propIDs) / sizeof(propIDs[0]); - if (!_options.NumMatchFinderCyclesDefined) - numProps--; - CMyComPtr<ICompressSetCoderProperties> setCoderProperties; - _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties); - if (setCoderProperties) - { - RINOK(setCoderProperties->SetCoderProperties(propIDs, props, numProps)); - } } else if (method == NFileHeader::NCompressionMethod::kBZip2) { - NWindows::NCOM::CPropVariant props[] = - { - _options.DicSize, - _options.NumPasses - #ifndef _7ZIP_ST - , _options.NumThreads - #endif - }; - PROPID propIDs[] = - { - NCoderPropID::kDictionarySize, - NCoderPropID::kNumPasses - #ifndef _7ZIP_ST - , NCoderPropID::kNumThreads - #endif - }; - CMyComPtr<ICompressSetCoderProperties> setCoderProperties; - _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties); - if (setCoderProperties) + } + } + { + CMyComPtr<ICompressSetCoderProperties> setCoderProps; + _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps); + if (setCoderProps) { - RINOK(setCoderProperties->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0]))); + RINOK(_options.MethodInfo.SetCoderProps(setCoderProps, + _options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL)); } } - } } CMyComPtr<ISequentialOutStream> outStreamNew; if (_options.PasswordIsDefined) diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h index 7ef7cfb2..5be33166 100755 --- a/CPP/7zip/Archive/Zip/ZipCompressionMode.h +++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h @@ -5,36 +5,54 @@ #include "Common/MyString.h" +#ifndef _7ZIP_ST +#include "../../../Windows/System.h" +#endif + +#include "../Common/HandlerOut.h" + namespace NArchive { namespace NZip { -struct CCompressionMethodMode +struct CBaseProps { - CRecordVector<Byte> MethodSequence; - UString MatchFinder; - UInt32 Algo; - UInt32 NumPasses; - UInt32 NumFastBytes; - bool NumMatchFinderCyclesDefined; - UInt32 NumMatchFinderCycles; - UInt32 DicSize; - UInt32 MemSize; - UInt32 Order; + CMethodProps MethodInfo; + Int32 Level; #ifndef _7ZIP_ST UInt32 NumThreads; + bool NumThreadsWasChanged; #endif - bool PasswordIsDefined; - AString Password; bool IsAesMode; Byte AesKeyMode; + + void Init() + { + MethodInfo.Clear(); + Level = -1; + #ifndef _7ZIP_ST + NumThreads = NWindows::NSystem::GetNumberOfProcessors();; + NumThreadsWasChanged = false; + #endif + IsAesMode = false; + AesKeyMode = 3; + } +}; + +struct CCompressionMethodMode: public CBaseProps +{ + CRecordVector<Byte> MethodSequence; + bool PasswordIsDefined; + AString Password; + + UInt64 _dataSizeReduce; + bool _dataSizeReduceDefined; - CCompressionMethodMode(): - NumMatchFinderCyclesDefined(false), - PasswordIsDefined(false), - IsAesMode(false), - AesKeyMode(3) - {} + CCompressionMethodMode(): PasswordIsDefined(false) + { + _dataSizeReduceDefined = false; + _dataSizeReduce = 0; + } }; }} diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index bd156322..2281ed5b 100755 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -107,7 +107,7 @@ static struct CStrongCryptoPair { NStrongCryptoFlags::kRC4, "RC4" } }; -static STATPROPSTG kProps[] = +static const STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, @@ -117,6 +117,7 @@ static STATPROPSTG kProps[] = { NULL, kpidCTime, VT_FILETIME}, { NULL, kpidATime, VT_FILETIME}, { NULL, kpidAttrib, VT_UI4}, + // { NULL, kpidPosixAttrib, VT_UI4}, { NULL, kpidEncrypted, VT_BOOL}, { NULL, kpidComment, VT_BSTR}, { NULL, kpidCRC, VT_UI4}, @@ -125,7 +126,7 @@ static STATPROPSTG kProps[] = { NULL, kpidUnpackVer, VT_UI4} }; -static STATPROPSTG kArcProps[] = +static const STATPROPSTG kArcProps[] = { { NULL, kpidBit64, VT_BOOL}, { NULL, kpidComment, VT_BSTR}, @@ -135,7 +136,7 @@ static STATPROPSTG kArcProps[] = CHandler::CHandler() { - InitMethodProperties(); + InitMethodProps(); } static AString BytesToString(const CByteBuffer &data) @@ -165,6 +166,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidComment: prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break; case kpidPhySize: prop = m_Archive.ArcInfo.GetPhySize(); break; case kpidOffset: if (m_Archive.ArcInfo.StartPosition != 0) prop = m_Archive.ArcInfo.StartPosition; break; + case kpidError: if (!m_Archive.IsOkHeaders) prop = "Incorrect headers"; break; } prop.Detach(value); COM_TRY_END @@ -194,7 +196,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val UInt32 unixTime; if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft)) prop = (UInt32)NFileTimeType::kWindows; - else if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime)) + else if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime)) prop = (UInt32)NFileTimeType::kUnix; else prop = (UInt32)NFileTimeType::kDOS; @@ -220,7 +222,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc)) { UInt32 unixTime; - if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime)) + if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime)) NTime::UnixTimeToFileTime(unixTime, utc); else { @@ -233,7 +235,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = utc; break; } - case kpidAttrib: prop = item.GetWinAttributes(); break; + case kpidAttrib: prop = item.GetWinAttrib(); break; + case kpidPosixAttrib: + { + UInt32 attrib; + if (item.GetPosixAttrib(attrib)) + prop = attrib; + break; + } case kpidEncrypted: prop = item.IsEncrypted(); break; case kpidComment: prop = item.GetUnicodeString(BytesToString(item.Comment)); break; case kpidCRC: if (item.IsThereCrc()) prop = item.FileCRC; break; @@ -435,7 +444,10 @@ public: ISequentialOutStream *realOutStream, IArchiveExtractCallback *extractCallback, ICompressProgressInfo *compressProgress, - UInt32 numThreads, Int32 &res); + #ifndef _7ZIP_ST + UInt32 numThreads, + #endif + Int32 &res); }; HRESULT CZipDecoder::Decode( @@ -444,7 +456,10 @@ HRESULT CZipDecoder::Decode( ISequentialOutStream *realOutStream, IArchiveExtractCallback *extractCallback, ICompressProgressInfo *compressProgress, - UInt32 numThreads, Int32 &res) + #ifndef _7ZIP_ST + UInt32 numThreads, + #endif + Int32 &res) { res = NExtract::NOperationResult::kDataError; CInStreamReleaser inStreamReleaser; @@ -805,15 +820,22 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->PrepareOperation(askMode)); Int32 res; - RINOK(myDecoder.Decode( + HRESULT hres = myDecoder.Decode( EXTERNAL_CODECS_VARS m_Archive, item, realOutStream, extractCallback, - progress, _numThreads, res)); + progress, + #ifndef _7ZIP_ST + _props.NumThreads, + #endif + res); + RINOK(hres); realOutStream.Release(); RINOK(extractCallback->SetOperationResult(res)) } - return S_OK; + lps->InSize = currentTotalPacked; + lps->OutSize = currentTotalUnPacked; + return lps->SetCur(); COM_TRY_END } diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h index fdb60aaf..33cf6fdc 100755 --- a/CPP/7zip/Archive/Zip/ZipHandler.h +++ b/CPP/7zip/Archive/Zip/ZipHandler.h @@ -12,10 +12,6 @@ #include "ZipIn.h" #include "ZipCompressionMode.h" -#ifndef _7ZIP_ST -#include "../../../Windows/System.h" -#endif - namespace NArchive { namespace NZip { @@ -46,53 +42,24 @@ private: CObjectVector<CItemEx> m_Items; CInArchive m_Archive; - int m_Level; - int m_MainMethod; - UInt32 m_DicSize; - UInt32 m_Algo; - UInt32 m_NumPasses; - UInt32 m_NumFastBytes; - UInt32 m_NumMatchFinderCycles; - UInt32 m_MemSize; - UInt32 m_Order; - - bool m_NumMatchFinderCyclesDefined; + CBaseProps _props; + int m_MainMethod; bool m_ForceAesMode; - bool m_IsAesMode; - Byte m_AesKeyMode; - bool m_WriteNtfsTimeExtra; bool m_ForceLocal; bool m_ForceUtf8; - #ifndef _7ZIP_ST - UInt32 _numThreads; - #endif - DECL_EXTERNAL_CODECS_VARS - void InitMethodProperties() + void InitMethodProps() { - m_Level = -1; + _props.Init(); m_MainMethod = -1; - m_Algo = - m_DicSize = - m_NumPasses = - m_NumFastBytes = - m_Order = - m_MemSize = - m_NumMatchFinderCycles = 0xFFFFFFFF; - m_NumMatchFinderCyclesDefined = false; m_ForceAesMode = false; - m_IsAesMode = false; - m_AesKeyMode = 3; // aes-256 m_WriteNtfsTimeExtra = true; m_ForceLocal = false; m_ForceUtf8 = false; - #ifndef _7ZIP_ST - _numThreads = NWindows::NSystem::GetNumberOfProcessors();; - #endif } }; diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp index a5e0f59d..427b0c31 100755 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -28,37 +28,6 @@ using namespace NTime; namespace NArchive { namespace NZip { -static const UInt32 kLzAlgoX1 = 0; -static const UInt32 kLzAlgoX5 = 1; - -static const UInt32 kDeflateNumPassesX1 = 1; -static const UInt32 kDeflateNumPassesX7 = 3; -static const UInt32 kDeflateNumPassesX9 = 10; - -static const UInt32 kDeflateNumFastBytesX1 = 32; -static const UInt32 kDeflateNumFastBytesX7 = 64; -static const UInt32 kDeflateNumFastBytesX9 = 128; - -static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; -static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; - -static const UInt32 kLzmaNumFastBytesX1 = 32; -static const UInt32 kLzmaNumFastBytesX7 = 64; - -static const UInt32 kLzmaDicSizeX1 = 1 << 16; -static const UInt32 kLzmaDicSizeX3 = 1 << 20; -static const UInt32 kLzmaDicSizeX5 = 1 << 24; -static const UInt32 kLzmaDicSizeX7 = 1 << 25; -static const UInt32 kLzmaDicSizeX9 = 1 << 26; - -static const UInt32 kBZip2NumPassesX1 = 1; -static const UInt32 kBZip2NumPassesX7 = 2; -static const UInt32 kBZip2NumPassesX9 = 7; - -static const UInt32 kBZip2DicSizeX1 = 100000; -static const UInt32 kBZip2DicSizeX3 = 500000; -static const UInt32 kBZip2DicSizeX5 = 900000; - STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) { *timeType = NFileTimeType::kDOS; @@ -99,6 +68,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt COM_TRY_BEGIN2 CObjectVector<CUpdateItem> updateItems; bool thereAreAesUpdates = false; + UInt64 largestSize = 0; + bool largestSizeDefined = false; for (UInt32 i = 0; i < numItems; i++) { CUpdateItem ui; @@ -178,7 +149,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt const wchar_t kSlash = L'/'; if (!name.IsEmpty()) { - if (name[name.Length() - 1] == kSlash) + if (name.Back() == kSlash) { if (!ui.IsDir) return E_INVALIDARG; @@ -235,6 +206,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; + if (largestSize < size) + largestSize = size; + largestSizeDefined = true; } ui.Size = size; } @@ -247,6 +221,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); } CCompressionMethodMode options; + (CBaseProps &)options = _props; + options._dataSizeReduce = largestSize; + options._dataSizeReduceDefined = largestSizeDefined; if (getTextPassword) { @@ -256,8 +233,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options.PasswordIsDefined = IntToBool(passwordIsDefined); if (options.PasswordIsDefined) { - options.IsAesMode = (m_ForceAesMode ? m_IsAesMode : thereAreAesUpdates); - options.AesKeyMode = m_AesKeyMode; + if (!m_ForceAesMode) + options.IsAesMode = thereAreAesUpdates; if (!IsAsciiString((const wchar_t *)password)) return E_INVALIDARG; @@ -272,13 +249,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt else options.PasswordIsDefined = false; - int level = m_Level; - if (level < 0) - level = 5; - Byte mainMethod; if (m_MainMethod < 0) - mainMethod = (Byte)(((level == 0) ? + mainMethod = (Byte)(((_props.Level == 0) ? NFileHeader::NCompressionMethod::kStored : NFileHeader::NCompressionMethod::kDeflated)); else @@ -286,83 +259,6 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options.MethodSequence.Add(mainMethod); if (mainMethod != NFileHeader::NCompressionMethod::kStored) options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored); - bool isDeflate = (mainMethod == NFileHeader::NCompressionMethod::kDeflated) || - (mainMethod == NFileHeader::NCompressionMethod::kDeflated64); - bool isLZMA = (mainMethod == NFileHeader::NCompressionMethod::kLZMA); - bool isLz = (isLZMA || isDeflate); - options.NumPasses = m_NumPasses; - options.DicSize = m_DicSize; - options.NumFastBytes = m_NumFastBytes; - options.NumMatchFinderCycles = m_NumMatchFinderCycles; - options.NumMatchFinderCyclesDefined = m_NumMatchFinderCyclesDefined; - options.Algo = m_Algo; - options.MemSize = m_MemSize; - options.Order = m_Order; - #ifndef _7ZIP_ST - options.NumThreads = _numThreads; - #endif - if (isLz) - { - if (isDeflate) - { - if (options.NumPasses == 0xFFFFFFFF) - options.NumPasses = (level >= 9 ? kDeflateNumPassesX9 : - (level >= 7 ? kDeflateNumPassesX7 : - kDeflateNumPassesX1)); - if (options.NumFastBytes == 0xFFFFFFFF) - options.NumFastBytes = (level >= 9 ? kDeflateNumFastBytesX9 : - (level >= 7 ? kDeflateNumFastBytesX7 : - kDeflateNumFastBytesX1)); - } - else if (isLZMA) - { - if (options.DicSize == 0xFFFFFFFF) - options.DicSize = - (level >= 9 ? kLzmaDicSizeX9 : - (level >= 7 ? kLzmaDicSizeX7 : - (level >= 5 ? kLzmaDicSizeX5 : - (level >= 3 ? kLzmaDicSizeX3 : - kLzmaDicSizeX1)))); - - if (options.NumFastBytes == 0xFFFFFFFF) - options.NumFastBytes = (level >= 7 ? kLzmaNumFastBytesX7 : - kLzmaNumFastBytesX1); - - options.MatchFinder = - (level >= 5 ? kLzmaMatchFinderX5 : - kLzmaMatchFinderX1); - } - - if (options.Algo == 0xFFFFFFFF) - options.Algo = (level >= 5 ? kLzAlgoX5 : - kLzAlgoX1); - } - if (mainMethod == NFileHeader::NCompressionMethod::kBZip2) - { - if (options.NumPasses == 0xFFFFFFFF) - options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 : - (level >= 7 ? kBZip2NumPassesX7 : - kBZip2NumPassesX1)); - if (options.DicSize == 0xFFFFFFFF) - options.DicSize = (level >= 5 ? kBZip2DicSizeX5 : - (level >= 3 ? kBZip2DicSizeX3 : - kBZip2DicSizeX1)); - } - if (mainMethod == NFileHeader::NCompressionMethod::kPPMd) - { - int level2 = level; - if (level2 < 1) level2 = 1; - if (level2 > 9) level2 = 9; - - if (options.MemSize == 0xFFFFFFFF) - options.MemSize = (1 << (19 + (level2 > 8 ? 8 : level2))); - - if (options.Order == 0xFFFFFFFF) - options.Order = 3 + level2; - - if (options.Algo == 0xFFFFFFFF) - options.Algo = (level2 >= 7 ? 1 : 0); - } return Update( EXTERNAL_CODECS_VARS @@ -371,16 +267,34 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt COM_TRY_END2 } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) +struct CMethodIndexToName +{ + unsigned Method; + const wchar_t *Name; +}; + +static const CMethodIndexToName k_SupportedMethods[] = { + { NFileHeader::NCompressionMethod::kStored, L"COPY" }, + { NFileHeader::NCompressionMethod::kDeflated, L"DEFLATE" }, + { NFileHeader::NCompressionMethod::kDeflated64, L"DEFLATE64" }, + { NFileHeader::NCompressionMethod::kBZip2, L"BZIP2" }, + { NFileHeader::NCompressionMethod::kLZMA, L"LZMA" }, + { NFileHeader::NCompressionMethod::kPPMd, L"PPMD" } +}; + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +{ + InitMethodProps(); #ifndef _7ZIP_ST - const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); - _numThreads = numProcessors; + const UInt32 numProcessors = _props.NumThreads; #endif - InitMethodProperties(); - for (int i = 0; i < numProperties; i++) + + for (int i = 0; i < numProps; i++) { - UString name = UString(names[i]); + UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; @@ -390,140 +304,112 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v if (name[0] == L'X') { UInt32 level = 9; - RINOK(ParsePropValue(name.Mid(1), prop, level)); - m_Level = level; - continue; + RINOK(ParsePropToUInt32(name.Mid(1), prop, level)); + _props.Level = level; + _props.MethodInfo.AddLevelProp(level); } else if (name == L"M") { if (prop.vt == VT_BSTR) { - UString m = prop.bstrVal; + UString m = prop.bstrVal, m2; m.MakeUpper(); - if (m == L"COPY") m_MainMethod = NFileHeader::NCompressionMethod::kStored; - else if (m == L"DEFLATE") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated; - else if (m == L"DEFLATE64") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated64; - else if (m == L"BZIP2") m_MainMethod = NFileHeader::NCompressionMethod::kBZip2; - else if (m == L"LZMA") m_MainMethod = NFileHeader::NCompressionMethod::kLZMA; - else if (m == L"PPMD") m_MainMethod = NFileHeader::NCompressionMethod::kPPMd; - else return E_INVALIDARG; + int colonPos = m.Find(L':'); + if (colonPos >= 0) + { + m2 = m.Mid(colonPos + 1); + m = m.Left(colonPos); + } + int k; + for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++) + { + const CMethodIndexToName &pair = k_SupportedMethods[k]; + if (m == pair.Name) + { + if (!m2.IsEmpty()) + { + RINOK(_props.MethodInfo.ParseParamsFromString(m2)); + } + m_MainMethod = pair.Method; + break; + } + } + if (k == ARRAY_SIZE(k_SupportedMethods)) + return E_INVALIDARG; } else if (prop.vt == VT_UI4) { - switch(prop.ulVal) + int k; + for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++) { - case NFileHeader::NCompressionMethod::kStored: - case NFileHeader::NCompressionMethod::kDeflated: - case NFileHeader::NCompressionMethod::kDeflated64: - case NFileHeader::NCompressionMethod::kBZip2: - case NFileHeader::NCompressionMethod::kLZMA: - m_MainMethod = (Byte)prop.ulVal; + unsigned method = k_SupportedMethods[k].Method; + if (prop.ulVal == method) + { + m_MainMethod = method; break; - default: - return E_INVALIDARG; + } } + if (k == ARRAY_SIZE(k_SupportedMethods)) + return E_INVALIDARG; } else return E_INVALIDARG; } else if (name.Left(2) == L"EM") { - if (prop.vt == VT_BSTR) + if (prop.vt != VT_BSTR) + return E_INVALIDARG; { - UString valueString = prop.bstrVal; - valueString.MakeUpper(); - if (valueString.Left(3) == L"AES") + UString m = prop.bstrVal; + m.MakeUpper(); + if (m.Left(3) == L"AES") { - valueString = valueString.Mid(3); - if (valueString == L"128") - m_AesKeyMode = 1; - else if (valueString == L"192") - m_AesKeyMode = 2; - else if (valueString == L"256" || valueString.IsEmpty()) - m_AesKeyMode = 3; + m = m.Mid(3); + if (m == L"128") + _props.AesKeyMode = 1; + else if (m == L"192") + _props.AesKeyMode = 2; + else if (m == L"256" || m.IsEmpty()) + _props.AesKeyMode = 3; else return E_INVALIDARG; - m_IsAesMode = true; + _props.IsAesMode = true; m_ForceAesMode = true; } - else if (valueString == L"ZIPCRYPTO") + else if (m == L"ZIPCRYPTO") { - m_IsAesMode = false; + _props.IsAesMode = false; m_ForceAesMode = true; } else return E_INVALIDARG; } - else - return E_INVALIDARG; - } - else if (name[0] == L'D') - { - UInt32 dicSize = kBZip2DicSizeX5; - RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize)); - m_DicSize = dicSize; - } - else if (name.Left(3) == L"MEM") - { - UInt32 memSize = 1 << 24; - RINOK(ParsePropDictionaryValue(name.Mid(3), prop, memSize)); - m_MemSize = memSize; - } - else if (name[0] == L'O') - { - UInt32 order = 8; - RINOK(ParsePropValue(name.Mid(1), prop, order)); - m_Order = order; - } - else if (name.Left(4) == L"PASS") - { - UInt32 num = kDeflateNumPassesX9; - RINOK(ParsePropValue(name.Mid(4), prop, num)); - m_NumPasses = num; - } - else if (name.Left(2) == L"FB") - { - UInt32 num = kDeflateNumFastBytesX9; - RINOK(ParsePropValue(name.Mid(2), prop, num)); - m_NumFastBytes = num; - } - else if (name.Left(2) == L"MC") - { - UInt32 num = 0xFFFFFFFF; - RINOK(ParsePropValue(name.Mid(2), prop, num)); - m_NumMatchFinderCycles = num; - m_NumMatchFinderCyclesDefined = true; } else if (name.Left(2) == L"MT") { #ifndef _7ZIP_ST - RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads)); + RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _props.NumThreads)); + _props.NumThreadsWasChanged = true; #endif } - else if (name.Left(1) == L"A") - { - UInt32 num = kLzAlgoX5; - RINOK(ParsePropValue(name.Mid(1), prop, num)); - m_Algo = num; - } else if (name.CompareNoCase(L"TC") == 0) { - RINOK(SetBoolProperty(m_WriteNtfsTimeExtra, prop)); + RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra)); } else if (name.CompareNoCase(L"CL") == 0) { - RINOK(SetBoolProperty(m_ForceLocal, prop)); + RINOK(PROPVARIANT_to_bool(prop, m_ForceLocal)); if (m_ForceLocal) m_ForceUtf8 = false; } else if (name.CompareNoCase(L"CU") == 0) { - RINOK(SetBoolProperty(m_ForceUtf8, prop)); + RINOK(PROPVARIANT_to_bool(prop, m_ForceUtf8)); if (m_ForceUtf8) m_ForceLocal = false; } else - return E_INVALIDARG; + return _props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop); } return S_OK; } diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index b36b61be..e930488f 100755 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -756,6 +756,7 @@ void CEcd64::Parse(const Byte *p) HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress) { + IsOkHeaders = true; // m_Signature must be kLocalFileHeaderSignature or // kEndOfCentralDirSignature // m_Position points to next byte after signature @@ -852,6 +853,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0) throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported); + if (numCdItems != items.Size()) + IsOkHeaders = false; if ((UInt16)ecd64.numEntriesInCDOnThisDisk != ((UInt16)numCdItems) || (UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) || (UInt32)ecd64.cdSize != (UInt32)cdSize || @@ -861,7 +864,6 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr _inBufMode = false; _inBuffer.Free(); - IsOkHeaders = (numCdItems == items.Size()); ArcInfo.FinishPosition = m_Position; return S_OK; } diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp index 139b0129..ad89f558 100755 --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -51,7 +51,7 @@ bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const return false; } -bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const +bool CExtraSubBlock::ExtractUnixTime(bool isCentral, int index, UInt32 &res) const { res = 0; UInt32 size = (UInt32)Data.GetCapacity(); @@ -60,6 +60,15 @@ bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const const Byte *p = (const Byte *)Data; Byte flags = *p++; size--; + if (isCentral) + { + if (index != NFileHeader::NUnixTime::kMTime || + (flags & (1 << NFileHeader::NUnixTime::kMTime)) == 0 || + size < 4) + return false; + res = GetUi32(p); + return true; + } for (int i = 0; i < 3; i++) if ((flags & (1 << i)) != 0) { @@ -88,7 +97,7 @@ bool CItem::IsDir() const if (!FromCentral) return false; WORD highAttributes = WORD((ExternalAttributes >> 16 ) & 0xFFFF); - switch(MadeByVersion.HostOS) + switch (MadeByVersion.HostOS) { case NFileHeader::NHostOS::kAMIGA: switch (highAttributes & NFileHeader::NAmigaAttribute::kIFMT) @@ -109,44 +118,41 @@ bool CItem::IsDir() const case NFileHeader::NHostOS::kAcorn: case NFileHeader::NHostOS::kMVS: return false; // change it throw kUnknownAttributes; + case NFileHeader::NHostOS::kUnix: + return (highAttributes & NFileHeader::NUnixAttribute::kIFDIR) != 0; default: - /* - switch (highAttributes & NFileHeader::NUnixAttribute::kIFMT) - { - case NFileHeader::NUnixAttribute::kIFDIR: - return true; - default: - return false; - } - */ return false; } } -UInt32 CLocalItem::GetWinAttributes() const -{ - DWORD winAttributes = 0; - if (IsDir()) - winAttributes |= FILE_ATTRIBUTE_DIRECTORY; - return winAttributes; -} - -UInt32 CItem::GetWinAttributes() const +UInt32 CItem::GetWinAttrib() const { - DWORD winAttributes = 0; - switch(MadeByVersion.HostOS) + DWORD winAttrib = 0; + switch (MadeByVersion.HostOS) { case NFileHeader::NHostOS::kFAT: case NFileHeader::NHostOS::kNTFS: if (FromCentral) - winAttributes = ExternalAttributes; + winAttrib = ExternalAttributes; break; - default: - winAttributes = 0; // must be converted from unix value; } - if (IsDir()) // test it; - winAttributes |= FILE_ATTRIBUTE_DIRECTORY; - return winAttributes; + if (IsDir()) // test it; + winAttrib |= FILE_ATTRIBUTE_DIRECTORY; + return winAttrib; +} + +bool CItem::GetPosixAttrib(UInt32 &attrib) const +{ + // some archivers can store PosixAttrib in high 16 bits even with HostOS=FAT. + if (FromCentral && MadeByVersion.HostOS == NFileHeader::NHostOS::kUnix) + { + attrib = ExternalAttributes >> 16; + return (attrib != 0); + } + attrib = 0; + if (IsDir()) + attrib = NFileHeader::NUnixAttribute::kIFDIR; + return false; } void CLocalItem::SetFlagBits(int startBitNumber, int numBits, int value) diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index 31f2de73..5efd433a 100755 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -3,7 +3,6 @@ #ifndef __ARCHIVE_ZIP_ITEM_H #define __ARCHIVE_ZIP_ITEM_H -#include "Common/Types.h" #include "Common/MyString.h" #include "Common/Buffer.h" #include "Common/UTFConvert.h" @@ -28,7 +27,7 @@ struct CExtraSubBlock UInt16 ID; CByteBuffer Data; bool ExtractNtfsTime(int index, FILETIME &ft) const; - bool ExtractUnixTime(int index, UInt32 &res) const; + bool ExtractUnixTime(bool isCentral, int index, UInt32 &res) const; }; struct CWzAesExtraField @@ -152,13 +151,13 @@ struct CExtraBlock return false; } - bool GetUnixTime(int index, UInt32 &res) const + bool GetUnixTime(bool isCentral, int index, UInt32 &res) const { for (int i = 0; i < SubBlocks.Size(); i++) { const CExtraSubBlock &sb = SubBlocks[i]; if (sb.ID == NFileHeader::NExtraID::kUnixTime) - return sb.ExtractUnixTime(index, res); + return sb.ExtractUnixTime(isCentral, index, res); } return false; } @@ -205,7 +204,6 @@ public: bool IsDir() const; bool IgnoreItem() const { return false; } - UInt32 GetWinAttributes() const; bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; } @@ -252,7 +250,8 @@ public: bool NtfsTimeIsDefined; bool IsDir() const; - UInt32 GetWinAttributes() const; + UInt32 GetWinAttrib() const; + bool GetPosixAttrib(UInt32 &attrib) const; bool IsThereCrc() const { @@ -277,5 +276,3 @@ public: }} #endif - - diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index d4fdee3d..490d9e26 100755 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -473,6 +473,9 @@ static HRESULT Update2St( items.Add(item); lps->ProgressOffset += NFileHeader::kLocalBlockSize; } + lps->InSize = unpackSizeTotal; + lps->OutSize = packSizeTotal; + RINOK(lps->SetCur()); archive.WriteCentralDir(items, comment); return S_OK; } @@ -493,7 +496,7 @@ static HRESULT Update2( UInt64 numBytesToCompress = 0; int i; - for(i = 0; i < updateItems.Size(); i++) + for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) @@ -527,6 +530,10 @@ static HRESULT Update2( complexity = 0; + CCompressionMethodMode options2; + if (options != 0) + options2 = *options; + #ifndef _7ZIP_ST const size_t kNumMaxThreads = (1 << 10); @@ -537,53 +544,58 @@ static HRESULT Update2( const size_t kMemPerThread = (1 << 25); const size_t kBlockSize = 1 << 16; - CCompressionMethodMode options2; - if (options != 0) - options2 = *options; - bool mtMode = ((options != 0) && (numThreads > 1)); if (numFilesToCompress <= 1) mtMode = false; - if (mtMode) + if (!mtMode) + { + if (numThreads < 2) + if (options2.MethodInfo.FindProp(NCoderPropID::kNumThreads) < 0 && + options2.NumThreadsWasChanged) + options2.MethodInfo.AddNumThreadsProp(1); + } + else { Byte method = options->MethodSequence.Front(); if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined) - mtMode = false; + numThreads = 1; if (method == NFileHeader::NCompressionMethod::kBZip2) { - UInt64 averageSize = numBytesToCompress / numFilesToCompress; - UInt32 blockSize = options->DicSize; - if (blockSize == 0) - blockSize = 1; - UInt64 averageNumberOfBlocks = averageSize / blockSize; - UInt32 numBZip2Threads = 32; - if (averageNumberOfBlocks < numBZip2Threads) - numBZip2Threads = (UInt32)averageNumberOfBlocks; - if (numBZip2Threads < 1) - numBZip2Threads = 1; - numThreads = numThreads / numBZip2Threads; - options2.NumThreads = numBZip2Threads; - if (numThreads <= 1) - mtMode = false; + bool fixedNumber; + UInt32 numBZip2Threads = options2.MethodInfo.Get_BZip2_NumThreads(fixedNumber); + if (!fixedNumber) + { + UInt64 averageSize = numBytesToCompress / numFilesToCompress; + UInt32 blockSize = options2.MethodInfo.Get_BZip2_BlockSize(); + UInt64 averageNumberOfBlocks = averageSize / blockSize + 1; + numBZip2Threads = 32; + if (averageNumberOfBlocks < numBZip2Threads) + numBZip2Threads = (UInt32)averageNumberOfBlocks; + options2.MethodInfo.AddNumThreadsProp(numBZip2Threads); + } + numThreads /= numBZip2Threads; } if (method == NFileHeader::NCompressionMethod::kLZMA) { - UInt32 numLZMAThreads = (options->Algo > 0 ? 2 : 1); + bool fixedNumber; + // we suppose that default LZMA is 2 thread. So we don't change it + UInt32 numLZMAThreads = options2.MethodInfo.Get_Lzma_NumThreads(fixedNumber); numThreads /= numLZMAThreads; - options2.NumThreads = numLZMAThreads; - if (numThreads <= 1) - mtMode = false; } + if (numThreads > numFilesToCompress) + numThreads = (UInt32)numFilesToCompress; + if (numThreads <= 1) + mtMode = false; } if (!mtMode) #endif return Update2St( EXTERNAL_CODECS_LOC_VARS - archive, inArchive,inStream, - inputItems, updateItems, options, comment, updateCallback); + archive, inArchive, inStream, + inputItems, updateItems, &options2, comment, updateCallback); #ifndef _7ZIP_ST @@ -606,7 +618,7 @@ static HRESULT Update2( { RINOK(memManager.AllocateSpaceAlways((size_t)numThreads * (kMemPerThread / kBlockSize))); - for(i = 0; i < updateItems.Size(); i++) + for (i = 0; i < updateItems.Size(); i++) refs.Refs.Add(CMemBlocks2()); UInt32 i; @@ -796,6 +808,7 @@ static HRESULT Update2( mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); itemIndex++; } + RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL)); archive.WriteCentralDir(items, comment); return S_OK; #endif |