Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2010-03-15 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:02 +0300
commit993daef9cbed7febf494217f07e40e0a26b3bc06 (patch)
tree41db24cb11222422aa3c4d61b80646344e3efefc /CPP/7zip/Archive
parentdb5eb6d638f5a5ec10517ed4a994b849a6cc7d29 (diff)
9.119.11
Diffstat (limited to 'CPP/7zip/Archive')
-rwxr-xr-xCPP/7zip/Archive/Com/ComHandler.cpp1
-rwxr-xr-xCPP/7zip/Archive/Com/ComIn.cpp34
-rwxr-xr-xCPP/7zip/Archive/Com/ComIn.h2
-rwxr-xr-xCPP/7zip/Archive/DebHandler.cpp30
-rwxr-xr-xCPP/7zip/Archive/PeHandler.cpp56
-rwxr-xr-xCPP/7zip/Archive/PpmdHandler.cpp456
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipAddCommon.cpp28
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipCompressionMode.h3
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandler.cpp3
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandler.h5
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandlerOut.cpp50
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHeader.h1
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 &sect = _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(&currentTotalPacked));
+ 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;
}