mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 21:14:58 -06:00
4.61 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
c10e6b16f6
commit
b717a4dbfe
@@ -9,34 +9,6 @@
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
/*
|
||||
static HRESULT ReadBytes(IInStream *inStream, void *data, UInt32 size)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
RINOK(ReadStream(inStream, data, size, &realProcessedSize));
|
||||
if(realProcessedSize != size)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT SafeRead(IInStream *inStream, void *data, UInt32 size)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
RINOK(ReadStream(inStream, data, size, &realProcessedSize));
|
||||
if(realProcessedSize != size)
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void SafeInByteRead(::CInBuffer &inBuffer, void *data, UInt32 size)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
inBuffer.ReadBytes(data, size, realProcessedSize);
|
||||
if(realProcessedSize != size)
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
}
|
||||
*/
|
||||
|
||||
Byte CInArchive::ReadByte()
|
||||
{
|
||||
Byte b;
|
||||
@@ -107,43 +79,43 @@ HRESULT CInArchive::Open2(IInStream *stream,
|
||||
inBuffer.SetStream(stream);
|
||||
inBuffer.Init();
|
||||
|
||||
CInArchiveInfo &archiveInfo = database.ArchiveInfo;
|
||||
CInArchiveInfo &ai = database.ArchiveInfo;
|
||||
|
||||
archiveInfo.Size = ReadUInt32(); // size of this cabinet file in bytes
|
||||
ai.Size = ReadUInt32();
|
||||
if (ReadUInt32() != 0)
|
||||
return S_FALSE;
|
||||
archiveInfo.FileHeadersOffset = ReadUInt32(); // offset of the first CFFILE entry
|
||||
ai.FileHeadersOffset = ReadUInt32();
|
||||
if (ReadUInt32() != 0)
|
||||
return S_FALSE;
|
||||
|
||||
archiveInfo.VersionMinor = ReadByte(); // cabinet file format version, minor
|
||||
archiveInfo.VersionMajor = ReadByte(); // cabinet file format version, major
|
||||
archiveInfo.NumFolders = ReadUInt16(); // number of CFFOLDER entries in this cabinet
|
||||
archiveInfo.NumFiles = ReadUInt16(); // number of CFFILE entries in this cabinet
|
||||
archiveInfo.Flags = ReadUInt16();
|
||||
if (archiveInfo.Flags > 7)
|
||||
ai.VersionMinor = ReadByte();
|
||||
ai.VersionMajor = ReadByte();
|
||||
ai.NumFolders = ReadUInt16();
|
||||
ai.NumFiles = ReadUInt16();
|
||||
ai.Flags = ReadUInt16();
|
||||
if (ai.Flags > 7)
|
||||
return S_FALSE;
|
||||
archiveInfo.SetID = ReadUInt16(); // must be the same for all cabinets in a set
|
||||
archiveInfo.CabinetNumber = ReadUInt16(); // number of this cabinet file in a set
|
||||
ai.SetID = ReadUInt16();
|
||||
ai.CabinetNumber = ReadUInt16();
|
||||
|
||||
if (archiveInfo.ReserveBlockPresent())
|
||||
if (ai.ReserveBlockPresent())
|
||||
{
|
||||
archiveInfo.PerCabinetAreaSize = ReadUInt16(); // (optional) size of per-cabinet reserved area
|
||||
archiveInfo.PerFolderAreaSize = ReadByte(); // (optional) size of per-folder reserved area
|
||||
archiveInfo.PerDataBlockAreaSize = ReadByte(); // (optional) size of per-datablock reserved area
|
||||
ai.PerCabinetAreaSize = ReadUInt16();
|
||||
ai.PerFolderAreaSize = ReadByte();
|
||||
ai.PerDataBlockAreaSize = ReadByte();
|
||||
|
||||
Skeep(archiveInfo.PerCabinetAreaSize);
|
||||
Skeep(ai.PerCabinetAreaSize);
|
||||
}
|
||||
|
||||
{
|
||||
if (archiveInfo.IsTherePrev())
|
||||
ReadOtherArchive(archiveInfo.PreviousArchive);
|
||||
if (archiveInfo.IsThereNext())
|
||||
ReadOtherArchive(archiveInfo.NextArchive);
|
||||
if (ai.IsTherePrev())
|
||||
ReadOtherArchive(ai.PreviousArchive);
|
||||
if (ai.IsThereNext())
|
||||
ReadOtherArchive(ai.NextArchive);
|
||||
}
|
||||
|
||||
int i;
|
||||
for(i = 0; i < archiveInfo.NumFolders; i++)
|
||||
for (i = 0; i < ai.NumFolders; i++)
|
||||
{
|
||||
CFolder folder;
|
||||
|
||||
@@ -152,15 +124,15 @@ HRESULT CInArchive::Open2(IInStream *stream,
|
||||
folder.CompressionTypeMajor = ReadByte();
|
||||
folder.CompressionTypeMinor = ReadByte();
|
||||
|
||||
Skeep(archiveInfo.PerFolderAreaSize);
|
||||
Skeep(ai.PerFolderAreaSize);
|
||||
database.Folders.Add(folder);
|
||||
}
|
||||
|
||||
RINOK(stream->Seek(database.StartPosition + archiveInfo.FileHeadersOffset, STREAM_SEEK_SET, NULL));
|
||||
RINOK(stream->Seek(database.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL));
|
||||
|
||||
inBuffer.SetStream(stream);
|
||||
inBuffer.Init();
|
||||
for(i = 0; i < archiveInfo.NumFiles; i++)
|
||||
for (i = 0; i < ai.NumFiles; i++)
|
||||
{
|
||||
CItem item;
|
||||
item.Size = ReadUInt32();
|
||||
@@ -224,16 +196,10 @@ bool CMvDatabaseEx::AreItemsEqual(int i1, int i2)
|
||||
const CDatabaseEx &db2 = Volumes[p2->VolumeIndex];
|
||||
const CItem &item1 = db1.Items[p1->ItemIndex];
|
||||
const CItem &item2 = db2.Items[p2->ItemIndex];;
|
||||
int f1 = GetFolderIndex(p1);
|
||||
int f2 = GetFolderIndex(p2);
|
||||
if (f1 != f2)
|
||||
return false;
|
||||
if (item1.Offset != item2.Offset)
|
||||
return false;
|
||||
if (item1.Size != item2.Size)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return GetFolderIndex(p1) == GetFolderIndex(p2) &&
|
||||
item1.Offset == item2.Offset &&
|
||||
item1.Size == item2.Size &&
|
||||
item1.Name == item2.Name;
|
||||
}
|
||||
|
||||
void CMvDatabaseEx::FillSortAndShrink()
|
||||
@@ -296,7 +262,7 @@ bool CMvDatabaseEx::Check()
|
||||
}
|
||||
UInt64 maxPos = 0;
|
||||
int prevFolder = -2;
|
||||
for(int i = 0; i < Items.Size(); i++)
|
||||
for (int i = 0; i < Items.Size(); i++)
|
||||
{
|
||||
const CMvItem &mvItem = Items[i];
|
||||
int fIndex = GetFolderIndex(&mvItem);
|
||||
|
||||
@@ -31,13 +31,13 @@ struct COtherArchive
|
||||
|
||||
struct CArchiveInfo
|
||||
{
|
||||
Byte VersionMinor; /* cabinet file format version, minor */
|
||||
Byte VersionMajor; /* cabinet file format version, major */
|
||||
UInt16 NumFolders; /* number of CFFOLDER entries in this cabinet */
|
||||
UInt16 NumFiles; /* number of CFFILE entries in this cabinet */
|
||||
UInt16 Flags; /* cabinet file option indicators */
|
||||
UInt16 SetID; /* must be the same for all cabinets in a set */
|
||||
UInt16 CabinetNumber; /* number of this cabinet file in a set */
|
||||
Byte VersionMinor; /* cabinet file format version, minor */
|
||||
Byte VersionMajor; /* cabinet file format version, major */
|
||||
UInt16 NumFolders; /* number of CFFOLDER entries in this cabinet */
|
||||
UInt16 NumFiles; /* number of CFFILE entries in this cabinet */
|
||||
UInt16 Flags; /* cabinet file option indicators */
|
||||
UInt16 SetID; /* must be the same for all cabinets in a set */
|
||||
UInt16 CabinetNumber; /* number of this cabinet file in a set */
|
||||
|
||||
bool ReserveBlockPresent() const { return (Flags & NHeader::NArchive::NFlags::kReservePresent) != 0; }
|
||||
|
||||
|
||||
@@ -346,10 +346,8 @@ HRESULT CInArchive::Open2()
|
||||
Clear();
|
||||
RINOK(_stream->Seek(kStartPos, STREAM_SEEK_CUR, &_position));
|
||||
|
||||
bool primVolDescDefined = false;
|
||||
m_BufferPos = 0;
|
||||
BlockSize = kBlockSize;
|
||||
VolDescs.Add(CVolumeDescriptor());
|
||||
for (;;)
|
||||
{
|
||||
Byte sig[7];
|
||||
@@ -396,42 +394,33 @@ HRESULT CInArchive::Open2()
|
||||
break;
|
||||
}
|
||||
case NVolDescType::kPrimaryVol:
|
||||
{
|
||||
if (primVolDescDefined)
|
||||
return S_FALSE;
|
||||
primVolDescDefined = true;
|
||||
CVolumeDescriptor &volDesc = VolDescs[0];
|
||||
ReadVolumeDescriptor(volDesc);
|
||||
// some burners write "Joliet" Escape Sequence to primary volume
|
||||
memset(volDesc.EscapeSequence, 0, sizeof(volDesc.EscapeSequence));
|
||||
break;
|
||||
}
|
||||
case NVolDescType::kSupplementaryVol:
|
||||
{
|
||||
CVolumeDescriptor sd;
|
||||
ReadVolumeDescriptor(sd);
|
||||
VolDescs.Add(sd);
|
||||
// some ISOs have two PrimaryVols.
|
||||
CVolumeDescriptor vd;
|
||||
ReadVolumeDescriptor(vd);
|
||||
if (sig[0] == NVolDescType::kPrimaryVol)
|
||||
{
|
||||
// some burners write "Joliet" Escape Sequence to primary volume
|
||||
memset(vd.EscapeSequence, 0, sizeof(vd.EscapeSequence));
|
||||
}
|
||||
VolDescs.Add(vd);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
MainVolDescIndex = 0;
|
||||
if (!primVolDescDefined)
|
||||
if (VolDescs.IsEmpty())
|
||||
return S_FALSE;
|
||||
for (int i = VolDescs.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (VolDescs[i].IsJoliet())
|
||||
{
|
||||
MainVolDescIndex = i;
|
||||
for (MainVolDescIndex = VolDescs.Size() - 1; MainVolDescIndex > 0; MainVolDescIndex--)
|
||||
if (VolDescs[MainVolDescIndex].IsJoliet())
|
||||
break;
|
||||
}
|
||||
}
|
||||
// MainVolDescIndex = 0; // to read primary volume
|
||||
if (VolDescs[MainVolDescIndex].LogicalBlockSize != kBlockSize)
|
||||
const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex];
|
||||
if (vd.LogicalBlockSize != kBlockSize)
|
||||
return S_FALSE;
|
||||
(CDirRecord &)_rootDir = VolDescs[MainVolDescIndex].RootDirRecord;
|
||||
(CDirRecord &)_rootDir = vd.RootDirRecord;
|
||||
ReadDir(_rootDir, 0);
|
||||
CreateRefs(_rootDir);
|
||||
ReadBootInfo();
|
||||
|
||||
@@ -264,6 +264,9 @@ struct CSection
|
||||
void Parse(const Byte *p);
|
||||
};
|
||||
|
||||
static bool operator <(const CSection &a1, const CSection &a2) { return (a1.Pa < a2.Pa); }
|
||||
static bool operator ==(const CSection &a1, const CSection &a2) { return (a1.Pa == a2.Pa); }
|
||||
|
||||
static AString GetName(const Byte *name)
|
||||
{
|
||||
const int kNameSize = 8;
|
||||
@@ -726,6 +729,34 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
if (fileSize > _totalSize)
|
||||
return S_FALSE;
|
||||
_totalSizeLimited = (_totalSize < fileSize) ? _totalSize : (UInt32)fileSize;
|
||||
|
||||
{
|
||||
CObjectVector<CSection> sections = _sections;
|
||||
sections.Sort();
|
||||
UInt32 limit = (1 << 12);
|
||||
int num = 0;
|
||||
for (int i = 0; i < sections.Size(); i++)
|
||||
{
|
||||
const CSection &s = sections[i];
|
||||
if (s.Pa > limit)
|
||||
{
|
||||
CSection s2;
|
||||
s2.Pa = s2.Va = limit;
|
||||
s2.PSize = s2.VSize = s.Pa - limit;
|
||||
char sz[32];
|
||||
ConvertUInt64ToString(++num, sz);
|
||||
s2.Name = "[data-";
|
||||
s2.Name += sz;
|
||||
s2.Name += "]";
|
||||
_sections.Add(s2);
|
||||
}
|
||||
UInt32 next = s.Pa + s.PSize;
|
||||
if (next < limit)
|
||||
break;
|
||||
limit = next;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,13 @@ extern "C"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/Defs.h"
|
||||
#include "../../MyVersion.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../../IPassword.h"
|
||||
#include "../../Common/CreateCoder.h"
|
||||
#include "../../Common/StreamObjects.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
#include "../../Compress/LZMA/LZMAEncoder.h"
|
||||
#include "../Common/InStreamWithCRC.h"
|
||||
|
||||
#include "ZipAddCommon.h"
|
||||
@@ -23,11 +27,59 @@ namespace NZip {
|
||||
static const CMethodId kMethodId_ZipBase = 0x040100;
|
||||
static const CMethodId kMethodId_BZip2 = 0x040202;
|
||||
|
||||
static const UInt32 kLzmaPropsSize = 5;
|
||||
static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize;
|
||||
|
||||
class CLzmaEncoder:
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
NCompress::NLZMA::CEncoder *EncoderSpec;
|
||||
CMyComPtr<ICompressCoder> Encoder;
|
||||
Byte Header[kLzmaHeaderSize];
|
||||
public:
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
};
|
||||
|
||||
HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
|
||||
{
|
||||
if (!Encoder)
|
||||
{
|
||||
EncoderSpec = new NCompress::NLZMA::CEncoder;
|
||||
Encoder = EncoderSpec;
|
||||
}
|
||||
CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
outStreamSpec->Init();
|
||||
RINOK(EncoderSpec->SetCoderProperties(propIDs, props, numProps));
|
||||
RINOK(EncoderSpec->WriteCoderProperties(outStream));
|
||||
if (outStreamSpec->GetSize() != kLzmaPropsSize)
|
||||
return E_FAIL;
|
||||
Header[0] = MY_VER_MAJOR;
|
||||
Header[1] = MY_VER_MINOR;
|
||||
Header[2] = kLzmaPropsSize;
|
||||
Header[3] = 0;
|
||||
memcpy(Header + 4, outStreamSpec->GetBuffer(), kLzmaPropsSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
RINOK(WriteStream(outStream, Header, kLzmaHeaderSize));
|
||||
return Encoder->Code(inStream, outStream, inSize, outSize, progress);
|
||||
}
|
||||
|
||||
|
||||
CAddCommon::CAddCommon(const CCompressionMethodMode &options):
|
||||
_options(options),
|
||||
_copyCoderSpec(NULL),
|
||||
_cryptoStreamSpec(0)
|
||||
{}
|
||||
{}
|
||||
|
||||
static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
|
||||
{
|
||||
@@ -38,7 +90,7 @@ static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
RINOK(inStream->Read(buffer, kBufferSize, &realProcessedSize));
|
||||
if(realProcessedSize == 0)
|
||||
if (realProcessedSize == 0)
|
||||
{
|
||||
resultCRC = CRC_GET_DIGEST(crc);
|
||||
return S_OK;
|
||||
@@ -87,7 +139,7 @@ HRESULT CAddCommon::Compress(
|
||||
}
|
||||
Byte method = 0;
|
||||
COutStreamReleaser outStreamReleaser;
|
||||
for(int i = 0; i < numTestMethods; i++)
|
||||
for (int i = 0; i < numTestMethods; i++)
|
||||
{
|
||||
if (inCrcStreamSpec != 0)
|
||||
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
@@ -127,7 +179,7 @@ HRESULT CAddCommon::Compress(
|
||||
{
|
||||
case NFileHeader::NCompressionMethod::kStored:
|
||||
{
|
||||
if(_copyCoderSpec == NULL)
|
||||
if (_copyCoderSpec == NULL)
|
||||
{
|
||||
_copyCoderSpec = new NCompress::CCopyCoder;
|
||||
_copyCoder = _copyCoderSpec;
|
||||
@@ -143,8 +195,41 @@ HRESULT CAddCommon::Compress(
|
||||
}
|
||||
default:
|
||||
{
|
||||
if(!_compressEncoder)
|
||||
if (!_compressEncoder)
|
||||
{
|
||||
if (method == NFileHeader::NCompressionMethod::kLZMA)
|
||||
{
|
||||
CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder();
|
||||
_compressEncoder = _lzmaEncoder;
|
||||
NWindows::NCOM::CPropVariant props[] =
|
||||
{
|
||||
#ifdef COMPRESS_MT
|
||||
_options.NumThreads,
|
||||
#endif
|
||||
_options.Algo,
|
||||
_options.DicSize,
|
||||
_options.NumFastBytes,
|
||||
(BSTR)(const wchar_t *)_options.MatchFinder,
|
||||
_options.NumMatchFinderCycles
|
||||
};
|
||||
PROPID propIDs[] =
|
||||
{
|
||||
#ifdef COMPRESS_MT
|
||||
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
|
||||
{
|
||||
CMethodId methodId;
|
||||
switch(method)
|
||||
{
|
||||
@@ -164,7 +249,7 @@ HRESULT CAddCommon::Compress(
|
||||
if (method == NFileHeader::NCompressionMethod::kDeflated ||
|
||||
method == NFileHeader::NCompressionMethod::kDeflated64)
|
||||
{
|
||||
NWindows::NCOM::CPropVariant properties[] =
|
||||
NWindows::NCOM::CPropVariant props[] =
|
||||
{
|
||||
_options.Algo,
|
||||
_options.NumPasses,
|
||||
@@ -185,12 +270,12 @@ HRESULT CAddCommon::Compress(
|
||||
_compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);
|
||||
if (setCoderProperties)
|
||||
{
|
||||
RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, numProps));
|
||||
RINOK(setCoderProperties->SetCoderProperties(propIDs, props, numProps));
|
||||
}
|
||||
}
|
||||
else if (method == NFileHeader::NCompressionMethod::kBZip2)
|
||||
{
|
||||
NWindows::NCOM::CPropVariant properties[] =
|
||||
NWindows::NCOM::CPropVariant props[] =
|
||||
{
|
||||
_options.DicSize,
|
||||
_options.NumPasses
|
||||
@@ -210,9 +295,10 @@ HRESULT CAddCommon::Compress(
|
||||
_compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);
|
||||
if (setCoderProperties)
|
||||
{
|
||||
RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0])));
|
||||
RINOK(setCoderProperties->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CMyComPtr<ISequentialOutStream> outStreamNew;
|
||||
if (_options.PasswordIsDefined)
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace NZip {
|
||||
struct CCompressionMethodMode
|
||||
{
|
||||
CRecordVector<Byte> MethodSequence;
|
||||
// bool MaximizeRatio;
|
||||
UString MatchFinder;
|
||||
UInt32 Algo;
|
||||
UInt32 NumPasses;
|
||||
UInt32 NumFastBytes;
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/StreamObjects.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
#include "../../Common/CreateCoder.h"
|
||||
#include "../../Common/FilterCoder.h"
|
||||
|
||||
#include "../../Compress/Copy/CopyCoder.h"
|
||||
#include "../../Compress/LZMA/LZMADecoder.h"
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
#include "../Common/OutStreamWithCRC.h"
|
||||
@@ -108,13 +110,13 @@ const wchar_t *kMethods[] =
|
||||
L"Tokenizing",
|
||||
L"Deflate",
|
||||
L"Deflate64",
|
||||
L"PKImploding",
|
||||
L"Unknown",
|
||||
L"BZip2"
|
||||
L"PKImploding"
|
||||
};
|
||||
|
||||
const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
|
||||
// const wchar_t *kUnknownMethod = L"Unknown";
|
||||
const wchar_t *kBZip2Method = L"BZip2";
|
||||
const wchar_t *kLZMAMethod = L"LZMA";
|
||||
const wchar_t *kJpegMethod = L"Jpeg";
|
||||
const wchar_t *kWavPackMethod = L"WavPack";
|
||||
const wchar_t *kPPMdMethod = L"PPMd";
|
||||
const wchar_t *kAESMethod = L"AES";
|
||||
@@ -294,15 +296,23 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
}
|
||||
if (methodId < kNumMethods)
|
||||
method += kMethods[methodId];
|
||||
else if (methodId == NFileHeader::NCompressionMethod::kPPMd)
|
||||
method += kPPMdMethod;
|
||||
else if (methodId == NFileHeader::NCompressionMethod::kWavPack)
|
||||
method += kWavPackMethod;
|
||||
else
|
||||
else switch (methodId)
|
||||
{
|
||||
wchar_t s[32];
|
||||
ConvertUInt64ToString(methodId, s);
|
||||
method += s;
|
||||
case NFileHeader::NCompressionMethod::kLZMA:
|
||||
method += kLZMAMethod;
|
||||
if (item.IsLzmaEOS())
|
||||
method += L":EOS";
|
||||
break;
|
||||
case NFileHeader::NCompressionMethod::kBZip2: method += kBZip2Method; break;
|
||||
case NFileHeader::NCompressionMethod::kJpeg: method += kJpegMethod; break;
|
||||
case NFileHeader::NCompressionMethod::kWavPack: method += kWavPackMethod; break;
|
||||
case NFileHeader::NCompressionMethod::kPPMd: method += kPPMdMethod; break;
|
||||
default:
|
||||
{
|
||||
wchar_t s[32];
|
||||
ConvertUInt64ToString(methodId, s);
|
||||
method += s;
|
||||
}
|
||||
}
|
||||
prop = method;
|
||||
break;
|
||||
@@ -367,6 +377,37 @@ STDMETHODIMP CHandler::Close()
|
||||
//////////////////////////////////////
|
||||
// CHandler::DecompressItems
|
||||
|
||||
class CLzmaDecoder:
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
NCompress::NLZMA::CDecoder *DecoderSpec;
|
||||
CMyComPtr<ICompressCoder> Decoder;
|
||||
public:
|
||||
CLzmaDecoder();
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
};
|
||||
|
||||
CLzmaDecoder::CLzmaDecoder()
|
||||
{
|
||||
DecoderSpec = new NCompress::NLZMA::CDecoder;
|
||||
Decoder = DecoderSpec;
|
||||
}
|
||||
|
||||
HRESULT CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
Byte buf[9];
|
||||
RINOK(ReadStream_FALSE(inStream, buf, 9));
|
||||
if (buf[2] != 5 || buf[3] != 0)
|
||||
return E_NOTIMPL;
|
||||
RINOK(DecoderSpec->SetDecoderProperties2(buf + 4, 5));
|
||||
return Decoder->Code(inStream, outStream, NULL, outSize, progress);
|
||||
}
|
||||
|
||||
struct CMethodItem
|
||||
{
|
||||
UInt16 ZipMethod;
|
||||
@@ -568,6 +609,8 @@ HRESULT CZipDecoder::Decode(
|
||||
mi.Coder = new NCompress::NShrink::CDecoder;
|
||||
else if (methodId == NFileHeader::NCompressionMethod::kImploded)
|
||||
mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
|
||||
else if (methodId == NFileHeader::NCompressionMethod::kLZMA)
|
||||
mi.Coder = new CLzmaDecoder;
|
||||
else
|
||||
{
|
||||
CMethodId szMethodID;
|
||||
@@ -656,6 +699,12 @@ HRESULT CZipDecoder::Decode(
|
||||
result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress);
|
||||
if (result == S_FALSE)
|
||||
return S_OK;
|
||||
if (result == E_NOTIMPL)
|
||||
{
|
||||
res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
RINOK(result);
|
||||
}
|
||||
bool crcOK = true;
|
||||
|
||||
@@ -25,16 +25,28 @@ using namespace NTime;
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
static const UInt32 kDeflateAlgoX1 = 0;
|
||||
static const UInt32 kDeflateAlgoX5 = 1;
|
||||
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 kNumFastBytesX1 = 32;
|
||||
static const UInt32 kNumFastBytesX7 = 64;
|
||||
static const UInt32 kNumFastBytesX9 = 128;
|
||||
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;
|
||||
@@ -173,24 +185,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
{
|
||||
bool defaultCharWasUsed;
|
||||
ui.Name = UnicodeStringToMultiByte(name, CP_OEMCP, '_', defaultCharWasUsed);
|
||||
tryUtf8 = (!m_ForseLocal && defaultCharWasUsed);
|
||||
tryUtf8 = (!m_ForseLocal && (defaultCharWasUsed ||
|
||||
MultiByteToUnicodeString(ui.Name, CP_OEMCP) != name));
|
||||
}
|
||||
|
||||
if (tryUtf8)
|
||||
{
|
||||
bool needUtf = false;
|
||||
for (int i = 0; i < name.Length(); i++)
|
||||
if ((unsigned)name[i] >= 0x80)
|
||||
{
|
||||
needUtf = true;
|
||||
break;
|
||||
}
|
||||
ui.IsUtf8 = needUtf;
|
||||
int i;
|
||||
for (i = 0; i < name.Length() && (unsigned)name[i] < 0x80; i++);
|
||||
ui.IsUtf8 = (i != name.Length());
|
||||
if (!ConvertUnicodeToUTF8(name, ui.Name))
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (ui.Name.Length() > 0xFFFF)
|
||||
if (ui.Name.Length() >= (1 << 16))
|
||||
return E_INVALIDARG;
|
||||
|
||||
ui.IndexInClient = i;
|
||||
@@ -272,6 +280,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
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);
|
||||
bool isBZip2 = (mainMethod == NFileHeader::NCompressionMethod::kBZip2);
|
||||
options.NumPasses = m_NumPasses;
|
||||
options.DicSize = m_DicSize;
|
||||
@@ -282,20 +292,41 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
#ifdef COMPRESS_MT
|
||||
options.NumThreads = _numThreads;
|
||||
#endif
|
||||
if (isDeflate)
|
||||
if (isLz)
|
||||
{
|
||||
if (options.NumPasses == 0xFFFFFFFF)
|
||||
options.NumPasses = (level >= 9 ? kDeflateNumPassesX9 :
|
||||
(level >= 7 ? kDeflateNumPassesX7 :
|
||||
kDeflateNumPassesX1));
|
||||
if (options.NumFastBytes == 0xFFFFFFFF)
|
||||
options.NumFastBytes = (level >= 9 ? kNumFastBytesX9 :
|
||||
(level >= 7 ? kNumFastBytesX7 :
|
||||
kNumFastBytesX1));
|
||||
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 ? kDeflateAlgoX5 :
|
||||
kDeflateAlgoX1);
|
||||
options.Algo = (level >= 5 ? kLzAlgoX5 :
|
||||
kLzAlgoX1);
|
||||
}
|
||||
if (isBZip2)
|
||||
{
|
||||
@@ -343,18 +374,14 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
{
|
||||
if (prop.vt == VT_BSTR)
|
||||
{
|
||||
UString valueString = prop.bstrVal;
|
||||
valueString.MakeUpper();
|
||||
if (valueString == L"COPY")
|
||||
m_MainMethod = NFileHeader::NCompressionMethod::kStored;
|
||||
else if (valueString == L"DEFLATE")
|
||||
m_MainMethod = NFileHeader::NCompressionMethod::kDeflated;
|
||||
else if (valueString == L"DEFLATE64")
|
||||
m_MainMethod = NFileHeader::NCompressionMethod::kDeflated64;
|
||||
else if (valueString == L"BZIP2")
|
||||
m_MainMethod = NFileHeader::NCompressionMethod::kBZip2;
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
UString m = prop.bstrVal;
|
||||
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 return E_INVALIDARG;
|
||||
}
|
||||
else if (prop.vt == VT_UI4)
|
||||
{
|
||||
@@ -364,6 +391,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
case NFileHeader::NCompressionMethod::kDeflated:
|
||||
case NFileHeader::NCompressionMethod::kDeflated64:
|
||||
case NFileHeader::NCompressionMethod::kBZip2:
|
||||
case NFileHeader::NCompressionMethod::kLZMA:
|
||||
m_MainMethod = (Byte)prop.ulVal;
|
||||
break;
|
||||
default:
|
||||
@@ -414,7 +442,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
}
|
||||
else if (name.Left(2) == L"FB")
|
||||
{
|
||||
UInt32 num = kNumFastBytesX9;
|
||||
UInt32 num = kDeflateNumFastBytesX9;
|
||||
RINOK(ParsePropValue(name.Mid(2), prop, num));
|
||||
m_NumFastBytes = num;
|
||||
}
|
||||
@@ -433,25 +461,25 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
|
||||
}
|
||||
else if (name.Left(1) == L"A")
|
||||
{
|
||||
UInt32 num = kDeflateAlgoX5;
|
||||
UInt32 num = kLzAlgoX5;
|
||||
RINOK(ParsePropValue(name.Mid(1), prop, num));
|
||||
m_Algo = num;
|
||||
}
|
||||
else if (name.CompareNoCase(L"TC") == 0)
|
||||
return SetBoolProperty(m_WriteNtfsTimeExtra, prop);
|
||||
{
|
||||
RINOK(SetBoolProperty(m_WriteNtfsTimeExtra, prop));
|
||||
}
|
||||
else if (name.CompareNoCase(L"CL") == 0)
|
||||
{
|
||||
RINOK(SetBoolProperty(m_ForseLocal, prop));
|
||||
if (m_ForseLocal)
|
||||
m_ForseUtf8 = false;
|
||||
return S_OK;
|
||||
}
|
||||
else if (name.CompareNoCase(L"CU") == 0)
|
||||
{
|
||||
RINOK(SetBoolProperty(m_ForseUtf8, prop));
|
||||
if (m_ForseUtf8)
|
||||
m_ForseLocal = false;
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
return E_INVALIDARG;
|
||||
|
||||
@@ -69,6 +69,10 @@ namespace NFileHeader
|
||||
kPKImploding = 10,
|
||||
|
||||
kBZip2 = 12,
|
||||
kLZMA = 14,
|
||||
kTerse = 18,
|
||||
kLz77 = 19,
|
||||
kJpeg = 0x60,
|
||||
kWavPack = 0x61,
|
||||
kPPMd = 0x62,
|
||||
kWzAES = 0x63
|
||||
@@ -170,6 +174,7 @@ namespace NFileHeader
|
||||
namespace NFlags
|
||||
{
|
||||
const int kEncrypted = 1 << 0;
|
||||
const int kLzmaEOS = 1 << 1;
|
||||
const int kDescriptorUsedMask = 1 << 3;
|
||||
const int kStrongEncrypted = 1 << 6;
|
||||
const int kUtf8 = 1 << 11;
|
||||
|
||||
@@ -51,20 +51,6 @@ bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CLocalItem::IsImplodeBigDictionary() const
|
||||
{
|
||||
if (CompressionMethod != NFileHeader::NCompressionMethod::kImploded)
|
||||
throw 12312212;
|
||||
return (Flags & NFileHeader::NFlags::kImplodeDictionarySizeMask) != 0;
|
||||
}
|
||||
|
||||
bool CLocalItem::IsImplodeLiteralsOn() const
|
||||
{
|
||||
if (CompressionMethod != NFileHeader::NCompressionMethod::kImploded)
|
||||
throw 12312213;
|
||||
return (Flags & NFileHeader::NFlags::kImplodeLiteralsOnMask) != 0;
|
||||
}
|
||||
|
||||
bool CLocalItem::IsDir() const
|
||||
{
|
||||
return NItemName::HasTailSlash(Name, GetCodePage());
|
||||
|
||||
@@ -188,8 +188,7 @@ public:
|
||||
bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; }
|
||||
bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; };
|
||||
|
||||
bool IsImplodeBigDictionary() const;
|
||||
bool IsImplodeLiteralsOn() const;
|
||||
bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
|
||||
|
||||
bool IsDir() const;
|
||||
bool IgnoreItem() const { return false; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// ZipUpdate.cpp
|
||||
lzma// ZipUpdate.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
@@ -568,6 +568,14 @@ static HRESULT Update2(
|
||||
if (numThreads <= 1)
|
||||
mtMode = false;
|
||||
}
|
||||
if (method == NFileHeader::NCompressionMethod::kLZMA)
|
||||
{
|
||||
UInt32 numLZMAThreads = (options->Algo > 0 ? 2 : 1);
|
||||
numThreads /= numLZMAThreads;
|
||||
options2.NumThreads = numLZMAThreads;
|
||||
if (numThreads <= 1)
|
||||
mtMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mtMode)
|
||||
|
||||
Reference in New Issue
Block a user