This commit is contained in:
Igor Pavlov
2011-04-11 00:00:00 +00:00
committed by Kornel Lesiński
parent de4f8c22fe
commit 35596517f2
322 changed files with 9989 additions and 7759 deletions

View File

@@ -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)
{
RINOK(setCoderProperties->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));
}
}
}
{
CMyComPtr<ICompressSetCoderProperties> setCoderProps;
_compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps);
if (setCoderProps)
{
RINOK(_options.MethodInfo.SetCoderProps(setCoderProps,
_options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL));
}
}
}
CMyComPtr<ISequentialOutStream> outStreamNew;
if (_options.PasswordIsDefined)

View File

@@ -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;
}
};
}}

View File

@@ -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
}

View File

@@ -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;
CBaseProps _props;
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;
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
}
};

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
UInt32 CItem::GetWinAttrib() const
{
DWORD winAttributes = 0;
if (IsDir())
winAttributes |= FILE_ATTRIBUTE_DIRECTORY;
return winAttributes;
}
UInt32 CItem::GetWinAttributes() 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)

View File

@@ -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

View File

@@ -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