diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2010-03-15 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:16:02 +0300 |
commit | 993daef9cbed7febf494217f07e40e0a26b3bc06 (patch) | |
tree | 41db24cb11222422aa3c4d61b80646344e3efefc /CPP/7zip/Archive | |
parent | db5eb6d638f5a5ec10517ed4a994b849a6cc7d29 (diff) |
9.119.11
Diffstat (limited to 'CPP/7zip/Archive')
-rwxr-xr-x | CPP/7zip/Archive/Com/ComHandler.cpp | 1 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Com/ComIn.cpp | 34 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Com/ComIn.h | 2 | ||||
-rwxr-xr-x | CPP/7zip/Archive/DebHandler.cpp | 30 | ||||
-rwxr-xr-x | CPP/7zip/Archive/PeHandler.cpp | 56 | ||||
-rwxr-xr-x | CPP/7zip/Archive/PpmdHandler.cpp | 456 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipAddCommon.cpp | 28 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipCompressionMode.h | 3 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipHandler.cpp | 3 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipHandler.h | 5 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipHandlerOut.cpp | 50 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Zip/ZipHeader.h | 1 |
12 files changed, 653 insertions, 16 deletions
diff --git a/CPP/7zip/Archive/Com/ComHandler.cpp b/CPP/7zip/Archive/Com/ComHandler.cpp index 39fce0ae..58f76439 100755 --- a/CPP/7zip/Archive/Com/ComHandler.cpp +++ b/CPP/7zip/Archive/Com/ComHandler.cpp @@ -44,6 +44,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break; case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break; + case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break; } prop.Detach(value); return S_OK; diff --git a/CPP/7zip/Archive/Com/ComIn.cpp b/CPP/7zip/Archive/Com/ComIn.cpp index 8f622122..2203ca53 100755 --- a/CPP/7zip/Archive/Com/ComIn.cpp +++ b/CPP/7zip/Archive/Com/ComIn.cpp @@ -174,8 +174,9 @@ bool CompoundMsiNameToFileName(const UString &name, UString &resultName) return true; } -static UString ConvertName(const Byte *p) +static UString ConvertName(const Byte *p, bool &isMsi) { + isMsi = false; UString s; for (int i = 0; i < kNameSizeMax; i += 2) { @@ -186,10 +187,19 @@ static UString ConvertName(const Byte *p) } UString msiName; if (CompoundMsiNameToFileName(s, msiName)) + { + isMsi = true; return msiName; + } return CompoundNameToFileName(s); } +static UString ConvertName(const Byte *p) +{ + bool isMsi; + return ConvertName(p, isMsi); +} + UString CDatabase::GetItemPath(UInt32 index) const { UString s; @@ -207,6 +217,7 @@ UString CDatabase::GetItemPath(UInt32 index) const HRESULT CDatabase::Open(IInStream *inStream) { + MainSubfile = -1; static const UInt32 kHeaderSize = 512; Byte p[kHeaderSize]; RINOK(ReadStream_FALSE(inStream, p, kHeaderSize)); @@ -353,7 +364,26 @@ HRESULT CDatabase::Open(IInStream *inStream) } } - return AddNode(-1, root.SonDid); + RINOK(AddNode(-1, root.SonDid)); + + unsigned numCabs = 0; + for (int i = 0; i < Refs.Size(); i++) + { + const CItem &item = Items[Refs[i].Did]; + if (item.IsDir() || numCabs > 1) + continue; + bool isMsiName; + UString msiName = ConvertName(item.Name, isMsiName); + if (isMsiName && msiName.Right(4).CompareNoCase(L".cab") == 0) + { + numCabs++; + MainSubfile = i; + } + } + if (numCabs > 1) + MainSubfile = -1; + + return S_OK; } }} diff --git a/CPP/7zip/Archive/Com/ComIn.h b/CPP/7zip/Archive/Com/ComIn.h index 05fc7387..429d3796 100755 --- a/CPP/7zip/Archive/Com/ComIn.h +++ b/CPP/7zip/Archive/Com/ComIn.h @@ -88,6 +88,8 @@ public: int SectorSizeBits; int MiniSectorSizeBits; + Int32 MainSubfile; + void Clear(); bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; } UString GetItemPath(UInt32 index) const; diff --git a/CPP/7zip/Archive/DebHandler.cpp b/CPP/7zip/Archive/DebHandler.cpp index 9f083269..b9724c2a 100755 --- a/CPP/7zip/Archive/DebHandler.cpp +++ b/CPP/7zip/Archive/DebHandler.cpp @@ -68,10 +68,10 @@ struct CItem class CInArchive { CMyComPtr<IInStream> m_Stream; - UInt64 m_Position; HRESULT GetNextItemReal(bool &filled, CItem &itemInfo); public: + UInt64 m_Position; HRESULT Open(IInStream *inStream); HRESULT GetNextItem(bool &filled, CItem &itemInfo); HRESULT SkipData(UInt64 dataSize); @@ -155,9 +155,9 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItem &item) size_t processedSize = sizeof(header); item.HeaderPos = m_Position; RINOK(ReadStream(m_Stream, header, &processedSize)); - m_Position += processedSize; if (processedSize != sizeof(header)) return S_OK; + m_Position += processedSize; char tempString[NHeader::kNameSize + 1]; MyStrNCpy(tempString, cur, NHeader::kNameSize); @@ -212,14 +212,20 @@ class CHandler: { CObjectVector<CItem> _items; CMyComPtr<IInStream> _stream; + Int32 _mainSubfile; + UInt64 _phySize; public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); }; +static STATPROPSTG kArcProps[] = +{ + { NULL, kpidPhySize, VT_UI8} +}; -STATPROPSTG kProps[] = +static STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidSize, VT_UI8}, @@ -227,7 +233,7 @@ STATPROPSTG kProps[] = }; IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO +IMP_IInArchive_ArcProps STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, @@ -235,6 +241,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, { COM_TRY_BEGIN { + _mainSubfile = -1; CInArchive archive; if (archive.Open(stream) != S_OK) return S_FALSE; @@ -258,6 +265,8 @@ STDMETHODIMP CHandler::Open(IInStream *stream, return S_FALSE; if (!filled) break; + if (item.Name.Left(5) == "data.") + _mainSubfile = _items.Size(); _items.Add(item); archive.SkipData(item.Size); if (openArchiveCallback != NULL) @@ -267,6 +276,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, } } _stream = stream; + _phySize = archive.m_Position; } return S_OK; COM_TRY_END @@ -285,6 +295,18 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: prop = _phySize; break; + case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break; + } + prop.Detach(value); + return S_OK; +} + STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index fd900a58..c791d6d7 100755 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -259,8 +259,9 @@ struct CSection // UInt16 NumRelocs; bool IsDebug; bool IsRealSect; + bool IsAdditionalSection; - CSection(): IsRealSect(false), IsDebug(false) {} + CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {} UInt64 GetPackSize() const { return PSize; } void UpdateTotalSize(UInt32 &totalSize) @@ -448,6 +449,7 @@ struct CResItem bool IsBmp() const { return Type == 2; } bool IsIcon() const { return Type == 3; } bool IsString() const { return Type == 6; } + bool IsRcData() const { return Type == 10; } }; struct CStringItem @@ -530,6 +532,7 @@ class CHandler: COptHeader _optHeader; UInt32 _totalSize; UInt32 _totalSizeLimited; + Int32 _mainSubfile; CRecordVector<CResItem> _items; CObjectVector<CStringItem> _strings; @@ -648,7 +651,7 @@ STATPROPSTG kArcProps[] = { L"Stack Commit", kpidStackCommit, VT_UI8}, { L"Heap Reserve", kpidHeapReserve, VT_UI8}, { L"Heap Commit", kpidHeapCommit, VT_UI8}, - }; +}; STATPROPSTG kProps[] = { @@ -689,7 +692,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidLinkerVer: { CVersion v = { _optHeader.LinkerVerMajor, _optHeader.LinkerVerMinor }; - VerToProp(v, prop); break; + VerToProp(v, prop); break; } @@ -716,6 +719,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidStackCommit: prop = _optHeader.StackCommit; break; case kpidHeapReserve: prop = _optHeader.HeapReserve; break; case kpidHeapCommit: prop = _optHeader.HeapCommit; break; + case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break; } prop.Detach(value); return S_OK; @@ -1240,16 +1244,26 @@ HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpe { UInt32 mask = (1 << numBits) - 1; size_t end = ((maxOffset + mask) & ~mask); - if (end < sect.VSize) + if (end < sect.VSize && end <= sect.PSize) { CSection sect2; sect2.Flags = 0; + + // we skip Zeros to start of aligned block + size_t i; + for (i = maxOffset; i < end; i++) + if (_buf[i] != 0) + break; + if (i == end) + maxOffset = end; + sect2.Pa = sect.Pa + (UInt32)maxOffset; sect2.Va = sect.Va + (UInt32)maxOffset; sect2.PSize = sect.VSize - (UInt32)maxOffset; sect2.VSize = sect2.PSize; sect2.Name = ".rsrc_1"; sect2.Time = 0; + sect2.IsAdditionalSection = true; _sections.Add(sect2); } } @@ -1262,6 +1276,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) const UInt32 kBufSize = 1 << 18; const UInt32 kSigSize = 2; + _mainSubfile = -1; + CByteBuffer buffer; buffer.SetCapacity(kBufSize); Byte *buf = buffer; @@ -1358,6 +1374,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) CSection s2; s2.Pa = s2.Va = limit; s2.PSize = s2.VSize = s.Pa - limit; + s2.IsAdditionalSection = true; s2.Name = '['; s2.Name += GetDecString(num++); s2.Name += ']'; @@ -1374,6 +1391,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) _parseResources = true; + UInt64 mainSize = 0, mainSize2 = 0; for (int i = 0; i < _sections.Size(); i++) { const CSection § = _sections[i]; @@ -1386,12 +1404,26 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) { _resourceFileName = GetUnicodeString(sect.Name); for (int j = 0; j < _items.Size(); j++) - if (_items[j].Enabled) + { + const CResItem &item = _items[j]; + if (item.Enabled) { mixItem.ResourceIndex = j; mixItem.StringIndex = -1; + if (item.IsRcData()) + { + if (item.Size >= mainSize) + { + mainSize2 = mainSize; + mainSize = item.Size; + _mainSubfile = _mixItems.Size(); + } + else if (item.Size >= mainSize2) + mainSize2 = item.Size; + } _mixItems.Add(mixItem); } + } if (sect.PSize > sect.VSize) { int numBits = _optHeader.GetNumFileAlignBits(); @@ -1410,6 +1442,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) sect2.VSize = sect2.PSize; sect2.Name = ".rsrc_2"; sect2.Time = 0; + sect2.IsAdditionalSection = true; _sections.Add(sect2); } } @@ -1422,8 +1455,21 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } mixItem.StringIndex = -1; mixItem.ResourceIndex = -1; + if (sect.IsAdditionalSection) + { + if (sect.PSize >= mainSize) + { + mainSize2 = mainSize; + mainSize = sect.PSize; + _mainSubfile = _mixItems.Size(); + } + else + mainSize2 = sect.PSize; + } _mixItems.Add(mixItem); } + if (mainSize2 >= (1 << 20) && mainSize < mainSize2 * 2) + _mainSubfile = -1; return S_OK; } diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp new file mode 100755 index 00000000..9b2ef048 --- /dev/null +++ b/CPP/7zip/Archive/PpmdHandler.cpp @@ -0,0 +1,456 @@ +/* PpmdHandler.c -- PPMd format handler +2010-03-10 : Igor Pavlov : Public domain +This code is based on: + PPMd var.H (2001) / var.I (2002): Dmitry Shkarin : Public domain + Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" +#include "../../../C/Alloc.h" +#include "../../../C/Ppmd7.h" +#include "../../../C/Ppmd8.h" + +#include "Common/ComTry.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/CWrappers.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +using namespace NWindows; + +namespace NArchive { +namespace NPpmd { + +static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } +static void SzBigFree(void *, void *address) { BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +static const UInt32 kBufSize = (1 << 20); + +struct CBuf +{ + Byte *Buf; + + CBuf(): Buf(0) {} + ~CBuf() { ::MidFree(Buf); } + bool Alloc() + { + if (!Buf) + Buf = (Byte *)::MidAlloc(kBufSize); + return (Buf != 0); + } +}; + +static const UInt32 kHeaderSize = 16; +static const UInt32 kSignature = 0x84ACAF8F; +static const unsigned kNewHeaderVer = 8; + +struct CItem +{ + UInt32 Attrib; + UInt32 Time; + AString Name; + + unsigned Order; + unsigned MemInMB; + unsigned Ver; + unsigned Restor; + + HRESULT ReadHeader(ISequentialInStream *s, UInt32 &headerSize); + bool IsSupported() const { return Ver == 7 || (Ver == 8 && Restor <= 1); } +}; + +HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize) +{ + Byte h[kHeaderSize]; + RINOK(ReadStream_FALSE(s, h, kHeaderSize)); + if (GetUi32(h) != kSignature) + return S_FALSE; + Attrib = GetUi32(h + 4); + Time = GetUi32(h + 12); + + unsigned info = GetUi16(h + 8); + Order = (info & 0xF) + 1; + MemInMB = ((info >> 4) & 0xFF) + 1; + Ver = info >> 12; + + UInt32 nameLen = GetUi16(h + 10); + Restor = nameLen >> 14; + if (Restor > 2) + return S_FALSE; + if (Ver >= kNewHeaderVer) + nameLen &= 0x3FFF; + if (nameLen > (1 << 9)) + return S_FALSE; + char *name = Name.GetBuffer(nameLen + 1); + HRESULT res = ReadStream_FALSE(s, name, nameLen); + name[nameLen] = 0; + headerSize = kHeaderSize + nameLen; + Name.ReleaseBuffer(); + return res; +} + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + public CMyUnknownImp +{ + CItem _item; + UInt32 _headerSize; + UInt64 _packSize; + bool _packSizeDefined; + CMyComPtr<ISequentialInStream> _stream; + +public: + MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq) + INTERFACE_IInArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); +}; + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidMethod, VT_BSTR} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + } + prop.Detach(value); + return S_OK; +} + + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +static void UIntToString(AString &s, const char *prefix, unsigned value) +{ + s += prefix; + char temp[16]; + ::ConvertUInt32ToString((UInt32)value, temp); + s += temp; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidPath: prop = MultiByteToUnicodeString(_item.Name, CP_ACP); break; + case kpidMTime: + { + FILETIME utc; + if (NTime::DosTimeToFileTime(_item.Time, utc)) + prop = utc; + break; + } + case kpidAttrib: prop = _item.Attrib; break; + case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidMethod: + { + AString s = "PPMd"; + s += (char)('A' + _item.Ver); + UIntToString(s, ":o", _item.Order); + UIntToString(s, ":mem", _item.MemInMB); + s += 'm'; + if (_item.Ver >= kNewHeaderVer && _item.Restor != 0) + UIntToString(s, ":r", _item.Restor); + prop = s; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *) +{ + return OpenSeq(stream); +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + COM_TRY_BEGIN + HRESULT res; + try + { + Close(); + res = _item.ReadHeader(stream, _headerSize); + } + catch(...) { res = S_FALSE; } + if (res == S_OK) + _stream = stream; + else + Close(); + return res; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _packSizeDefined = false; + _stream.Release(); + return S_OK; +} + +static const UInt32 kTopValue = (1 << 24); +static const UInt32 kBot = (1 << 15); + +struct CRangeDecoder +{ + IPpmd7_RangeDec s; + UInt32 Range; + UInt32 Code; + UInt32 Low; + CByteInBufWrap *Stream; + +public: + bool Init() + { + Code = 0; + Low = 0; + Range = 0xFFFFFFFF; + for (int i = 0; i < 4; i++) + Code = (Code << 8) | Stream->ReadByte(); + return Code < 0xFFFFFFFF; + } + + void Normalize() + { + while ((Low ^ (Low + Range)) < kTopValue || + Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1)) + { + Code = (Code << 8) | Stream->ReadByte(); + Range <<= 8; + Low <<= 8; + } + } + + CRangeDecoder(); +}; + + +extern "C" { + +static UInt32 Range_GetThreshold(void *pp, UInt32 total) +{ + CRangeDecoder *p = (CRangeDecoder *)pp; + return p->Code / (p->Range /= total); +} + +static void Range_Decode(void *pp, UInt32 start, UInt32 size) +{ + CRangeDecoder *p = (CRangeDecoder *)pp; + start *= p->Range; + p->Low += start; + p->Code -= start; + p->Range *= size; + p->Normalize(); +} + +static UInt32 Range_DecodeBit(void *pp, UInt32 size0) +{ + CRangeDecoder *p = (CRangeDecoder *)pp; + if (p->Code / (p->Range >>= 14) < size0) + { + Range_Decode(p, 0, size0); + return 0; + } + else + { + Range_Decode(p, size0, (1 << 14) - size0); + return 1; + } +} + +} + +CRangeDecoder::CRangeDecoder() +{ + s.GetThreshold = Range_GetThreshold; + s.Decode = Range_Decode; + s.DecodeBit = Range_DecodeBit; +} + +struct CPpmdCpp +{ + unsigned Ver; + CRangeDecoder _rc; + CPpmd7 _ppmd7; + CPpmd8 _ppmd8; + + CPpmdCpp(unsigned version) + { + Ver = version; + Ppmd7_Construct(&_ppmd7); + Ppmd8_Construct(&_ppmd8); + } + + ~CPpmdCpp() + { + Ppmd7_Free(&_ppmd7, &g_BigAlloc); + Ppmd8_Free(&_ppmd8, &g_BigAlloc); + } + + bool Alloc(UInt32 memInMB) + { + memInMB <<= 20; + if (Ver == 7) + return Ppmd7_Alloc(&_ppmd7, memInMB, &g_BigAlloc) != 0; + return Ppmd8_Alloc(&_ppmd8, memInMB, &g_BigAlloc) != 0; + } + + void Init(unsigned order, unsigned restor) + { + if (Ver == 7) + Ppmd7_Init(&_ppmd7, order); + else + Ppmd8_Init(&_ppmd8, order, restor);; + } + + bool InitRc(CByteInBufWrap *inStream) + { + if (Ver == 7) + { + _rc.Stream = inStream; + return _rc.Init(); + } + else + { + _ppmd8.Stream.In = &inStream->p; + return Ppmd8_RangeDec_Init(&_ppmd8) != 0; + } + } + + bool IsFinishedOK() + { + if (Ver == 7) + return Ppmd7z_RangeDec_IsFinishedOK(&_rc); + return Ppmd8_RangeDec_IsFinishedOK(&_ppmd8); + } +}; + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + if (numItems == 0) + return S_OK; + if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + // extractCallback->SetTotal(_packSize); + UInt64 currentTotalPacked = 0; + RINOK(extractCallback->SetCompleted(¤tTotalPacked)); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); + if (!testMode && !realOutStream) + return S_OK; + + extractCallback->PrepareOperation(askMode); + + CByteInBufWrap inBuf; + if (!inBuf.Alloc(1 << 20)) + return E_OUTOFMEMORY; + inBuf.Stream = _stream; + + CBuf outBuf; + if (!outBuf.Alloc()) + return E_OUTOFMEMORY; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, true); + + CPpmdCpp ppmd(_item.Ver); + if (!ppmd.Alloc(_item.MemInMB)) + return E_OUTOFMEMORY; + Int32 opRes = NExtract::NOperationResult::kUnSupportedMethod; + if (_item.IsSupported()) + { + opRes = NExtract::NOperationResult::kDataError; + ppmd.Init(_item.Order, _item.Restor); + inBuf.Init(); + UInt64 outSize = 0; + if (ppmd.InitRc(&inBuf) && !inBuf.Extra && inBuf.Res == S_OK) + for (;;) + { + lps->InSize = _packSize = inBuf.GetProcessed(); + lps->OutSize = outSize; + RINOK(lps->SetCur()); + + size_t i; + int sym = 0; + + if (ppmd.Ver == 7) + { + for (i = 0; i < kBufSize; i++) + { + sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.s); + if (inBuf.Extra || sym < 0) + break; + outBuf.Buf[i] = (Byte)sym; + } + } + else + { + for (i = 0; i < kBufSize; i++) + { + sym = Ppmd8_DecodeSymbol(&ppmd._ppmd8); + if (inBuf.Extra || sym < 0) + break; + outBuf.Buf[i] = (Byte)sym; + } + } + + outSize += i; + _packSize = _headerSize + inBuf.GetProcessed(); + _packSizeDefined = true; + if (realOutStream) + { + RINOK(WriteStream(realOutStream, outBuf.Buf, i)); + } + if (sym < 0) + { + if (sym == -1 && ppmd.IsFinishedOK()) + opRes = NExtract::NOperationResult::kOK; + break; + } + } + RINOK(inBuf.Res); + } + realOutStream.Release(); + return extractCallback->SetOperationResult(opRes); +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = + { L"Ppmd", L"pmd", 0, 0xD, { 0x8F, 0xAF, 0xAC, 0x84 }, 4, false, CreateArc, 0 }; + +REGISTER_ARC(Ppmd) + +}} diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index 0a74a3d1..7fed3cab 100755 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -15,6 +15,7 @@ #include "../../Common/StreamUtils.h" #include "../../Compress/LzmaEncoder.h" +#include "../../Compress/PpmdZip.h" #include "../Common/InStreamWithCRC.h" @@ -169,13 +170,14 @@ HRESULT CAddCommon::Compress( else { if (!_cryptoStreamSpec->Filter) + { _cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder; - RINOK(_filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length())); + _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length()); + } UInt32 crc = 0; RINOK(GetStreamCRC(inStream, crc)); RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL)); - RINOK(_filterSpec->CryptoSetCRC(crc)); - RINOK(_filterSpec->WriteHeader(outStream)); + RINOK(_filterSpec->WriteHeader(outStream, crc)); } RINOK(_cryptoStreamSpec->SetOutStream(outStream)); outStreamReleaser.FilterCoder = _cryptoStreamSpec; @@ -235,6 +237,26 @@ HRESULT CAddCommon::Compress( 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 { CMethodId methodId; diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h index e5acfa6b..7ef7cfb2 100755 --- a/CPP/7zip/Archive/Zip/ZipCompressionMode.h +++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h @@ -18,6 +18,9 @@ struct CCompressionMethodMode bool NumMatchFinderCyclesDefined; UInt32 NumMatchFinderCycles; UInt32 DicSize; + UInt32 MemSize; + UInt32 Order; + #ifndef _7ZIP_ST UInt32 NumThreads; #endif diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index df1ca20b..64477766 100755 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -18,6 +18,7 @@ #include "../../Compress/CopyCoder.h" #include "../../Compress/LzmaDecoder.h" #include "../../Compress/ImplodeDecoder.h" +#include "../../Compress/PpmdZip.h" #include "../../Compress/ShrinkDecoder.h" #include "../../Crypto/WzAes.h" @@ -595,6 +596,8 @@ HRESULT CZipDecoder::Decode( mi.Coder = new NCompress::NImplode::NDecoder::CCoder; else if (methodId == NFileHeader::NCompressionMethod::kLZMA) mi.Coder = new CLzmaDecoder; + else if (methodId == NFileHeader::NCompressionMethod::kPPMd) + mi.Coder = new NCompress::NPpmdZip::CDecoder(true); else { CMethodId szMethodID; diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h index 6236b20c..55ebff25 100755 --- a/CPP/7zip/Archive/Zip/ZipHandler.h +++ b/CPP/7zip/Archive/Zip/ZipHandler.h @@ -53,6 +53,9 @@ private: UInt32 m_NumPasses; UInt32 m_NumFastBytes; UInt32 m_NumMatchFinderCycles; + UInt32 m_MemSize; + UInt32 m_Order; + bool m_NumMatchFinderCyclesDefined; bool m_ForceAesMode; @@ -77,6 +80,8 @@ private: m_DicSize = m_NumPasses = m_NumFastBytes = + m_Order = + m_MemSize = m_NumMatchFinderCycles = 0xFFFFFFFF; m_NumMatchFinderCyclesDefined = false; m_ForceAesMode = false; diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp index 3571fdeb..b190dd2f 100755 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -51,6 +51,18 @@ static const UInt32 kLzmaDicSizeX5 = 1 << 24; static const UInt32 kLzmaDicSizeX7 = 1 << 25; static const UInt32 kLzmaDicSizeX9 = 1 << 26; +static const UInt32 kPpmdMemSizeX1 = (1 << 20); +static const UInt32 kPpmdMemSizeX3 = (1 << 22); +static const UInt32 kPpmdMemSizeX5 = (1 << 24); +static const UInt32 kPpmdMemSizeX7 = (1 << 26); +static const UInt32 kPpmdMemSizeX9 = (1 << 27); + +static const UInt32 kPpmdOrderX1 = 4; +static const UInt32 kPpmdOrderX3 = 6; +static const UInt32 kPpmdOrderX5 = 8; +static const UInt32 kPpmdOrderX7 = 10; +static const UInt32 kPpmdOrderX9 = 16; + static const UInt32 kBZip2NumPassesX1 = 1; static const UInt32 kBZip2NumPassesX7 = 2; static const UInt32 kBZip2NumPassesX9 = 7; @@ -290,13 +302,14 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt (mainMethod == NFileHeader::NCompressionMethod::kDeflated64); bool isLZMA = (mainMethod == NFileHeader::NCompressionMethod::kLZMA); bool isLz = (isLZMA || isDeflate); - bool isBZip2 = (mainMethod == NFileHeader::NCompressionMethod::kBZip2); 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 @@ -336,7 +349,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt options.Algo = (level >= 5 ? kLzAlgoX5 : kLzAlgoX1); } - if (isBZip2) + if (mainMethod == NFileHeader::NCompressionMethod::kBZip2) { if (options.NumPasses == 0xFFFFFFFF) options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 : @@ -347,6 +360,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt (level >= 3 ? kBZip2DicSizeX3 : kBZip2DicSizeX1)); } + if (mainMethod == NFileHeader::NCompressionMethod::kPPMd) + { + if (options.MemSize == 0xFFFFFFFF) + options.MemSize = + (level >= 9 ? kPpmdMemSizeX9 : + (level >= 7 ? kPpmdMemSizeX7 : + (level >= 5 ? kPpmdMemSizeX5 : + (level >= 3 ? kPpmdMemSizeX3 : + kPpmdMemSizeX1)))); + + if (options.Order == 0xFFFFFFFF) + options.Order = + (level >= 9 ? kPpmdOrderX9 : + (level >= 7 ? kPpmdOrderX7 : + (level >= 5 ? kPpmdOrderX5 : + (level >= 3 ? kPpmdOrderX3 : + kPpmdOrderX1)))); + + options.Algo = 0; + } return Update( EXTERNAL_CODECS_VARS @@ -389,6 +422,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v 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; } else if (prop.vt == VT_UI4) @@ -446,6 +480,18 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize)); m_DicSize = dicSize; } + else if (name.Left(3) == L"MEM") + { + UInt32 memSize = kPpmdMemSizeX5; + RINOK(ParsePropDictionaryValue(name.Mid(3), prop, memSize)); + m_MemSize = memSize; + } + else if (name[0] == L'O') + { + UInt32 order = kPpmdOrderX5; + RINOK(ParsePropValue(name.Mid(1), prop, order)); + m_Order = order; + } else if (name.Left(4) == L"PASS") { UInt32 num = kDeflateNumPassesX9; diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h index 1233af6c..eeff5980 100755 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -89,6 +89,7 @@ namespace NFileHeader const Byte kExtractVersion_BZip2 = 46; const Byte kExtractVersion_Aes = 51; const Byte kExtractVersion_LZMA = 63; + const Byte kExtractVersion_PPMd = 63; // const Byte kSupportedVersion = 20; } |