mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 23:14:54 -06:00
Update to 7-Zip Version 21.02
This commit is contained in:
1183
CPP/7zip/7zip_gcc.mak
Normal file
1183
CPP/7zip/7zip_gcc.mak
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,10 @@
|
||||
C_OBJS = $(C_OBJS) \
|
||||
$O\Aes.obj
|
||||
|
||||
!IF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64"
|
||||
!IF defined(USE_C_AES) || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64"
|
||||
C_OBJS = $(C_OBJS) \
|
||||
$O\AesOpt.obj
|
||||
!ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64"
|
||||
ASM_OBJS = $(ASM_OBJS) \
|
||||
$O\AesOpt.obj
|
||||
!ENDIF
|
||||
|
||||
@@ -57,18 +57,20 @@ struct CCompressionMethodMode
|
||||
#endif
|
||||
|
||||
bool PasswordIsDefined;
|
||||
UString Password;
|
||||
UString Password; // _Wipe
|
||||
|
||||
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
|
||||
CCompressionMethodMode():
|
||||
DefaultMethod_was_Inserted(false),
|
||||
Filter_was_Inserted(false),
|
||||
PasswordIsDefined(false)
|
||||
DefaultMethod_was_Inserted(false)
|
||||
, Filter_was_Inserted(false)
|
||||
#ifndef _7ZIP_ST
|
||||
, NumThreads(1)
|
||||
, MultiThreadMixer(true)
|
||||
#endif
|
||||
, PasswordIsDefined(false)
|
||||
{}
|
||||
|
||||
~CCompressionMethodMode() { Password.Wipe_and_Empty(); }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -158,7 +158,7 @@ STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *
|
||||
|
||||
if (_pos != _glob->Pos)
|
||||
{
|
||||
RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
|
||||
RINOK(_glob->Stream->Seek((Int64)_pos, STREAM_SEEK_SET, NULL));
|
||||
_glob->Pos = _pos;
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *
|
||||
{
|
||||
if (_pos != _glob->Pos)
|
||||
{
|
||||
RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
|
||||
RINOK(_glob->Stream->Seek((Int64)_pos, STREAM_SEEK_SET, NULL));
|
||||
_glob->Pos = _pos;
|
||||
}
|
||||
|
||||
@@ -276,6 +276,7 @@ HRESULT CDecoder::Decode(
|
||||
|
||||
if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
|
||||
{
|
||||
_bindInfoPrev_Defined = false;
|
||||
_mixerRef.Release();
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
@@ -348,7 +349,7 @@ HRESULT CDecoder::Decode(
|
||||
_bindInfoPrev_Defined = true;
|
||||
}
|
||||
|
||||
_mixer->ReInit();
|
||||
RINOK(_mixer->ReInit2());
|
||||
|
||||
UInt32 packStreamIndex = 0;
|
||||
UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
|
||||
@@ -396,10 +397,10 @@ HRESULT CDecoder::Decode(
|
||||
if (setDecoderProperties)
|
||||
{
|
||||
const CByteBuffer &props = coderInfo.Props;
|
||||
size_t size = props.Size();
|
||||
if (size > 0xFFFFFFFF)
|
||||
const UInt32 size32 = (UInt32)props.Size();
|
||||
if (props.Size() != size32)
|
||||
return E_NOTIMPL;
|
||||
HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size);
|
||||
HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, size32);
|
||||
if (res == E_INVALIDARG)
|
||||
res = E_NOTIMPL;
|
||||
RINOK(res);
|
||||
@@ -415,17 +416,17 @@ HRESULT CDecoder::Decode(
|
||||
isEncrypted = true;
|
||||
if (!getTextPassword)
|
||||
return E_NOTIMPL;
|
||||
CMyComBSTR passwordBSTR;
|
||||
CMyComBSTR_Wipe passwordBSTR;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
|
||||
passwordIsDefined = true;
|
||||
password.Empty();
|
||||
password.Wipe_and_Empty();
|
||||
size_t len = 0;
|
||||
if (passwordBSTR)
|
||||
{
|
||||
password = passwordBSTR;
|
||||
len = password.Len();
|
||||
}
|
||||
CByteBuffer buffer(len * 2);
|
||||
CByteBuffer_Wipe buffer(len * 2);
|
||||
for (size_t k = 0; k < len; k++)
|
||||
{
|
||||
wchar_t c = passwordBSTR[k];
|
||||
@@ -444,7 +445,7 @@ HRESULT CDecoder::Decode(
|
||||
if (setFinishMode)
|
||||
{
|
||||
finishMode = fullUnpack;
|
||||
RINOK(setFinishMode->SetFinishMode(BoolToInt(finishMode)));
|
||||
RINOK(setFinishMode->SetFinishMode(BoolToUInt(finishMode)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -487,36 +488,49 @@ HRESULT CDecoder::Decode(
|
||||
CLockedInStream *lockedInStreamSpec = new CLockedInStream;
|
||||
CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;
|
||||
|
||||
bool needMtLock = false;
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
bool needMtLock = _useMixerMT;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (folderInfo.PackStreams.Size() > 1)
|
||||
{
|
||||
// lockedInStream.Pos = (UInt64)(Int64)-1;
|
||||
// RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos));
|
||||
RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos));
|
||||
RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStreamSpec->Pos));
|
||||
lockedInStreamSpec->Stream = inStream;
|
||||
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))
|
||||
#endif
|
||||
/*
|
||||
For ST-mixer mode:
|
||||
If parallel input stream reading from pack streams is possible,
|
||||
we must use MT-lock for packed streams.
|
||||
Internal decoders in 7-Zip will not read pack streams in parallel in ST-mixer mode.
|
||||
So we force to needMtLock mode only if there is unknown (external) decoder.
|
||||
*/
|
||||
if (!needMtLock && _mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))
|
||||
needMtLock = true;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> packStream;
|
||||
UInt64 packPos = startPos + packPositions[j];
|
||||
const UInt64 packPos = startPos + packPositions[j];
|
||||
|
||||
if (folderInfo.PackStreams.Size() == 1)
|
||||
{
|
||||
RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL));
|
||||
RINOK(inStream->Seek((Int64)packPos, STREAM_SEEK_SET, NULL));
|
||||
packStream = inStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef USE_MIXER_MT
|
||||
#ifdef USE_MIXER_ST
|
||||
if (_useMixerMT || needMtLock)
|
||||
if (needMtLock)
|
||||
#endif
|
||||
{
|
||||
CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
|
||||
@@ -542,7 +556,7 @@ HRESULT CDecoder::Decode(
|
||||
streamSpec->Init(packPositions[j + 1] - packPositions[j]);
|
||||
}
|
||||
|
||||
unsigned num = inStreams.Size();
|
||||
const unsigned num = inStreams.Size();
|
||||
CObjArray<ISequentialInStream *> inStreamPointers(num);
|
||||
for (i = 0; i < num; i++)
|
||||
inStreamPointers[i] = inStreams[i];
|
||||
|
||||
@@ -158,7 +158,7 @@ HRESULT CEncoder::CreateMixerCoder(
|
||||
{
|
||||
RINOK(CreateCoder_Index(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodFull.CodecIndex, true, cod));
|
||||
(unsigned)methodFull.CodecIndex, true, cod));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -215,7 +215,7 @@ HRESULT CEncoder::CreateMixerCoder(
|
||||
if (cryptoSetPassword)
|
||||
{
|
||||
const unsigned sizeInBytes = _options.Password.Len() * 2;
|
||||
CByteBuffer buffer(sizeInBytes);
|
||||
CByteBuffer_Wipe buffer(sizeInBytes);
|
||||
for (unsigned i = 0; i < _options.Password.Len(); i++)
|
||||
{
|
||||
wchar_t c = _options.Password[i];
|
||||
@@ -249,11 +249,12 @@ public:
|
||||
|
||||
STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed)
|
||||
{
|
||||
if (!_buf->Write(data, size))
|
||||
HRESULT res = _buf->Write_HRESULT(data, size);
|
||||
if (res != S_OK)
|
||||
{
|
||||
if (processed)
|
||||
*processed = 0;
|
||||
return E_FAIL;
|
||||
return res;
|
||||
}
|
||||
if (processed)
|
||||
*processed = size;
|
||||
@@ -309,7 +310,7 @@ HRESULT CEncoder::Encode(
|
||||
RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
|
||||
}
|
||||
|
||||
_mixer->ReInit();
|
||||
RINOK(_mixer->ReInit2());
|
||||
|
||||
CMtEncMultiProgress *mtProgressSpec = NULL;
|
||||
CMyComPtr<ICompressProgressInfo> mtProgress;
|
||||
@@ -478,7 +479,7 @@ HRESULT CEncoder::Encode(
|
||||
unpackSize = streamSize;
|
||||
}
|
||||
else
|
||||
streamSize = _mixer->GetBondStreamSize(bond);
|
||||
streamSize = _mixer->GetBondStreamSize((unsigned)bond);
|
||||
coderUnpackSizes.Add(streamSize);
|
||||
}
|
||||
|
||||
@@ -609,13 +610,13 @@ HRESULT CEncoder::EncoderConstr()
|
||||
int bond = _bindInfo.FindBond_for_PackStream(outIndex);
|
||||
if (bond >= 0)
|
||||
{
|
||||
ci = _bindInfo.Bonds[bond].UnpackIndex;
|
||||
ci = _bindInfo.Bonds[(unsigned)bond].UnpackIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
int si = _bindInfo.FindStream_in_PackStreams(outIndex);
|
||||
if (si >= 0)
|
||||
_bindInfo.PackStreams.MoveToFront(si);
|
||||
_bindInfo.PackStreams.MoveToFront((unsigned)si);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
class CEncoder
|
||||
class CEncoder MY_UNCOPYABLE
|
||||
{
|
||||
#ifdef USE_MIXER_ST
|
||||
NCoderMixer2::CMixerST *_mixerST;
|
||||
|
||||
@@ -217,6 +217,10 @@ HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult)
|
||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)
|
||||
{
|
||||
// for GCC
|
||||
// CFolderOutStream *folderOutStream = new CFolderOutStream;
|
||||
// CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
|
||||
|
||||
COM_TRY_BEGIN
|
||||
|
||||
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
|
||||
@@ -350,7 +354,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
#ifndef _NO_CRYPTO
|
||||
bool isEncrypted = false;
|
||||
bool passwordIsDefined = false;
|
||||
UString password;
|
||||
UString_Wipe password;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -411,7 +415,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
{
|
||||
RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError));
|
||||
// continue;
|
||||
return E_FAIL;
|
||||
// return E_FAIL;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,34 +107,62 @@ static void ConvertMethodIdToString(AString &res, UInt64 id)
|
||||
res += s + len - ConvertMethodIdToString_Back(s + len, id);
|
||||
}
|
||||
|
||||
static unsigned GetStringForSizeValue(char *s, UInt32 val)
|
||||
|
||||
static char *GetStringForSizeValue(char *s, UInt32 val)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i <= 31; i++)
|
||||
if (((UInt32)1 << i) == val)
|
||||
{
|
||||
if (i < 10)
|
||||
if (i >= 10)
|
||||
{
|
||||
s[0] = (char)('0' + i);
|
||||
s[1] = 0;
|
||||
return 1;
|
||||
*s++= (char)('0' + i / 10);
|
||||
i %= 10;
|
||||
}
|
||||
if (i < 20) { s[0] = '1'; s[1] = (char)('0' + i - 10); }
|
||||
else if (i < 30) { s[0] = '2'; s[1] = (char)('0' + i - 20); }
|
||||
else { s[0] = '3'; s[1] = (char)('0' + i - 30); }
|
||||
s[2] = 0;
|
||||
return 2;
|
||||
*s++ = (char)('0' + i);
|
||||
*s = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
char c = 'b';
|
||||
if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
|
||||
else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
|
||||
::ConvertUInt32ToString(val, s);
|
||||
unsigned pos = MyStringLen(s);
|
||||
s[pos++] = c;
|
||||
s[pos] = 0;
|
||||
return pos;
|
||||
s = ConvertUInt32ToString(val, s);
|
||||
*s++ = c;
|
||||
*s = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static void GetLzma2String(char *s, unsigned d)
|
||||
{
|
||||
if (d > 40)
|
||||
{
|
||||
*s = 0;
|
||||
return;
|
||||
// s = MyStpCpy(s, "unsup");
|
||||
}
|
||||
else if ((d & 1) == 0)
|
||||
d = (d >> 1) + 12;
|
||||
else
|
||||
{
|
||||
// s = GetStringForSizeValue(s, (UInt32)3 << ((d >> 1) + 11));
|
||||
d = (d >> 1) + 1;
|
||||
char c = 'k';
|
||||
if (d >= 10)
|
||||
{
|
||||
c = 'm';
|
||||
d -= 10;
|
||||
}
|
||||
s = ConvertUInt32ToString((UInt32)3 << d, s);
|
||||
*s++ = c;
|
||||
*s = 0;
|
||||
return;
|
||||
}
|
||||
ConvertUInt32ToString(d, s);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static inline void AddHexToString(UString &res, Byte value)
|
||||
{
|
||||
@@ -147,8 +175,7 @@ static char *AddProp32(char *s, const char *name, UInt32 v)
|
||||
{
|
||||
*s++ = ':';
|
||||
s = MyStpCpy(s, name);
|
||||
::ConvertUInt32ToString(v, s);
|
||||
return s + MyStringLen(s);
|
||||
return ConvertUInt32ToString(v, s);
|
||||
}
|
||||
|
||||
void CHandler::AddMethodName(AString &s, UInt64 id)
|
||||
@@ -184,10 +211,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
if (id == k_LZMA2)
|
||||
{
|
||||
s += "LZMA2:";
|
||||
if ((pm.Lzma2Prop & 1) == 0)
|
||||
ConvertUInt32ToString((pm.Lzma2Prop >> 1) + 12, temp);
|
||||
else
|
||||
GetStringForSizeValue(temp, 3 << ((pm.Lzma2Prop >> 1) + 11));
|
||||
GetLzma2String(temp, pm.Lzma2Prop);
|
||||
s += temp;
|
||||
}
|
||||
else if (id == k_LZMA)
|
||||
@@ -244,14 +268,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
return prop.Detach(value);
|
||||
#ifndef _SFX
|
||||
COM_TRY_END
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, int index)
|
||||
static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, unsigned index)
|
||||
{
|
||||
UInt64 value;
|
||||
if (v.GetItem(index, value))
|
||||
@@ -416,7 +439,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
|
||||
if (propsSize == 5)
|
||||
{
|
||||
UInt32 dicSize = GetUi32((const Byte *)props + 1);
|
||||
char *dest = s + GetStringForSizeValue(s, dicSize);
|
||||
char *dest = GetStringForSizeValue(s, dicSize);
|
||||
UInt32 d = props[0];
|
||||
if (d != 0x5D)
|
||||
{
|
||||
@@ -434,24 +457,16 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
|
||||
{
|
||||
name = "LZMA2";
|
||||
if (propsSize == 1)
|
||||
{
|
||||
Byte d = props[0];
|
||||
if ((d & 1) == 0)
|
||||
ConvertUInt32ToString((UInt32)((d >> 1) + 12), s);
|
||||
else
|
||||
GetStringForSizeValue(s, 3 << ((d >> 1) + 11));
|
||||
}
|
||||
GetLzma2String(s, props[0]);
|
||||
}
|
||||
else if (id == k_PPMD)
|
||||
{
|
||||
name = "PPMD";
|
||||
if (propsSize == 5)
|
||||
{
|
||||
Byte order = *props;
|
||||
char *dest = s;
|
||||
*dest++ = 'o';
|
||||
ConvertUInt32ToString(order, dest);
|
||||
dest += MyStringLen(dest);
|
||||
dest = ConvertUInt32ToString(*props, dest);
|
||||
dest = MyStpCpy(dest, ":mem");
|
||||
GetStringForSizeValue(dest, GetUi32(props + 1));
|
||||
}
|
||||
@@ -650,7 +665,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
PropVariant_Clear(value);
|
||||
RINOK(PropVariant_Clear(value));
|
||||
// COM_TRY_BEGIN
|
||||
// NCOM::CPropVariant prop;
|
||||
|
||||
@@ -753,7 +768,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
|
||||
#endif
|
||||
}
|
||||
// prop.Detach(value);
|
||||
// return prop.Detach(value);
|
||||
return S_OK;
|
||||
// COM_TRY_END
|
||||
}
|
||||
@@ -824,7 +839,7 @@ STDMETHODIMP CHandler::Close()
|
||||
#ifndef _NO_CRYPTO
|
||||
_isEncrypted = false;
|
||||
_passwordIsDefined = false;
|
||||
_password.Empty();
|
||||
_password.Wipe_and_Empty();
|
||||
#endif
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
|
||||
@@ -129,6 +129,10 @@ public:
|
||||
DECL_ISetCompressCodecsInfo
|
||||
|
||||
CHandler();
|
||||
~CHandler()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private:
|
||||
CMyComPtr<IInStream> _inStream;
|
||||
@@ -137,7 +141,7 @@ private:
|
||||
#ifndef _NO_CRYPTO
|
||||
bool _isEncrypted;
|
||||
bool _passwordIsDefined;
|
||||
UString _password;
|
||||
UString _password; // _Wipe
|
||||
#endif
|
||||
|
||||
#ifdef EXTRACT_ONLY
|
||||
|
||||
@@ -111,7 +111,7 @@ HRESULT CHandler::SetMainMethod(
|
||||
}
|
||||
|
||||
const UInt64 kSolidBytes_Min = (1 << 24);
|
||||
const UInt64 kSolidBytes_Max = ((UInt64)1 << 32) - 1;
|
||||
const UInt64 kSolidBytes_Max = ((UInt64)1 << 32);
|
||||
|
||||
bool needSolid = false;
|
||||
|
||||
@@ -140,26 +140,52 @@ HRESULT CHandler::SetMainMethod(
|
||||
case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break;
|
||||
case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break;
|
||||
case k_Deflate: dicSize = (UInt32)1 << 15; break;
|
||||
case k_Deflate64: dicSize = (UInt32)1 << 16; break;
|
||||
case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;
|
||||
default: continue;
|
||||
}
|
||||
|
||||
_numSolidBytes = (UInt64)dicSize << 7;
|
||||
if (_numSolidBytes < kSolidBytes_Min) _numSolidBytes = kSolidBytes_Min;
|
||||
if (_numSolidBytes > kSolidBytes_Max) _numSolidBytes = kSolidBytes_Max;
|
||||
|
||||
if (methodFull.Id == k_LZMA2)
|
||||
{
|
||||
// he we calculate default chunk Size for LZMA2 as defined in LZMA2 encoder code
|
||||
UInt64 cs = (UInt64)dicSize << 2;
|
||||
const UInt32 kMinSize = (UInt32)1 << 20;
|
||||
const UInt32 kMaxSize = (UInt32)1 << 28;
|
||||
if (cs < kMinSize) cs = kMinSize;
|
||||
if (cs > kMaxSize) cs = kMaxSize;
|
||||
if (cs < dicSize) cs = dicSize;
|
||||
cs += (kMinSize - 1);
|
||||
cs &= ~(UInt64)(kMinSize - 1);
|
||||
// we want to use at least 64 chunks (threads) per one solid block.
|
||||
_numSolidBytes = cs << 6;
|
||||
const UInt64 kSolidBytes_Lzma2_Max = ((UInt64)1 << 34);
|
||||
if (_numSolidBytes > kSolidBytes_Lzma2_Max)
|
||||
_numSolidBytes = kSolidBytes_Lzma2_Max;
|
||||
}
|
||||
else
|
||||
{
|
||||
_numSolidBytes = (UInt64)dicSize << 7;
|
||||
if (_numSolidBytes > kSolidBytes_Max)
|
||||
_numSolidBytes = kSolidBytes_Max;
|
||||
}
|
||||
|
||||
if (_numSolidBytes < kSolidBytes_Min)
|
||||
_numSolidBytes = kSolidBytes_Min;
|
||||
_numSolidBytesDefined = true;
|
||||
}
|
||||
|
||||
if (!_numSolidBytesDefined)
|
||||
{
|
||||
if (needSolid)
|
||||
_numSolidBytes = kSolidBytes_Max;
|
||||
else
|
||||
_numSolidBytes = 0;
|
||||
}
|
||||
_numSolidBytesDefined = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, UInt64 &ft, bool &ftDefined)
|
||||
static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, unsigned index, PROPID propID, UInt64 &ft, bool &ftDefined)
|
||||
{
|
||||
// ft = 0;
|
||||
// ftDefined = false;
|
||||
@@ -289,8 +315,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
|
||||
bool need_CTime = (Write_CTime.Def && Write_CTime.Val);
|
||||
bool need_ATime = (Write_ATime.Def && Write_ATime.Val);
|
||||
bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def);
|
||||
bool need_Attrib = (Write_Attrib.Def && Write_Attrib.Val || !Write_Attrib.Def);
|
||||
bool need_MTime = (Write_MTime.Def ? Write_MTime.Val : true);
|
||||
bool need_Attrib = (Write_Attrib.Def ? Write_Attrib.Val : true);
|
||||
|
||||
if (db && !db->Files.IsEmpty())
|
||||
{
|
||||
@@ -313,7 +339,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
CUpdateItem ui;
|
||||
ui.NewProps = IntToBool(newProps);
|
||||
ui.NewData = IntToBool(newData);
|
||||
ui.IndexInArchive = indexInArchive;
|
||||
ui.IndexInArchive = (int)indexInArchive;
|
||||
ui.IndexInClient = i;
|
||||
ui.IsAnti = false;
|
||||
ui.Size = 0;
|
||||
@@ -322,23 +348,23 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
// bool isAltStream = false;
|
||||
if (ui.IndexInArchive != -1)
|
||||
{
|
||||
if (db == 0 || (unsigned)ui.IndexInArchive >= db->Files.Size())
|
||||
if (!db || (unsigned)ui.IndexInArchive >= db->Files.Size())
|
||||
return E_INVALIDARG;
|
||||
const CFileItem &fi = db->Files[ui.IndexInArchive];
|
||||
const CFileItem &fi = db->Files[(unsigned)ui.IndexInArchive];
|
||||
if (!ui.NewProps)
|
||||
{
|
||||
_db.GetPath(ui.IndexInArchive, name);
|
||||
_db.GetPath((unsigned)ui.IndexInArchive, name);
|
||||
}
|
||||
ui.IsDir = fi.IsDir;
|
||||
ui.Size = fi.Size;
|
||||
// isAltStream = fi.IsAltStream;
|
||||
ui.IsAnti = db->IsItemAnti(ui.IndexInArchive);
|
||||
ui.IsAnti = db->IsItemAnti((unsigned)ui.IndexInArchive);
|
||||
|
||||
if (!ui.NewProps)
|
||||
{
|
||||
ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime);
|
||||
ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime);
|
||||
ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime);
|
||||
ui.CTimeDefined = db->CTime.GetItem((unsigned)ui.IndexInArchive, ui.CTime);
|
||||
ui.ATimeDefined = db->ATime.GetItem((unsigned)ui.IndexInArchive, ui.ATime);
|
||||
ui.MTimeDefined = db->MTime.GetItem((unsigned)ui.IndexInArchive, ui.MTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,10 +596,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2);
|
||||
|
||||
methodMode.PasswordIsDefined = false;
|
||||
methodMode.Password.Empty();
|
||||
methodMode.Password.Wipe_and_Empty();
|
||||
if (getPassword2)
|
||||
{
|
||||
CMyComBSTR password;
|
||||
CMyComBSTR_Wipe password;
|
||||
Int32 passwordIsDefined;
|
||||
RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
|
||||
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
|
||||
@@ -752,7 +778,7 @@ HRESULT COutHandler::SetSolidFromString(const UString &s)
|
||||
_solidExtension = true;
|
||||
continue;
|
||||
}
|
||||
i += (int)(end - start);
|
||||
i += (unsigned)(end - start);
|
||||
if (i == s2.Len())
|
||||
return E_INVALIDARG;
|
||||
wchar_t c = s2[i++];
|
||||
@@ -830,7 +856,7 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
|
||||
}
|
||||
|
||||
UInt32 number;
|
||||
int index = ParseStringToUInt32(name, number);
|
||||
unsigned index = ParseStringToUInt32(name, number);
|
||||
// UString realName = name.Ptr(index);
|
||||
if (index == 0)
|
||||
{
|
||||
|
||||
@@ -108,8 +108,9 @@ const UInt32 k_SWAP4 = 0x20304;
|
||||
const UInt32 k_LZMA = 0x30101;
|
||||
const UInt32 k_PPMD = 0x30401;
|
||||
|
||||
const UInt32 k_Deflate = 0x40108;
|
||||
const UInt32 k_BZip2 = 0x40202;
|
||||
const UInt32 k_Deflate = 0x40108;
|
||||
const UInt32 k_Deflate64 = 0x40109;
|
||||
const UInt32 k_BZip2 = 0x40202;
|
||||
|
||||
const UInt32 k_BCJ = 0x3030103;
|
||||
const UInt32 k_BCJ2 = 0x303011B;
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "../../../../C/7zCrc.h"
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
// #include "../../../Common/UTFConvert.h"
|
||||
|
||||
#include "../../Common/StreamObjects.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
@@ -32,6 +34,7 @@ using namespace NCOM;
|
||||
namespace NArchive {
|
||||
namespace N7z {
|
||||
|
||||
unsigned BoolVector_CountSum(const CBoolVector &v);
|
||||
unsigned BoolVector_CountSum(const CBoolVector &v)
|
||||
{
|
||||
unsigned sum = 0;
|
||||
@@ -59,9 +62,13 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
|
||||
class CInArchiveException {};
|
||||
class CUnsupportedFeatureException: public CInArchiveException {};
|
||||
|
||||
MY_ATTR_NORETURN
|
||||
static void ThrowException() { throw CInArchiveException(); }
|
||||
MY_ATTR_NORETURN
|
||||
static inline void ThrowEndOfData() { ThrowException(); }
|
||||
MY_ATTR_NORETURN
|
||||
static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); }
|
||||
MY_ATTR_NORETURN
|
||||
static inline void ThrowIncorrect() { ThrowException(); }
|
||||
|
||||
class CStreamSwitch
|
||||
@@ -328,7 +335,7 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
|
||||
{
|
||||
memcpy(_header, p, kHeaderSize);
|
||||
_arhiveBeginStreamPosition += offset + pos;
|
||||
return stream->Seek(_arhiveBeginStreamPosition + kHeaderSize, STREAM_SEEK_SET, NULL);
|
||||
return stream->Seek((Int64)(_arhiveBeginStreamPosition + kHeaderSize), STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,7 +351,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
|
||||
Close();
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition))
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition))
|
||||
RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL))
|
||||
RINOK(stream->Seek((Int64)_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL))
|
||||
RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit));
|
||||
_stream = stream;
|
||||
return S_OK;
|
||||
@@ -478,7 +485,7 @@ void CDatabase::GetPath(unsigned index, UString &path) const
|
||||
|
||||
#if defined(_WIN32) && defined(MY_CPU_LE)
|
||||
|
||||
wmemcpy(s, (const wchar_t *)p, size);
|
||||
wmemcpy(s, (const wchar_t *)(const void *)p, size);
|
||||
|
||||
#else
|
||||
|
||||
@@ -506,10 +513,27 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
|
||||
if (size >= (1 << 14))
|
||||
return S_OK;
|
||||
|
||||
// (size) includes null terminator
|
||||
|
||||
/*
|
||||
#if WCHAR_MAX > 0xffff
|
||||
|
||||
const Byte *p = ((const Byte *)NamesBuf + offset * 2);
|
||||
size = Utf16LE__Get_Num_WCHARs(p, size - 1);
|
||||
// (size) doesn't include null terminator
|
||||
RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size));
|
||||
wchar_t *s = path->bstrVal;
|
||||
wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, size, s);
|
||||
*sEnd = 0;
|
||||
if (s + size != sEnd) return E_FAIL;
|
||||
|
||||
#else
|
||||
*/
|
||||
|
||||
RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1));
|
||||
wchar_t *s = path->bstrVal;
|
||||
|
||||
const Byte *p = ((const Byte *)NamesBuf + offset * 2);
|
||||
// Utf16LE__To_WCHARs_Sep(p, size, s);
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
@@ -518,10 +542,14 @@ HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
if (c == L'/')
|
||||
c = WCHAR_PATH_SEPARATOR;
|
||||
else if (c == L'\\')
|
||||
c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme
|
||||
#endif
|
||||
*s++ = c;
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
return S_OK;
|
||||
|
||||
/*
|
||||
@@ -673,7 +701,7 @@ void CInArchive::ReadUnpackInfo(
|
||||
{
|
||||
UInt32 indexOfMainStream = 0;
|
||||
UInt32 numPackStreams = 0;
|
||||
folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
|
||||
folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr);
|
||||
|
||||
CNum numInStreams = 0;
|
||||
CNum numCoders = inByte->ReadNum();
|
||||
@@ -794,10 +822,10 @@ void CInArchive::ReadUnpackInfo(
|
||||
folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
|
||||
}
|
||||
|
||||
size_t dataSize = _inByteBack->GetPtr() - startBufPtr;
|
||||
const size_t dataSize = (size_t)(_inByteBack->GetPtr() - startBufPtr);
|
||||
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
|
||||
folders.FoStartPackStreamIndex[fo] = packStreamIndex;
|
||||
folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
|
||||
folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr);
|
||||
folders.CodersData.CopyFrom(startBufPtr, dataSize);
|
||||
|
||||
// if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported();
|
||||
@@ -962,6 +990,8 @@ void CInArchive::ReadSubStreamsInfo(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CInArchive::ReadStreamsInfo(
|
||||
const CObjectVector<CByteBuffer> *dataVector,
|
||||
UInt64 &dataOffset,
|
||||
@@ -974,7 +1004,11 @@ void CInArchive::ReadStreamsInfo(
|
||||
if (type == NID::kPackInfo)
|
||||
{
|
||||
dataOffset = ReadNumber();
|
||||
if (dataOffset > _rangeLimit)
|
||||
ThrowIncorrect();
|
||||
ReadPackInfo(folders);
|
||||
if (folders.PackPositions[folders.NumPackStreams] > _rangeLimit - dataOffset)
|
||||
ThrowIncorrect();
|
||||
type = ReadID();
|
||||
}
|
||||
|
||||
@@ -1029,7 +1063,7 @@ void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v)
|
||||
mask = 0x80;
|
||||
}
|
||||
p[i] = ((b & mask) != 0);
|
||||
mask >>= 1;
|
||||
mask = (Byte)(mask >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1090,8 +1124,8 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
|
||||
for (CNum i = 0; i < folders.NumFolders; i++)
|
||||
{
|
||||
CByteBuffer &data = dataVector.AddNew();
|
||||
UInt64 unpackSize64 = folders.GetFolderUnpackSize(i);
|
||||
size_t unpackSize = (size_t)unpackSize64;
|
||||
const UInt64 unpackSize64 = folders.GetFolderUnpackSize(i);
|
||||
const size_t unpackSize = (size_t)unpackSize64;
|
||||
if (unpackSize != unpackSize64)
|
||||
ThrowUnsupported();
|
||||
data.Alloc(unpackSize);
|
||||
@@ -1106,7 +1140,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
_stream, baseOffset + dataOffset,
|
||||
folders, i,
|
||||
NULL, // *unpackSize
|
||||
NULL, // &unpackSize64
|
||||
|
||||
outStream,
|
||||
NULL, // *compressProgress
|
||||
@@ -1127,6 +1161,9 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
|
||||
if (dataAfterEnd_Error)
|
||||
ThereIsHeaderError = true;
|
||||
|
||||
if (unpackSize != outStreamSpec->GetPos())
|
||||
ThrowIncorrect();
|
||||
|
||||
if (folders.FolderCRCs.ValidAndDefined(i))
|
||||
if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])
|
||||
ThrowIncorrect();
|
||||
@@ -1226,8 +1263,8 @@ HRESULT CInArchive::ReadHeader(
|
||||
unsigned i;
|
||||
for (i = 0; i < numFiles; i++)
|
||||
{
|
||||
size_t curRem = (rem - pos) / 2;
|
||||
const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos);
|
||||
const size_t curRem = (rem - pos) / 2;
|
||||
const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf + pos);
|
||||
size_t j;
|
||||
for (j = 0; j < curRem && buf[j] != 0; j++);
|
||||
if (j == curRem)
|
||||
@@ -1519,13 +1556,13 @@ HRESULT CInArchive::ReadDatabase2(
|
||||
const unsigned kCheckSize = 512;
|
||||
Byte buf[kCheckSize];
|
||||
RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize));
|
||||
UInt64 rem = fileSize - cur;
|
||||
const UInt64 rem = fileSize - cur;
|
||||
unsigned checkSize = kCheckSize;
|
||||
if (rem < kCheckSize)
|
||||
checkSize = (unsigned)(rem);
|
||||
if (checkSize < 3)
|
||||
return S_FALSE;
|
||||
RINOK(_stream->Seek(fileSize - checkSize, STREAM_SEEK_SET, NULL));
|
||||
RINOK(_stream->Seek((Int64)(fileSize - checkSize), STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize));
|
||||
|
||||
if (buf[checkSize - 1] != 0)
|
||||
@@ -1534,8 +1571,8 @@ HRESULT CInArchive::ReadDatabase2(
|
||||
unsigned i;
|
||||
for (i = checkSize - 2;; i--)
|
||||
{
|
||||
if (buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo ||
|
||||
buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo)
|
||||
if ((buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo) ||
|
||||
(buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo))
|
||||
break;
|
||||
if (i == 0)
|
||||
return S_FALSE;
|
||||
@@ -1543,7 +1580,7 @@ HRESULT CInArchive::ReadDatabase2(
|
||||
nextHeaderSize = checkSize - i;
|
||||
nextHeaderOffset = rem - nextHeaderSize;
|
||||
nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);
|
||||
RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL));
|
||||
RINOK(_stream->Seek((Int64)cur, STREAM_SEEK_SET, NULL));
|
||||
db.StartHeaderWasRecovered = true;
|
||||
}
|
||||
else
|
||||
@@ -1560,25 +1597,32 @@ HRESULT CInArchive::ReadDatabase2(
|
||||
if ((Int64)nextHeaderOffset < 0 ||
|
||||
nextHeaderSize > ((UInt64)1 << 62))
|
||||
return S_FALSE;
|
||||
|
||||
HeadersSize = kHeaderSize;
|
||||
|
||||
if (nextHeaderSize == 0)
|
||||
{
|
||||
if (nextHeaderOffset != 0)
|
||||
return S_FALSE;
|
||||
db.IsArc = true;
|
||||
db.HeadersSize = HeadersSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!db.StartHeaderWasRecovered)
|
||||
db.IsArc = true;
|
||||
|
||||
HeadersSize += kHeaderSize + nextHeaderSize;
|
||||
HeadersSize += nextHeaderSize;
|
||||
// db.EndHeaderOffset = nextHeaderOffset;
|
||||
_rangeLimit = nextHeaderOffset;
|
||||
|
||||
db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize;
|
||||
if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize)
|
||||
{
|
||||
db.UnexpectedEnd = true;
|
||||
return S_FALSE;
|
||||
}
|
||||
RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));
|
||||
RINOK(_stream->Seek((Int64)nextHeaderOffset, STREAM_SEEK_CUR, NULL));
|
||||
|
||||
size_t nextHeaderSize_t = (size_t)nextHeaderSize;
|
||||
if (nextHeaderSize_t != nextHeaderSize)
|
||||
|
||||
@@ -174,13 +174,14 @@ struct CDatabase: public CFolders
|
||||
HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();
|
||||
};
|
||||
|
||||
|
||||
struct CInArchiveInfo
|
||||
{
|
||||
CArchiveVersion Version;
|
||||
UInt64 StartPosition;
|
||||
UInt64 StartPositionAfterHeader;
|
||||
UInt64 DataStartPosition;
|
||||
UInt64 DataStartPosition2;
|
||||
UInt64 StartPosition; // in stream
|
||||
UInt64 StartPositionAfterHeader; // in stream
|
||||
UInt64 DataStartPosition; // in stream
|
||||
UInt64 DataStartPosition2; // in stream. it's for headers
|
||||
CRecordVector<UInt64> FileInfoPopIDs;
|
||||
|
||||
void Clear()
|
||||
@@ -193,6 +194,7 @@ struct CInArchiveInfo
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CDbEx: public CDatabase
|
||||
{
|
||||
CInArchiveInfo ArcInfo;
|
||||
@@ -202,6 +204,7 @@ struct CDbEx: public CDatabase
|
||||
|
||||
UInt64 HeadersSize;
|
||||
UInt64 PhySize;
|
||||
// UInt64 EndHeaderOffset; // relative to position after StartHeader (32 bytes)
|
||||
|
||||
/*
|
||||
CRecordVector<size_t> SecureOffsets;
|
||||
@@ -255,6 +258,7 @@ struct CDbEx: public CDatabase
|
||||
|
||||
HeadersSize = 0;
|
||||
PhySize = 0;
|
||||
// EndHeaderOffset = 0;
|
||||
}
|
||||
|
||||
bool CanUpdate() const
|
||||
@@ -349,6 +353,8 @@ class CInArchive
|
||||
UInt64 _arhiveBeginStreamPosition;
|
||||
UInt64 _fileEndPosition;
|
||||
|
||||
UInt64 _rangeLimit; // relative to position after StartHeader (32 bytes)
|
||||
|
||||
Byte _header[kHeaderSize];
|
||||
|
||||
UInt64 HeadersSize;
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
{
|
||||
FOR_VECTOR(i, PackStreams)
|
||||
if (PackStreams[i] == packStream)
|
||||
return i;
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
{
|
||||
FOR_VECTOR(i, Bonds)
|
||||
if (Bonds[i].PackIndex == packStream)
|
||||
return i;
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "../../../../C/7zCrc.h"
|
||||
|
||||
#include "../../../Common/AutoPtr.h"
|
||||
// #include "../../../Common/UTFConvert.h"
|
||||
|
||||
#include "../../Common/StreamObjects.h"
|
||||
|
||||
@@ -196,7 +197,7 @@ void COutArchive::WriteNumber(UInt64 value)
|
||||
break;
|
||||
}
|
||||
firstByte |= mask;
|
||||
mask >>= 1;
|
||||
mask = (Byte)(mask >> 1);
|
||||
}
|
||||
WriteByte(firstByte);
|
||||
for (; i > 0; i--)
|
||||
@@ -206,9 +207,9 @@ void COutArchive::WriteNumber(UInt64 value)
|
||||
}
|
||||
}
|
||||
|
||||
static UInt32 GetBigNumberSize(UInt64 value)
|
||||
static unsigned GetBigNumberSize(UInt64 value)
|
||||
{
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 1; i < 9; i++)
|
||||
if (value < (((UInt64)1 << (i * 7))))
|
||||
break;
|
||||
@@ -264,18 +265,18 @@ void COutArchive::WriteFolder(const CFolder &folder)
|
||||
for (idSize = 1; idSize < sizeof(id); idSize++)
|
||||
if ((id >> (8 * idSize)) == 0)
|
||||
break;
|
||||
idSize &= 0xF;
|
||||
// idSize &= 0xF; // idSize is smaller than 16 already
|
||||
Byte temp[16];
|
||||
for (unsigned t = idSize; t != 0; t--, id >>= 8)
|
||||
temp[t] = (Byte)(id & 0xFF);
|
||||
|
||||
Byte b = (Byte)(idSize);
|
||||
bool isComplex = !coder.IsSimpleCoder();
|
||||
unsigned b = idSize;
|
||||
const bool isComplex = !coder.IsSimpleCoder();
|
||||
b |= (isComplex ? 0x10 : 0);
|
||||
|
||||
size_t propsSize = coder.Props.Size();
|
||||
const size_t propsSize = coder.Props.Size();
|
||||
b |= ((propsSize != 0) ? 0x20 : 0);
|
||||
temp[0] = b;
|
||||
temp[0] = (Byte)b;
|
||||
WriteBytes(temp, idSize + 1);
|
||||
if (isComplex)
|
||||
{
|
||||
@@ -309,7 +310,7 @@ void COutArchive::WriteBoolVector(const CBoolVector &boolVector)
|
||||
{
|
||||
if (boolVector[i])
|
||||
b |= mask;
|
||||
mask >>= 1;
|
||||
mask = (Byte)(mask >> 1);
|
||||
if (mask == 0)
|
||||
{
|
||||
WriteByte(b);
|
||||
@@ -476,7 +477,7 @@ void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, B
|
||||
{
|
||||
const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);
|
||||
const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2;
|
||||
SkipToAligned(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSizeShifts);
|
||||
SkipToAligned(3 + bvSize + GetBigNumberSize(dataSize), itemSizeShifts);
|
||||
|
||||
WriteByte(type);
|
||||
WriteNumber(dataSize);
|
||||
@@ -545,7 +546,39 @@ void COutArchive::WriteHeader(
|
||||
|
||||
WriteByte(NID::kHeader);
|
||||
|
||||
// Archive Properties
|
||||
/*
|
||||
{
|
||||
// It's example for per archive properies writing
|
||||
|
||||
WriteByte(NID::kArchiveProperties);
|
||||
|
||||
// you must use random 40-bit number that will identify you
|
||||
// then you can use same kDeveloperID for any properties and methods
|
||||
const UInt64 kDeveloperID = 0x123456789A; // change that value to real random 40-bit number
|
||||
|
||||
#define GENERATE_7Z_ID(developerID, subID) (((UInt64)0x3F << 56) | ((UInt64)developerID << 16) | subID)
|
||||
|
||||
{
|
||||
const UInt64 kSubID = 0x1; // you can use small number for subID
|
||||
const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID);
|
||||
WriteNumber(kID);
|
||||
const unsigned kPropsSize = 3; // it's example size
|
||||
WriteNumber(kPropsSize);
|
||||
for (unsigned i = 0; i < kPropsSize; i++)
|
||||
WriteByte((Byte)(i & 0xFF));
|
||||
}
|
||||
{
|
||||
const UInt64 kSubID = 0x2; // you can use small number for subID
|
||||
const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID);
|
||||
WriteNumber(kID);
|
||||
const unsigned kPropsSize = 5; // it's example size
|
||||
WriteNumber(kPropsSize);
|
||||
for (unsigned i = 0; i < kPropsSize; i++)
|
||||
WriteByte((Byte)(i + 16));
|
||||
}
|
||||
WriteByte(NID::kEnd);
|
||||
}
|
||||
*/
|
||||
|
||||
if (db.Folders.Size() > 0)
|
||||
{
|
||||
@@ -637,7 +670,15 @@ void COutArchive::WriteHeader(
|
||||
const UString &name = db.Names[i];
|
||||
if (!name.IsEmpty())
|
||||
numDefined++;
|
||||
namesDataSize += (name.Len() + 1) * 2;
|
||||
const size_t numUtfChars =
|
||||
/*
|
||||
#if WCHAR_MAX > 0xffff
|
||||
Get_Num_Utf16_chars_from_wchar_string(name.Ptr());
|
||||
#else
|
||||
*/
|
||||
name.Len();
|
||||
// #endif
|
||||
namesDataSize += (numUtfChars + 1) * 2;
|
||||
}
|
||||
|
||||
if (numDefined > 0)
|
||||
@@ -654,6 +695,25 @@ void COutArchive::WriteHeader(
|
||||
for (unsigned t = 0; t <= name.Len(); t++)
|
||||
{
|
||||
wchar_t c = name[t];
|
||||
|
||||
/*
|
||||
#if WCHAR_MAX > 0xffff
|
||||
if (c >= 0x10000)
|
||||
{
|
||||
c -= 0x10000;
|
||||
if (c < (1 << 20))
|
||||
{
|
||||
unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF);
|
||||
WriteByte((Byte)c0);
|
||||
WriteByte((Byte)(c0 >> 8));
|
||||
c = 0xdc00 + (c & 0x3FF);
|
||||
}
|
||||
else
|
||||
c = '_'; // we change character unsupported by UTF16
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
WriteByte((Byte)c);
|
||||
WriteByte((Byte)(c >> 8));
|
||||
}
|
||||
@@ -855,7 +915,7 @@ HRESULT COutArchive::WriteDatabase(
|
||||
h.NextHeaderSize = headerSize;
|
||||
h.NextHeaderCRC = headerCRC;
|
||||
h.NextHeaderOffset = headerOffset;
|
||||
RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL));
|
||||
RINOK(Stream->Seek((Int64)_prefixHeaderPos, STREAM_SEEK_SET, NULL));
|
||||
return WriteStartHeader(h);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,8 +55,8 @@ struct CFilterMode
|
||||
#define PE_SIG 0x00004550
|
||||
#define PE_OptHeader_Magic_32 0x10B
|
||||
#define PE_OptHeader_Magic_64 0x20B
|
||||
#define PE_SectHeaderSize 40
|
||||
#define PE_SECT_EXECUTE 0x20000000
|
||||
// #define PE_SectHeaderSize 40
|
||||
// #define PE_SECT_EXECUTE 0x20000000
|
||||
|
||||
static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
|
||||
{
|
||||
@@ -254,10 +254,12 @@ static BoolInt Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode)
|
||||
if (subChunkSize < 0x10 || subChunkSize > 0x12 || GetUi16(buf + 0x14) != 1)
|
||||
return False;
|
||||
|
||||
unsigned numChannels = GetUi16(buf + 0x16);
|
||||
unsigned bitsPerSample = GetUi16(buf + 0x22);
|
||||
|
||||
if ((bitsPerSample & 0x7) != 0 || bitsPerSample >= 256 || numChannels >= 256)
|
||||
const unsigned numChannels = GetUi16(buf + 0x16);
|
||||
const unsigned bitsPerSample = GetUi16(buf + 0x22);
|
||||
if ((bitsPerSample & 0x7) != 0)
|
||||
return False;
|
||||
const UInt32 delta = (UInt32)numChannels * (bitsPerSample >> 3);
|
||||
if (delta == 0 || delta > 256)
|
||||
return False;
|
||||
|
||||
pos = 0x14 + subChunkSize;
|
||||
@@ -271,9 +273,6 @@ static BoolInt Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode)
|
||||
subChunkSize = GetUi32(buf + pos + 4);
|
||||
if (GetUi32(buf + pos) == WAV_SUBCHUNK_data)
|
||||
{
|
||||
unsigned delta = numChannels * (bitsPerSample >> 3);
|
||||
if (delta >= 256)
|
||||
return False;
|
||||
filterMode->Id = k_Delta;
|
||||
filterMode->Delta = delta;
|
||||
return True;
|
||||
@@ -418,7 +417,7 @@ static unsigned Get_FilterGroup_for_Folder(
|
||||
static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
UInt64 position, UInt64 size, ICompressProgressInfo *progress)
|
||||
{
|
||||
RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0));
|
||||
RINOK(inStream->Seek((Int64)position, STREAM_SEEK_SET, 0));
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
|
||||
streamSpec->SetStream(inStream);
|
||||
@@ -642,13 +641,13 @@ struct CRefItem
|
||||
if (sortByType)
|
||||
{
|
||||
int slashPos = ui.Name.ReverseFind_PathSepar();
|
||||
NamePos = slashPos + 1;
|
||||
NamePos = (unsigned)(slashPos + 1);
|
||||
int dotPos = ui.Name.ReverseFind_Dot();
|
||||
if (dotPos <= slashPos)
|
||||
ExtensionPos = ui.Name.Len();
|
||||
else
|
||||
{
|
||||
ExtensionPos = dotPos + 1;
|
||||
ExtensionPos = (unsigned)(dotPos + 1);
|
||||
if (ExtensionPos != ui.Name.Len())
|
||||
{
|
||||
AString s;
|
||||
@@ -836,7 +835,7 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo
|
||||
{
|
||||
const wchar_t *ext;
|
||||
if (dotPos > slashPos)
|
||||
ext = ui.Name.Ptr(dotPos + 1);
|
||||
ext = ui.Name.Ptr((unsigned)(dotPos + 1));
|
||||
else
|
||||
ext = ui.Name.RightPtr(0);
|
||||
|
||||
@@ -1071,12 +1070,12 @@ static HRESULT MakeExeMethod(CCompressionMethodMode &mode,
|
||||
if (alignBits != 0)
|
||||
{
|
||||
if (alignBits > 2 || filterMode.Id == k_Delta)
|
||||
nextMethod.AddProp32(NCoderPropID::kPosStateBits, alignBits);
|
||||
nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits);
|
||||
unsigned lc = 0;
|
||||
if (alignBits < 3)
|
||||
lc = 3 - alignBits;
|
||||
lc = (unsigned)(3 - alignBits);
|
||||
nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);
|
||||
nextMethod.AddProp32(NCoderPropID::kLitPosBits, alignBits);
|
||||
nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1453,7 +1452,7 @@ public:
|
||||
|
||||
UInt64 StartPos;
|
||||
const CFolders *Folders;
|
||||
int FolderIndex;
|
||||
unsigned FolderIndex;
|
||||
|
||||
// bool send_UnpackSize;
|
||||
// UInt64 UnpackSize;
|
||||
@@ -1609,7 +1608,10 @@ HRESULT Update(
|
||||
|
||||
CRecordVector<CFilterMode2> filters;
|
||||
CObjectVector<CSolidGroup> groups;
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
bool thereAreRepacks = false;
|
||||
#endif
|
||||
|
||||
bool useFilters = options.UseFilters;
|
||||
if (useFilters)
|
||||
@@ -1636,7 +1638,7 @@ HRESULT Update(
|
||||
{
|
||||
int index = updateItems[i].IndexInArchive;
|
||||
if (index != -1)
|
||||
fileIndexToUpdateIndexMap[(unsigned)index] = i;
|
||||
fileIndexToUpdateIndexMap[(unsigned)index] = (int)i;
|
||||
}
|
||||
|
||||
for (i = 0; i < db->NumFolders; i++)
|
||||
@@ -1656,7 +1658,7 @@ HRESULT Update(
|
||||
{
|
||||
indexInFolder++;
|
||||
int updateIndex = fileIndexToUpdateIndexMap[fi];
|
||||
if (updateIndex >= 0 && !updateItems[updateIndex].NewData)
|
||||
if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData)
|
||||
{
|
||||
numCopyItems++;
|
||||
repackSize += file.Size;
|
||||
@@ -1688,7 +1690,9 @@ HRESULT Update(
|
||||
complexity += db->GetFolderFullPackSize(i);
|
||||
else
|
||||
{
|
||||
#ifndef _7ZIP_ST
|
||||
thereAreRepacks = true;
|
||||
#endif
|
||||
complexity += repackSize;
|
||||
if (inSizeForReduce2 < repackSize)
|
||||
inSizeForReduce2 = repackSize;
|
||||
@@ -1727,10 +1731,12 @@ HRESULT Update(
|
||||
#ifndef _7ZIP_ST
|
||||
|
||||
CStreamBinder sb;
|
||||
/*
|
||||
if (options.MultiThreadMixer)
|
||||
{
|
||||
RINOK(sb.CreateEvents());
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1742,7 +1748,9 @@ HRESULT Update(
|
||||
#ifdef EXTERNAL_CODECS
|
||||
threadDecoder.__externalCodecs = __externalCodecs;
|
||||
#endif
|
||||
RINOK(threadDecoder.Create());
|
||||
WRes wres = threadDecoder.Create();
|
||||
if (wres != 0)
|
||||
return HRESULT_FROM_WIN32(wres);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1887,7 +1895,7 @@ HRESULT Update(
|
||||
if (ui.HasStream())
|
||||
continue;
|
||||
}
|
||||
else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream)
|
||||
else if (ui.IndexInArchive != -1 && db->Files[(unsigned)ui.IndexInArchive].HasStream)
|
||||
continue;
|
||||
/*
|
||||
if (ui.TreeFolderIndex >= 0)
|
||||
@@ -1912,8 +1920,8 @@ HRESULT Update(
|
||||
}
|
||||
else
|
||||
{
|
||||
GetFile(*db, ui.IndexInArchive, file, file2);
|
||||
db->GetPath(ui.IndexInArchive, name);
|
||||
GetFile(*db, (unsigned)ui.IndexInArchive, file, file2);
|
||||
db->GetPath((unsigned)ui.IndexInArchive, name);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2065,7 +2073,7 @@ HRESULT Update(
|
||||
{
|
||||
indexInFolder++;
|
||||
int updateIndex = fileIndexToUpdateIndexMap[fi];
|
||||
if (updateIndex >= 0 && !updateItems[updateIndex].NewData)
|
||||
if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData)
|
||||
needExtract = true;
|
||||
// decodeSize += file.Size;
|
||||
}
|
||||
@@ -2099,8 +2107,8 @@ HRESULT Update(
|
||||
{
|
||||
repackBase = threadDecoder.FosSpec;
|
||||
CMyComPtr<ISequentialOutStream> sbOutStream;
|
||||
sb.CreateStreams(&sbInStream, &sbOutStream);
|
||||
sb.ReInit();
|
||||
sb.CreateStreams2(sbInStream, sbOutStream);
|
||||
RINOK(sb.Create_ReInit());
|
||||
|
||||
threadDecoder.FosSpec->_stream = sbOutStream;
|
||||
|
||||
@@ -2171,7 +2179,9 @@ HRESULT Update(
|
||||
#ifndef _7ZIP_ST
|
||||
if (options.MultiThreadMixer)
|
||||
{
|
||||
threadDecoder.Start();
|
||||
WRes wres = threadDecoder.Start();
|
||||
if (wres != 0)
|
||||
return HRESULT_FROM_WIN32(wres);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -2197,7 +2207,11 @@ HRESULT Update(
|
||||
inStreamSizeCount.Release();
|
||||
sbInStream.Release();
|
||||
|
||||
threadDecoder.WaitExecuteFinish();
|
||||
{
|
||||
WRes wres = threadDecoder.WaitExecuteFinish();
|
||||
if (wres != 0)
|
||||
return HRESULT_FROM_WIN32(wres);
|
||||
}
|
||||
|
||||
HRESULT decodeRes = threadDecoder.Result;
|
||||
// if (res == k_My_HRESULT_CRC_ERROR)
|
||||
@@ -2259,7 +2273,7 @@ HRESULT Update(
|
||||
int updateIndex = fileIndexToUpdateIndexMap[fi];
|
||||
if (updateIndex >= 0)
|
||||
{
|
||||
const CUpdateItem &ui = updateItems[updateIndex];
|
||||
const CUpdateItem &ui = updateItems[(unsigned)updateIndex];
|
||||
if (ui.NewData)
|
||||
continue;
|
||||
|
||||
@@ -2347,7 +2361,7 @@ HRESULT Update(
|
||||
{
|
||||
int slashPos = ui.Name.ReverseFind_PathSepar();
|
||||
int dotPos = ui.Name.ReverseFind_Dot();
|
||||
const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : dotPos + 1);
|
||||
const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : (unsigned)(dotPos + 1));
|
||||
if (numSubFiles == 0)
|
||||
prevExtension = ext;
|
||||
else if (!StringsAreEqualNoCase(ext, prevExtension))
|
||||
@@ -2403,8 +2417,8 @@ HRESULT Update(
|
||||
}
|
||||
else
|
||||
{
|
||||
GetFile(*db, ui.IndexInArchive, file, file2);
|
||||
db->GetPath(ui.IndexInArchive, name);
|
||||
GetFile(*db, (unsigned)ui.IndexInArchive, file, file2);
|
||||
db->GetPath((unsigned)ui.IndexInArchive, name);
|
||||
}
|
||||
if (file2.IsAnti || file.IsDir)
|
||||
return E_FAIL;
|
||||
|
||||
@@ -31,7 +31,7 @@ struct CTreeFolder
|
||||
struct CUpdateItem
|
||||
{
|
||||
int IndexInArchive;
|
||||
int IndexInClient;
|
||||
unsigned IndexInClient;
|
||||
|
||||
UInt64 CTime;
|
||||
UInt64 ATime;
|
||||
|
||||
@@ -240,7 +240,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
mainIndex = -1;
|
||||
break;
|
||||
}
|
||||
mainIndex = i;
|
||||
mainIndex = (int)i;
|
||||
}
|
||||
}
|
||||
if (mainIndex >= 0)
|
||||
|
||||
@@ -618,13 +618,15 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
_items.DeleteFrontal(1);
|
||||
for (unsigned i = 0; i < _items.Size(); i++)
|
||||
if (_items[i].Name.IsPrefixedBy("data.tar."))
|
||||
{
|
||||
if (_mainSubfile < 0)
|
||||
_mainSubfile = i;
|
||||
_mainSubfile = (int)i;
|
||||
else
|
||||
{
|
||||
_mainSubfile = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -845,7 +847,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
}
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"Ar", "ar a deb lib", 0, 0xEC,
|
||||
"Ar", "ar a deb udeb lib", 0, 0xEC,
|
||||
kSignature,
|
||||
0,
|
||||
0,
|
||||
|
||||
@@ -46,7 +46,7 @@ static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
|
||||
return SetPropStrFromBin((const char *)&guid, sizeof(guid), value);
|
||||
}
|
||||
|
||||
int FindFormatCalssId(const GUID *clsid)
|
||||
static int FindFormatCalssId(const GUID *clsid)
|
||||
{
|
||||
GUID cls = *clsid;
|
||||
CLS_ARC_ID_ITEM(cls) = 0;
|
||||
@@ -59,6 +59,7 @@ int FindFormatCalssId(const GUID *clsid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);
|
||||
STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -89,6 +90,7 @@ STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value);
|
||||
STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -130,17 +132,20 @@ STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value);
|
||||
STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
return GetHandlerProperty2(g_DefaultArcIndex, propID, value);
|
||||
}
|
||||
|
||||
STDAPI GetNumberOfFormats(UINT32 *numFormats);
|
||||
STDAPI GetNumberOfFormats(UINT32 *numFormats)
|
||||
{
|
||||
*numFormats = g_NumArcs;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc);
|
||||
STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc)
|
||||
{
|
||||
*isArc = NULL;
|
||||
|
||||
@@ -235,13 +235,13 @@ namespace NFileType
|
||||
namespace NFlags
|
||||
{
|
||||
const Byte kGarbled = 1 << 0;
|
||||
const Byte kAnsiPage = 1 << 1; // or (OLD_SECURED_FLAG) obsolete
|
||||
// const Byte kAnsiPage = 1 << 1; // or (OLD_SECURED_FLAG) obsolete
|
||||
const Byte kVolume = 1 << 2;
|
||||
const Byte kExtFile = 1 << 3;
|
||||
const Byte kPathSym = 1 << 4;
|
||||
const Byte kBackup = 1 << 5; // obsolete
|
||||
const Byte kSecured = 1 << 6;
|
||||
const Byte kDualName = 1 << 7;
|
||||
// const Byte kPathSym = 1 << 4;
|
||||
// const Byte kBackup = 1 << 5; // obsolete
|
||||
// const Byte kSecured = 1 << 6;
|
||||
// const Byte kDualName = 1 << 7;
|
||||
}
|
||||
|
||||
namespace NHostOS
|
||||
@@ -375,6 +375,32 @@ HRESULT CArcHeader::Parse(const Byte *p, unsigned size)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
struct CExtendedInfo
|
||||
{
|
||||
UInt64 Size;
|
||||
bool CrcError;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Size = 0;
|
||||
CrcError = false;
|
||||
}
|
||||
void ParseToPropVar(NCOM::CPropVariant &prop) const
|
||||
{
|
||||
if (Size != 0)
|
||||
{
|
||||
AString s;
|
||||
s += "Extended:";
|
||||
s.Add_UInt32((UInt32)Size);
|
||||
if (CrcError)
|
||||
s += ":CRC_ERROR";
|
||||
prop = s;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CItem
|
||||
{
|
||||
AString Name;
|
||||
@@ -399,6 +425,8 @@ struct CItem
|
||||
// Byte LastChapter;
|
||||
|
||||
UInt64 DataPosition;
|
||||
|
||||
CExtendedInfo ExtendedInfo;
|
||||
|
||||
bool IsEncrypted() const { return (Flags & NFlags::kGarbled) != 0; }
|
||||
bool IsDir() const { return (FileType == NFileType::kDirectory); }
|
||||
@@ -462,7 +490,7 @@ enum EErrorType
|
||||
{
|
||||
k_ErrorType_OK,
|
||||
k_ErrorType_Corrupted,
|
||||
k_ErrorType_UnexpectedEnd,
|
||||
k_ErrorType_UnexpectedEnd
|
||||
};
|
||||
|
||||
class CArc
|
||||
@@ -476,19 +504,22 @@ public:
|
||||
UInt64 NumFiles;
|
||||
CArcHeader Header;
|
||||
|
||||
CExtendedInfo ExtendedInfo;
|
||||
|
||||
HRESULT Open();
|
||||
HRESULT GetNextItem(CItem &item, bool &filled);
|
||||
void Close()
|
||||
{
|
||||
IsArc = false;
|
||||
Error = k_ErrorType_OK;
|
||||
ExtendedInfo.Clear();
|
||||
}
|
||||
private:
|
||||
UInt32 _blockSize;
|
||||
Byte _block[kBlockSizeMax + 4];
|
||||
unsigned _blockSize;
|
||||
CByteBuffer _block;
|
||||
|
||||
HRESULT ReadBlock(bool &filled, bool readSignature);
|
||||
HRESULT SkipExtendedHeaders();
|
||||
HRESULT ReadBlock(bool &filled, CExtendedInfo *extendedInfo);
|
||||
HRESULT SkipExtendedHeaders(CExtendedInfo &extendedInfo);
|
||||
HRESULT Read(void *data, size_t *size);
|
||||
};
|
||||
|
||||
@@ -503,14 +534,14 @@ HRESULT CArc::Read(void *data, size_t *size)
|
||||
{ size_t _processed_ = (_size_); RINOK(Read(_dest_, &_processed_)); \
|
||||
if (_processed_ != (_size_)) { Error = k_ErrorType_UnexpectedEnd; return S_OK; } }
|
||||
|
||||
HRESULT CArc::ReadBlock(bool &filled, bool readSignature)
|
||||
HRESULT CArc::ReadBlock(bool &filled, CExtendedInfo *extendedInfo)
|
||||
{
|
||||
Error = k_ErrorType_OK;
|
||||
filled = false;
|
||||
Byte buf[4];
|
||||
unsigned signSize = readSignature ? 2 : 0;
|
||||
const unsigned signSize = extendedInfo ? 0 : 2;
|
||||
READ_STREAM(buf, signSize + 2)
|
||||
if (readSignature)
|
||||
if (!extendedInfo)
|
||||
if (buf[0] != kSig0 || buf[1] != kSig1)
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
@@ -519,28 +550,48 @@ HRESULT CArc::ReadBlock(bool &filled, bool readSignature)
|
||||
_blockSize = Get16(buf + signSize);
|
||||
if (_blockSize == 0) // end of archive
|
||||
return S_OK;
|
||||
if (_blockSize < kBlockSizeMin ||
|
||||
_blockSize > kBlockSizeMax)
|
||||
|
||||
if (!extendedInfo)
|
||||
if (_blockSize < kBlockSizeMin || _blockSize > kBlockSizeMax)
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
const size_t readSize = _blockSize + 4;
|
||||
if (readSize > _block.Size())
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
return S_OK;
|
||||
// extended data size is limited by (64 KB)
|
||||
// _blockSize is less than 64 KB
|
||||
const size_t upSize = (_blockSize > kBlockSizeMax ? (1 << 16) : kBlockSizeMax);
|
||||
_block.Alloc(upSize + 4);
|
||||
}
|
||||
READ_STREAM(_block, _blockSize + 4);
|
||||
|
||||
if (extendedInfo)
|
||||
extendedInfo->Size += _blockSize;
|
||||
|
||||
READ_STREAM(_block, readSize);
|
||||
if (Get32(_block + _blockSize) != CrcCalc(_block, _blockSize))
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
return S_OK;
|
||||
if (extendedInfo)
|
||||
extendedInfo->CrcError = true;
|
||||
else
|
||||
{
|
||||
Error = k_ErrorType_Corrupted;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
filled = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CArc::SkipExtendedHeaders()
|
||||
HRESULT CArc::SkipExtendedHeaders(CExtendedInfo &extendedInfo)
|
||||
{
|
||||
extendedInfo.Clear();
|
||||
for (UInt32 i = 0;; i++)
|
||||
{
|
||||
bool filled;
|
||||
RINOK(ReadBlock(filled, false));
|
||||
RINOK(ReadBlock(filled, &extendedInfo));
|
||||
if (!filled)
|
||||
return S_OK;
|
||||
if (Callback && (i & 0xFF) == 0)
|
||||
@@ -551,17 +602,17 @@ HRESULT CArc::SkipExtendedHeaders()
|
||||
HRESULT CArc::Open()
|
||||
{
|
||||
bool filled;
|
||||
RINOK(ReadBlock(filled, true));
|
||||
RINOK(ReadBlock(filled, NULL)); // (extendedInfo = NULL)
|
||||
if (!filled)
|
||||
return S_FALSE;
|
||||
RINOK(Header.Parse(_block, _blockSize));
|
||||
IsArc = true;
|
||||
return SkipExtendedHeaders();
|
||||
return SkipExtendedHeaders(ExtendedInfo);
|
||||
}
|
||||
|
||||
HRESULT CArc::GetNextItem(CItem &item, bool &filled)
|
||||
{
|
||||
RINOK(ReadBlock(filled, true));
|
||||
RINOK(ReadBlock(filled, NULL)); // (extendedInfo = NULL)
|
||||
if (!filled)
|
||||
return S_OK;
|
||||
filled = false;
|
||||
@@ -576,7 +627,7 @@ HRESULT CArc::GetNextItem(CItem &item, bool &filled)
|
||||
extraData = GetUi32(_block + pos);
|
||||
*/
|
||||
|
||||
RINOK(SkipExtendedHeaders());
|
||||
RINOK(SkipExtendedHeaders(item.ExtendedInfo));
|
||||
filled = true;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -603,7 +654,8 @@ static const Byte kArcProps[] =
|
||||
kpidCTime,
|
||||
kpidMTime,
|
||||
kpidHostOS,
|
||||
kpidComment
|
||||
kpidComment,
|
||||
kpidCharacts
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
@@ -619,7 +671,8 @@ static const Byte kProps[] =
|
||||
kpidCRC,
|
||||
kpidMethod,
|
||||
kpidHostOS,
|
||||
kpidComment
|
||||
kpidComment,
|
||||
kpidCharacts
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
@@ -671,10 +724,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break;
|
||||
case k_ErrorType_Corrupted: v |= kpv_ErrorFlags_HeadersError; break;
|
||||
case k_ErrorType_OK:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
case kpidCharacts: _arc.ExtendedInfo.ParseToPropVar(prop); break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -706,6 +763,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidHostOS: SetHostOS(item.HostOS, prop); break;
|
||||
case kpidMTime: SetTime(item.MTime, prop); break;
|
||||
case kpidComment: SetUnicodeString(item.Comment, prop); break;
|
||||
case kpidCharacts: item.ExtendedInfo.ParseToPropVar(prop); break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
|
||||
511
CPP/7zip/Archive/Base64Handler.cpp
Normal file
511
CPP/7zip/Archive/Base64Handler.cpp
Normal file
@@ -0,0 +1,511 @@
|
||||
// Base64Handler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/IntToString.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
#include "../Common/InBuffer.h"
|
||||
|
||||
/*
|
||||
spaces:
|
||||
9(TAB),10(LF),13(CR),32(SPACE)
|
||||
Non-breaking space:
|
||||
0xa0 : Unicode, Windows code pages 1250-1258
|
||||
0xff (unused): DOS code pages
|
||||
|
||||
end of stream markers: '=' (0x3d):
|
||||
"=" , if numBytes (% 3 == 2)
|
||||
"==" , if numBytes (% 3 == 1)
|
||||
*/
|
||||
|
||||
|
||||
static const Byte k_Base64Table[256] =
|
||||
{
|
||||
66,77,77,77,77,77,77,77,77,65,65,77,77,65,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
65,77,77,77,77,77,77,77,77,77,77,62,77,77,77,63,
|
||||
52,53,54,55,56,57,58,59,60,61,77,77,77,64,77,77,
|
||||
77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
|
||||
15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77,
|
||||
77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
|
||||
41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
65,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77
|
||||
};
|
||||
|
||||
static const unsigned k_Code_Equals = 64;
|
||||
static const unsigned k_Code_Space = 65;
|
||||
static const unsigned k_Code_Zero = 66;
|
||||
|
||||
API_FUNC_static_IsArc IsArc_Base64(const Byte *p, size_t size)
|
||||
{
|
||||
size_t num = 0;
|
||||
size_t firstSpace = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (size == 0)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
UInt32 c = k_Base64Table[(Byte)(*p++)];
|
||||
size--;
|
||||
if (c < 64)
|
||||
{
|
||||
num++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == k_Code_Space)
|
||||
{
|
||||
if (p[-1] == ' ' && firstSpace == 0)
|
||||
firstSpace = num;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c != k_Code_Equals)
|
||||
return k_IsArc_Res_NO;
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
// we try to redece false positive detection here.
|
||||
// we don't expect space character in starting base64 line
|
||||
const unsigned kNumExpectedNonSpaceSyms = 20;
|
||||
if (firstSpace != 0 && firstSpace < num && firstSpace < kNumExpectedNonSpaceSyms)
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
|
||||
num &= 3;
|
||||
|
||||
if (num <= 1)
|
||||
return k_IsArc_Res_NO;
|
||||
if (num != 3)
|
||||
{
|
||||
if (size == 0)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
UInt32 c = k_Base64Table[(Byte)(*p++)];
|
||||
size--;
|
||||
if (c != k_Code_Equals)
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (size == 0)
|
||||
return k_IsArc_Res_YES;
|
||||
UInt32 c = k_Base64Table[(Byte)(*p++)];
|
||||
size--;
|
||||
if (c == k_Code_Space)
|
||||
continue;
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum EBase64Res
|
||||
{
|
||||
k_Base64_RES_MaybeFinished,
|
||||
k_Base64_RES_Finished,
|
||||
k_Base64_RES_NeedMoreInput,
|
||||
k_Base64_RES_UnexpectedChar
|
||||
};
|
||||
|
||||
|
||||
static EBase64Res Base64ToBin(Byte *p, size_t size, const Byte **srcEnd, Byte **destEnd)
|
||||
{
|
||||
Byte *dest = p;
|
||||
UInt32 val = 1;
|
||||
EBase64Res res = k_Base64_RES_NeedMoreInput;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
if (val == 1)
|
||||
res = k_Base64_RES_MaybeFinished;
|
||||
break;
|
||||
}
|
||||
UInt32 c = k_Base64Table[(Byte)(*p++)];
|
||||
size--;
|
||||
if (c < 64)
|
||||
{
|
||||
val = (val << 6) | c;
|
||||
if ((val & ((UInt32)1 << 24)) == 0)
|
||||
continue;
|
||||
dest[0] = (Byte)(val >> 16);
|
||||
dest[1] = (Byte)(val >> 8);
|
||||
dest[2] = (Byte)(val);
|
||||
dest += 3;
|
||||
val = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == k_Code_Space)
|
||||
continue;
|
||||
|
||||
if (c == k_Code_Equals)
|
||||
{
|
||||
if (val >= (1 << 12))
|
||||
{
|
||||
if (val & (1 << 18))
|
||||
{
|
||||
res = k_Base64_RES_Finished;
|
||||
break;
|
||||
}
|
||||
if (size == 0)
|
||||
break;
|
||||
c = k_Base64Table[(Byte)(*p++)];
|
||||
size--;
|
||||
if (c == k_Code_Equals)
|
||||
{
|
||||
res = k_Base64_RES_Finished;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p--;
|
||||
res = k_Base64_RES_UnexpectedChar;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val >= ((UInt32)1 << 12))
|
||||
{
|
||||
if (val & (1 << 18))
|
||||
{
|
||||
*dest++ = (Byte)(val >> 10);
|
||||
val <<= 2;
|
||||
}
|
||||
*dest++ = (Byte)(val >> 4);
|
||||
}
|
||||
|
||||
*srcEnd = p;
|
||||
*destEnd = dest;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static const Byte *Base64_SkipSpaces(const Byte *p, size_t size)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (size == 0)
|
||||
return p;
|
||||
UInt32 c = k_Base64Table[(Byte)(*p++)];
|
||||
size--;
|
||||
if (c == k_Code_Space)
|
||||
continue;
|
||||
return p - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// the following function is used by DmgHandler.cpp
|
||||
|
||||
Byte *Base64ToBin(Byte *dest, const char *src);
|
||||
Byte *Base64ToBin(Byte *dest, const char *src)
|
||||
{
|
||||
UInt32 val = 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
UInt32 c = k_Base64Table[(Byte)(*src++)];
|
||||
|
||||
if (c < 64)
|
||||
{
|
||||
val = (val << 6) | c;
|
||||
if ((val & ((UInt32)1 << 24)) == 0)
|
||||
continue;
|
||||
dest[0] = (Byte)(val >> 16);
|
||||
dest[1] = (Byte)(val >> 8);
|
||||
dest[2] = (Byte)(val);
|
||||
dest += 3;
|
||||
val = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == k_Code_Space)
|
||||
continue;
|
||||
|
||||
if (c == k_Code_Equals)
|
||||
break;
|
||||
|
||||
if (c == k_Code_Zero && val == 1) // end of string
|
||||
return dest;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (val < (1 << 12))
|
||||
return NULL;
|
||||
|
||||
if (val & (1 << 18))
|
||||
{
|
||||
*dest++ = (Byte)(val >> 10);
|
||||
val <<= 2;
|
||||
}
|
||||
else if (k_Base64Table[(Byte)(*src++)] != k_Code_Equals)
|
||||
return NULL;
|
||||
*dest++ = (Byte)(val >> 4);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte c = k_Base64Table[(Byte)(*src++)];
|
||||
if (c == k_Code_Space)
|
||||
continue;
|
||||
if (c == k_Code_Zero)
|
||||
return dest;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace NArchive {
|
||||
namespace NBase64 {
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
bool _isArc;
|
||||
UInt64 _phySize;
|
||||
size_t _size;
|
||||
EBase64Res _sres;
|
||||
CByteBuffer _data;
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(IInArchive)
|
||||
INTERFACE_IInArchive(;)
|
||||
};
|
||||
|
||||
static const Byte kProps[] =
|
||||
{
|
||||
kpidSize,
|
||||
kpidPackSize,
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps_NO_Table
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
*numItems = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPhySize: if (_phySize != 0) prop = _phySize; break;
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
if (_sres == k_Base64_RES_NeedMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
if (v != 0)
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
// COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidSize: prop = (UInt64)_size; break;
|
||||
case kpidPackSize: prop = _phySize; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
// COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
static HRESULT ReadStream_OpenProgress(ISequentialInStream *stream, void *data, size_t size, IArchiveOpenCallback *openCallback) throw()
|
||||
{
|
||||
UInt64 bytes = 0;
|
||||
while (size != 0)
|
||||
{
|
||||
const UInt32 kBlockSize = ((UInt32)1 << 24);
|
||||
UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;
|
||||
UInt32 processedSizeLoc;
|
||||
RINOK(stream->Read(data, curSize, &processedSizeLoc));
|
||||
if (processedSizeLoc == 0)
|
||||
return E_FAIL;
|
||||
data = (void *)((Byte *)data + processedSizeLoc);
|
||||
size -= processedSizeLoc;
|
||||
bytes += processedSizeLoc;
|
||||
const UInt64 files = 1;
|
||||
RINOK(openCallback->SetCompleted(&files, &bytes));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
{
|
||||
Close();
|
||||
{
|
||||
const unsigned kStartSize = 1 << 12;
|
||||
_data.Alloc(kStartSize);
|
||||
size_t size = kStartSize;
|
||||
RINOK(ReadStream(stream, _data, &size));
|
||||
UInt32 isArcRes = IsArc_Base64(_data, size);
|
||||
if (isArcRes == k_IsArc_Res_NO)
|
||||
return S_FALSE;
|
||||
}
|
||||
_isArc = true;
|
||||
|
||||
UInt64 packSize64;
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &packSize64));
|
||||
|
||||
if (packSize64 == 0)
|
||||
return S_FALSE;
|
||||
|
||||
size_t curSize = 1 << 16;
|
||||
if (curSize > packSize64)
|
||||
curSize = (size_t)packSize64;
|
||||
const unsigned kLogStep = 4;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
|
||||
_data.Alloc(curSize);
|
||||
RINOK(ReadStream_OpenProgress(stream, _data, curSize, openCallback));
|
||||
|
||||
const Byte *srcEnd;
|
||||
Byte *dest;
|
||||
_sres = Base64ToBin(_data, curSize, &srcEnd, &dest);
|
||||
_size = dest - _data;
|
||||
size_t mainSize = srcEnd - _data;
|
||||
_phySize = mainSize;
|
||||
if (_sres == k_Base64_RES_UnexpectedChar)
|
||||
break;
|
||||
if (curSize != mainSize)
|
||||
{
|
||||
const Byte *end2 = Base64_SkipSpaces(srcEnd, curSize - mainSize);
|
||||
if ((size_t)(end2 - _data) != curSize)
|
||||
break;
|
||||
_phySize = curSize;
|
||||
}
|
||||
|
||||
if (curSize == packSize64)
|
||||
break;
|
||||
|
||||
UInt64 curSize64 = packSize64;
|
||||
if (curSize < (packSize64 >> kLogStep))
|
||||
curSize64 = (UInt64)curSize << kLogStep;
|
||||
curSize = (size_t)curSize64;
|
||||
if (curSize != curSize64)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
if (_size == 0)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_phySize = 0;
|
||||
_size = 0;
|
||||
_isArc = false;
|
||||
_sres = k_Base64_RES_MaybeFinished;
|
||||
_data.Free();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = 1;
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
if (numItems != 1 || *indices != 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
RINOK(extractCallback->SetTotal(_size));
|
||||
|
||||
CLocalProgress *lps = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(extractCallback, false);
|
||||
|
||||
{
|
||||
lps->InSize = lps->OutSize = 0;
|
||||
RINOK(lps->SetCur());
|
||||
|
||||
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);
|
||||
|
||||
if (realOutStream)
|
||||
{
|
||||
RINOK(WriteStream(realOutStream, (const Byte *)_data, _size));
|
||||
realOutStream.Release();
|
||||
}
|
||||
|
||||
Int32 opRes = NExtract::NOperationResult::kOK;
|
||||
|
||||
if (_sres != k_Base64_RES_Finished)
|
||||
{
|
||||
if (_sres == k_Base64_RES_NeedMoreInput)
|
||||
opRes = NExtract::NOperationResult::kUnexpectedEnd;
|
||||
else if (_sres == k_Base64_RES_UnexpectedChar)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
}
|
||||
|
||||
RINOK(extractCallback->SetOperationResult(opRes));
|
||||
}
|
||||
|
||||
lps->InSize = _phySize;
|
||||
lps->OutSize = _size;
|
||||
return lps->SetCur();
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
REGISTER_ARC_I_NO_SIG(
|
||||
"Base64", "b64", 0, 0xC5,
|
||||
0,
|
||||
NArcInfoFlags::kKeepName | NArcInfoFlags::kStartOpen | NArcInfoFlags::kByExtOnlyOpen,
|
||||
IsArc_Base64)
|
||||
|
||||
}}
|
||||
@@ -309,11 +309,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
|
||||
case kpidMethod:
|
||||
{
|
||||
UInt32 realFolderIndex = item.GetFolderIndex(db.Folders.Size());
|
||||
const CFolder &folder = db.Folders[realFolderIndex];
|
||||
char s[kMethodNameBufSize];;
|
||||
SetMethodName(s, folder.GetMethod(), folder.MethodMinor);
|
||||
prop = s;
|
||||
const int realFolderIndex = item.GetFolderIndex(db.Folders.Size());
|
||||
if (realFolderIndex >= 0)
|
||||
{
|
||||
const CFolder &folder = db.Folders[(unsigned)realFolderIndex];
|
||||
char s[kMethodNameBufSize];;
|
||||
SetMethodName(s, folder.GetMethod(), folder.MethodMinor);
|
||||
prop = s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -341,7 +344,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
|
||||
CInArchive archive;
|
||||
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
|
||||
callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
|
||||
if (callback)
|
||||
callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
|
||||
|
||||
CMyComPtr<IInStream> nextStream = inStream;
|
||||
bool prevChecked = false;
|
||||
@@ -420,7 +424,10 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(callback->SetCompleted(&numItems, NULL));
|
||||
if (callback)
|
||||
{
|
||||
RINOK(callback->SetCompleted(&numItems, NULL));
|
||||
}
|
||||
|
||||
nextStream = NULL;
|
||||
|
||||
@@ -1007,7 +1014,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned startIndex2 = m_Database.FolderStartFileIndex[folderIndex];
|
||||
const unsigned startIndex2 = m_Database.FolderStartFileIndex[(unsigned)folderIndex];
|
||||
unsigned startIndex = startIndex2;
|
||||
extractStatuses.Clear();
|
||||
for (; startIndex < index; startIndex++)
|
||||
@@ -1037,8 +1044,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
CFolderOutStream *cabFolderOutStream = new CFolderOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream(cabFolderOutStream);
|
||||
|
||||
unsigned folderIndex2 = item.GetFolderIndex(db.Folders.Size());
|
||||
const CFolder &folder = db.Folders[folderIndex2];
|
||||
const int folderIndex2 = item.GetFolderIndex(db.Folders.Size());
|
||||
if (folderIndex2 < 0)
|
||||
return E_FAIL;
|
||||
const CFolder &folder = db.Folders[(unsigned)folderIndex2];
|
||||
|
||||
cabFolderOutStream->Init(&m_Database, &extractStatuses, startIndex2,
|
||||
curUnpack, extractCallback, testMode);
|
||||
@@ -1107,12 +1116,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
}
|
||||
|
||||
const CDatabaseEx &db2 = m_Database.Volumes[volIndex];
|
||||
const CFolder &folder2 = db2.Folders[locFolderIndex];
|
||||
if (locFolderIndex < 0)
|
||||
return E_FAIL;
|
||||
const CFolder &folder2 = db2.Folders[(unsigned)locFolderIndex];
|
||||
|
||||
if (bl == 0)
|
||||
{
|
||||
cabBlockInStreamSpec->ReservedSize = db2.ArcInfo.GetDataBlockReserveSize();
|
||||
RINOK(db2.Stream->Seek(db2.StartPosition + folder2.DataStart, STREAM_SEEK_SET, NULL));
|
||||
RINOK(db2.Stream->Seek((Int64)(db2.StartPosition + folder2.DataStart), STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
|
||||
if (bl == folder2.NumDataBlocks)
|
||||
@@ -1242,7 +1253,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
if (res != S_OK || cabFolderOutStream->NeedMoreWrite())
|
||||
{
|
||||
RINOK(cabFolderOutStream->FlushCorrupted(folderIndex2));
|
||||
RINOK(cabFolderOutStream->FlushCorrupted((unsigned)folderIndex2));
|
||||
}
|
||||
|
||||
totalUnPacked += curUnpack;
|
||||
|
||||
@@ -114,8 +114,8 @@ HRESULT CSignatureFinder::Find()
|
||||
Byte b = Signature[0];
|
||||
for (;;)
|
||||
{
|
||||
if (*p == b) break; p++;
|
||||
if (*p == b) break; p++;
|
||||
if (*p == b) { break; } p++;
|
||||
if (*p == b) { break; } p++;
|
||||
}
|
||||
Pos = (UInt32)(p - Buf);
|
||||
if (End - Pos < _HeaderSize)
|
||||
@@ -311,7 +311,7 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
|
||||
{
|
||||
// printf("\n!!! Seek Error !!!!\n");
|
||||
// fflush(stdout);
|
||||
RINOK(db.Stream->Seek(db.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL));
|
||||
RINOK(db.Stream->Seek((Int64)(db.StartPosition + ai.FileHeadersOffset), STREAM_SEEK_SET, NULL));
|
||||
limitedStreamSpec->Init(ai.Size - ai.FileHeadersOffset);
|
||||
_inBuffer.Init();
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ struct CDatabase
|
||||
|
||||
int GetNumberOfNewFolders() const
|
||||
{
|
||||
int res = Folders.Size();
|
||||
int res = (int)Folders.Size();
|
||||
if (IsTherePrevFolder())
|
||||
res--;
|
||||
return res;
|
||||
|
||||
@@ -56,8 +56,8 @@ struct CItem
|
||||
if (ContinuedFromPrev())
|
||||
return 0;
|
||||
if (ContinuedToNext())
|
||||
return numFolders - 1;
|
||||
return FolderIndex;
|
||||
return (int)numFolders - 1;
|
||||
return (int)FolderIndex;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -145,10 +145,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidMethod:
|
||||
{
|
||||
if (!item.IsDir())
|
||||
{
|
||||
if (item.Section == 0)
|
||||
prop = "Copy";
|
||||
else if (item.Section < m_Database.Sections.Size())
|
||||
prop = m_Database.Sections[(unsigned)item.Section].GetMethodName();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kpidBlock:
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include "ChmIn.h"
|
||||
|
||||
#define Get16(p) GetUi16(p)
|
||||
#define Get32(p) GetUi32(p)
|
||||
#define Get64(p) GetUi64(p)
|
||||
|
||||
@@ -117,7 +116,7 @@ UString CSectionInfo::GetMethodName() const
|
||||
if (!IsLzx())
|
||||
{
|
||||
UString temp;
|
||||
if (ConvertUTF8ToUnicode(Name, temp))
|
||||
ConvertUTF8ToUnicode(Name, temp);
|
||||
s += temp;
|
||||
s += ": ";
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ enum EType
|
||||
k_Type_Msp,
|
||||
k_Type_Doc,
|
||||
k_Type_Ppt,
|
||||
k_Type_Xls,
|
||||
k_Type_Xls
|
||||
};
|
||||
|
||||
static const char * const kExtensions[] =
|
||||
@@ -51,10 +51,10 @@ static const char * const kExtensions[] =
|
||||
|
||||
namespace NFatID
|
||||
{
|
||||
static const UInt32 kFree = 0xFFFFFFFF;
|
||||
// static const UInt32 kFree = 0xFFFFFFFF;
|
||||
static const UInt32 kEndOfChain = 0xFFFFFFFE;
|
||||
static const UInt32 kFatSector = 0xFFFFFFFD;
|
||||
static const UInt32 kMatSector = 0xFFFFFFFC;
|
||||
// static const UInt32 kFatSector = 0xFFFFFFFD;
|
||||
// static const UInt32 kMatSector = 0xFFFFFFFC;
|
||||
static const UInt32 kMaxValue = 0xFFFFFFFA;
|
||||
}
|
||||
|
||||
@@ -62,9 +62,9 @@ namespace NItemType
|
||||
{
|
||||
static const Byte kEmpty = 0;
|
||||
static const Byte kStorage = 1;
|
||||
static const Byte kStream = 2;
|
||||
static const Byte kLockBytes = 3;
|
||||
static const Byte kProperty = 4;
|
||||
// static const Byte kStream = 2;
|
||||
// static const Byte kLockBytes = 3;
|
||||
// static const Byte kProperty = 4;
|
||||
static const Byte kRootStorage = 5;
|
||||
}
|
||||
|
||||
@@ -298,7 +298,7 @@ static bool CompoundMsiNameToFileName(const UString &name, UString &res)
|
||||
for (unsigned i = 0; i < name.Len(); i++)
|
||||
{
|
||||
wchar_t c = name[i];
|
||||
if (c < k_Msi_StartUnicodeChar || c > k_Msi_StartUnicodeChar + k_Msi_UnicodeRange)
|
||||
if (c < (wchar_t)k_Msi_StartUnicodeChar || c > (wchar_t)(k_Msi_StartUnicodeChar + k_Msi_UnicodeRange))
|
||||
return false;
|
||||
/*
|
||||
if (i == 0)
|
||||
@@ -578,11 +578,10 @@ HRESULT CDatabase::Open(IInStream *inStream)
|
||||
{
|
||||
// bool isThereExt = (msiName.Find(L'.') >= 0);
|
||||
bool isMsiSpec = (msiName[0] == k_Msi_SpecChar);
|
||||
if (msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab")
|
||||
|| !isMsiSpec && msiName.Len() >= 3 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe")
|
||||
// || !isMsiSpec && !isThereExt
|
||||
if ((msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab"))
|
||||
|| (!isMsiSpec && msiName.Len() >= 3 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe"))
|
||||
// || (!isMsiSpec && !isThereExt)
|
||||
)
|
||||
|
||||
{
|
||||
numCabs++;
|
||||
MainSubfile = i;
|
||||
|
||||
@@ -137,7 +137,7 @@ bool CBondsChecks::CheckCoder(unsigned coderIndex)
|
||||
return false;
|
||||
_coderUsed[coderIndex] = true;
|
||||
|
||||
UInt32 start = BindInfo->Coder_to_Stream[coderIndex];
|
||||
const UInt32 start = BindInfo->Coder_to_Stream[coderIndex];
|
||||
|
||||
for (unsigned i = 0; i < coder.NumStreams; i++)
|
||||
{
|
||||
@@ -146,10 +146,10 @@ bool CBondsChecks::CheckCoder(unsigned coderIndex)
|
||||
if (BindInfo->IsStream_in_PackStreams(ind))
|
||||
continue;
|
||||
|
||||
int bond = BindInfo->FindBond_for_PackStream(ind);
|
||||
const int bond = BindInfo->FindBond_for_PackStream(ind);
|
||||
if (bond < 0)
|
||||
return false;
|
||||
if (!CheckCoder(BindInfo->Bonds[bond].UnpackIndex))
|
||||
if (!CheckCoder(BindInfo->Bonds[(unsigned)bond].UnpackIndex))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -246,15 +246,15 @@ bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex)
|
||||
if (coderIndex == _bi.UnpackCoder)
|
||||
return true;
|
||||
|
||||
int bond = _bi.FindBond_for_UnpackStream(coderIndex);
|
||||
const int bond = _bi.FindBond_for_UnpackStream(coderIndex);
|
||||
if (bond < 0)
|
||||
throw 20150213;
|
||||
|
||||
/*
|
||||
UInt32 coderIndex, coderStreamIndex;
|
||||
_bi.GetCoder_for_Stream(_bi.Bonds[bond].PackIndex, coderIndex, coderStreamIndex);
|
||||
_bi.GetCoder_for_Stream(_bi.Bonds[(unsigned)bond].PackIndex, coderIndex, coderStreamIndex);
|
||||
*/
|
||||
UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[bond].PackIndex];
|
||||
const UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[(unsigned)bond].PackIndex];
|
||||
|
||||
if (!IsFilter_Vector[nextCoder])
|
||||
return false;
|
||||
@@ -267,11 +267,11 @@ bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex)
|
||||
if (_bi.IsStream_in_PackStreams(streamIndex))
|
||||
return true;
|
||||
|
||||
int bond = _bi.FindBond_for_PackStream(streamIndex);
|
||||
const int bond = _bi.FindBond_for_PackStream(streamIndex);
|
||||
if (bond < 0)
|
||||
throw 20150213;
|
||||
|
||||
UInt32 nextCoder = _bi.Bonds[bond].UnpackIndex;
|
||||
const UInt32 nextCoder = _bi.Bonds[(unsigned)bond].UnpackIndex;
|
||||
|
||||
if (!IsFilter_Vector[nextCoder])
|
||||
return false;
|
||||
@@ -281,8 +281,8 @@ bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex)
|
||||
|
||||
bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex)
|
||||
{
|
||||
UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
|
||||
UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
|
||||
const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
|
||||
const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
|
||||
for (UInt32 i = 0; i < numStreams; i++)
|
||||
if (!Is_PackSize_Correct_for_Stream(startIndex + i))
|
||||
return false;
|
||||
@@ -293,19 +293,19 @@ bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex)
|
||||
{
|
||||
if (IsExternal_Vector[coderIndex])
|
||||
return true;
|
||||
UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
|
||||
UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
|
||||
const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
|
||||
const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
|
||||
for (UInt32 i = 0; i < numStreams; i++)
|
||||
{
|
||||
UInt32 si = startIndex + i;
|
||||
const UInt32 si = startIndex + i;
|
||||
if (_bi.IsStream_in_PackStreams(si))
|
||||
continue;
|
||||
|
||||
int bond = _bi.FindBond_for_PackStream(si);
|
||||
const int bond = _bi.FindBond_for_PackStream(si);
|
||||
if (bond < 0)
|
||||
throw 20150213;
|
||||
|
||||
if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[bond].UnpackIndex))
|
||||
if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[(unsigned)bond].UnpackIndex))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -360,7 +360,7 @@ CCoder &CMixerST::GetCoder(unsigned index)
|
||||
return _coders[index];
|
||||
}
|
||||
|
||||
void CMixerST::ReInit() {}
|
||||
HRESULT CMixerST::ReInit2() { return S_OK; }
|
||||
|
||||
HRESULT CMixerST::GetInStream2(
|
||||
ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
||||
@@ -444,18 +444,18 @@ HRESULT CMixerST::GetInStream(
|
||||
}
|
||||
}
|
||||
|
||||
int bond = FindBond_for_Stream(
|
||||
const int bond = FindBond_for_Stream(
|
||||
true, // forInputStream
|
||||
inStreamIndex);
|
||||
if (bond < 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
RINOK(GetInStream2(inStreams, /* inSizes, */
|
||||
_bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream));
|
||||
_bi.Bonds[(unsigned)bond].Get_OutIndex(EncodeMode), &seqInStream));
|
||||
|
||||
while (_binderStreams.Size() <= (unsigned)bond)
|
||||
_binderStreams.AddNew();
|
||||
CStBinderStream &bs = _binderStreams[bond];
|
||||
CStBinderStream &bs = _binderStreams[(unsigned)bond];
|
||||
|
||||
if (bs.StreamRef || bs.InStreamSpec)
|
||||
return E_NOTIMPL;
|
||||
@@ -498,13 +498,13 @@ HRESULT CMixerST::GetOutStream(
|
||||
}
|
||||
}
|
||||
|
||||
int bond = FindBond_for_Stream(
|
||||
const int bond = FindBond_for_Stream(
|
||||
false, // forInputStream
|
||||
outStreamIndex);
|
||||
if (bond < 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
|
||||
UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode);
|
||||
|
||||
UInt32 coderIndex = inStreamIndex;
|
||||
UInt32 coderStreamIndex = 0;
|
||||
@@ -560,7 +560,7 @@ HRESULT CMixerST::GetOutStream(
|
||||
|
||||
while (_binderStreams.Size() <= (unsigned)bond)
|
||||
_binderStreams.AddNew();
|
||||
CStBinderStream &bs = _binderStreams[bond];
|
||||
CStBinderStream &bs = _binderStreams[(unsigned)bond];
|
||||
|
||||
if (bs.StreamRef || bs.OutStreamSpec)
|
||||
return E_NOTIMPL;
|
||||
@@ -610,13 +610,13 @@ HRESULT CMixerST::FinishStream(UInt32 streamIndex)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int bond = FindBond_for_Stream(
|
||||
const int bond = FindBond_for_Stream(
|
||||
false, // forInputStream
|
||||
streamIndex);
|
||||
if (bond < 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
|
||||
UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode);
|
||||
|
||||
UInt32 coderIndex = inStreamIndex;
|
||||
UInt32 coderStreamIndex = 0;
|
||||
@@ -654,7 +654,7 @@ void CMixerST::SelectMainCoder(bool useFirst)
|
||||
unsigned ci = _bi.UnpackCoder;
|
||||
|
||||
int firstNonFilter = -1;
|
||||
int firstAllowed = ci;
|
||||
unsigned firstAllowed = ci;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -674,7 +674,7 @@ void CMixerST::SelectMainCoder(bool useFirst)
|
||||
UInt32 st = _bi.Coder_to_Stream[ci];
|
||||
if (_bi.IsStream_in_PackStreams(st))
|
||||
break;
|
||||
int bond = _bi.FindBond_for_PackStream(st);
|
||||
const int bond = _bi.FindBond_for_PackStream(st);
|
||||
if (bond < 0)
|
||||
throw 20150213;
|
||||
|
||||
@@ -682,15 +682,15 @@ void CMixerST::SelectMainCoder(bool useFirst)
|
||||
break;
|
||||
|
||||
if (firstNonFilter == -1 && !IsFilter_Vector[ci])
|
||||
firstNonFilter = ci;
|
||||
firstNonFilter = (int)ci;
|
||||
|
||||
ci = _bi.Bonds[bond].UnpackIndex;
|
||||
ci = _bi.Bonds[(unsigned)bond].UnpackIndex;
|
||||
}
|
||||
|
||||
if (useFirst)
|
||||
ci = firstAllowed;
|
||||
else if (firstNonFilter >= 0)
|
||||
ci = firstNonFilter;
|
||||
ci = (unsigned)firstNonFilter;
|
||||
|
||||
MainCoderIndex = ci;
|
||||
}
|
||||
@@ -919,7 +919,8 @@ HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
|
||||
_streamBinders.Clear();
|
||||
FOR_VECTOR (i, _bi.Bonds)
|
||||
{
|
||||
RINOK(_streamBinders.AddNew().CreateEvents());
|
||||
// RINOK(_streamBinders.AddNew().CreateEvents());
|
||||
_streamBinders.AddNew();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -941,10 +942,13 @@ CCoder &CMixerMT::GetCoder(unsigned index)
|
||||
return _coders[index];
|
||||
}
|
||||
|
||||
void CMixerMT::ReInit()
|
||||
HRESULT CMixerMT::ReInit2()
|
||||
{
|
||||
FOR_VECTOR (i, _streamBinders)
|
||||
_streamBinders[i].ReInit();
|
||||
{
|
||||
RINOK(_streamBinders[i].Create_ReInit());
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CMixerMT::SelectMainCoder(bool useFirst)
|
||||
@@ -962,10 +966,10 @@ void CMixerMT::SelectMainCoder(bool useFirst)
|
||||
UInt32 st = _bi.Coder_to_Stream[ci];
|
||||
if (_bi.IsStream_in_PackStreams(st))
|
||||
break;
|
||||
int bond = _bi.FindBond_for_PackStream(st);
|
||||
const int bond = _bi.FindBond_for_PackStream(st);
|
||||
if (bond < 0)
|
||||
throw 20150213;
|
||||
ci = _bi.Bonds[bond].UnpackIndex;
|
||||
ci = _bi.Bonds[(unsigned)bond].UnpackIndex;
|
||||
}
|
||||
|
||||
MainCoderIndex = ci;
|
||||
@@ -1012,9 +1016,9 @@ HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStr
|
||||
outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
|
||||
}
|
||||
|
||||
_streamBinders[i].CreateStreams(
|
||||
&_coders[inCoderIndex].InStreams[inCoderStreamIndex],
|
||||
&_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
|
||||
_streamBinders[i].CreateStreams2(
|
||||
_coders[inCoderIndex].InStreams[inCoderStreamIndex],
|
||||
_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
|
||||
|
||||
CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
|
||||
_coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
|
||||
@@ -1072,18 +1076,31 @@ HRESULT CMixerMT::Code(
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != MainCoderIndex)
|
||||
{
|
||||
RINOK(_coders[i].Create());
|
||||
const WRes wres = _coders[i].Create();
|
||||
if (wres != 0)
|
||||
return HRESULT_FROM_WIN32(wres);
|
||||
}
|
||||
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != MainCoderIndex)
|
||||
_coders[i].Start();
|
||||
{
|
||||
const WRes wres = _coders[i].Start();
|
||||
if (wres != 0)
|
||||
return HRESULT_FROM_WIN32(wres);
|
||||
}
|
||||
|
||||
_coders[MainCoderIndex].Code(progress);
|
||||
|
||||
WRes wres = 0;
|
||||
for (i = 0; i < _coders.Size(); i++)
|
||||
if (i != MainCoderIndex)
|
||||
_coders[i].WaitExecuteFinish();
|
||||
{
|
||||
WRes wres2 = _coders[i].WaitExecuteFinish();
|
||||
if (wres == 0)
|
||||
wres = wres2;
|
||||
}
|
||||
if (wres != 0)
|
||||
return HRESULT_FROM_WIN32(wres);
|
||||
|
||||
RINOK(ReturnIfError(E_ABORT));
|
||||
RINOK(ReturnIfError(E_OUTOFMEMORY));
|
||||
|
||||
@@ -107,7 +107,7 @@ struct CBindInfo
|
||||
{
|
||||
FOR_VECTOR (i, Bonds)
|
||||
if (Bonds[i].PackIndex == packStream)
|
||||
return i;
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ struct CBindInfo
|
||||
{
|
||||
FOR_VECTOR (i, Bonds)
|
||||
if (Bonds[i].UnpackIndex == unpackStream)
|
||||
return i;
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ struct CBindInfo
|
||||
{
|
||||
FOR_VECTOR(i, PackStreams)
|
||||
if (PackStreams[i] == streamIndex)
|
||||
return i;
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -251,6 +251,7 @@ public:
|
||||
// , InternalPackSizeError(false)
|
||||
{}
|
||||
|
||||
virtual ~CMixer() {};
|
||||
/*
|
||||
Sequence of calling:
|
||||
|
||||
@@ -279,7 +280,7 @@ public:
|
||||
virtual void AddCoder(const CCreatedCoder &cod) = 0;
|
||||
virtual CCoder &GetCoder(unsigned index) = 0;
|
||||
virtual void SelectMainCoder(bool useFirst) = 0;
|
||||
virtual void ReInit() = 0;
|
||||
virtual HRESULT ReInit2() = 0;
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0;
|
||||
virtual HRESULT Code(
|
||||
ISequentialInStream * const *inStreams,
|
||||
@@ -322,6 +323,8 @@ class CMixerST:
|
||||
public CMixer,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLASS_NO_COPY(CMixerST)
|
||||
|
||||
HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
||||
UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
|
||||
HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
|
||||
@@ -345,7 +348,7 @@ public:
|
||||
virtual void AddCoder(const CCreatedCoder &cod);
|
||||
virtual CCoder &GetCoder(unsigned index);
|
||||
virtual void SelectMainCoder(bool useFirst);
|
||||
virtual void ReInit();
|
||||
virtual HRESULT ReInit2();
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
|
||||
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
|
||||
virtual HRESULT Code(
|
||||
@@ -402,7 +405,7 @@ public:
|
||||
};
|
||||
|
||||
CCoderMT(): EncodeMode(false) {}
|
||||
~CCoderMT() { CVirtThread::WaitThreadFinish(); }
|
||||
virtual ~CCoderMT() { CVirtThread::WaitThreadFinish(); }
|
||||
|
||||
void Code(ICompressProgressInfo *progress);
|
||||
};
|
||||
@@ -413,11 +416,14 @@ class CMixerMT:
|
||||
public CMixer,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLASS_NO_COPY(CMixerMT)
|
||||
|
||||
CObjectVector<CStreamBinder> _streamBinders;
|
||||
|
||||
HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
|
||||
HRESULT ReturnIfError(HRESULT code);
|
||||
|
||||
// virtual ~CMixerMT() {};
|
||||
public:
|
||||
CObjectVector<CCoderMT> _coders;
|
||||
|
||||
@@ -427,7 +433,7 @@ public:
|
||||
virtual void AddCoder(const CCreatedCoder &cod);
|
||||
virtual CCoder &GetCoder(unsigned index);
|
||||
virtual void SelectMainCoder(bool useFirst);
|
||||
virtual void ReInit();
|
||||
virtual HRESULT ReInit2();
|
||||
virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
|
||||
{ _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
|
||||
virtual HRESULT Code(
|
||||
|
||||
@@ -179,8 +179,8 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
|
||||
}
|
||||
if (number > 64)
|
||||
return E_FAIL;
|
||||
for (int j = _methods.Size(); j <= (int)number; j++)
|
||||
_methods.Add(COneMethodInfo());
|
||||
for (unsigned j = _methods.Size(); j <= number; j++)
|
||||
_methods.AddNew();
|
||||
return _methods[number].ParseMethodFromPROPVARIANT(realName, value);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,10 @@ namespace NArchive {
|
||||
namespace NItemName {
|
||||
|
||||
static const wchar_t kOsPathSepar = WCHAR_PATH_SEPARATOR;
|
||||
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
static const wchar_t kUnixPathSepar = L'/';
|
||||
#endif
|
||||
|
||||
void ReplaceSlashes_OsToUnix
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
@@ -44,17 +47,35 @@ UString GetOsPath_Remove_TailSlash(const UString &name)
|
||||
}
|
||||
|
||||
|
||||
void ReplaceToOsSlashes_Remove_TailSlash(UString &name)
|
||||
{
|
||||
if (!name.IsEmpty())
|
||||
{
|
||||
void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
name.Replace(kUnixPathSepar, kOsPathSepar);
|
||||
useBackslashReplacement
|
||||
#endif
|
||||
|
||||
if (name.Back() == kOsPathSepar)
|
||||
name.DeleteBack();
|
||||
)
|
||||
{
|
||||
if (name.IsEmpty())
|
||||
return;
|
||||
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
{
|
||||
// name.Replace(kUnixPathSepar, kOsPathSepar);
|
||||
const unsigned len = name.Len();
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = name[i];
|
||||
if (c == L'/')
|
||||
c = WCHAR_PATH_SEPARATOR;
|
||||
else if (useBackslashReplacement && c == L'\\')
|
||||
c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme
|
||||
else
|
||||
continue;
|
||||
name.ReplaceOneCharAtPos(i, c);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (name.Back() == kOsPathSepar)
|
||||
name.DeleteBack();
|
||||
}
|
||||
|
||||
|
||||
@@ -66,12 +87,15 @@ bool HasTailSlash(const AString &name, UINT
|
||||
{
|
||||
if (name.IsEmpty())
|
||||
return false;
|
||||
char c =
|
||||
char c;
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
*CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0);
|
||||
#else
|
||||
name.Back();
|
||||
if (codePage != CP_UTF8)
|
||||
c = *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
c = name.Back();
|
||||
}
|
||||
return (c == '/');
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ void ReplaceSlashes_OsToUnix(UString &name);
|
||||
UString GetOsPath(const UString &name);
|
||||
UString GetOsPath_Remove_TailSlash(const UString &name);
|
||||
|
||||
void ReplaceToOsSlashes_Remove_TailSlash(UString &name);
|
||||
void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool useBackslashReplacement = false);
|
||||
|
||||
bool HasTailSlash(const AString &name, UINT codePage);
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
UInt64 localPos = _pos - s.GlobalOffset;
|
||||
if (localPos != s.LocalPos)
|
||||
{
|
||||
RINOK(s.Stream->Seek(localPos, STREAM_SEEK_SET, &s.LocalPos));
|
||||
RINOK(s.Stream->Seek((Int64)localPos, STREAM_SEEK_SET, &s.LocalPos));
|
||||
}
|
||||
UInt64 rem = s.Size - localPos;
|
||||
if (size > rem)
|
||||
@@ -60,9 +60,9 @@ STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosi
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_pos = offset;
|
||||
_pos = (UInt64)offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
*newPosition = (UInt64)offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *pr
|
||||
if (_stream)
|
||||
result = _stream->Write(data, size, &size);
|
||||
if (_calculate)
|
||||
Sha1_Update(&_sha, (const Byte *)data, size);
|
||||
Sha1_Update(Sha(), (const Byte *)data, size);
|
||||
_size += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "../../../../C/Sha1.h"
|
||||
|
||||
#include "../../../Common/MyBuffer2.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../IStream.h"
|
||||
@@ -15,10 +16,16 @@ class COutStreamWithSha1:
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
CSha1 _sha;
|
||||
// CSha1 _sha;
|
||||
bool _calculate;
|
||||
CAlignedBuffer _sha;
|
||||
|
||||
CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; }
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
COutStreamWithSha1(): _sha(sizeof(CSha1)) {}
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
@@ -26,11 +33,11 @@ public:
|
||||
{
|
||||
_size = 0;
|
||||
_calculate = calculate;
|
||||
Sha1_Init(&_sha);
|
||||
Sha1_Init(Sha());
|
||||
}
|
||||
void InitSha1() { Sha1_Init(&_sha); }
|
||||
void InitSha1() { Sha1_Init(Sha()); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
void Final(Byte *digest) { Sha1_Final(&_sha, digest); }
|
||||
void Final(Byte *digest) { Sha1_Final(Sha(), digest); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -131,7 +131,7 @@ enum EErrorType
|
||||
{
|
||||
k_ErrorType_OK,
|
||||
k_ErrorType_Corrupted,
|
||||
k_ErrorType_UnexpectedEnd,
|
||||
k_ErrorType_UnexpectedEnd
|
||||
};
|
||||
|
||||
struct CInArchive
|
||||
@@ -218,7 +218,7 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size)
|
||||
{
|
||||
if (size < k_OctRecord_Size)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
for (int i = 6; i < k_OctRecord_Size; i++)
|
||||
for (unsigned i = 6; i < k_OctRecord_Size; i++)
|
||||
{
|
||||
char c = p[i];
|
||||
if (c < '0' || c > '7')
|
||||
@@ -231,7 +231,7 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size)
|
||||
{
|
||||
if (size < k_HexRecord_Size)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
for (int i = 6; i < k_HexRecord_Size; i++)
|
||||
for (unsigned i = 6; i < k_HexRecord_Size; i++)
|
||||
{
|
||||
char c = p[i];
|
||||
if ((c < '0' || c > '9') &&
|
||||
@@ -268,7 +268,9 @@ API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size)
|
||||
if (nameSize > (1 << 8))
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
if (numLinks == 0 || numLinks >= (1 << 10))
|
||||
// 20.03: some cpio files have (numLinks == 0).
|
||||
// if (numLinks == 0) return k_IsArc_Res_NO;
|
||||
if (numLinks >= (1 << 10))
|
||||
return k_IsArc_Res_NO;
|
||||
if (nameSize == 0 || nameSize > kNameSizeMax)
|
||||
return k_IsArc_Res_NO;
|
||||
@@ -462,6 +464,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break;
|
||||
case k_ErrorType_Corrupted: v |= kpv_ErrorFlags_HeadersError; break;
|
||||
case k_ErrorType_OK:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
prop = v;
|
||||
break;
|
||||
@@ -565,23 +570,30 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
|
||||
{
|
||||
// Read tailing zeros.
|
||||
// Most of cpio files use 512-bytes aligned zeros
|
||||
UInt64 pos = arc.Processed;
|
||||
const UInt32 kTailSize_MAX = 1 << 9;
|
||||
// rare case: 4K/8K aligment is possible also
|
||||
const unsigned kTailSize_MAX = 1 << 9;
|
||||
Byte buf[kTailSize_MAX];
|
||||
|
||||
UInt32 rem = (kTailSize_MAX - (UInt32)pos) & (kTailSize_MAX - 1);
|
||||
if (rem != 0)
|
||||
unsigned pos = (unsigned)arc.Processed & (kTailSize_MAX - 1);
|
||||
if (pos != 0) // use this check to support 512 bytes alignment only
|
||||
for (;;)
|
||||
{
|
||||
rem++; // we need to see that it's end of file
|
||||
unsigned rem = kTailSize_MAX - pos;
|
||||
size_t processed = rem;
|
||||
RINOK(ReadStream(stream, buf, &processed));
|
||||
if (processed < rem)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < processed && buf[i] == 0; i++);
|
||||
if (i == processed)
|
||||
_phySize += processed;
|
||||
}
|
||||
RINOK(ReadStream(stream, buf + pos, &processed));
|
||||
if (processed != rem)
|
||||
break;
|
||||
|
||||
for (; pos < kTailSize_MAX && buf[pos] == 0; pos++)
|
||||
{}
|
||||
if (pos != kTailSize_MAX)
|
||||
break;
|
||||
_phySize += processed;
|
||||
pos = 0;
|
||||
|
||||
// use break to support 512 bytes alignment zero tail
|
||||
// don't use break to support 512*n bytes alignment zero tail
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,7 +634,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
UString res;
|
||||
bool needConvert = true;
|
||||
#ifdef _WIN32
|
||||
if (ConvertUTF8ToUnicode(item.Name, res))
|
||||
// if (
|
||||
ConvertUTF8ToUnicode(item.Name, res);
|
||||
// )
|
||||
needConvert = false;
|
||||
#endif
|
||||
if (needConvert)
|
||||
|
||||
@@ -22,11 +22,24 @@
|
||||
|
||||
#include "IArchive.h"
|
||||
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
#define NT_CHECK_FAIL_ACTION return FALSE;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)
|
||||
#define NT_CHECK_FAIL_ACTION return FALSE;
|
||||
#endif
|
||||
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(
|
||||
#ifdef UNDER_CE
|
||||
HANDLE
|
||||
#else
|
||||
HINSTANCE
|
||||
#endif
|
||||
hInstance, DWORD dwReason, LPVOID /*lpReserved*/);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(
|
||||
#ifdef UNDER_CE
|
||||
@@ -50,7 +63,22 @@ BOOL WINAPI DllMain(
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
#include "../../Common/StringConvert.h"
|
||||
// #include <stdio.h>
|
||||
|
||||
// STDAPI LibStartup();
|
||||
static __attribute__((constructor)) void Init_ForceToUTF8();
|
||||
static __attribute__((constructor)) void Init_ForceToUTF8()
|
||||
{
|
||||
g_ForceToUTF8 = IsNativeUTF8();
|
||||
// printf("\nDLLExports2.cpp::Init_ForceToUTF8 =%d\n", g_ForceToUTF8 ? 1 : 0);
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
DEFINE_GUID(CLSID_CArchiveHandler,
|
||||
k_7zip_GUID_Data1,
|
||||
@@ -62,6 +90,7 @@ STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);
|
||||
STDAPI CreateHasher(const GUID *clsid, IHasher **hasher);
|
||||
STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);
|
||||
|
||||
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject);
|
||||
STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
|
||||
{
|
||||
// COM_TRY_BEGIN
|
||||
@@ -76,16 +105,20 @@ STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
|
||||
// COM_TRY_END
|
||||
}
|
||||
|
||||
STDAPI SetLargePageMode();
|
||||
STDAPI SetLargePageMode()
|
||||
{
|
||||
#if defined(_7ZIP_LARGE_PAGES)
|
||||
#ifdef _WIN32
|
||||
SetLargePageSize();
|
||||
#endif
|
||||
#endif
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
extern bool g_CaseSensitive;
|
||||
|
||||
STDAPI SetCaseSensitive(Int32 caseSensitive);
|
||||
STDAPI SetCaseSensitive(Int32 caseSensitive)
|
||||
{
|
||||
g_CaseSensitive = (caseSensitive != 0);
|
||||
@@ -96,6 +129,7 @@ STDAPI SetCaseSensitive(Int32 caseSensitive)
|
||||
|
||||
CExternalCodecs g_ExternalCodecs;
|
||||
|
||||
STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo);
|
||||
STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -114,6 +148,7 @@ STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo)
|
||||
|
||||
#else
|
||||
|
||||
STDAPI SetCodecs(ICompressCodecsInfo *);
|
||||
STDAPI SetCodecs(ICompressCodecsInfo *)
|
||||
{
|
||||
return S_OK;
|
||||
|
||||
@@ -33,99 +33,22 @@
|
||||
#define Get32(p) GetBe32(p)
|
||||
#define Get64(p) GetBe64(p)
|
||||
|
||||
static const Byte k_Base64Table[256] =
|
||||
{
|
||||
66,77,77,77,77,77,77,77,77,65,65,77,77,65,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
65,77,77,77,77,77,77,77,77,77,77,62,77,77,77,63,
|
||||
52,53,54,55,56,57,58,59,60,61,77,77,77,64,77,77,
|
||||
77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
|
||||
15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77,
|
||||
77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
|
||||
41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
|
||||
77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77
|
||||
};
|
||||
|
||||
static Byte *Base64ToBin(Byte *dest, const char *src)
|
||||
{
|
||||
UInt32 val = 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
UInt32 c = k_Base64Table[(Byte)(*src++)];
|
||||
|
||||
if (c < 64)
|
||||
{
|
||||
val = (val << 6) | c;
|
||||
if ((val & ((UInt32)1 << 24)) == 0)
|
||||
continue;
|
||||
dest[0] = (Byte)(val >> 16);
|
||||
dest[1] = (Byte)(val >> 8);
|
||||
dest[2] = (Byte)(val);
|
||||
dest += 3;
|
||||
val = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == 65) // space
|
||||
continue;
|
||||
|
||||
if (c == 64) // '='
|
||||
break;
|
||||
|
||||
if (c == 66 && val == 1) // end of string
|
||||
return dest;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (val < (1 << 12))
|
||||
return NULL;
|
||||
|
||||
if (val & (1 << 18))
|
||||
{
|
||||
*dest++ = (Byte)(val >> 10);
|
||||
*dest++ = (Byte)(val >> 2);
|
||||
}
|
||||
else if (k_Base64Table[(Byte)(*src++)] != 64) // '='
|
||||
return NULL;
|
||||
else
|
||||
*dest++ = (Byte)(val >> 4);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte c = k_Base64Table[(Byte)(*src++)];
|
||||
if (c == 65) // space
|
||||
continue;
|
||||
if (c == 66) // end of string
|
||||
return dest;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Byte *Base64ToBin(Byte *dest, const char *src);
|
||||
|
||||
namespace NArchive {
|
||||
namespace NDmg {
|
||||
|
||||
enum
|
||||
{
|
||||
METHOD_ZERO_0 = 0,
|
||||
METHOD_COPY = 1,
|
||||
METHOD_ZERO_2 = 2, // without file CRC calculation
|
||||
METHOD_ADC = 0x80000004,
|
||||
METHOD_ZLIB = 0x80000005,
|
||||
METHOD_BZIP2 = 0x80000006,
|
||||
METHOD_LZFSE = 0x80000007,
|
||||
METHOD_COMMENT = 0x7FFFFFFE, // is used to comment "+beg" and "+end" in extra field.
|
||||
METHOD_END = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
static const UInt32 METHOD_ZERO_0 = 0;
|
||||
static const UInt32 METHOD_COPY = 1;
|
||||
static const UInt32 METHOD_ZERO_2 = 2; // without file CRC calculation
|
||||
static const UInt32 METHOD_ADC = 0x80000004;
|
||||
static const UInt32 METHOD_ZLIB = 0x80000005;
|
||||
static const UInt32 METHOD_BZIP2 = 0x80000006;
|
||||
static const UInt32 METHOD_LZFSE = 0x80000007;
|
||||
static const UInt32 METHOD_COMMENT = 0x7FFFFFFE; // is used to comment "+beg" and "+end" in extra field.
|
||||
static const UInt32 METHOD_END = 0xFFFFFFFF;
|
||||
|
||||
|
||||
struct CBlock
|
||||
{
|
||||
@@ -266,7 +189,7 @@ void CMethods::GetString(AString &res) const
|
||||
|
||||
for (i = 0; i < Types.Size(); i++)
|
||||
{
|
||||
UInt32 type = Types[i];
|
||||
const UInt32 type = Types[i];
|
||||
if (type == METHOD_COMMENT || type == METHOD_END)
|
||||
continue;
|
||||
char buf[16];
|
||||
@@ -407,6 +330,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidWarning:
|
||||
if (_masterCrcError)
|
||||
prop = "Master CRC error";
|
||||
break;
|
||||
|
||||
case kpidWarningFlags:
|
||||
{
|
||||
@@ -727,7 +651,8 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
if (xmlPair2.Len > len)
|
||||
xmlPair2.Len = len;
|
||||
CByteBuffer buf2;
|
||||
if (ReadData(stream, xmlPair2, buf2) != S_OK
|
||||
if (xmlPair2.Len < len
|
||||
|| ReadData(stream, xmlPair2, buf2) != S_OK
|
||||
|| memcmp(buf2, sz, len) != 0)
|
||||
{
|
||||
// if absolute offset is not OK, probably it's archive with offset
|
||||
@@ -1054,7 +979,9 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef DMG_SHOW_RAW
|
||||
#define RAW_PREFIX "raw" STRING_PATH_SEPARATOR
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
@@ -1608,7 +1535,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos)
|
||||
static unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos)
|
||||
{
|
||||
unsigned left = 0, right = blocks.Size();
|
||||
for (;;)
|
||||
@@ -1762,8 +1689,8 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
}
|
||||
|
||||
const CBlock &block = File->Blocks[_latestBlock];
|
||||
UInt64 offset = _virtPos - block.UnpPos;
|
||||
UInt64 rem = block.UnpSize - offset;
|
||||
const UInt64 offset = _virtPos - block.UnpPos;
|
||||
const UInt64 rem = block.UnpSize - offset;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
|
||||
@@ -1777,7 +1704,7 @@ STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
else if (block.IsZeroMethod())
|
||||
memset(data, 0, size);
|
||||
else if (size != 0)
|
||||
memcpy(data, _chunks[_latestChunk].Buf + offset, size);
|
||||
memcpy(data, _chunks[_latestChunk].Buf + (size_t)offset, size);
|
||||
|
||||
_virtPos += size;
|
||||
if (processedSize)
|
||||
|
||||
@@ -226,6 +226,7 @@ void CSegment::Parse(const Byte *p, bool mode64, bool be)
|
||||
|
||||
// Section types
|
||||
|
||||
/*
|
||||
#define SHT_NULL 0
|
||||
#define SHT_PROGBITS 1
|
||||
#define SHT_SYMTAB 2
|
||||
@@ -234,7 +235,9 @@ void CSegment::Parse(const Byte *p, bool mode64, bool be)
|
||||
#define SHT_HASH 5
|
||||
#define SHT_DYNAMIC 6
|
||||
#define SHT_NOTE 7
|
||||
*/
|
||||
#define SHT_NOBITS 8
|
||||
/*
|
||||
#define SHT_REL 9
|
||||
#define SHT_SHLIB 10
|
||||
#define SHT_DYNSYM 11
|
||||
@@ -245,7 +248,7 @@ void CSegment::Parse(const Byte *p, bool mode64, bool be)
|
||||
#define SHT_PREINIT_ARRAY 16
|
||||
#define SHT_GROUP 17
|
||||
#define SHT_SYMTAB_SHNDX 18
|
||||
|
||||
*/
|
||||
|
||||
static const CUInt32PCharPair g_SectTypes[] =
|
||||
{
|
||||
@@ -633,11 +636,11 @@ static const CUInt32PCharPair g_MIPS_Flags[] =
|
||||
};
|
||||
|
||||
|
||||
#define ET_NONE 0
|
||||
// #define ET_NONE 0
|
||||
#define ET_REL 1
|
||||
#define ET_EXEC 2
|
||||
// #define ET_EXEC 2
|
||||
#define ET_DYN 3
|
||||
#define ET_CORE 4
|
||||
// #define ET_CORE 4
|
||||
|
||||
static const char * const g_Types[] =
|
||||
{
|
||||
|
||||
@@ -99,6 +99,8 @@ static UInt32 Crc16Calc(Byte const *data, size_t size)
|
||||
|
||||
|
||||
#define EXT4_GOOD_OLD_INODE_SIZE 128
|
||||
#define EXT_NODE_SIZE_MIN 128
|
||||
|
||||
|
||||
// inodes numbers
|
||||
|
||||
@@ -436,9 +438,9 @@ bool CHeader::Parse(const Byte *p)
|
||||
LE_16 (0x58, InodeSize);
|
||||
if (FirstInode < k_INODE_GOOD_OLD_FIRST)
|
||||
return false;
|
||||
if (InodeSize > (UInt32)1 << BlockBits)
|
||||
return false;
|
||||
if (GetLog(InodeSize) < 0)
|
||||
if (InodeSize > ((UInt32)1 << BlockBits)
|
||||
|| InodeSize < EXT_NODE_SIZE_MIN
|
||||
|| GetLog(InodeSize) < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -603,7 +605,7 @@ struct CExtent
|
||||
if (Len > (UInt32)0x8000)
|
||||
{
|
||||
IsInited = false;
|
||||
Len -= (UInt32)0x8000;
|
||||
Len = (UInt16)(Len - (UInt32)0x8000);
|
||||
}
|
||||
LE_32 (0x08, PhyStart);
|
||||
UInt16 hi;
|
||||
@@ -628,8 +630,8 @@ struct CNode
|
||||
int DirIndex; // in _dirs[]
|
||||
|
||||
UInt16 Mode;
|
||||
UInt16 Uid;
|
||||
UInt16 Gid;
|
||||
UInt32 Uid; // fixed 21.02
|
||||
UInt32 Gid; // fixed 21.02
|
||||
// UInt16 Checksum;
|
||||
|
||||
UInt64 FileSize;
|
||||
@@ -730,6 +732,8 @@ bool CNode::Parse(const Byte *p, const CHeader &_h)
|
||||
|
||||
if (_h.InodeSize > 128)
|
||||
{
|
||||
// InodeSize is power of 2, so the following check is not required:
|
||||
// if (_h.InodeSize < 128 + 2) return false;
|
||||
UInt16 extra_isize;
|
||||
LE_16 (0x80, extra_isize);
|
||||
if (128 + extra_isize > _h.InodeSize)
|
||||
@@ -842,7 +846,7 @@ class CHandler:
|
||||
}
|
||||
|
||||
|
||||
const int GetParentAux(const CItem &item) const
|
||||
int GetParentAux(const CItem &item) const
|
||||
{
|
||||
if (item.Node < _h.FirstInode && _auxSysIndex >= 0)
|
||||
return _auxSysIndex;
|
||||
@@ -931,7 +935,7 @@ HRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned iNodeDir)
|
||||
return S_FALSE;
|
||||
|
||||
if (_isUTF)
|
||||
_isUTF = CheckUTF8(item.Name);
|
||||
_isUTF = CheckUTF8_AString(item.Name);
|
||||
|
||||
if (iNode == 0)
|
||||
{
|
||||
@@ -1201,7 +1205,7 @@ HRESULT CHandler::Open2(IInStream *inStream)
|
||||
UInt32 numNodes = _h.InodesPerGroup;
|
||||
if (numNodes > _h.NumInodes)
|
||||
numNodes = _h.NumInodes;
|
||||
size_t nodesDataSize = (size_t)numNodes * _h.InodeSize;
|
||||
const size_t nodesDataSize = (size_t)numNodes * _h.InodeSize;
|
||||
|
||||
if (nodesDataSize / _h.InodeSize != numNodes)
|
||||
return S_FALSE;
|
||||
@@ -1213,7 +1217,7 @@ HRESULT CHandler::Open2(IInStream *inStream)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
UInt32 numReserveInodes = _h.NumInodes - _h.NumFreeInodes + 1;
|
||||
const UInt32 numReserveInodes = _h.NumInodes - _h.NumFreeInodes + 1;
|
||||
// numReserveInodes = _h.NumInodes + 1;
|
||||
if (numReserveInodes != 0)
|
||||
{
|
||||
@@ -1348,7 +1352,8 @@ HRESULT CHandler::Open2(IInStream *inStream)
|
||||
RINOK(CheckProgress());
|
||||
}
|
||||
|
||||
if (_nodes[_refs[k_INODE_ROOT]].ParentNode != k_INODE_ROOT)
|
||||
int ref = _refs[k_INODE_ROOT];
|
||||
if (ref < 0 || _nodes[ref].ParentNode != k_INODE_ROOT)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -682,7 +682,7 @@ HRESULT CDatabase::Open()
|
||||
RINOK(ReadStream_FALSE(InStream, byteBuf, readSize));
|
||||
NumCurUsedBytes += readSize;
|
||||
|
||||
const UInt32 *src = (const UInt32 *)(const Byte *)byteBuf;
|
||||
const UInt32 *src = (const UInt32 *)(const void *)(const Byte *)byteBuf;
|
||||
UInt32 *dest = Fat + i;
|
||||
if (numFreeClustersDefined)
|
||||
for (UInt32 j = 0; j < size; j++)
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
((UInt32)((const Byte *)(p))[1] << 8) | \
|
||||
((const Byte *)(p))[2] )
|
||||
|
||||
#define Get16(p) GetBe16(p)
|
||||
// #define Get16(p) GetBe16(p)
|
||||
#define Get24(p) GetBe24(p)
|
||||
#define Get32(p) GetBe32(p)
|
||||
|
||||
namespace NArchive {
|
||||
namespace NFlv {
|
||||
|
||||
static const UInt32 kFileSizeMax = (UInt32)1 << 30;
|
||||
// static const UInt32 kFileSizeMax = (UInt32)1 << 30;
|
||||
static const UInt32 kNumChunksMax = (UInt32)1 << 23;
|
||||
|
||||
static const UInt32 kTagHeaderSize = 11;
|
||||
|
||||
@@ -333,16 +333,25 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
{
|
||||
case kpidPath:
|
||||
{
|
||||
// Windows BDP partitions can have identical names.
|
||||
// So we add the partition number at front
|
||||
UString s;
|
||||
for (unsigned i = 0; i < kNameLen; i++)
|
||||
s.Add_UInt32(index);
|
||||
{
|
||||
wchar_t c = (wchar_t)Get16(item.Name + i * 2);
|
||||
if (c == 0)
|
||||
break;
|
||||
s += c;
|
||||
UString s2;
|
||||
for (unsigned i = 0; i < kNameLen; i++)
|
||||
{
|
||||
wchar_t c = (wchar_t)Get16(item.Name + i * 2);
|
||||
if (c == 0)
|
||||
break;
|
||||
s2 += c;
|
||||
}
|
||||
if (!s2.IsEmpty())
|
||||
{
|
||||
s += '.';
|
||||
s += s2;
|
||||
}
|
||||
}
|
||||
if (s.IsEmpty())
|
||||
s.Add_UInt32(index);
|
||||
{
|
||||
s += '.';
|
||||
const char *ext = NULL;
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace NGz {
|
||||
|
||||
namespace NFlags
|
||||
{
|
||||
const Byte kIsText = 1 << 0;
|
||||
// const Byte kIsText = 1 << 0;
|
||||
const Byte kCrc = 1 << 1;
|
||||
const Byte kExtra = 1 << 2;
|
||||
const Byte kName = 1 << 3;
|
||||
@@ -234,7 +234,8 @@ static UInt32 Is_Deflate(const Byte *p, size_t size)
|
||||
return k_IsArc_Res_NO;
|
||||
if (size < 4)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
if (GetUi16(p) != (UInt16)~GetUi16(p + 2))
|
||||
UInt16 r = (UInt16)~GetUi16(p + 2);
|
||||
if (GetUi16(p) != r)
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
else if (type == 2)
|
||||
@@ -248,8 +249,8 @@ static UInt32 Is_Deflate(const Byte *p, size_t size)
|
||||
return k_IsArc_Res_YES;
|
||||
}
|
||||
|
||||
static unsigned kNameMaxLen = 1 << 12;
|
||||
static unsigned kCommentMaxLen = 1 << 16;
|
||||
static const unsigned kNameMaxLen = 1 << 12;
|
||||
static const unsigned kCommentMaxLen = 1 << 16;
|
||||
|
||||
API_FUNC_static_IsArc IsArc_Gz(const Byte *p, size_t size)
|
||||
{
|
||||
@@ -962,7 +963,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
UString name = prop.bstrVal;
|
||||
int slashPos = name.ReverseFind_PathSepar();
|
||||
if (slashPos >= 0)
|
||||
name.DeleteFrontal(slashPos + 1);
|
||||
name.DeleteFrontal((unsigned)(slashPos + 1));
|
||||
newItem.Name = UnicodeStringToMultiByte(name, CP_ACP);
|
||||
if (!newItem.Name.IsEmpty())
|
||||
newItem.Flags |= NFlags::kName;
|
||||
@@ -1019,7 +1020,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
newItem.WriteHeader(outStream);
|
||||
offset += _headerSize;
|
||||
}
|
||||
RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
|
||||
RINOK(_stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL));
|
||||
|
||||
return NCompress::CopyStream(_stream, outStream, progress);
|
||||
|
||||
|
||||
@@ -269,7 +269,7 @@ HRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64
|
||||
for (;;)
|
||||
{
|
||||
UInt32 size = 0;
|
||||
HRESULT(stream->Read(buf, kBufSize, &size));
|
||||
RINOK(stream->Read(buf, kBufSize, &size));
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
|
||||
@@ -275,7 +275,7 @@ struct CItem
|
||||
|
||||
CItem(): UseAttr(false), UseInlineData(false) {}
|
||||
bool IsDir() const { return Type == RECORD_TYPE_FOLDER; }
|
||||
const CFork &GetFork(bool isResource) const { return (CFork & )*(isResource ? &ResourceFork: &DataFork ); }
|
||||
const CFork &GetFork(bool isResource) const { return (const CFork & )*(isResource ? &ResourceFork: &DataFork ); }
|
||||
};
|
||||
|
||||
struct CAttr
|
||||
@@ -320,12 +320,14 @@ public:
|
||||
UInt64 SpecOffset;
|
||||
UInt64 PhySize;
|
||||
UInt64 PhySize2;
|
||||
UInt64 ArcFileSize;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
SpecOffset = 0;
|
||||
PhySize = 0;
|
||||
PhySize2 = 0;
|
||||
ArcFileSize = 0;
|
||||
HeadersError = false;
|
||||
ThereAreAltStreams = false;
|
||||
// CaseSensetive = false;
|
||||
@@ -440,7 +442,10 @@ HRESULT CDatabase::ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inSt
|
||||
{
|
||||
if (fork.NumBlocks >= Header.NumBlocks)
|
||||
return S_FALSE;
|
||||
size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog;
|
||||
if ((ArcFileSize >> Header.BlockSizeLog) + 1 < fork.NumBlocks)
|
||||
return S_FALSE;
|
||||
|
||||
const size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog;
|
||||
if ((totalSize >> Header.BlockSizeLog) != fork.NumBlocks)
|
||||
return S_FALSE;
|
||||
buf.Alloc(totalSize);
|
||||
@@ -473,20 +478,36 @@ struct CNodeDescriptor
|
||||
// Byte Height;
|
||||
unsigned NumRecords;
|
||||
|
||||
bool CheckNumRecords(unsigned nodeSizeLog)
|
||||
{
|
||||
return (kNodeDescriptor_Size + ((UInt32)NumRecords + 1) * 2 <= ((UInt32)1 << nodeSizeLog));
|
||||
}
|
||||
void Parse(const Byte *p);
|
||||
bool Parse(const Byte *p, unsigned nodeSizeLog);
|
||||
};
|
||||
|
||||
void CNodeDescriptor::Parse(const Byte *p)
|
||||
|
||||
bool CNodeDescriptor::Parse(const Byte *p, unsigned nodeSizeLog)
|
||||
{
|
||||
fLink = Get32(p);
|
||||
// bLink = Get32(p + 4);
|
||||
Kind = p[8];
|
||||
// Height = p[9];
|
||||
NumRecords = Get16(p + 10);
|
||||
|
||||
const size_t nodeSize = (size_t)1 << nodeSizeLog;
|
||||
if (kNodeDescriptor_Size + ((UInt32)NumRecords + 1) * 2 > nodeSize)
|
||||
return false;
|
||||
const size_t limit = nodeSize - ((UInt32)NumRecords + 1) * 2;
|
||||
|
||||
p += nodeSize - 2;
|
||||
|
||||
for (unsigned i = 0; i < NumRecords; i++)
|
||||
{
|
||||
const UInt32 offs = Get16(p);
|
||||
p -= 2;
|
||||
const UInt32 offsNext = Get16(p);
|
||||
if (offs < kNodeDescriptor_Size
|
||||
|| offs >= offsNext
|
||||
|| offsNext > limit)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct CHeaderRec
|
||||
@@ -576,7 +597,7 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec
|
||||
if (node == 0)
|
||||
return S_OK;
|
||||
|
||||
CByteBuffer usedBuf(hr.TotalNodes);
|
||||
CByteArr usedBuf(hr.TotalNodes);
|
||||
memset(usedBuf, 0, hr.TotalNodes);
|
||||
|
||||
while (node != 0)
|
||||
@@ -585,10 +606,9 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec
|
||||
return S_FALSE;
|
||||
usedBuf[node] = 1;
|
||||
|
||||
size_t nodeOffset = (size_t)node << hr.NodeSizeLog;
|
||||
const size_t nodeOffset = (size_t)node << hr.NodeSizeLog;
|
||||
CNodeDescriptor desc;
|
||||
desc.Parse(p + nodeOffset);
|
||||
if (!desc.CheckNumRecords(hr.NodeSizeLog))
|
||||
if (!desc.Parse(p + nodeOffset, hr.NodeSizeLog))
|
||||
return S_FALSE;
|
||||
if (desc.Kind != kNodeType_Leaf)
|
||||
return S_FALSE;
|
||||
@@ -597,18 +617,16 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec
|
||||
|
||||
for (unsigned i = 0; i < desc.NumRecords; i++)
|
||||
{
|
||||
const UInt32 nodeSize = (UInt32)1 << hr.NodeSizeLog;
|
||||
const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2);
|
||||
const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2);
|
||||
if (offs > nodeSize || offsNext > nodeSize)
|
||||
return S_FALSE;
|
||||
UInt32 recSize = offsNext - offs;
|
||||
const UInt32 nodeSize = (1 << hr.NodeSizeLog);
|
||||
const Byte *r = p + nodeOffset + nodeSize - i * 2;
|
||||
const UInt32 offs = Get16(r - 2);
|
||||
UInt32 recSize = Get16(r - 4) - offs;
|
||||
const unsigned kKeyLen = 10;
|
||||
|
||||
if (recSize != 2 + kKeyLen + kNumFixedExtents * 8)
|
||||
return S_FALSE;
|
||||
|
||||
const Byte *r = p + nodeOffset + offs;
|
||||
r = p + nodeOffset + offs;
|
||||
if (Get16(r) != kKeyLen)
|
||||
return S_FALSE;
|
||||
|
||||
@@ -717,7 +735,7 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe
|
||||
if (node == 0)
|
||||
return S_OK;
|
||||
|
||||
CByteBuffer usedBuf(hr.TotalNodes);
|
||||
CByteArr usedBuf(hr.TotalNodes);
|
||||
memset(usedBuf, 0, hr.TotalNodes);
|
||||
|
||||
CFork resFork;
|
||||
@@ -728,10 +746,9 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe
|
||||
return S_FALSE;
|
||||
usedBuf[node] = 1;
|
||||
|
||||
size_t nodeOffset = (size_t)node << hr.NodeSizeLog;
|
||||
const size_t nodeOffset = (size_t)node << hr.NodeSizeLog;
|
||||
CNodeDescriptor desc;
|
||||
desc.Parse(p + nodeOffset);
|
||||
if (!desc.CheckNumRecords(hr.NodeSizeLog))
|
||||
if (!desc.Parse(p + nodeOffset, hr.NodeSizeLog))
|
||||
return S_FALSE;
|
||||
if (desc.Kind != kNodeType_Leaf)
|
||||
return S_FALSE;
|
||||
@@ -739,19 +756,14 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe
|
||||
for (unsigned i = 0; i < desc.NumRecords; i++)
|
||||
{
|
||||
const UInt32 nodeSize = (1 << hr.NodeSizeLog);
|
||||
const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2);
|
||||
const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2);
|
||||
UInt32 recSize = offsNext - offs;
|
||||
if (offs >= nodeSize
|
||||
|| offsNext > nodeSize
|
||||
|| offsNext < offs)
|
||||
return S_FALSE;
|
||||
|
||||
const Byte *r = p + nodeOffset + nodeSize - i * 2;
|
||||
const UInt32 offs = Get16(r - 2);
|
||||
UInt32 recSize = Get16(r - 4) - offs;
|
||||
const unsigned kHeadSize = 14;
|
||||
if (recSize < kHeadSize)
|
||||
return S_FALSE;
|
||||
|
||||
const Byte *r = p + nodeOffset + offs;
|
||||
r = p + nodeOffset + offs;
|
||||
UInt32 keyLen = Get16(r);
|
||||
|
||||
// UInt16 pad = Get16(r + 2);
|
||||
@@ -805,7 +817,7 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe
|
||||
|
||||
if (progress && (i & 0xFFF) == 0)
|
||||
{
|
||||
UInt64 numFiles = 0;
|
||||
const UInt64 numFiles = 0;
|
||||
RINOK(progress->SetCompleted(&numFiles, NULL));
|
||||
}
|
||||
}
|
||||
@@ -873,13 +885,6 @@ bool CDatabase::Parse_decmpgfs(const CAttr &attr, CItem &item, bool &skip)
|
||||
|
||||
HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents> *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress)
|
||||
{
|
||||
unsigned reserveSize = (unsigned)(Header.NumFolders + 1 + Header.NumFiles);
|
||||
Items.ClearAndReserve(reserveSize);
|
||||
Refs.ClearAndReserve(reserveSize);
|
||||
|
||||
CRecordVector<CIdIndexPair> IdToIndexMap;
|
||||
IdToIndexMap.ClearAndReserve(reserveSize);
|
||||
|
||||
CByteBuffer buf;
|
||||
RINOK(ReadFile(fork, buf, inStream));
|
||||
const Byte *p = (const Byte *)buf;
|
||||
@@ -888,10 +893,24 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
|
||||
// nodeDesc.Parse(p);
|
||||
CHeaderRec hr;
|
||||
RINOK(hr.Parse2(buf));
|
||||
|
||||
|
||||
CRecordVector<CIdIndexPair> IdToIndexMap;
|
||||
|
||||
const unsigned reserveSize = (unsigned)(Header.NumFolders + 1 + Header.NumFiles);
|
||||
|
||||
const unsigned kBasicRecSize = 0x58;
|
||||
const unsigned kMinRecSize = kBasicRecSize + 10;
|
||||
|
||||
if ((UInt64)reserveSize * kMinRecSize < buf.Size())
|
||||
{
|
||||
Items.ClearAndReserve(reserveSize);
|
||||
Refs.ClearAndReserve(reserveSize);
|
||||
IdToIndexMap.ClearAndReserve(reserveSize);
|
||||
}
|
||||
|
||||
// CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC);
|
||||
|
||||
CByteBuffer usedBuf(hr.TotalNodes);
|
||||
CByteArr usedBuf(hr.TotalNodes);
|
||||
memset(usedBuf, 0, hr.TotalNodes);
|
||||
|
||||
CFork resFork;
|
||||
@@ -908,8 +927,7 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
|
||||
|
||||
const size_t nodeOffset = (size_t)node << hr.NodeSizeLog;
|
||||
CNodeDescriptor desc;
|
||||
desc.Parse(p + nodeOffset);
|
||||
if (!desc.CheckNumRecords(hr.NodeSizeLog))
|
||||
if (!desc.Parse(p + nodeOffset, hr.NodeSizeLog))
|
||||
return S_FALSE;
|
||||
if (desc.Kind != kNodeType_Leaf)
|
||||
return S_FALSE;
|
||||
@@ -917,16 +935,13 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
|
||||
for (unsigned i = 0; i < desc.NumRecords; i++)
|
||||
{
|
||||
const UInt32 nodeSize = (1 << hr.NodeSizeLog);
|
||||
const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2);
|
||||
const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2);
|
||||
UInt32 recSize = offsNext - offs;
|
||||
if (offs >= nodeSize
|
||||
|| offsNext > nodeSize
|
||||
|| offsNext < offs
|
||||
|| recSize < 6)
|
||||
const Byte *r = p + nodeOffset + nodeSize - i * 2;
|
||||
const UInt32 offs = Get16(r - 2);
|
||||
UInt32 recSize = Get16(r - 4) - offs;
|
||||
if (recSize < 6)
|
||||
return S_FALSE;
|
||||
|
||||
const Byte *r = p + nodeOffset + offs;
|
||||
r = p + nodeOffset + offs;
|
||||
UInt32 keyLen = Get16(r);
|
||||
UInt32 parentID = Get32(r + 2);
|
||||
if (keyLen < 6 || (keyLen & 1) != 0 || keyLen + 2 > recSize)
|
||||
@@ -952,7 +967,6 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
|
||||
type != RECORD_TYPE_FILE)
|
||||
continue;
|
||||
|
||||
const unsigned kBasicRecSize = 0x58;
|
||||
if (recSize < kBasicRecSize)
|
||||
return S_FALSE;
|
||||
|
||||
@@ -1042,7 +1056,7 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
|
||||
}
|
||||
if (progress && (Items.Size() & 0xFFF) == 0)
|
||||
{
|
||||
UInt64 numItems = Items.Size();
|
||||
const UInt64 numItems = Items.Size();
|
||||
RINOK(progress->SetCompleted(&numItems, NULL));
|
||||
}
|
||||
}
|
||||
@@ -1286,9 +1300,12 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
|
||||
if (h.NumFolders > ((UInt32)1 << 29) ||
|
||||
h.NumFiles > ((UInt32)1 << 30))
|
||||
return S_FALSE;
|
||||
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_END, &ArcFileSize));
|
||||
|
||||
if (progress)
|
||||
{
|
||||
UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1;
|
||||
const UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1;
|
||||
RINOK(progress->SetTotal(&numFiles, NULL));
|
||||
}
|
||||
|
||||
@@ -1313,13 +1330,6 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
|
||||
h.VolID = Get64(p + 0x68);
|
||||
*/
|
||||
|
||||
/*
|
||||
UInt64 endPos;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));
|
||||
if ((endPos >> h.BlockSizeLog) < h.NumBlocks)
|
||||
return S_FALSE;
|
||||
*/
|
||||
|
||||
ResFileName = kResFileName;
|
||||
|
||||
CFork extentsFork, catalogFork, attrFork;
|
||||
@@ -1499,7 +1509,7 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
|
||||
else
|
||||
s = &Items[ref.ItemIndex].Name;
|
||||
*data = (const wchar_t *)(*s);
|
||||
*dataSize = (s->Len() + 1) * sizeof(wchar_t);
|
||||
*dataSize = (s->Len() + 1) * (UInt32)sizeof(wchar_t);
|
||||
*propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1700,7 +1710,7 @@ HRESULT CHandler::ExtractZlibFile(
|
||||
}
|
||||
|
||||
outPos += blockSize;
|
||||
UInt64 progressPos = progressStart + outPos;
|
||||
const UInt64 progressPos = progressStart + outPos;
|
||||
RINOK(extractCallback->SetCompleted(&progressPos));
|
||||
}
|
||||
|
||||
@@ -1884,7 +1894,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
}
|
||||
pos += cur;
|
||||
extentRem -= cur;
|
||||
UInt64 processed = currentTotalSize + pos;
|
||||
const UInt64 processed = currentTotalSize + pos;
|
||||
RINOK(extractCallback->SetCompleted(&processed));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,30 @@
|
||||
#define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x)
|
||||
#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x)
|
||||
|
||||
/*
|
||||
How the function in 7-Zip returns object for output parameter via pointer
|
||||
|
||||
1) The caller sets the value of variable before function call:
|
||||
PROPVARIANT : vt = VT_EMPTY
|
||||
BSTR : NULL
|
||||
IUnknown* and derived interfaces : NULL
|
||||
another scalar types : any non-initialized value is allowed
|
||||
|
||||
2) The callee in current 7-Zip code now can free input object for output parameter:
|
||||
PROPVARIANT : the callee calls VariantClear(propvaiant_ptr) for input
|
||||
value stored in variable
|
||||
another types : the callee ignores stored value.
|
||||
|
||||
3) The callee writes new value to variable for output parameter and
|
||||
returns execution to caller.
|
||||
|
||||
4) The caller must free or release object returned by the callee:
|
||||
PROPVARIANT : VariantClear(&propvaiant)
|
||||
BSTR : SysFreeString(bstr)
|
||||
IUnknown* and derived interfaces : if (ptr) ptr->Relase()
|
||||
*/
|
||||
|
||||
|
||||
namespace NFileTimeType
|
||||
{
|
||||
enum EEnum
|
||||
@@ -34,6 +58,7 @@ namespace NArcInfoFlags
|
||||
const UInt32 kPreArc = 1 << 9; // such archive can be stored before real archive (like SFX stub)
|
||||
const UInt32 kSymLinks = 1 << 10; // the handler supports symbolic links
|
||||
const UInt32 kHardLinks = 1 << 11; // the handler supports hard links
|
||||
const UInt32 kByExtOnlyOpen = 1 << 12; // call handler only if file extension matches
|
||||
}
|
||||
|
||||
namespace NArchive
|
||||
@@ -106,7 +131,7 @@ namespace NArchive
|
||||
enum
|
||||
{
|
||||
kOK = 0
|
||||
, // kError
|
||||
// , kError
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -137,13 +162,13 @@ IArchiveExtractCallback::GetStream()
|
||||
Int32 askExtractMode (Extract::NAskMode)
|
||||
if (askMode != NExtract::NAskMode::kExtract)
|
||||
{
|
||||
then the callee can not real stream: (*inStream == NULL)
|
||||
then the callee doesn't write data to stream: (*outStream == NULL)
|
||||
}
|
||||
|
||||
Out:
|
||||
(*inStream == NULL) - for directories
|
||||
(*inStream == NULL) - if link (hard link or symbolic link) was created
|
||||
if (*inStream == NULL && askMode == NExtract::NAskMode::kExtract)
|
||||
(*outStream == NULL) - for directories
|
||||
(*outStream == NULL) - if link (hard link or symbolic link) was created
|
||||
if (*outStream == NULL && askMode == NExtract::NAskMode::kExtract)
|
||||
{
|
||||
then the caller must skip extracting of that file.
|
||||
}
|
||||
|
||||
@@ -121,9 +121,9 @@ static int Parse(const Byte *p)
|
||||
#define kType_Data 0
|
||||
#define kType_Eof 1
|
||||
#define kType_Seg 2
|
||||
#define kType_CsIp 3
|
||||
// #define kType_CsIp 3
|
||||
#define kType_High 4
|
||||
#define kType_Ip32 5
|
||||
// #define kType_Ip32 5
|
||||
|
||||
#define kType_MAX 5
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/MyLinux.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
@@ -221,16 +222,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidSymLink:
|
||||
if (_archive.IsSusp)
|
||||
{
|
||||
UString s;
|
||||
UInt32 mode;
|
||||
if (item.GetPx(_archive.SuspSkipSize, k_Px_Mode, mode))
|
||||
{
|
||||
if (((mode >> 12) & 0xF) == 10)
|
||||
if (MY_LIN_S_ISLNK(mode))
|
||||
{
|
||||
AString s8;
|
||||
if (item.GetSymLink(_archive.SuspSkipSize, s8))
|
||||
{
|
||||
s = MultiByteToUnicodeString(s8, CP_OEMCP);
|
||||
UString s = MultiByteToUnicodeString(s8, CP_OEMCP);
|
||||
prop = s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,10 +299,12 @@ void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d)
|
||||
|
||||
static const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' };
|
||||
|
||||
/*
|
||||
static const Byte kSig_NSR02[5] = { 'N', 'S', 'R', '0', '2' };
|
||||
static const Byte kSig_NSR03[5] = { 'N', 'S', 'R', '0', '3' };
|
||||
static const Byte kSig_BEA01[5] = { 'B', 'E', 'A', '0', '1' };
|
||||
static const Byte kSig_TEA01[5] = { 'T', 'E', 'A', '0', '1' };
|
||||
*/
|
||||
|
||||
static inline bool CheckSignature(const Byte *sig, const Byte *data)
|
||||
{
|
||||
|
||||
@@ -149,7 +149,7 @@ struct CDirRecord
|
||||
}
|
||||
|
||||
|
||||
const bool GetSymLink(int skipSize, AString &link) const
|
||||
bool GetSymLink(int skipSize, AString &link) const
|
||||
{
|
||||
link.Empty();
|
||||
const Byte *p = NULL;
|
||||
@@ -208,7 +208,7 @@ struct CDirRecord
|
||||
return true;
|
||||
}
|
||||
|
||||
static const bool GetLe32Be32(const Byte *p, UInt32 &dest)
|
||||
static bool GetLe32Be32(const Byte *p, UInt32 &dest)
|
||||
{
|
||||
UInt32 v1 = GetUi32(p);
|
||||
UInt32 v2 = GetBe32(p + 4);
|
||||
@@ -221,7 +221,7 @@ struct CDirRecord
|
||||
}
|
||||
|
||||
|
||||
const bool GetPx(int skipSize, unsigned pxType, UInt32 &val) const
|
||||
bool GetPx(int skipSize, unsigned pxType, UInt32 &val) const
|
||||
{
|
||||
val = 0;
|
||||
const Byte *p = NULL;
|
||||
@@ -237,7 +237,7 @@ struct CDirRecord
|
||||
}
|
||||
|
||||
/*
|
||||
const bool GetTf(int skipSize, unsigned pxType, CRecordingDateTime &t) const
|
||||
bool GetTf(int skipSize, unsigned pxType, CRecordingDateTime &t) const
|
||||
{
|
||||
const Byte *p = NULL;
|
||||
unsigned len = 0;
|
||||
|
||||
@@ -451,7 +451,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
}
|
||||
|
||||
REGISTER_ARC_I(
|
||||
"lzip", "lz tlz", "* .tar", 0xC5,
|
||||
"lzip", "lz tlz", "* .tar", 0xC4,
|
||||
k_Signature,
|
||||
0,
|
||||
NArcInfoFlags::kKeepName,
|
||||
|
||||
@@ -41,6 +41,7 @@ static UInt16 g_LzhCrc16Table[256];
|
||||
|
||||
#define CRC16_UPDATE_BYTE(crc, b) (g_LzhCrc16Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
UInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size);
|
||||
UInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
@@ -83,13 +84,7 @@ struct CExtension
|
||||
AString GetString() const
|
||||
{
|
||||
AString s;
|
||||
for (size_t i = 0; i < Data.Size(); i++)
|
||||
{
|
||||
char c = (char)Data[i];
|
||||
if (c == 0)
|
||||
break;
|
||||
s += c;
|
||||
}
|
||||
s.SetFrom_CalcLen((const char *)(const Byte *)Data, (unsigned)Data.Size());
|
||||
return s;
|
||||
}
|
||||
};
|
||||
@@ -184,11 +179,13 @@ struct CItem
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool GetUnixTime(UInt32 &value) const
|
||||
{
|
||||
value = 0;
|
||||
int index = FindExt(kExtIdUnixTime);
|
||||
if (index < 0)
|
||||
if (index < 0
|
||||
|| Extensions[index].Data.Size() < 4)
|
||||
{
|
||||
if (Level == 2)
|
||||
{
|
||||
@@ -220,13 +217,14 @@ struct CItem
|
||||
|
||||
AString GetName() const
|
||||
{
|
||||
AString dirName (GetDirName());
|
||||
AString s (GetDirName());
|
||||
const char kDirSeparator = '\\';
|
||||
// check kDirSeparator in Linux
|
||||
dirName.Replace((char)(unsigned char)0xFF, kDirSeparator);
|
||||
if (!dirName.IsEmpty() && dirName.Back() != kDirSeparator)
|
||||
dirName += kDirSeparator;
|
||||
return dirName + GetFileName();
|
||||
s.Replace((char)(unsigned char)0xFF, kDirSeparator);
|
||||
if (!s.IsEmpty() && s.Back() != kDirSeparator)
|
||||
s += kDirSeparator;
|
||||
s += GetFileName();
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -332,7 +330,7 @@ static HRESULT GetNextItem(ISequentialInStream *stream, bool &filled, CItem &ite
|
||||
return S_FALSE;
|
||||
CExtension ext;
|
||||
RINOK(ReadStream_FALSE(stream, &ext.Type, 1))
|
||||
nextSize -= 3;
|
||||
nextSize = (UInt16)(nextSize - 3);
|
||||
ext.Data.Alloc(nextSize);
|
||||
RINOK(ReadStream_FALSE(stream, (Byte *)ext.Data, nextSize))
|
||||
item.Extensions.Add(ext);
|
||||
|
||||
@@ -242,29 +242,25 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
}
|
||||
|
||||
|
||||
static void DictSizeToString(UInt32 val, char *s)
|
||||
static char * DictSizeToString(UInt32 val, char *s)
|
||||
{
|
||||
for (unsigned i = 0; i <= 31; i++)
|
||||
if (((UInt32)1 << i) == val)
|
||||
{
|
||||
::ConvertUInt32ToString(i, s);
|
||||
return;
|
||||
}
|
||||
return ::ConvertUInt32ToString(i, s);
|
||||
char c = 'b';
|
||||
if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
|
||||
else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
|
||||
::ConvertUInt32ToString(val, s);
|
||||
s += MyStringLen(s);
|
||||
s = ::ConvertUInt32ToString(val, s);
|
||||
*s++ = c;
|
||||
*s = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
static char *AddProp32(char *s, const char *name, UInt32 v)
|
||||
{
|
||||
*s++ = ':';
|
||||
s = MyStpCpy(s, name);
|
||||
::ConvertUInt32ToString(v, s);
|
||||
return s + MyStringLen(s);
|
||||
return ::ConvertUInt32ToString(v, s);
|
||||
}
|
||||
|
||||
void CHandler::GetMethod(NCOM::CPropVariant &prop)
|
||||
@@ -277,8 +273,7 @@ void CHandler::GetMethod(NCOM::CPropVariant &prop)
|
||||
if (_header.FilterID != 0)
|
||||
s = MyStpCpy(s, "BCJ ");
|
||||
s = MyStpCpy(s, "LZMA:");
|
||||
DictSizeToString(_header.GetDicSize(), s);
|
||||
s += strlen(s);
|
||||
s = DictSizeToString(_header.GetDicSize(), s);
|
||||
|
||||
UInt32 d = _header.GetProp();
|
||||
// if (d != 0x5D)
|
||||
@@ -315,10 +310,10 @@ API_FUNC_static_IsArc IsArc_Lzma(const Byte *p, size_t size)
|
||||
return k_IsArc_Res_NEED_MORE;
|
||||
if (p[0] >= 5 * 5 * 9)
|
||||
return k_IsArc_Res_NO;
|
||||
UInt64 unpackSize = GetUi64(p + 1 + 4);
|
||||
const UInt64 unpackSize = GetUi64(p + 1 + 4);
|
||||
if (unpackSize != (UInt64)(Int64)-1)
|
||||
{
|
||||
if (size >= ((UInt64)1 << 56))
|
||||
if (unpackSize >= ((UInt64)1 << 56))
|
||||
return k_IsArc_Res_NO;
|
||||
}
|
||||
if (unpackSize != 0)
|
||||
|
||||
@@ -35,11 +35,11 @@ namespace NMacho {
|
||||
|
||||
#define CPU_SUBTYPE_I386_ALL 3
|
||||
|
||||
#define CPU_TYPE_PPC64 (CPU_ARCH_ABI64 | CPU_TYPE_PPC)
|
||||
// #define CPU_TYPE_PPC64 (CPU_ARCH_ABI64 | CPU_TYPE_PPC)
|
||||
#define CPU_TYPE_AMD64 (CPU_ARCH_ABI64 | CPU_TYPE_386)
|
||||
#define CPU_TYPE_ARM64 (CPU_ARCH_ABI64 | CPU_TYPE_ARM)
|
||||
|
||||
#define CPU_SUBTYPE_LIB64 (1 << 31)
|
||||
#define CPU_SUBTYPE_LIB64 ((UInt32)1 << 31)
|
||||
|
||||
#define CPU_SUBTYPE_POWERPC_970 100
|
||||
|
||||
|
||||
@@ -51,10 +51,10 @@ struct CChs
|
||||
bool Check() const { return GetSector() > 0; }
|
||||
};
|
||||
|
||||
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
||||
|
||||
// Chs in some MBRs contains only low bits of "Cyl number". So we disable check.
|
||||
/*
|
||||
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
||||
static int CompareChs(const CChs &c1, const CChs &c2)
|
||||
{
|
||||
RINOZ(MyCompare(c1.GetCyl(), c2.GetCyl()));
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace NMub {
|
||||
#define MACH_CPU_TYPE_AMD64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_386)
|
||||
#define MACH_CPU_TYPE_ARM64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_ARM)
|
||||
|
||||
#define MACH_CPU_SUBTYPE_LIB64 (1 << 31)
|
||||
#define MACH_CPU_SUBTYPE_LIB64 ((UInt32)1 << 31)
|
||||
|
||||
#define MACH_CPU_SUBTYPE_I386_ALL 3
|
||||
|
||||
@@ -124,14 +124,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
}
|
||||
if (ext)
|
||||
strcpy(temp, ext);
|
||||
if (item.SubType != 0 && (
|
||||
item.Type != MACH_CPU_TYPE_386 &&
|
||||
item.Type != MACH_CPU_TYPE_AMD64 ||
|
||||
(item.SubType & ~(UInt32)MACH_CPU_SUBTYPE_LIB64) != MACH_CPU_SUBTYPE_I386_ALL))
|
||||
if (item.SubType != 0)
|
||||
if ((item.Type != MACH_CPU_TYPE_386 &&
|
||||
item.Type != MACH_CPU_TYPE_AMD64)
|
||||
|| (item.SubType & ~(UInt32)MACH_CPU_SUBTYPE_LIB64) != MACH_CPU_SUBTYPE_I386_ALL
|
||||
)
|
||||
{
|
||||
unsigned pos = MyStringLen(temp);
|
||||
temp[pos++] = '-';
|
||||
ConvertUInt32ToString(item.SubType, temp + pos);
|
||||
ConvertUInt32ToString(item.SubType, temp + pos);
|
||||
}
|
||||
return PropVarEm_Set_Str(value, temp);
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ static const Byte kArcProps[] =
|
||||
{
|
||||
kpidMethod,
|
||||
kpidSolid,
|
||||
kpidBit64,
|
||||
kpidHeadersSize,
|
||||
kpidEmbeddedStubSize,
|
||||
kpidSubType
|
||||
@@ -134,6 +135,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidBit64: if (_archive.Is64Bit) prop = true; break;
|
||||
case kpidMethod: prop = _methodString; break;
|
||||
case kpidSolid: prop = _archive.IsSolid; break;
|
||||
case kpidOffset: prop = _archive.StartOffset; break;
|
||||
|
||||
@@ -155,7 +155,7 @@ enum
|
||||
kNumCmds
|
||||
};
|
||||
|
||||
static const unsigned kNumAdditionalParkCmds = 3;
|
||||
|
||||
|
||||
struct CCommandInfo
|
||||
{
|
||||
@@ -506,18 +506,20 @@ void CInArchive::AddLicense(UInt32 param, Int32 langID)
|
||||
#endif
|
||||
|
||||
|
||||
#define kVar_CMDLINE 20
|
||||
// #define kVar_CMDLINE 20
|
||||
#define kVar_INSTDIR 21
|
||||
#define kVar_OUTDIR 22
|
||||
#define kVar_EXEDIR 23
|
||||
#define kVar_LANGUAGE 24
|
||||
// #define kVar_LANGUAGE 24
|
||||
#define kVar_TEMP 25
|
||||
#define kVar_PLUGINSDIR 26
|
||||
#define kVar_EXEPATH 27 // NSIS 2.26+
|
||||
#define kVar_EXEFILE 28 // NSIS 2.26+
|
||||
// #define kVar_EXEFILE 28 // NSIS 2.26+
|
||||
|
||||
#define kVar_HWNDPARENT_225 27
|
||||
#ifdef NSIS_SCRIPT
|
||||
#define kVar_HWNDPARENT 29
|
||||
#endif
|
||||
|
||||
// #define kVar__CLICK 30
|
||||
#define kVar_Spec_OUTDIR_225 29 // NSIS 2.04 - 2.25
|
||||
@@ -606,9 +608,9 @@ void CInArchive::AddParam_UInt(UInt32 value)
|
||||
#define NS_CODE_SKIP 252
|
||||
#define NS_CODE_VAR 253
|
||||
#define NS_CODE_SHELL 254
|
||||
#define NS_CODE_LANG 255
|
||||
// #define NS_CODE_LANG 255
|
||||
|
||||
#define NS_3_CODE_LANG 1
|
||||
// #define NS_3_CODE_LANG 1
|
||||
#define NS_3_CODE_SHELL 2
|
||||
#define NS_3_CODE_VAR 3
|
||||
#define NS_3_CODE_SKIP 4
|
||||
@@ -1364,7 +1366,7 @@ void CInArchive::ReadString2(AString &s, UInt32 pos)
|
||||
|
||||
#ifdef NSIS_SCRIPT
|
||||
|
||||
#define DEL_DIR 1
|
||||
// #define DEL_DIR 1
|
||||
#define DEL_RECURSE 2
|
||||
#define DEL_REBOOT 4
|
||||
// #define DEL_SIMPLE 8
|
||||
@@ -1445,9 +1447,11 @@ static void FlagsToString2(CDynLimBuf &s, const char * const *table, unsigned nu
|
||||
|
||||
static bool DoesNeedQuotes(const char *s)
|
||||
{
|
||||
char c = s[0];
|
||||
if (c == 0 || c == '#' || c == ';' || (c == '/' && s[1] == '*'))
|
||||
return true;
|
||||
{
|
||||
char c = s[0];
|
||||
if (c == 0 || c == '#' || c == ';' || (c == '/' && s[1] == '*'))
|
||||
return true;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
char c = *s++;
|
||||
@@ -1737,12 +1741,12 @@ void CNsis_CtlColors::Parse(const Byte *p)
|
||||
|
||||
// Win32 constants
|
||||
#define MY__TRANSPARENT 1
|
||||
#define MY__OPAQUE 2
|
||||
// #define MY__OPAQUE 2
|
||||
|
||||
#define MY__GENERIC_READ (1 << 31)
|
||||
#define MY__GENERIC_WRITE (1 << 30)
|
||||
#define MY__GENERIC_EXECUTE (1 << 29)
|
||||
#define MY__GENERIC_ALL (1 << 28)
|
||||
#define MY__GENERIC_READ ((UInt32)1 << 31)
|
||||
#define MY__GENERIC_WRITE ((UInt32)1 << 30)
|
||||
#define MY__GENERIC_EXECUTE ((UInt32)1 << 29)
|
||||
#define MY__GENERIC_ALL ((UInt32)1 << 28)
|
||||
|
||||
#define MY__CREATE_NEW 1
|
||||
#define MY__CREATE_ALWAYS 2
|
||||
@@ -2068,9 +2072,11 @@ void CSection::Parse(const Byte *p)
|
||||
#define SF_BOLD (1 << 3)
|
||||
#define SF_RO (1 << 4)
|
||||
#define SF_EXPAND (1 << 5)
|
||||
/*
|
||||
#define SF_PSELECTED (1 << 6)
|
||||
#define SF_TOGGLED (1 << 7)
|
||||
#define SF_NAMECHG (1 << 8)
|
||||
*/
|
||||
|
||||
bool CInArchive::PrintSectionBegin(const CSection §, unsigned index)
|
||||
{
|
||||
@@ -2115,7 +2121,7 @@ bool CInArchive::PrintSectionBegin(const CSection §, unsigned index)
|
||||
Script += ' ';
|
||||
else
|
||||
*/
|
||||
SmallSpaceComment();
|
||||
SmallSpaceComment();
|
||||
Script += "Section_";
|
||||
Add_UInt(index);
|
||||
|
||||
@@ -2290,14 +2296,15 @@ bool CInArchive::CompareCommands(const Byte *rawCmds, const Byte *sequence, size
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static const UInt32 kSectionSize_base = 6 * 4;
|
||||
static const UInt32 kSectionSize_8bit = kSectionSize_base + 1024;
|
||||
static const UInt32 kSectionSize_16bit = kSectionSize_base + 1024 * 2;
|
||||
static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2;
|
||||
// static const UInt32 kSectionSize_8bit = kSectionSize_base + 1024;
|
||||
// static const UInt32 kSectionSize_16bit = kSectionSize_base + 1024 * 2;
|
||||
// static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2;
|
||||
// 8196 is default string length in NSIS-Unicode since 2.37.3
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void AddString(AString &dest, const char *src)
|
||||
{
|
||||
@@ -2330,8 +2337,13 @@ AString CInArchive::GetFormatDescription() const
|
||||
|
||||
if (IsUnicode)
|
||||
AddString(s, "Unicode");
|
||||
|
||||
if (Is64Bit)
|
||||
AddString(s, "64-bit");
|
||||
|
||||
if (LogCmdIsEnabled)
|
||||
AddString(s, "log");
|
||||
|
||||
if (BadCmd >= 0)
|
||||
{
|
||||
AddString(s, "BadCmd=");
|
||||
@@ -2342,9 +2354,11 @@ AString CInArchive::GetFormatDescription() const
|
||||
|
||||
#ifdef NSIS_SCRIPT
|
||||
|
||||
static const unsigned kNumAdditionalParkCmds = 3;
|
||||
|
||||
unsigned CInArchive::GetNumSupportedCommands() const
|
||||
{
|
||||
unsigned numCmds = IsPark() ? kNumCmds : kNumCmds - kNumAdditionalParkCmds;
|
||||
unsigned numCmds = IsPark() ? (unsigned)kNumCmds : (unsigned)(kNumCmds) - kNumAdditionalParkCmds;
|
||||
if (!LogCmdIsEnabled)
|
||||
numCmds--;
|
||||
if (!IsUnicode)
|
||||
@@ -2792,26 +2806,20 @@ bool CInArchive::IsAbsolutePathVar(UInt32 strPos) const
|
||||
return false;
|
||||
}
|
||||
|
||||
#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
|
||||
#define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
|
||||
|
||||
// We use same check as in NSIS decoder
|
||||
bool IsDrivePath(const wchar_t *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; }
|
||||
bool IsDrivePath(const char *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; }
|
||||
static bool IsDrivePath(const wchar_t *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; }
|
||||
static bool IsDrivePath(const char *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\' */ ; }
|
||||
|
||||
static bool IsAbsolutePath(const wchar_t *s)
|
||||
{
|
||||
return
|
||||
s[0] == WCHAR_PATH_SEPARATOR &&
|
||||
s[1] == WCHAR_PATH_SEPARATOR ||
|
||||
IsDrivePath(s);
|
||||
return (s[0] == WCHAR_PATH_SEPARATOR && s[1] == WCHAR_PATH_SEPARATOR) || IsDrivePath(s);
|
||||
}
|
||||
|
||||
static bool IsAbsolutePath(const char *s)
|
||||
{
|
||||
return
|
||||
s[0] == CHAR_PATH_SEPARATOR &&
|
||||
s[1] == CHAR_PATH_SEPARATOR ||
|
||||
IsDrivePath(s);
|
||||
return (s[0] == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR) || IsDrivePath(s);
|
||||
}
|
||||
|
||||
void CInArchive::SetItemName(CItem &item, UInt32 strPos)
|
||||
@@ -3748,8 +3756,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
|
||||
|
||||
for (UInt32 j = i - 1; j >= kkk + 3; j--)
|
||||
{
|
||||
const Byte *pCmd = p + kCmdSize * (j - kkk);
|
||||
AddParam(GET_CMD_PARAM(pCmd, 0));
|
||||
const Byte *pCmd2 = p + kCmdSize * (j - kkk);
|
||||
AddParam(GET_CMD_PARAM(pCmd2, 0));
|
||||
}
|
||||
NewLine();
|
||||
Tab(true);
|
||||
@@ -3850,13 +3858,13 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
|
||||
{
|
||||
case k_ExecFlags_AutoClose:
|
||||
case k_ExecFlags_RebootFlag:
|
||||
if (v < 2) s2 = (v == 0) ? "false" : "true"; break;
|
||||
if (v < 2) { s2 = (v == 0) ? "false" : "true"; } break;
|
||||
case k_ExecFlags_ShellVarContext:
|
||||
if (v < 2) s2 = (v == 0) ? "current" : "all"; break;
|
||||
if (v < 2) { s2 = (v == 0) ? "current" : "all"; } break;
|
||||
case k_ExecFlags_Silent:
|
||||
if (v < 2) s2 = (v == 0) ? "normal" : "silent"; break;
|
||||
if (v < 2) { s2 = (v == 0) ? "normal" : "silent"; } break;
|
||||
case k_ExecFlags_RegView:
|
||||
if (v == 0) s2 = "32";
|
||||
if (v == 0) s2 = "32";
|
||||
else if (v == 256) s2 = "64";
|
||||
break;
|
||||
case k_ExecFlags_DetailsPrint:
|
||||
@@ -3864,6 +3872,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
|
||||
else if (v == 2) s2 = "textonly";
|
||||
else if (v == 4) s2 = "listonly";
|
||||
else if (v == 6) s2 = "none";
|
||||
break;
|
||||
}
|
||||
if (s2)
|
||||
{
|
||||
@@ -4400,7 +4409,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
|
||||
s += 'F';
|
||||
Add_UInt(key - kMy_VK_F1 + 1);
|
||||
}
|
||||
else if (key >= 'A' && key <= 'Z' || key >= '0' && key <= '9')
|
||||
else if ((key >= 'A' && key <= 'Z') || (key >= '0' && key <= '9'))
|
||||
s += (char)key;
|
||||
else
|
||||
{
|
||||
@@ -4687,6 +4696,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
|
||||
s += "Text";
|
||||
AddParam(params[1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case EW_SECTIONSET:
|
||||
@@ -4829,9 +4839,6 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (curSectionIndex == 49)
|
||||
curSectionIndex = curSectionIndex;
|
||||
|
||||
if (PrintSectionBegin(sect, curSectionIndex))
|
||||
curSectionIndex++;
|
||||
else
|
||||
@@ -4846,8 +4853,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
|
||||
|
||||
static int CompareItems(void *const *p1, void *const *p2, void *param)
|
||||
{
|
||||
const CItem &i1 = **(CItem **)p1;
|
||||
const CItem &i2 = **(CItem **)p2;
|
||||
const CItem &i1 = **(const CItem *const *)p1;
|
||||
const CItem &i2 = **(const CItem *const *)p2;
|
||||
RINOZ(MyCompare(i1.Pos, i2.Pos));
|
||||
const CInArchive *inArchive = (const CInArchive *)param;
|
||||
if (inArchive->IsUnicode)
|
||||
@@ -4970,14 +4977,15 @@ HRESULT CInArchive::SortItems()
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef NSIS_SCRIPT
|
||||
// Flags for common_header.flags
|
||||
#define CH_FLAGS_DETAILS_SHOWDETAILS 1
|
||||
#define CH_FLAGS_DETAILS_NEVERSHOW 2
|
||||
// #define CH_FLAGS_DETAILS_SHOWDETAILS 1
|
||||
// #define CH_FLAGS_DETAILS_NEVERSHOW 2
|
||||
#define CH_FLAGS_PROGRESS_COLORED 4
|
||||
#define CH_FLAGS_SILENT 8
|
||||
#define CH_FLAGS_SILENT_LOG 16
|
||||
#define CH_FLAGS_AUTO_CLOSE 32
|
||||
#define CH_FLAGS_DIR_NO_SHOW 64 // unused now
|
||||
// #define CH_FLAGS_DIR_NO_SHOW 64 // unused now
|
||||
#define CH_FLAGS_NO_ROOT_DIR 128
|
||||
#define CH_FLAGS_COMP_ONLY_ON_CUSTOM 256
|
||||
#define CH_FLAGS_NO_CUSTOM 512
|
||||
@@ -4989,29 +4997,59 @@ static const char * const k_PostStrings[] =
|
||||
, "uninstcmd" // NSIS 2.25+, used by uninstaller:
|
||||
, "wininit" // NSIS 2.25+, used by move file on reboot
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
void CBlockHeader::Parse(const Byte *p, unsigned bhoSize)
|
||||
{
|
||||
if (bhoSize == 12)
|
||||
{
|
||||
// UInt64 a = GetUi64(p);
|
||||
if (GetUi32(p + 4) != 0)
|
||||
throw 1;
|
||||
}
|
||||
Offset = GetUi32(p);
|
||||
Num = GetUi32(p + bhoSize - 4);
|
||||
}
|
||||
|
||||
#define PARSE_BH(k, bh) bh.Parse (p1 + 4 + bhoSize * k, bhoSize)
|
||||
|
||||
|
||||
HRESULT CInArchive::Parse()
|
||||
{
|
||||
// UInt32 offset = ReadUInt32();
|
||||
// ???? offset == FirstHeader.HeaderSize
|
||||
const Byte *p = _data;
|
||||
const Byte * const p1 = _data;
|
||||
|
||||
if (_size < 4 + 8 * 8)
|
||||
if (_size < 4 + 12 * 8)
|
||||
Is64Bit = false;
|
||||
else
|
||||
{
|
||||
Is64Bit = true;
|
||||
// here we test high 32-bit of possible UInt64 CBlockHeader::Offset field
|
||||
for (int k = 0; k < 8; k++)
|
||||
if (GetUi32(p1 + 4 + 12 * k + 4) != 0)
|
||||
Is64Bit = false;
|
||||
}
|
||||
|
||||
const unsigned bhoSize = Is64Bit ? 12 : 8;
|
||||
if (_size < 4 + bhoSize * 8)
|
||||
return S_FALSE;
|
||||
|
||||
CBlockHeader bhEntries, bhStrings, bhLangTables;
|
||||
bhEntries.Parse(p + 4 + 8 * 2);
|
||||
bhStrings.Parse(p + 4 + 8 * 3);
|
||||
bhLangTables.Parse(p + 4 + 8 * 4);
|
||||
|
||||
PARSE_BH (2, bhEntries);
|
||||
PARSE_BH (3, bhStrings);
|
||||
PARSE_BH (4, bhLangTables);
|
||||
|
||||
#ifdef NSIS_SCRIPT
|
||||
|
||||
CBlockHeader bhFont;
|
||||
bhPages.Parse(p + 4 + 8 * 0);
|
||||
bhSections.Parse(p + 4 + 8 * 1);
|
||||
bhCtlColors.Parse(p + 4 + 8 * 5);
|
||||
bhFont.Parse(p + 4 + 8 * 6);
|
||||
bhData.Parse(p + 4 + 8 * 7);
|
||||
PARSE_BH (0, bhPages);
|
||||
PARSE_BH (1, bhSections);
|
||||
PARSE_BH (5, bhCtlColors);
|
||||
PARSE_BH (6, bhFont);
|
||||
PARSE_BH (7, bhData);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5084,6 +5122,7 @@ HRESULT CInArchive::Parse()
|
||||
case NMethodType::kDeflate: m = "zlib"; break;
|
||||
case NMethodType::kBZip2: m = "bzip2"; break;
|
||||
case NMethodType::kLZMA: m = "lzma"; break;
|
||||
default: break;
|
||||
}
|
||||
Script += "SetCompressor";
|
||||
if (IsSolid)
|
||||
@@ -5167,7 +5206,7 @@ HRESULT CInArchive::Parse()
|
||||
memset(strUsed, 0, NumStringChars);
|
||||
|
||||
{
|
||||
UInt32 ehFlags = Get32(p);
|
||||
UInt32 ehFlags = Get32(p1);
|
||||
UInt32 showDetails = ehFlags & 3;// CH_FLAGS_DETAILS_SHOWDETAILS & CH_FLAGS_DETAILS_NEVERSHOW;
|
||||
if (showDetails >= 1 && showDetails <= 2)
|
||||
{
|
||||
@@ -5208,11 +5247,16 @@ HRESULT CInArchive::Parse()
|
||||
}
|
||||
}
|
||||
|
||||
unsigned paramsOffset = 4 + 8 * 8;
|
||||
if (bhPages.Offset == 276)
|
||||
paramsOffset -= 8;
|
||||
unsigned paramsOffset;
|
||||
{
|
||||
unsigned numBhs = 8;
|
||||
// probably its for old NSIS?
|
||||
if (bhoSize == 8 && bhPages.Offset == 276)
|
||||
numBhs = 7;
|
||||
paramsOffset = 4 + bhoSize * numBhs;
|
||||
}
|
||||
|
||||
const Byte *p2 = p + paramsOffset;
|
||||
const Byte *p2 = p1 + paramsOffset;
|
||||
|
||||
{
|
||||
UInt32 rootKey = Get32(p2); // (rootKey = -1) in uninstaller by default (the bug in NSIS)
|
||||
@@ -5261,7 +5305,8 @@ HRESULT CInArchive::Parse()
|
||||
}
|
||||
|
||||
UInt32 license_bg = Get32(p2 + 36);
|
||||
if (license_bg != (UInt32)(Int32)-1 && license_bg != -15) // COLOR_BTNFACE
|
||||
if (license_bg != (UInt32)(Int32)-1 &&
|
||||
license_bg != (UInt32)(Int32)-15) // COLOR_BTNFACE
|
||||
{
|
||||
Script += "LicenseBkColor";
|
||||
if ((Int32)license_bg == -5) // COLOR_WINDOW
|
||||
@@ -5275,13 +5320,19 @@ HRESULT CInArchive::Parse()
|
||||
AddLF();
|
||||
}
|
||||
|
||||
UInt32 langtable_size = Get32(p2 + 32);
|
||||
if (bhLangTables.Num > 0)
|
||||
{
|
||||
const UInt32 langtable_size = Get32(p2 + 32);
|
||||
|
||||
if (langtable_size == (UInt32)(Int32)-1)
|
||||
return E_NOTIMPL; // maybe it's old NSIS archive()
|
||||
|
||||
UInt32 numStrings = (langtable_size - 10) / 4;
|
||||
if (langtable_size < 10)
|
||||
return S_FALSE;
|
||||
if (bhLangTables.Num > (_size - bhLangTables.Offset) / langtable_size)
|
||||
return S_FALSE;
|
||||
|
||||
const UInt32 numStrings = (langtable_size - 10) / 4;
|
||||
_numLangStrings = numStrings;
|
||||
AddLF();
|
||||
Separator();
|
||||
@@ -5289,12 +5340,12 @@ HRESULT CInArchive::Parse()
|
||||
PrintNumComment("LANG STRINGS", numStrings);
|
||||
AddLF();
|
||||
|
||||
if (licenseLangIndex >= 0)
|
||||
if (licenseLangIndex >= 0 && (unsigned)licenseLangIndex < numStrings)
|
||||
{
|
||||
for (UInt32 i = 0; i < bhLangTables.Num; i++)
|
||||
{
|
||||
const Byte *p = _data + bhLangTables.Offset + langtable_size * i;
|
||||
LANGID langID = Get16(p);
|
||||
const Byte * const p = _data + bhLangTables.Offset + langtable_size * i;
|
||||
const UInt16 langID = Get16(p);
|
||||
UInt32 val = Get32(p + 10 + (UInt32)licenseLangIndex * 4);
|
||||
if (val != 0)
|
||||
{
|
||||
@@ -5309,33 +5360,24 @@ HRESULT CInArchive::Parse()
|
||||
AddLF();
|
||||
}
|
||||
|
||||
UInt32 brandingText = 0;
|
||||
UInt32 caption = 0;
|
||||
UInt32 name = 0;
|
||||
UInt32 names[3] = { 0 };
|
||||
|
||||
UInt32 i;
|
||||
for (i = 0; i < bhLangTables.Num; i++)
|
||||
{
|
||||
const Byte *p = _data + bhLangTables.Offset + langtable_size * i;
|
||||
LANGID langID = Get16(p);
|
||||
const Byte * const p = _data + bhLangTables.Offset + langtable_size * i;
|
||||
const UInt16 langID = Get16(p);
|
||||
if (i == 0 || langID == 1033)
|
||||
_mainLang = p + 10;
|
||||
for (unsigned k = 0; k < ARRAY_SIZE(names) && k < numStrings; k++)
|
||||
{
|
||||
UInt32 v = Get32(p + 10 + 0 * 4);
|
||||
if (v != 0 && (langID == 1033 || brandingText == 0))
|
||||
brandingText = v;
|
||||
}
|
||||
{
|
||||
UInt32 v = Get32(p + 10 + 1 * 4);
|
||||
if (v != 0 && (langID == 1033 || caption == 0))
|
||||
caption = v;
|
||||
}
|
||||
{
|
||||
UInt32 v = Get32(p + 10 + 2 * 4);
|
||||
if (v != 0 && (langID == 1033 || name == 0))
|
||||
name = v;
|
||||
UInt32 v = Get32(p + 10 + k * 4);
|
||||
if (v != 0 && (langID == 1033 || names[k] == 0))
|
||||
names[k] = v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const UInt32 name = names[2];
|
||||
if (name != 0)
|
||||
{
|
||||
Script += "Name";
|
||||
@@ -5346,6 +5388,7 @@ HRESULT CInArchive::Parse()
|
||||
}
|
||||
|
||||
/*
|
||||
const UInt32 caption = names[1];
|
||||
if (caption != 0)
|
||||
{
|
||||
Script += "Caption";
|
||||
@@ -5354,6 +5397,7 @@ HRESULT CInArchive::Parse()
|
||||
}
|
||||
*/
|
||||
|
||||
const UInt32 brandingText = names[0];
|
||||
if (brandingText != 0)
|
||||
{
|
||||
Script += "BrandingText";
|
||||
@@ -5365,8 +5409,8 @@ HRESULT CInArchive::Parse()
|
||||
|
||||
for (i = 0; i < bhLangTables.Num; i++)
|
||||
{
|
||||
const Byte *p = _data + bhLangTables.Offset + langtable_size * i;
|
||||
LANGID langID = Get16(p);
|
||||
const Byte * const p = _data + bhLangTables.Offset + langtable_size * i;
|
||||
const UInt16 langID = Get16(p);
|
||||
|
||||
AddLF();
|
||||
AddCommentAndString("LANG:");
|
||||
@@ -5641,10 +5685,12 @@ HRESULT CInArchive::Open2(const Byte *sig, size_t size)
|
||||
if (Get32((const Byte *)buf) != FirstHeader.HeaderSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
size_t processedSize = FirstHeader.HeaderSize;
|
||||
RINOK(Decoder.Read(_data, &processedSize));
|
||||
if (processedSize != FirstHeader.HeaderSize)
|
||||
return S_FALSE;
|
||||
{
|
||||
size_t processedSize = FirstHeader.HeaderSize;
|
||||
RINOK(Decoder.Read(_data, &processedSize));
|
||||
if (processedSize != FirstHeader.HeaderSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
#ifdef NSIS_SCRIPT
|
||||
if (IsSolid)
|
||||
@@ -5824,14 +5870,25 @@ HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *maxCheckStartPositio
|
||||
DataStreamOffset = pos + kStartHeaderSize;
|
||||
FirstHeader.Flags = Get32(buf);
|
||||
if ((FirstHeader.Flags & (~kFlagsMask)) != 0)
|
||||
{
|
||||
// return E_NOTIMPL;
|
||||
return S_FALSE;
|
||||
}
|
||||
IsInstaller = (FirstHeader.Flags & NFlags::kUninstall) == 0;
|
||||
|
||||
FirstHeader.HeaderSize = Get32(buf + kSignatureSize + 4);
|
||||
FirstHeader.ArcSize = Get32(buf + kSignatureSize + 8);
|
||||
if (FirstHeader.ArcSize <= kStartHeaderSize)
|
||||
return S_FALSE;
|
||||
|
||||
|
||||
/*
|
||||
if ((FirstHeader.Flags & NFlags::k_BI_ExternalFileSupport) != 0)
|
||||
{
|
||||
UInt32 datablock_low = Get32(buf + kSignatureSize + 12);
|
||||
UInt32 datablock_high = Get32(buf + kSignatureSize + 16);
|
||||
}
|
||||
*/
|
||||
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_END, &_fileSize));
|
||||
|
||||
IsArc = true;
|
||||
@@ -5872,7 +5929,8 @@ UString CInArchive::ConvertToUnicode(const AString &s) const
|
||||
if (IsUnicode)
|
||||
{
|
||||
UString res;
|
||||
if (ConvertUTF8ToUnicode(s, res))
|
||||
// if (
|
||||
ConvertUTF8ToUnicode(s, res);
|
||||
return res;
|
||||
}
|
||||
return MultiByteToUnicodeString(s);
|
||||
@@ -5886,6 +5944,7 @@ void CInArchive::Clear2()
|
||||
IsNsis200 = false;
|
||||
LogCmdIsEnabled = false;
|
||||
BadCmd = -1;
|
||||
Is64Bit = false;
|
||||
|
||||
#ifdef NSIS_SCRIPT
|
||||
Name.Empty();
|
||||
|
||||
@@ -34,6 +34,11 @@ namespace NFlags
|
||||
const UInt32 kSilent = 2;
|
||||
const UInt32 kNoCrc = 4;
|
||||
const UInt32 kForceCrc = 8;
|
||||
// NSISBI fork flags:
|
||||
const UInt32 k_BI_LongOffset = 16;
|
||||
const UInt32 k_BI_ExternalFileSupport = 32;
|
||||
const UInt32 k_BI_ExternalFile = 64;
|
||||
const UInt32 k_BI_IsStubInstaller = 128;
|
||||
}
|
||||
|
||||
struct CFirstHeader
|
||||
@@ -58,11 +63,7 @@ struct CBlockHeader
|
||||
UInt32 Offset;
|
||||
UInt32 Num;
|
||||
|
||||
void Parse(const Byte *p)
|
||||
{
|
||||
Offset = GetUi32(p);
|
||||
Num = GetUi32(p + 4);
|
||||
}
|
||||
void Parse(const Byte *p, unsigned bhoSize);
|
||||
};
|
||||
|
||||
struct CItem
|
||||
@@ -159,6 +160,7 @@ public:
|
||||
CByteBuffer _data;
|
||||
CObjectVector<CItem> Items;
|
||||
bool IsUnicode;
|
||||
bool Is64Bit;
|
||||
private:
|
||||
UInt32 _stringsPos; // relative to _data
|
||||
UInt32 NumStringChars;
|
||||
@@ -170,7 +172,6 @@ private:
|
||||
ENsisType NsisType;
|
||||
bool IsNsis200; // NSIS 2.03 and before
|
||||
bool IsNsis225; // NSIS 2.25 and before
|
||||
|
||||
bool LogCmdIsEnabled;
|
||||
int BadCmd; // -1: no bad command; in another cases lowest bad command id
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ enum
|
||||
Posix name can be after or before Win32 name
|
||||
*/
|
||||
|
||||
static const Byte kFileNameType_Posix = 0; // for hard links
|
||||
// static const Byte kFileNameType_Posix = 0; // for hard links
|
||||
static const Byte kFileNameType_Win32 = 1; // after Dos name
|
||||
static const Byte kFileNameType_Dos = 2; // short name
|
||||
static const Byte kFileNameType_Win32Dos = 3; // short and full name are same
|
||||
@@ -386,8 +386,8 @@ struct CAttr
|
||||
|
||||
static int CompareAttr(void *const *elem1, void *const *elem2, void *)
|
||||
{
|
||||
const CAttr &a1 = *(*((const CAttr **)elem1));
|
||||
const CAttr &a2 = *(*((const CAttr **)elem2));
|
||||
const CAttr &a1 = *(*((const CAttr *const *)elem1));
|
||||
const CAttr &a2 = *(*((const CAttr *const *)elem2));
|
||||
RINOZ(MyCompare(a1.Type, a2.Type));
|
||||
if (a1.Name.IsEmpty())
|
||||
{
|
||||
@@ -717,12 +717,16 @@ static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte
|
||||
UInt32 dist = (v >> (16 - numDistBits));
|
||||
if (dist >= sbOffset)
|
||||
return 0;
|
||||
Int32 offs = -1 - dist;
|
||||
Byte *p = dest + destSize;
|
||||
for (UInt32 t = 0; t < len; t++)
|
||||
p[t] = p[t + offs];
|
||||
const size_t offs = 1 + dist;
|
||||
Byte *p = dest + destSize - offs;
|
||||
destSize += len;
|
||||
sbOffset += len;
|
||||
const Byte *lim = p + len;
|
||||
p[offs] = *p; ++p;
|
||||
p[offs] = *p; ++p;
|
||||
do
|
||||
p[offs] = *p;
|
||||
while (++p != lim);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1094,7 +1098,7 @@ struct CMftRec
|
||||
void CMftRec::ParseDataNames()
|
||||
{
|
||||
DataRefs.Clear();
|
||||
DataAttrs.Sort(CompareAttr, 0);
|
||||
DataAttrs.Sort(CompareAttr, NULL);
|
||||
|
||||
for (unsigned i = 0; i < DataAttrs.Size();)
|
||||
{
|
||||
@@ -2188,7 +2192,7 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
|
||||
*data = (const wchar_t *)EmptyString;
|
||||
else
|
||||
*data = s->GetRawPtr();
|
||||
*dataSize = (s->Len() + 1) * sizeof(wchar_t);
|
||||
*dataSize = (s->Len() + 1) * (UInt32)sizeof(wchar_t);
|
||||
*propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE;
|
||||
#endif
|
||||
return S_OK;
|
||||
|
||||
@@ -363,8 +363,8 @@ struct CSection
|
||||
|
||||
CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {}
|
||||
|
||||
const UInt32 GetSizeExtract() const { return PSize; }
|
||||
const UInt32 GetSizeMin() const { return MyMin(PSize, VSize); }
|
||||
UInt32 GetSizeExtract() const { return PSize; }
|
||||
UInt32 GetSizeMin() const { return MyMin(PSize, VSize); }
|
||||
|
||||
void UpdateTotalSize(UInt32 &totalSize) const
|
||||
{
|
||||
@@ -768,15 +768,15 @@ class CHandler:
|
||||
bool _oneLang;
|
||||
UString _resourcesPrefix;
|
||||
CUsedBitmap _usedRes;
|
||||
bool _parseResources;
|
||||
// bool _parseResources;
|
||||
bool _checksumError;
|
||||
|
||||
bool IsOpt() const { return _header.OptHeaderSize != 0; }
|
||||
|
||||
COptHeader _optHeader;
|
||||
|
||||
bool _allowTail;
|
||||
bool _coffMode;
|
||||
bool _allowTail;
|
||||
|
||||
HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection);
|
||||
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
|
||||
@@ -2005,10 +2005,12 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi
|
||||
const UInt32 mask = ((UInt32)1 << numBits) - 1;
|
||||
const size_t end = (size_t)((sect.VSize + mask) & (UInt32)~mask);
|
||||
if (end > sect.VSize)
|
||||
{
|
||||
if (end <= sect.PSize)
|
||||
fileSize = end;
|
||||
else
|
||||
fileSize = sect.PSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2459,7 +2461,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
_parseResources = true;
|
||||
bool _parseResources = true;
|
||||
// _parseResources = false;
|
||||
|
||||
UInt64 mainSize = 0, mainSize2 = 0;
|
||||
@@ -2467,11 +2469,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
for (i = 0; i < _sections.Size(); i++)
|
||||
{
|
||||
const CSection § = _sections[i];
|
||||
CMixItem mixItem;
|
||||
mixItem.SectionIndex = i;
|
||||
if (IsOpt())
|
||||
if (_parseResources && sect.Name == ".rsrc" && _items.IsEmpty())
|
||||
if (_parseResources && sect.Name == ".rsrc")
|
||||
{
|
||||
// 20.01: we try to parse only first copy of .rsrc section.
|
||||
_parseResources = false;
|
||||
const unsigned numMixItems = _mixItems.Size();
|
||||
HRESULT res = OpenResources(i, stream, callback);
|
||||
if (res == S_OK)
|
||||
@@ -2483,6 +2485,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
const CResItem &item = _items[j];
|
||||
if (item.Enabled)
|
||||
{
|
||||
CMixItem mixItem;
|
||||
mixItem.SectionIndex = i;
|
||||
mixItem.ResourceIndex = j;
|
||||
if (item.IsRcDataOrUnknown())
|
||||
{
|
||||
@@ -2531,6 +2535,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
_mixItems.DeleteFrom(numMixItems);
|
||||
CloseResources();
|
||||
}
|
||||
|
||||
if (sect.IsAdditionalSection)
|
||||
{
|
||||
if (sect.PSize >= mainSize)
|
||||
@@ -2542,6 +2547,9 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
else if (sect.PSize >= mainSize2)
|
||||
mainSize2 = sect.PSize;
|
||||
}
|
||||
|
||||
CMixItem mixItem;
|
||||
mixItem.SectionIndex = i;
|
||||
_mixItems.Add(mixItem);
|
||||
}
|
||||
|
||||
@@ -3017,7 +3025,7 @@ static const Byte kProps[] =
|
||||
|
||||
enum
|
||||
{
|
||||
kpidSubSystem = kpidUserDefined,
|
||||
kpidSubSystem = kpidUserDefined
|
||||
// , kpidImageBase
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* PpmdHandler.cpp -- PPMd format handler
|
||||
2015-11-30 : Igor Pavlov : Public domain
|
||||
2020 : 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 */
|
||||
@@ -59,7 +59,7 @@ struct CItem
|
||||
unsigned Restor;
|
||||
|
||||
HRESULT ReadHeader(ISequentialInStream *s, UInt32 &headerSize);
|
||||
bool IsSupported() const { return Ver == 7 || (Ver == 8 && Restor <= 1); }
|
||||
bool IsSupported() const { return Ver == 7 || (Ver == 8 && Restor < PPMD8_RESTORE_METHOD_UNSUPPPORTED); }
|
||||
};
|
||||
|
||||
HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize)
|
||||
@@ -218,91 +218,11 @@ STDMETHODIMP CHandler::Close()
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const UInt32 kTopValue = (1 << 24);
|
||||
static const UInt32 kBot = (1 << 15);
|
||||
|
||||
struct CRangeDecoder
|
||||
{
|
||||
IPpmd7_RangeDec vt;
|
||||
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" {
|
||||
|
||||
#define GET_RangeDecoder CRangeDecoder *p = CONTAINER_FROM_VTBL(pp, CRangeDecoder, vt);
|
||||
|
||||
static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total)
|
||||
{
|
||||
GET_RangeDecoder
|
||||
return p->Code / (p->Range /= total);
|
||||
}
|
||||
|
||||
static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size)
|
||||
{
|
||||
GET_RangeDecoder
|
||||
start *= p->Range;
|
||||
p->Low += start;
|
||||
p->Code -= start;
|
||||
p->Range *= size;
|
||||
p->Normalize();
|
||||
}
|
||||
|
||||
static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0)
|
||||
{
|
||||
GET_RangeDecoder
|
||||
if (p->Code / (p->Range >>= 14) < size0)
|
||||
{
|
||||
Range_Decode(&p->vt, 0, size0);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Range_Decode(&p->vt, size0, (1 << 14) - size0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CRangeDecoder::CRangeDecoder()
|
||||
{
|
||||
vt.GetThreshold = Range_GetThreshold;
|
||||
vt.Decode = Range_Decode;
|
||||
vt.DecodeBit = Range_DecodeBit;
|
||||
}
|
||||
|
||||
struct CPpmdCpp
|
||||
{
|
||||
unsigned Ver;
|
||||
CRangeDecoder _rc;
|
||||
CPpmd7 _ppmd7;
|
||||
CPpmd8 _ppmd8;
|
||||
|
||||
@@ -339,20 +259,20 @@ struct CPpmdCpp
|
||||
{
|
||||
if (Ver == 7)
|
||||
{
|
||||
_rc.Stream = inStream;
|
||||
return _rc.Init();
|
||||
_ppmd7.rc.dec.Stream = &inStream->vt;
|
||||
return (Ppmd7a_RangeDec_Init(&_ppmd7.rc.dec) != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ppmd8.Stream.In = &inStream->vt;
|
||||
return Ppmd8_RangeDec_Init(&_ppmd8) != 0;
|
||||
return Ppmd8_Init_RangeDec(&_ppmd8) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFinishedOK()
|
||||
{
|
||||
if (Ver == 7)
|
||||
return Ppmd7z_RangeDec_IsFinishedOK(&_rc);
|
||||
return Ppmd7z_RangeDec_IsFinishedOK(&_ppmd7.rc.dec);
|
||||
return Ppmd8_RangeDec_IsFinishedOK(&_ppmd8);
|
||||
}
|
||||
};
|
||||
@@ -416,14 +336,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
size_t i;
|
||||
int sym = 0;
|
||||
|
||||
Byte *buf = outBuf.Buf;
|
||||
if (ppmd.Ver == 7)
|
||||
{
|
||||
for (i = 0; i < kBufSize; i++)
|
||||
{
|
||||
sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.vt);
|
||||
sym = Ppmd7a_DecodeSymbol(&ppmd._ppmd7);
|
||||
if (inBuf.Extra || sym < 0)
|
||||
break;
|
||||
outBuf.Buf[i] = (Byte)sym;
|
||||
buf[i] = (Byte)sym;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -433,7 +354,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
sym = Ppmd8_DecodeSymbol(&ppmd._ppmd8);
|
||||
if (inBuf.Extra || sym < 0)
|
||||
break;
|
||||
outBuf.Buf[i] = (Byte)sym;
|
||||
buf[i] = (Byte)sym;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/IntToString.h"
|
||||
#include "../../Common/MyBuffer2.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
|
||||
@@ -31,13 +32,21 @@ namespace NQcow {
|
||||
|
||||
static const Byte k_Signature[] = SIGNATURE;
|
||||
|
||||
/*
|
||||
VA to PA maps:
|
||||
high bits (L1) : : in L1 Table : the reference to L1 Table
|
||||
mid bits (L2) : _numMidBits : in L2 Table : the reference to cluster
|
||||
low bits : _clusterBits
|
||||
*/
|
||||
|
||||
class CHandler: public CHandlerImg
|
||||
{
|
||||
unsigned _clusterBits;
|
||||
unsigned _numMidBits;
|
||||
UInt64 _compressedFlag;
|
||||
|
||||
CObjectVector<CByteBuffer> _tables;
|
||||
CObjArray2<UInt32> _dir;
|
||||
CAlignedBuffer _table;
|
||||
UInt64 _cacheCluster;
|
||||
CByteBuffer _cache;
|
||||
CByteBuffer _cacheCompressed;
|
||||
@@ -63,7 +72,7 @@ class CHandler: public CHandlerImg
|
||||
UInt32 _version;
|
||||
UInt32 _cryptMethod;
|
||||
|
||||
HRESULT Seek(UInt64 offset)
|
||||
HRESULT Seek2(UInt64 offset)
|
||||
{
|
||||
_posInArc = offset;
|
||||
return Stream->Seek(offset, STREAM_SEEK_SET, NULL);
|
||||
@@ -72,7 +81,7 @@ class CHandler: public CHandlerImg
|
||||
HRESULT InitAndSeek()
|
||||
{
|
||||
_virtPos = 0;
|
||||
return Seek(0);
|
||||
return Seek2(0);
|
||||
}
|
||||
|
||||
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback);
|
||||
@@ -85,10 +94,15 @@ public:
|
||||
};
|
||||
|
||||
|
||||
static const UInt32 kEmptyDirItem = (UInt32)0 - 1;
|
||||
|
||||
STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
// printf("\nRead _virtPos = %6d size = %6d\n", (UInt32)_virtPos, size);
|
||||
|
||||
if (_virtPos >= _size)
|
||||
return S_OK;
|
||||
{
|
||||
@@ -101,9 +115,9 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
UInt64 cluster = _virtPos >> _clusterBits;
|
||||
size_t clusterSize = (size_t)1 << _clusterBits;
|
||||
size_t lowBits = (size_t)_virtPos & (clusterSize - 1);
|
||||
const UInt64 cluster = _virtPos >> _clusterBits;
|
||||
const size_t clusterSize = (size_t)1 << _clusterBits;
|
||||
const size_t lowBits = (size_t)_virtPos & (clusterSize - 1);
|
||||
{
|
||||
size_t rem = clusterSize - lowBits;
|
||||
if (size > rem)
|
||||
@@ -113,21 +127,19 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
if (cluster == _cacheCluster)
|
||||
{
|
||||
memcpy(data, _cache + lowBits, size);
|
||||
_virtPos += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
UInt64 high = cluster >> _numMidBits;
|
||||
const UInt64 high = cluster >> _numMidBits;
|
||||
|
||||
if (high < _tables.Size())
|
||||
if (high < _dir.Size())
|
||||
{
|
||||
const CByteBuffer &buffer = _tables[(unsigned)high];
|
||||
const UInt32 tabl = _dir[(unsigned)high];
|
||||
|
||||
if (buffer.Size() != 0)
|
||||
if (tabl != kEmptyDirItem)
|
||||
{
|
||||
size_t midBits = (size_t)cluster & (((size_t)1 << _numMidBits) - 1);
|
||||
const Byte *buffer = _table + ((size_t)tabl << (_numMidBits + 3));
|
||||
const size_t midBits = (size_t)cluster & (((size_t)1 << _numMidBits) - 1);
|
||||
const Byte *p = (const Byte *)buffer + (midBits << 3);
|
||||
UInt64 v = Get64(p);
|
||||
|
||||
@@ -137,19 +149,32 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (_version <= 1)
|
||||
return E_FAIL;
|
||||
unsigned numOffsetBits = (62 - (_clusterBits - 8));
|
||||
UInt64 offset = v & (((UInt64)1 << 62) - 1);
|
||||
|
||||
/*
|
||||
the example of table record for 12-bit clusters (4KB uncompressed).
|
||||
2 bits : isCompressed status
|
||||
4 bits : num_sectors_minus1; packSize = (num_sectors_minus1 + 1) * 512;
|
||||
it uses one additional bit over unpacked cluster_bits
|
||||
49 bits : offset of 512-sector
|
||||
9 bits : offset in 512-sector
|
||||
*/
|
||||
|
||||
const unsigned numOffsetBits = (62 - (_clusterBits - 9 + 1));
|
||||
const UInt64 offset = v & (((UInt64)1 << 62) - 1);
|
||||
const size_t dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
|
||||
offset &= ((UInt64)1 << numOffsetBits) - 1;
|
||||
UInt64 sectorOffset = offset >> 9 << 9;
|
||||
UInt64 offset2inCache = sectorOffset - _comprPos;
|
||||
UInt64 sectorOffset = offset & (((UInt64)1 << numOffsetBits) - (1 << 9));
|
||||
const UInt64 offset2inCache = sectorOffset - _comprPos;
|
||||
|
||||
// _comprPos is aligned for 512-bytes
|
||||
// we try to use previous _cacheCompressed that contains compressed data
|
||||
// that was read for previous unpacking
|
||||
|
||||
if (sectorOffset >= _comprPos && offset2inCache < _comprSize)
|
||||
{
|
||||
if (offset2inCache != 0)
|
||||
{
|
||||
_comprSize -= (size_t)offset2inCache;
|
||||
memmove(_cacheCompressed, _cacheCompressed + offset2inCache, _comprSize);
|
||||
memmove(_cacheCompressed, _cacheCompressed + (size_t)offset2inCache, _comprSize);
|
||||
_comprPos = sectorOffset;
|
||||
}
|
||||
sectorOffset += _comprSize;
|
||||
@@ -160,25 +185,27 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
_comprSize = 0;
|
||||
}
|
||||
|
||||
// printf("\nDeflate");
|
||||
if (sectorOffset != _posInArc)
|
||||
if (dataSize > _comprSize)
|
||||
{
|
||||
// printf("\nDeflate %12I64x %12I64x\n", sectorOffset, sectorOffset - _posInArc);
|
||||
RINOK(Seek(sectorOffset));
|
||||
if (sectorOffset != _posInArc)
|
||||
{
|
||||
// printf("\nDeflate-Seek %12I64x %12I64x\n", sectorOffset, sectorOffset - _posInArc);
|
||||
RINOK(Seek2(sectorOffset));
|
||||
}
|
||||
if (_cacheCompressed.Size() < dataSize)
|
||||
return E_FAIL;
|
||||
const size_t dataSize3 = dataSize - _comprSize;
|
||||
size_t dataSize2 = dataSize3;
|
||||
// printf("\n\n=======\nReadStream = %6d _comprPos = %6d \n", (UInt32)dataSize2, (UInt32)_comprPos);
|
||||
RINOK(ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2));
|
||||
_posInArc += dataSize2;
|
||||
if (dataSize2 != dataSize3)
|
||||
return E_FAIL;
|
||||
_comprSize += dataSize2;
|
||||
}
|
||||
|
||||
if (_cacheCompressed.Size() < dataSize)
|
||||
return E_FAIL;
|
||||
size_t dataSize3 = dataSize - _comprSize;
|
||||
size_t dataSize2 = dataSize3;
|
||||
RINOK(ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2));
|
||||
_posInArc += dataSize2;
|
||||
if (dataSize2 != dataSize3)
|
||||
return E_FAIL;
|
||||
_comprSize += dataSize2;
|
||||
|
||||
const size_t kSectorMask = (1 << 9) - 1;
|
||||
size_t offsetInSector = ((size_t)offset & kSectorMask);
|
||||
const size_t offsetInSector = ((size_t)offset & kSectorMask);
|
||||
_bufInStreamSpec->Init(_cacheCompressed + offsetInSector, dataSize - offsetInSector);
|
||||
|
||||
_cacheCluster = (UInt64)(Int64)-1;
|
||||
@@ -187,7 +214,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
_bufOutStreamSpec->Init(_cache, clusterSize);
|
||||
|
||||
// Do we need to use smaller block than clusterSize for last cluster?
|
||||
UInt64 blockSize64 = clusterSize;
|
||||
const UInt64 blockSize64 = clusterSize;
|
||||
HRESULT res = _deflateDecoderSpec->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL);
|
||||
|
||||
/*
|
||||
@@ -206,10 +233,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
continue;
|
||||
/*
|
||||
memcpy(data, _cache + lowBits, size);
|
||||
_virtPos += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
break;
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -221,7 +245,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
if (v != _posInArc)
|
||||
{
|
||||
// printf("\n%12I64x\n", v - _posInArc);
|
||||
RINOK(Seek(v));
|
||||
RINOK(Seek2(v));
|
||||
}
|
||||
HRESULT res = Stream->Read(data, size, &size);
|
||||
_posInArc += size;
|
||||
@@ -235,11 +259,13 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
}
|
||||
|
||||
memset(data, 0, size);
|
||||
_virtPos += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
_virtPos += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -347,8 +373,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||
const UInt64 backOffset = Get64(buf + 8);
|
||||
// UInt32 backSize = Get32(buf + 0x10);
|
||||
|
||||
UInt64 l1Offset = 0;
|
||||
UInt32 l1Size = 0;
|
||||
UInt64 l1Offset;
|
||||
UInt32 l1Size;
|
||||
|
||||
if (_version == 1)
|
||||
{
|
||||
@@ -364,8 +390,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||
l1Offset = Get64(buf + 0x28);
|
||||
if (l1Offset < 0x30)
|
||||
return S_FALSE;
|
||||
unsigned numBits2 = (_clusterBits + _numMidBits);
|
||||
UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2;
|
||||
const unsigned numBits2 = (_clusterBits + _numMidBits);
|
||||
const UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2;
|
||||
if (l1Size64 > ((UInt32)1 << 31))
|
||||
return S_FALSE;
|
||||
l1Size = (UInt32)l1Size64;
|
||||
@@ -381,8 +407,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||
l1Size = Get32(buf + 0x24);
|
||||
l1Offset = Get64(buf + 0x28); // must be aligned for cluster
|
||||
|
||||
UInt64 refOffset = Get64(buf + 0x30); // must be aligned for cluster
|
||||
UInt32 refClusters = Get32(buf + 0x38);
|
||||
const UInt64 refOffset = Get64(buf + 0x30); // must be aligned for cluster
|
||||
const UInt32 refClusters = Get32(buf + 0x38);
|
||||
|
||||
// UInt32 numSnapshots = Get32(buf + 0x3C);
|
||||
// UInt64 snapshotsOffset = Get64(buf + 0x40); // must be aligned for cluster
|
||||
@@ -393,14 +419,14 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||
|
||||
if (refClusters != 0)
|
||||
{
|
||||
size_t numBytes = refClusters << _clusterBits;
|
||||
const size_t numBytes = refClusters << _clusterBits;
|
||||
/*
|
||||
CByteBuffer refs;
|
||||
refs.Alloc(numBytes);
|
||||
RINOK(stream->Seek(refOffset, STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadStream_FALSE(stream, refs, numBytes));
|
||||
*/
|
||||
UInt64 end = refOffset + numBytes;
|
||||
const UInt64 end = refOffset + numBytes;
|
||||
if (_phySize < end)
|
||||
_phySize = end;
|
||||
/*
|
||||
@@ -426,7 +452,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||
|
||||
CByteBuffer table;
|
||||
{
|
||||
size_t t1SizeBytes = (size_t)l1Size << 3;
|
||||
const size_t t1SizeBytes = (size_t)l1Size << 3;
|
||||
if ((t1SizeBytes >> 3) != l1Size)
|
||||
return S_FALSE;
|
||||
table.Alloc(t1SizeBytes);
|
||||
@@ -442,41 +468,72 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||
}
|
||||
}
|
||||
|
||||
if (openCallback)
|
||||
{
|
||||
UInt64 totalBytes = (UInt64)l1Size << (_numMidBits + 3);
|
||||
RINOK(openCallback->SetTotal(NULL, &totalBytes));
|
||||
}
|
||||
|
||||
_compressedFlag = (_version <= 1) ? ((UInt64)1 << 63) : ((UInt64)1 << 62);
|
||||
const UInt64 offsetMask = _compressedFlag - 1;
|
||||
|
||||
for (UInt32 i = 0; i < l1Size; i++)
|
||||
UInt32 numTables = 0;
|
||||
UInt32 i;
|
||||
|
||||
for (i = 0; i < l1Size; i++)
|
||||
{
|
||||
if (openCallback)
|
||||
{
|
||||
UInt64 numBytes = (UInt64)i << (_numMidBits + 3);
|
||||
RINOK(openCallback->SetCompleted(NULL, &numBytes));
|
||||
}
|
||||
const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask;
|
||||
if (v != 0)
|
||||
numTables++;
|
||||
}
|
||||
|
||||
CByteBuffer &buf2 = _tables.AddNew();
|
||||
|
||||
if (numTables != 0)
|
||||
{
|
||||
const size_t size = (size_t)numTables << (_numMidBits + 3);
|
||||
if (size >> (_numMidBits + 3) != numTables)
|
||||
return E_OUTOFMEMORY;
|
||||
_table.Alloc(size);
|
||||
if (!_table.IsAllocated())
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
_dir.SetSize(l1Size);
|
||||
|
||||
UInt32 curTable = 0;
|
||||
|
||||
if (openCallback)
|
||||
{
|
||||
const UInt64 totalBytes = (UInt64)numTables << (_numMidBits + 3);
|
||||
RINOK(openCallback->SetTotal(NULL, &totalBytes));
|
||||
}
|
||||
|
||||
for (i = 0; i < l1Size; i++)
|
||||
{
|
||||
Byte *buf2;
|
||||
const size_t midSize = (size_t)1 << (_numMidBits + 3);
|
||||
|
||||
{
|
||||
UInt64 v = Get64((const Byte *)table + (size_t)i * 8);
|
||||
v &= offsetMask;
|
||||
const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask;
|
||||
if (v == 0)
|
||||
{
|
||||
_dir[i] = kEmptyDirItem;
|
||||
continue;
|
||||
|
||||
buf2.Alloc((size_t)1 << (_numMidBits + 3));
|
||||
RINOK(stream->Seek(v, STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadStream_FALSE(stream, buf2, clusterSize));
|
||||
}
|
||||
|
||||
const UInt64 end = v + clusterSize;
|
||||
_dir[i] = curTable;
|
||||
const size_t tableOffset = ((size_t)curTable << (_numMidBits + 3));
|
||||
buf2 = (Byte *)_table + tableOffset;
|
||||
curTable++;
|
||||
|
||||
if (openCallback && (tableOffset & 0xFFFFF) == 0)
|
||||
{
|
||||
const UInt64 numBytes = tableOffset;
|
||||
RINOK(openCallback->SetCompleted(NULL, &numBytes));
|
||||
}
|
||||
|
||||
RINOK(stream->Seek(v, STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadStream_FALSE(stream, buf2, midSize));
|
||||
|
||||
const UInt64 end = v + midSize;
|
||||
if (_phySize < end)
|
||||
_phySize = end;
|
||||
}
|
||||
|
||||
for (size_t k = 0; k < clusterSize; k += 8)
|
||||
for (size_t k = 0; k < midSize; k += 8)
|
||||
{
|
||||
const UInt64 v = Get64((const Byte *)buf2 + (size_t)k);
|
||||
if (v == 0)
|
||||
@@ -519,12 +576,15 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||
}
|
||||
}
|
||||
|
||||
UInt64 end = offset + dataSize;
|
||||
const UInt64 end = offset + dataSize;
|
||||
if (_phySize < end)
|
||||
_phySize = end;
|
||||
}
|
||||
}
|
||||
|
||||
if (curTable != numTables)
|
||||
return E_FAIL;
|
||||
|
||||
if (_cryptMethod != 0)
|
||||
_unsupported = true;
|
||||
|
||||
@@ -538,7 +598,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_tables.Clear();
|
||||
_table.Free();
|
||||
_dir.Free();
|
||||
_phySize = 0;
|
||||
_size = 0;
|
||||
|
||||
@@ -588,7 +649,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
|
||||
_deflateDecoderSpec->Set_NeedFinishInput(true);
|
||||
}
|
||||
|
||||
size_t clusterSize = (size_t)1 << _clusterBits;
|
||||
const size_t clusterSize = (size_t)1 << _clusterBits;
|
||||
_cache.AllocAtLeast(clusterSize);
|
||||
_cacheCompressed.AllocAtLeast(clusterSize * 2);
|
||||
}
|
||||
|
||||
@@ -124,19 +124,13 @@ static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val)
|
||||
bool CLinkInfo::Parse(const Byte *p, unsigned size)
|
||||
{
|
||||
const Byte *pStart = p;
|
||||
unsigned num = ReadVarInt(p, size, &Type);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
|
||||
num = ReadVarInt(p, size, &Flags);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
|
||||
unsigned num;
|
||||
UInt64 len;
|
||||
num = ReadVarInt(p, size, &len);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
|
||||
num = ReadVarInt(p, size, &Type); if (num == 0) { return false; } p += num; size -= num;
|
||||
num = ReadVarInt(p, size, &Flags); if (num == 0) { return false; } p += num; size -= num;
|
||||
num = ReadVarInt(p, size, &len); if (num == 0) { return false; } p += num; size -= num;
|
||||
if (size != len)
|
||||
return false;
|
||||
|
||||
NameLen = (unsigned)len;
|
||||
NameOffset = (unsigned)(p - pStart);
|
||||
return true;
|
||||
@@ -319,10 +313,10 @@ bool CCryptoInfo::Parse(const Byte *p, size_t size)
|
||||
Cnt = 0;
|
||||
|
||||
unsigned num = ReadVarInt(p, size, &Algo);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
if (num == 0) { return false; } p += num; size -= num;
|
||||
|
||||
num = ReadVarInt(p, size, &Flags);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
if (num == 0) { return false; } p += num; size -= num;
|
||||
|
||||
if (size > 0)
|
||||
Cnt = p[0];
|
||||
@@ -344,10 +338,10 @@ bool CItem::FindExtra_Version(UInt64 &version) const
|
||||
|
||||
UInt64 flags;
|
||||
unsigned num = ReadVarInt(p, size, &flags);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
if (num == 0) { return false; } p += num; size -= num;
|
||||
|
||||
num = ReadVarInt(p, size, &version);
|
||||
if (num == 0) return false; p += num; size -= num;
|
||||
if (num == 0) { return false; } p += num; size -= num;
|
||||
|
||||
return size == 0;
|
||||
}
|
||||
@@ -406,8 +400,8 @@ void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop)
|
||||
s.SetFrom_CalcLen((const char *)(Extra + link.NameOffset), link.NameLen);
|
||||
|
||||
UString unicode;
|
||||
if (ConvertUTF8ToUnicode(s, unicode))
|
||||
prop = NItemName::GetOsPath(unicode);
|
||||
ConvertUTF8ToUnicode(s, unicode);
|
||||
prop = NItemName::GetOsPath(unicode);
|
||||
}
|
||||
|
||||
bool CItem::GetAltStreamName(AString &name) const
|
||||
@@ -596,11 +590,12 @@ public:
|
||||
|
||||
static HRESULT MySetPassword(ICryptoGetTextPassword *getTextPassword, NCrypto::NRar5::CDecoder *cryptoDecoderSpec)
|
||||
{
|
||||
CMyComBSTR password;
|
||||
CMyComBSTR_Wipe password;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&password));
|
||||
AString utf8;
|
||||
AString_Wipe utf8;
|
||||
const unsigned kPasswordLen_MAX = 127;
|
||||
UString unicode = (LPCOLESTR)password;
|
||||
UString_Wipe unicode;
|
||||
unicode.SetFromBstr(password);
|
||||
if (unicode.Len() > kPasswordLen_MAX)
|
||||
unicode.DeleteFrom(kPasswordLen_MAX);
|
||||
ConvertUnicodeToUTF8(unicode, utf8);
|
||||
@@ -1153,7 +1148,7 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz
|
||||
}
|
||||
else
|
||||
{
|
||||
res = res;
|
||||
// res = res;
|
||||
}
|
||||
|
||||
if (isCryptoMode)
|
||||
@@ -1434,8 +1429,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
AString s;
|
||||
s.SetFrom_CalcLen((const char *)(const Byte *)cmt, (unsigned)cmt.Size());
|
||||
UString unicode;
|
||||
if (ConvertUTF8ToUnicode(s, unicode))
|
||||
prop = unicode;
|
||||
ConvertUTF8ToUnicode(s, unicode);
|
||||
prop = unicode;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1686,13 +1681,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
if (name[0] != ':')
|
||||
s += ':';
|
||||
s += name;
|
||||
if (!ConvertUTF8ToUnicode(s, unicodeName))
|
||||
break;
|
||||
ConvertUTF8ToUnicode(s, unicodeName);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ConvertUTF8ToUnicode(item.Name, unicodeName))
|
||||
break;
|
||||
ConvertUTF8ToUnicode(item.Name, unicodeName);
|
||||
|
||||
if (item.Version_Defined)
|
||||
{
|
||||
char temp[32];
|
||||
@@ -1752,8 +1746,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
{
|
||||
name.DeleteFrontal(1);
|
||||
UString unicodeName;
|
||||
if (ConvertUTF8ToUnicode(name, unicodeName))
|
||||
prop = unicodeName;
|
||||
ConvertUTF8ToUnicode(name, unicodeName);
|
||||
prop = unicodeName;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -466,7 +466,7 @@ bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
|
||||
for (unsigned i = 0; i < sizeof(item.Salt); i++)
|
||||
item.Salt[i] = p[i];
|
||||
p += sizeof(item.Salt);
|
||||
size -= sizeof(item.Salt);
|
||||
size -= (unsigned)sizeof(item.Salt);
|
||||
}
|
||||
|
||||
// some rar archives have HasExtTime flag without field.
|
||||
@@ -526,31 +526,36 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
|
||||
}
|
||||
// m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld());
|
||||
|
||||
// Salt
|
||||
const UInt32 kSaltSize = 8;
|
||||
Byte salt[kSaltSize];
|
||||
if (!ReadBytesAndTestSize(salt, kSaltSize))
|
||||
return S_FALSE;
|
||||
m_Position += kSaltSize;
|
||||
RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize))
|
||||
// Password
|
||||
CMyComBSTR password;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&password))
|
||||
unsigned len = 0;
|
||||
if (password)
|
||||
len = MyStringLen(password);
|
||||
if (len > kPasswordLen_MAX)
|
||||
len = kPasswordLen_MAX;
|
||||
|
||||
CByteArr buffer(len * 2);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = password[i];
|
||||
((Byte *)buffer)[i * 2] = (Byte)c;
|
||||
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
|
||||
// Salt
|
||||
const UInt32 kSaltSize = 8;
|
||||
Byte salt[kSaltSize];
|
||||
if (!ReadBytesAndTestSize(salt, kSaltSize))
|
||||
return S_FALSE;
|
||||
m_Position += kSaltSize;
|
||||
RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize))
|
||||
}
|
||||
|
||||
m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2);
|
||||
{
|
||||
// Password
|
||||
CMyComBSTR_Wipe password;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&password))
|
||||
unsigned len = 0;
|
||||
if (password)
|
||||
len = MyStringLen(password);
|
||||
if (len > kPasswordLen_MAX)
|
||||
len = kPasswordLen_MAX;
|
||||
|
||||
CByteBuffer_Wipe buffer(len * 2);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = password[i];
|
||||
((Byte *)buffer)[i * 2] = (Byte)c;
|
||||
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
|
||||
}
|
||||
|
||||
m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2);
|
||||
}
|
||||
|
||||
const UInt32 kDecryptedBufferSize = (1 << 12);
|
||||
if (m_DecryptedDataAligned.Size() == 0)
|
||||
@@ -1621,7 +1626,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
// if (getTextPassword)
|
||||
{
|
||||
CMyComBSTR password;
|
||||
CMyComBSTR_Wipe password;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&password));
|
||||
|
||||
if (item.UnPackVersion >= 29)
|
||||
@@ -1631,7 +1636,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
len = MyStringLen(password);
|
||||
if (len > kPasswordLen_MAX)
|
||||
len = kPasswordLen_MAX;
|
||||
CByteArr buffer(len * 2);
|
||||
CByteBuffer_Wipe buffer(len * 2);
|
||||
for (unsigned k = 0; k < len; k++)
|
||||
{
|
||||
wchar_t c = password[k];
|
||||
@@ -1642,13 +1647,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
}
|
||||
else
|
||||
{
|
||||
AString oemPassword;
|
||||
AString_Wipe oemPassword;
|
||||
if (password)
|
||||
{
|
||||
UString unicode = (LPCOLESTR)password;
|
||||
UString_Wipe unicode;
|
||||
unicode.SetFromBstr(password);
|
||||
if (unicode.Len() > kPasswordLen_MAX)
|
||||
unicode.DeleteFrom(kPasswordLen_MAX);
|
||||
oemPassword = UnicodeStringToMultiByte(unicode, CP_OEMCP);
|
||||
UnicodeStringToMultiByte2(oemPassword, unicode, CP_OEMCP);
|
||||
}
|
||||
rar20CryptoDecoderSpec->SetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len());
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ struct CInArcInfo
|
||||
UInt32 DataCRC;
|
||||
bool EndOfArchive_was_Read;
|
||||
|
||||
CInArcInfo(): EndFlags(0), EndOfArchive_was_Read(false), VolNumber(0) {}
|
||||
CInArcInfo(): EndFlags(0), VolNumber(0), EndOfArchive_was_Read(false) {}
|
||||
|
||||
UInt64 GetPhySize() const { return EndPos - StartPos; }
|
||||
|
||||
|
||||
@@ -142,8 +142,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
}
|
||||
|
||||
int dotPos = name.ReverseFind_Dot();
|
||||
const UString prefix = name.Left(dotPos + 1);
|
||||
const UString ext = name.Ptr(dotPos + 1);
|
||||
const UString prefix = name.Left((unsigned)(dotPos + 1));
|
||||
const UString ext = name.Ptr((unsigned)(dotPos + 1));
|
||||
UString ext2 = ext;
|
||||
ext2.MakeLower_Ascii();
|
||||
|
||||
|
||||
@@ -43,9 +43,9 @@ static const unsigned kNumDirLevelsMax = (1 << 10);
|
||||
#define Get64(p) (be ? GetBe64(p) : GetUi64(p))
|
||||
*/
|
||||
|
||||
UInt16 Get16b(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); }
|
||||
UInt32 Get32b(const Byte *p, bool be) { return be ? GetBe32(p) : GetUi32(p); }
|
||||
UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); }
|
||||
static UInt16 Get16b(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); }
|
||||
static UInt32 Get32b(const Byte *p, bool be) { return be ? GetBe32(p) : GetUi32(p); }
|
||||
static UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); }
|
||||
|
||||
#define Get16(p) Get16b(p, be)
|
||||
#define Get32(p) Get32b(p, be)
|
||||
@@ -127,6 +127,10 @@ static const char * const k_Flags[] =
|
||||
, "ALWAYS_FRAGMENTS"
|
||||
, "DUPLICATES_REMOVED"
|
||||
, "EXPORTABLE"
|
||||
, "UNCOMPRESSED_XATTRS"
|
||||
, "NO_XATTRS"
|
||||
, "COMPRESSOR_OPTIONS"
|
||||
, "UNCOMPRESSED_IDS"
|
||||
};
|
||||
|
||||
static const UInt32 kNotCompressedBit16 = (1 << 15);
|
||||
@@ -135,10 +139,10 @@ static const UInt32 kNotCompressedBit32 = (1 << 24);
|
||||
#define GET_COMPRESSED_BLOCK_SIZE(size) ((size) & ~kNotCompressedBit32)
|
||||
#define IS_COMPRESSED_BLOCK(size) (((size) & kNotCompressedBit32) == 0)
|
||||
|
||||
static const UInt32 kHeaderSize1 = 0x33;
|
||||
static const UInt32 kHeaderSize2 = 0x3F;
|
||||
// static const UInt32 kHeaderSize1 = 0x33;
|
||||
// static const UInt32 kHeaderSize2 = 0x3F;
|
||||
static const UInt32 kHeaderSize3 = 0x77;
|
||||
static const UInt32 kHeaderSize4 = 0x60;
|
||||
// static const UInt32 kHeaderSize4 = 0x60;
|
||||
|
||||
struct CHeader
|
||||
{
|
||||
@@ -1282,7 +1286,8 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
|
||||
&status, &g_Alloc);
|
||||
if (res != 0)
|
||||
return SResToHRESULT(res);
|
||||
if (status != LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
if (status != LZMA_STATUS_FINISHED_WITH_MARK
|
||||
&& status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
return S_FALSE;
|
||||
}
|
||||
else
|
||||
@@ -1349,7 +1354,7 @@ HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end)
|
||||
{
|
||||
if (end < start || end - start >= ((UInt64)1 << 32))
|
||||
return S_FALSE;
|
||||
UInt32 size = (UInt32)(end - start);
|
||||
const UInt32 size = (UInt32)(end - start);
|
||||
RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL));
|
||||
_dynOutStreamSpec->Init();
|
||||
UInt32 packPos = 0;
|
||||
@@ -1361,8 +1366,11 @@ HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end)
|
||||
return S_FALSE;
|
||||
UInt32 packSize = size - packPos;
|
||||
RINOK(ReadMetadataBlock(packSize));
|
||||
if (_dynOutStreamSpec->GetSize() >= ((UInt64)1 << 32))
|
||||
return S_FALSE;
|
||||
{
|
||||
const size_t tSize = _dynOutStreamSpec->GetSize();
|
||||
if (tSize != (UInt32)tSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
packPos += packSize;
|
||||
}
|
||||
data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize());
|
||||
@@ -1526,7 +1534,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned
|
||||
if (_openCodePage == CP_UTF8)
|
||||
{
|
||||
tempString.SetFrom_CalcLen((const char *)p, size);
|
||||
if (!CheckUTF8(tempString))
|
||||
if (!CheckUTF8_AString(tempString))
|
||||
_openCodePage = CP_OEMCP;
|
||||
}
|
||||
|
||||
@@ -1649,11 +1657,14 @@ HRESULT CHandler::Open2(IInStream *inStream)
|
||||
{
|
||||
UInt32 pos = 0;
|
||||
UInt32 totalSize = (UInt32)_inodesData.Data.Size();
|
||||
const unsigned kMinNodeParseSize = 4;
|
||||
if (_h.NumInodes > totalSize / kMinNodeParseSize)
|
||||
return S_FALSE;
|
||||
_nodesPos.ClearAndReserve(_h.NumInodes);
|
||||
_nodes.ClearAndReserve(_h.NumInodes);
|
||||
// we use _blockToNode for binary search seed optimizations
|
||||
_blockToNode.ClearAndReserve(_inodesData.GetNumBlocks() + 1);
|
||||
int curBlock = 0;
|
||||
unsigned curBlock = 0;
|
||||
for (UInt32 i = 0; i < _h.NumInodes; i++)
|
||||
{
|
||||
CNode n;
|
||||
@@ -2131,9 +2142,9 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
|
||||
bool compressed;
|
||||
if (blockIndex < _blockCompressed.Size())
|
||||
{
|
||||
compressed = _blockCompressed[(int)blockIndex];
|
||||
blockOffset = _blockOffsets[(int)blockIndex];
|
||||
packBlockSize = (UInt32)(_blockOffsets[(int)blockIndex + 1] - blockOffset);
|
||||
compressed = _blockCompressed[(unsigned)blockIndex];
|
||||
blockOffset = _blockOffsets[(unsigned)blockIndex];
|
||||
packBlockSize = (UInt32)(_blockOffsets[(unsigned)blockIndex + 1] - blockOffset);
|
||||
blockOffset += node.StartBlock;
|
||||
}
|
||||
else
|
||||
@@ -2167,14 +2178,16 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
|
||||
bool outBufWasWritten;
|
||||
UInt32 outBufWasWrittenSize;
|
||||
HRESULT res = Decompress(_outStream, _cachedBlock, &outBufWasWritten, &outBufWasWrittenSize, packBlockSize, _h.BlockSize);
|
||||
RINOK(res);
|
||||
if (outBufWasWritten)
|
||||
_cachedUnpackBlockSize = outBufWasWrittenSize;
|
||||
else
|
||||
_cachedUnpackBlockSize = (UInt32)_outStreamSpec->GetPos();
|
||||
RINOK(res);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (packBlockSize > _h.BlockSize)
|
||||
return S_FALSE;
|
||||
RINOK(ReadStream_FALSE(_limitedInStream, _cachedBlock, packBlockSize));
|
||||
_cachedUnpackBlockSize = packBlockSize;
|
||||
}
|
||||
|
||||
@@ -776,21 +776,21 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
|
||||
|
||||
static UInt16 Read16(CInBuffer &stream)
|
||||
{
|
||||
UInt16 res = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
UInt32 res = 0;
|
||||
for (unsigned i = 0; i < 2; i++)
|
||||
{
|
||||
Byte b;
|
||||
if (!stream.ReadByte(b))
|
||||
throw 1;
|
||||
res |= (UInt16)b << (i * 8);
|
||||
res |= (UInt32)b << (i * 8);
|
||||
}
|
||||
return res;
|
||||
return (UInt16)res;
|
||||
}
|
||||
|
||||
static UInt32 Read32(CInBuffer &stream)
|
||||
{
|
||||
UInt32 res = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
Byte b;
|
||||
if (!stream.ReadByte(b))
|
||||
@@ -826,7 +826,7 @@ UInt32 CBitReader::ReadBits(unsigned numBits)
|
||||
res <<= numBits;
|
||||
NumBits -= numBits;
|
||||
res |= (Val >> NumBits);
|
||||
Val &= (1 << NumBits) - 1;
|
||||
Val = (Byte)(Val & (((unsigned)1 << NumBits) - 1));
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -24,7 +24,9 @@ using namespace NWindows;
|
||||
namespace NArchive {
|
||||
namespace NTar {
|
||||
|
||||
static const UINT k_DefaultCodePage = CP_OEMCP; // it uses it if UTF8 check in names shows error
|
||||
// 21.02: we use UTF8 code page by default, even if some files show error
|
||||
// before 21.02 : CP_OEMCP;
|
||||
// static const UINT k_DefaultCodePage = CP_UTF8;
|
||||
|
||||
|
||||
static const Byte kProps[] =
|
||||
@@ -39,13 +41,15 @@ static const Byte kProps[] =
|
||||
kpidGroup,
|
||||
kpidSymLink,
|
||||
kpidHardLink,
|
||||
kpidCharacts
|
||||
// kpidLinkType
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidHeadersSize,
|
||||
kpidCodePage
|
||||
kpidCodePage,
|
||||
kpidCharacts
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
@@ -67,8 +71,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
case k_ErrorType_UnexpectedEnd: flags = kpv_ErrorFlags_UnexpectedEnd; break;
|
||||
case k_ErrorType_Corrupted: flags = kpv_ErrorFlags_HeadersError; break;
|
||||
// case k_ErrorType_OK: break;
|
||||
// case k_ErrorType_Warning: break;
|
||||
default: break;
|
||||
}
|
||||
prop = flags;
|
||||
if (flags != 0)
|
||||
prop = flags;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -96,6 +104,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
prop = name;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidCharacts:
|
||||
{
|
||||
AString s = _encodingCharacts.GetCharactsString();
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -119,12 +134,64 @@ HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &
|
||||
*/
|
||||
if (item.IsPaxExtendedHeader())
|
||||
_thereIsPaxExtendedHeader = true;
|
||||
if (item.IsThereWarning())
|
||||
_warning = true;
|
||||
}
|
||||
_phySize += item.HeaderSize;
|
||||
_headersSize += item.HeaderSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void CEncodingCharacts::Check(const AString &s)
|
||||
{
|
||||
IsAscii = s.IsAscii();
|
||||
if (!IsAscii)
|
||||
{
|
||||
/*
|
||||
{
|
||||
Oem_Checked = true;
|
||||
UString u;
|
||||
MultiByteToUnicodeString2(u, s, CP_OEMCP);
|
||||
Oem_Ok = (u.Find((wchar_t)0xfffd) <= 0);
|
||||
}
|
||||
Utf_Checked = true;
|
||||
*/
|
||||
UtfCheck.Check_AString(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AString CEncodingCharacts::GetCharactsString() const
|
||||
{
|
||||
AString s;
|
||||
if (IsAscii)
|
||||
{
|
||||
s += "ASCII";
|
||||
}
|
||||
/*
|
||||
if (Oem_Checked)
|
||||
{
|
||||
s.Add_Space_if_NotEmpty();
|
||||
s += (Oem_Ok ? "oem-ok" : "oem-error");
|
||||
}
|
||||
if (Utf_Checked)
|
||||
*/
|
||||
else
|
||||
{
|
||||
s.Add_Space_if_NotEmpty();
|
||||
s += (UtfCheck.IsOK() ? "UTF8" : "UTF8-ERROR"); // "UTF8-error"
|
||||
{
|
||||
AString s2;
|
||||
UtfCheck.PrintStatus(s2);
|
||||
s.Add_Space_if_NotEmpty();
|
||||
s += s2;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
{
|
||||
UInt64 endPos = 0;
|
||||
@@ -135,12 +202,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
|
||||
_phySizeDefined = true;
|
||||
|
||||
bool utf8_OK = true;
|
||||
if (!_forceCodePage)
|
||||
{
|
||||
if (!utf8_OK)
|
||||
_curCodePage = k_DefaultCodePage;
|
||||
}
|
||||
// bool utf8_OK = true;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -151,8 +213,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
break;
|
||||
|
||||
_isArc = true;
|
||||
_items.Add(item);
|
||||
|
||||
/*
|
||||
if (!_forceCodePage)
|
||||
{
|
||||
if (utf8_OK) utf8_OK = CheckUTF8(item.Name, item.NameCouldBeReduced);
|
||||
@@ -160,8 +222,14 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
if (utf8_OK) utf8_OK = CheckUTF8(item.User);
|
||||
if (utf8_OK) utf8_OK = CheckUTF8(item.Group);
|
||||
}
|
||||
|
||||
RINOK(stream->Seek(item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize));
|
||||
*/
|
||||
|
||||
item.EncodingCharacts.Check(item.Name);
|
||||
_encodingCharacts.Update(item.EncodingCharacts);
|
||||
|
||||
_items.Add(item);
|
||||
|
||||
RINOK(stream->Seek((Int64)item.GetPackSizeAligned(), STREAM_SEEK_CUR, &_phySize));
|
||||
if (_phySize > endPos)
|
||||
{
|
||||
_error = k_ErrorType_UnexpectedEnd;
|
||||
@@ -188,11 +256,13 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (!_forceCodePage)
|
||||
{
|
||||
if (!utf8_OK)
|
||||
_curCodePage = k_DefaultCodePage;
|
||||
}
|
||||
*/
|
||||
_openCodePage = _curCodePage;
|
||||
|
||||
if (_items.Size() == 0)
|
||||
@@ -255,6 +325,7 @@ STDMETHODIMP CHandler::Close()
|
||||
_latestIsRead = false;
|
||||
// _isSparse = false;
|
||||
_thereIsPaxExtendedHeader = false;
|
||||
_encodingCharacts.Clear();
|
||||
_items.Clear();
|
||||
_seqStream.Release();
|
||||
_stream.Release();
|
||||
@@ -315,7 +386,8 @@ void CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant
|
||||
else
|
||||
MultiByteToUnicodeString2(dest, s, _curCodePage);
|
||||
if (toOs)
|
||||
NItemName::ReplaceToOsSlashes_Remove_TailSlash(dest);
|
||||
NItemName::ReplaceToOsSlashes_Remove_TailSlash(dest,
|
||||
true); // useBackslashReplacement
|
||||
prop = dest;
|
||||
}
|
||||
|
||||
@@ -358,6 +430,17 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidSymLink: if (item->LinkFlag == NFileHeader::NLinkFlag::kSymLink && !item->LinkName.IsEmpty()) TarStringToUnicode(item->LinkName, prop); break;
|
||||
case kpidHardLink: if (item->LinkFlag == NFileHeader::NLinkFlag::kHardLink && !item->LinkName.IsEmpty()) TarStringToUnicode(item->LinkName, prop); break;
|
||||
// case kpidLinkType: prop = (int)item->LinkFlag; break;
|
||||
case kpidCharacts:
|
||||
{
|
||||
AString s = item->EncodingCharacts.GetCharactsString();
|
||||
if (item->IsThereWarning())
|
||||
{
|
||||
s.Add_Space_if_NotEmpty();
|
||||
s += "HEADER_ERROR";
|
||||
}
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -407,7 +490,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
Int32 index = allFilesMode ? i : indices[i];
|
||||
const UInt32 index = allFilesMode ? i : indices[i];
|
||||
const CItemEx *item;
|
||||
if (seqMode)
|
||||
{
|
||||
@@ -475,7 +558,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
{
|
||||
if (!seqMode)
|
||||
{
|
||||
RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
RINOK(_stream->Seek((Int64)item->GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
streamSpec->Init(item->GetPackSizeAligned());
|
||||
RINOK(copyCoder->Code(inStream2, outStream, NULL, NULL, progress));
|
||||
@@ -566,7 +649,7 @@ STDMETHODIMP CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
UInt64 phyPos = PhyOffsets[left] + relat;
|
||||
if (_needStartSeek || _phyPos != phyPos)
|
||||
{
|
||||
RINOK(Handler->_stream->Seek(item.GetDataPosition() + phyPos, STREAM_SEEK_SET, NULL));
|
||||
RINOK(Handler->_stream->Seek((Int64)(item.GetDataPosition() + phyPos), STREAM_SEEK_SET, NULL));
|
||||
_needStartSeek = false;
|
||||
_phyPos = phyPos;
|
||||
}
|
||||
@@ -604,7 +687,7 @@ STDMETHODIMP CSparseStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
_virtPos = (UInt64)offset;
|
||||
if (newPosition)
|
||||
*newPosition = _virtPos;
|
||||
return S_OK;
|
||||
@@ -650,7 +733,6 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
void CHandler::Init()
|
||||
{
|
||||
_forceCodePage = false;
|
||||
// _codePage = CP_OEMCP;
|
||||
_curCodePage = _specifiedCodePage = CP_UTF8; // CP_OEMCP;
|
||||
_thereIsPaxExtendedHeader = false;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,8 @@ private:
|
||||
UInt32 _curCodePage;
|
||||
UInt32 _openCodePage;
|
||||
|
||||
CEncodingCharacts _encodingCharacts;
|
||||
|
||||
NCompress::CCopyCoder *copyCoderSpec;
|
||||
CMyComPtr<ICompressCoder> copyCoder;
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId,
|
||||
AString &res, UINT codePage, bool convertSlash = false)
|
||||
HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res,
|
||||
UINT codePage, unsigned utfFlags, bool convertSlash)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(callback->GetProperty(index, propId, &prop));
|
||||
@@ -39,7 +39,7 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
|
||||
|
||||
if (codePage == CP_UTF8)
|
||||
{
|
||||
ConvertUnicodeToUTF8(s, res);
|
||||
ConvertUnicodeToUTF8_Flags(s, res, utfFlags);
|
||||
// if (!ConvertUnicodeToUTF8(s, res)) // return E_INVALIDARG;
|
||||
}
|
||||
else
|
||||
@@ -56,8 +56,8 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
|
||||
|
||||
static int CompareUpdateItems(void *const *p1, void *const *p2, void *)
|
||||
{
|
||||
const CUpdateItem &u1 = *(*((const CUpdateItem **)p1));
|
||||
const CUpdateItem &u2 = *(*((const CUpdateItem **)p2));
|
||||
const CUpdateItem &u1 = *(*((const CUpdateItem *const *)p1));
|
||||
const CUpdateItem &u2 = *(*((const CUpdateItem *const *)p2));
|
||||
if (!u1.NewProps)
|
||||
{
|
||||
if (u2.NewProps)
|
||||
@@ -78,8 +78,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if ((_stream && (_error != k_ErrorType_OK || _warning /* || _isSparse */)) || _seqStream)
|
||||
return E_NOTIMPL;
|
||||
CObjectVector<CUpdateItem> updateItems;
|
||||
UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage);
|
||||
|
||||
const UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage);
|
||||
const unsigned utfFlags = g_Unicode_To_UTF8_Flags;
|
||||
/*
|
||||
// for debug only:
|
||||
unsigned utfFlags = 0;
|
||||
utfFlags |= UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE;
|
||||
utfFlags |= UTF_FLAG__TO_UTF8__SURROGATE_ERROR;
|
||||
*/
|
||||
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
CUpdateItem ui;
|
||||
@@ -94,7 +101,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
|
||||
ui.NewProps = IntToBool(newProps);
|
||||
ui.NewData = IntToBool(newData);
|
||||
ui.IndexInArc = indexInArc;
|
||||
ui.IndexInArc = (int)indexInArc;
|
||||
ui.IndexInClient = i;
|
||||
|
||||
if (IntToBool(newProps))
|
||||
@@ -138,11 +145,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime);
|
||||
}
|
||||
|
||||
RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, true));
|
||||
RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, utfFlags, true));
|
||||
if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/')
|
||||
ui.Name += '/';
|
||||
RINOK(GetPropString(callback, i, kpidUser, ui.User, codePage));
|
||||
RINOK(GetPropString(callback, i, kpidGroup, ui.Group, codePage));
|
||||
RINOK(GetPropString(callback, i, kpidUser, ui.User, codePage, utfFlags, false));
|
||||
RINOK(GetPropString(callback, i, kpidGroup, ui.Group, codePage, utfFlags, false));
|
||||
}
|
||||
|
||||
if (IntToBool(newData))
|
||||
@@ -168,7 +175,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
updateItems.Sort(CompareUpdateItems, NULL);
|
||||
}
|
||||
|
||||
return UpdateArchive(_stream, outStream, _items, updateItems, codePage, callback);
|
||||
return UpdateArchive(_stream, outStream, _items, updateItems, codePage, utfFlags, callback);
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ namespace NFileHeader
|
||||
const char kGnu_LongLink = 'K';
|
||||
const char kGnu_LongName = 'L';
|
||||
const char kSparse = 'S';
|
||||
const char kLabel = 'V';
|
||||
const char kDumpDir = 'D'; /* GNUTYPE_DUMPDIR.
|
||||
data: list of files created by the --incremental (-G) option
|
||||
Each file name is preceded by either
|
||||
|
||||
@@ -81,14 +81,14 @@ static void ReadString(const char *s, unsigned size, AString &result)
|
||||
static bool ParseInt64(const char *p, Int64 &val)
|
||||
{
|
||||
UInt32 h = GetBe32(p);
|
||||
val = GetBe64(p + 4);
|
||||
val = (Int64)GetBe64(p + 4);
|
||||
if (h == (UInt32)1 << 31)
|
||||
return ((val >> 63) & 1) == 0;
|
||||
if (h == (UInt32)(Int32)-1)
|
||||
return ((val >> 63) & 1) != 0;
|
||||
UInt64 uv;
|
||||
bool res = OctalToNumber(p, 12, uv);
|
||||
val = uv;
|
||||
val = (Int64)uv;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,9 @@ static bool ParseSize(const char *p, UInt64 &val)
|
||||
val = GetBe64(p + 4);
|
||||
return ((val >> 63) & 1) == 0;
|
||||
}
|
||||
return OctalToNumber(p, 12, val);
|
||||
return OctalToNumber(p, 12, val,
|
||||
true // 20.03: allow empty size for 'V' Label entry
|
||||
);
|
||||
}
|
||||
|
||||
#define CHECK(x) { if (!(x)) return k_IsArc_Res_NO; }
|
||||
@@ -201,8 +203,8 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
|
||||
// we allow empty Mode value for LongName prefix items
|
||||
RIF(OctalToNumber32(p, 8, item.Mode, true)); p += 8;
|
||||
|
||||
if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8;
|
||||
if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8;
|
||||
if (!OctalToNumber32(p, 8, item.UID)) { item.UID = 0; } p += 8;
|
||||
if (!OctalToNumber32(p, 8, item.GID)) { item.GID = 0; } p += 8;
|
||||
|
||||
RIF(ParseSize(p, item.PackSize));
|
||||
item.Size = item.PackSize;
|
||||
@@ -245,6 +247,15 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
|
||||
item.PackSize = 0;
|
||||
item.Size = 0;
|
||||
}
|
||||
|
||||
if (item.LinkFlag == NFileHeader::NLinkFlag::kDirectory)
|
||||
{
|
||||
// GNU tar ignores Size field, if LinkFlag is kDirectory
|
||||
// 21.02 : we set PackSize = 0 to be more compatible with GNU tar
|
||||
item.PackSize = 0;
|
||||
// item.Size = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
TAR standard requires sum of unsigned byte values.
|
||||
But some TAR programs use sum of signed byte values.
|
||||
@@ -269,7 +280,7 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
|
||||
|
||||
if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse)
|
||||
{
|
||||
Byte isExtended = buf[482];
|
||||
Byte isExtended = (Byte)buf[482];
|
||||
if (isExtended != 0 && isExtended != 1)
|
||||
return S_OK;
|
||||
RIF(ParseSize(buf + 483, item.Size));
|
||||
@@ -309,7 +320,7 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
|
||||
}
|
||||
|
||||
item.HeaderSize += NFileHeader::kRecordSize;
|
||||
isExtended = buf[21 * 24];
|
||||
isExtended = (Byte)buf[21 * 24];
|
||||
if (isExtended != 0 && isExtended != 1)
|
||||
return S_OK;
|
||||
for (unsigned i = 0; i < 21; i++)
|
||||
@@ -442,9 +453,16 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro
|
||||
case 'x':
|
||||
case 'X':
|
||||
{
|
||||
// pax Extended Header
|
||||
if (item.Name.IsPrefixedBy("PaxHeader/")
|
||||
|| item.Name.Find("PaxHeaders.4467/") >= 0)
|
||||
const char *s = item.Name.Ptr();
|
||||
if (IsString1PrefixedByString2(s, "./"))
|
||||
s += 2;
|
||||
if (IsString1PrefixedByString2(s, "./"))
|
||||
s += 2;
|
||||
if ( IsString1PrefixedByString2(s, "PaxHeader/")
|
||||
|| IsString1PrefixedByString2(s, "PaxHeaders.X/")
|
||||
|| IsString1PrefixedByString2(s, "PaxHeaders.4467/")
|
||||
|| StringsAreEqual_Ascii(s, "@PaxHeader")
|
||||
)
|
||||
{
|
||||
RINOK(ReadDataToString(stream, item, pax, error));
|
||||
if (error != k_ErrorType_OK)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#define __ARCHIVE_TAR_ITEM_H
|
||||
|
||||
#include "../../../Common/MyLinux.h"
|
||||
#include "../../../Common/UTFConvert.h"
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
|
||||
@@ -108,8 +109,52 @@ struct CItem
|
||||
}
|
||||
|
||||
UInt64 GetPackSizeAligned() const { return (PackSize + 0x1FF) & (~((UInt64)0x1FF)); }
|
||||
|
||||
bool IsThereWarning() const
|
||||
{
|
||||
// that Header Warning is possible if (Size != 0) for dir item
|
||||
return (PackSize < Size) && (LinkFlag == NFileHeader::NLinkFlag::kDirectory);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct CEncodingCharacts
|
||||
{
|
||||
bool IsAscii;
|
||||
// bool Oem_Checked;
|
||||
// bool Oem_Ok;
|
||||
// bool Utf_Checked;
|
||||
CUtf8Check UtfCheck;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
IsAscii = true;
|
||||
// Oem_Checked = false;
|
||||
// Oem_Ok = false;
|
||||
// Utf_Checked = false;
|
||||
UtfCheck.Clear();
|
||||
}
|
||||
|
||||
void Update(const CEncodingCharacts &ec)
|
||||
{
|
||||
if (!ec.IsAscii)
|
||||
IsAscii = false;
|
||||
|
||||
// if (ec.Utf_Checked)
|
||||
{
|
||||
UtfCheck.Update(ec.UtfCheck);
|
||||
// Utf_Checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
CEncodingCharacts() { Clear(); }
|
||||
void Check(const AString &s);
|
||||
AString GetCharactsString() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct CItemEx: public CItem
|
||||
{
|
||||
UInt64 HeaderPos;
|
||||
@@ -117,6 +162,8 @@ struct CItemEx: public CItem
|
||||
bool NameCouldBeReduced;
|
||||
bool LinkNameCouldBeReduced;
|
||||
|
||||
CEncodingCharacts EncodingCharacts;
|
||||
|
||||
UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }
|
||||
UInt64 GetFullSize() const { return HeaderSize + PackSize; }
|
||||
};
|
||||
|
||||
@@ -62,7 +62,7 @@ static void WriteOctal_12_Signed(char *s, Int64 val)
|
||||
{
|
||||
if (val >= 0)
|
||||
{
|
||||
WriteOctal_12(s, val);
|
||||
WriteOctal_12(s, (UInt64)val);
|
||||
return;
|
||||
}
|
||||
s[0] = s[1] = s[2] = s[3] = (char)(Byte)0xFF;
|
||||
|
||||
@@ -15,13 +15,10 @@
|
||||
namespace NArchive {
|
||||
namespace NTar {
|
||||
|
||||
HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId,
|
||||
AString &res, UINT codePage, bool convertSlash = false);
|
||||
|
||||
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
const CObjectVector<NArchive::NTar::CItemEx> &inputItems,
|
||||
const CObjectVector<CUpdateItem> &updateItems,
|
||||
UINT codePage,
|
||||
UINT codePage, unsigned utfFlags,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
COutArchive outArchive;
|
||||
@@ -43,7 +40,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
if (ui.NewData)
|
||||
complexity += ui.Size;
|
||||
else
|
||||
complexity += inputItems[ui.IndexInArc].GetFullSize();
|
||||
complexity += inputItems[(unsigned)ui.IndexInArc].GetFullSize();
|
||||
}
|
||||
|
||||
RINOK(updateCallback->SetTotal(complexity));
|
||||
@@ -95,12 +92,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
memcpy(item.Magic, NFileHeader::NMagic::kUsTar_00, 8);
|
||||
}
|
||||
else
|
||||
item = inputItems[ui.IndexInArc];
|
||||
item = inputItems[(unsigned)ui.IndexInArc];
|
||||
|
||||
AString symLink;
|
||||
if (ui.NewData || ui.NewProps)
|
||||
{
|
||||
RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidSymLink, symLink, codePage, true));
|
||||
RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidSymLink, symLink, codePage, utfFlags, true));
|
||||
if (!symLink.IsEmpty())
|
||||
{
|
||||
item.LinkFlag = NFileHeader::NLinkFlag::kSymLink;
|
||||
@@ -159,7 +156,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
|
||||
{
|
||||
AString hardLink;
|
||||
RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, true));
|
||||
RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink, codePage, utfFlags, true));
|
||||
if (!hardLink.IsEmpty())
|
||||
{
|
||||
item.LinkFlag = NFileHeader::NLinkFlag::kHardLink;
|
||||
@@ -189,7 +186,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
outArchive.Pos = fileHeaderStartPos;
|
||||
item.PackSize = copyCoderSpec->TotalSize;
|
||||
RINOK(outArchive.WriteHeader(item));
|
||||
RINOK(outSeekStream->Seek(item.PackSize, STREAM_SEEK_CUR, NULL));
|
||||
RINOK(outSeekStream->Seek((Int64)item.PackSize, STREAM_SEEK_CUR, NULL));
|
||||
outArchive.Pos += item.PackSize;
|
||||
}
|
||||
RINOK(outArchive.FillDataResidual(item.PackSize));
|
||||
@@ -201,7 +198,7 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
}
|
||||
else
|
||||
{
|
||||
const CItemEx &existItem = inputItems[ui.IndexInArc];
|
||||
const CItemEx &existItem = inputItems[(unsigned)ui.IndexInArc];
|
||||
UInt64 size;
|
||||
|
||||
if (ui.NewProps)
|
||||
@@ -231,12 +228,12 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
item.GID = existItem.GID;
|
||||
|
||||
RINOK(outArchive.WriteHeader(item));
|
||||
RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
RINOK(inStream->Seek((Int64)existItem.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
size = existItem.PackSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL));
|
||||
RINOK(inStream->Seek((Int64)existItem.HeaderPos, STREAM_SEEK_SET, NULL));
|
||||
size = existItem.GetFullSize();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace NTar {
|
||||
struct CUpdateItem
|
||||
{
|
||||
int IndexInArc;
|
||||
int IndexInClient;
|
||||
unsigned IndexInClient;
|
||||
UInt64 Size;
|
||||
Int64 MTime;
|
||||
UInt32 Mode;
|
||||
@@ -30,9 +30,12 @@ struct CUpdateItem
|
||||
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
const CObjectVector<CItemEx> &inputItems,
|
||||
const CObjectVector<CUpdateItem> &updateItems,
|
||||
UINT codePage,
|
||||
UINT codePage, unsigned utfFlags,
|
||||
IArchiveUpdateCallback *updateCallback);
|
||||
|
||||
HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res,
|
||||
UINT codePage, unsigned utfFlags, bool convertSlash);
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -39,13 +39,13 @@ static const UInt64 kFileNameLengthTotalMax = (UInt64)1 << 33;
|
||||
static const UInt64 kInlineExtentsSizeMax = (UInt64)1 << 33;
|
||||
|
||||
#define CRC16_INIT_VAL 0
|
||||
#define CRC16_GET_DIGEST(crc) (crc)
|
||||
// #define CRC16_GET_DIGEST(crc) (crc)
|
||||
#define CRC16_UPDATE_BYTE(crc, b) ((UInt16)(g_Crc16Table[(((crc) >> 8) ^ (b)) & 0xFF] ^ ((crc) << 8)))
|
||||
|
||||
#define kCrc16Poly 0x1021
|
||||
static UInt16 g_Crc16Table[256];
|
||||
|
||||
void MY_FAST_CALL Crc16GenerateTable(void)
|
||||
static void MY_FAST_CALL Crc16GenerateTable(void)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < 256; i++)
|
||||
@@ -57,7 +57,7 @@ void MY_FAST_CALL Crc16GenerateTable(void)
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL Crc16_Update(UInt32 v, const void *data, size_t size)
|
||||
static UInt32 MY_FAST_CALL Crc16_Update(UInt32 v, const void *data, size_t size)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 ; size--, p++)
|
||||
@@ -65,7 +65,7 @@ UInt32 MY_FAST_CALL Crc16_Update(UInt32 v, const void *data, size_t size)
|
||||
return v;
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL Crc16Calc(const void *data, size_t size)
|
||||
static UInt32 MY_FAST_CALL Crc16Calc(const void *data, size_t size)
|
||||
{
|
||||
return Crc16_Update(CRC16_INIT_VAL, data, size);
|
||||
}
|
||||
|
||||
@@ -351,7 +351,7 @@ class CInArchive
|
||||
UInt64 _processedProgressBytes;
|
||||
|
||||
UInt64 _fileNameLengthTotal;
|
||||
int _numRefs;
|
||||
unsigned _numRefs;
|
||||
UInt32 _numExtents;
|
||||
UInt64 _inlineExtentsSize;
|
||||
bool CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const;
|
||||
|
||||
@@ -52,7 +52,7 @@ static const Byte k_IntelMeSignature[] =
|
||||
0x5A, 0xA5, 0xF0, 0x0F
|
||||
};
|
||||
|
||||
bool IsIntelMe(const Byte *p)
|
||||
static bool IsIntelMe(const Byte *p)
|
||||
{
|
||||
return memcmp(p, k_IntelMeSignature, sizeof(k_IntelMeSignature)) == 0;
|
||||
}
|
||||
@@ -318,19 +318,19 @@ static const CUInt32PCharPair g_FFS_FILE_ATTRIBUTES[] =
|
||||
|
||||
// SECTION_TYPE
|
||||
|
||||
#define SECTION_ALL 0x00
|
||||
// #define SECTION_ALL 0x00
|
||||
|
||||
#define SECTION_COMPRESSION 0x01
|
||||
#define SECTION_GUID_DEFINED 0x02
|
||||
|
||||
// Leaf section Type values
|
||||
#define SECTION_PE32 0x10
|
||||
#define SECTION_PIC 0x11
|
||||
#define SECTION_TE 0x12
|
||||
// #define SECTION_PE32 0x10
|
||||
// #define SECTION_PIC 0x11
|
||||
// #define SECTION_TE 0x12
|
||||
#define SECTION_DXE_DEPEX 0x13
|
||||
#define SECTION_VERSION 0x14
|
||||
#define SECTION_USER_INTERFACE 0x15
|
||||
#define SECTION_COMPATIBILITY16 0x16
|
||||
// #define SECTION_COMPATIBILITY16 0x16
|
||||
#define SECTION_FIRMWARE_VOLUME_IMAGE 0x17
|
||||
#define SECTION_FREEFORM_SUBTYPE_GUID 0x18
|
||||
#define SECTION_RAW 0x19
|
||||
@@ -471,7 +471,7 @@ public:
|
||||
|
||||
bool Parse(const Byte *p)
|
||||
{
|
||||
int i;
|
||||
unsigned i;
|
||||
for (i = 0; i < kFileHeaderSize; i++)
|
||||
if (p[i] != 0xFF)
|
||||
break;
|
||||
@@ -719,11 +719,11 @@ class CHandler:
|
||||
|
||||
HRESULT ParseIntelMe(int bufIndex, UInt32 posBase,
|
||||
UInt32 exactSize, UInt32 limitSize,
|
||||
int parent, int method, int level);
|
||||
int parent, int method, unsigned level);
|
||||
|
||||
HRESULT ParseVolume(int bufIndex, UInt32 posBase,
|
||||
UInt32 exactSize, UInt32 limitSize,
|
||||
int parent, int method, int level);
|
||||
int parent, int method, unsigned level);
|
||||
|
||||
HRESULT OpenCapsule(IInStream *stream);
|
||||
HRESULT OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback);
|
||||
@@ -857,13 +857,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
}
|
||||
|
||||
#ifdef SHOW_DEBUG_INFO
|
||||
static void PrintLevel(int level)
|
||||
static void PrintLevel(unsigned level)
|
||||
{
|
||||
PRF(printf("\n"));
|
||||
for (int i = 0; i < level; i++)
|
||||
for (unsigned i = 0; i < level; i++)
|
||||
PRF(printf(" "));
|
||||
}
|
||||
static void MyPrint(UInt32 posBase, UInt32 size, int level, const char *name)
|
||||
static void MyPrint(UInt32 posBase, UInt32 size, unsigned level, const char *name)
|
||||
{
|
||||
PrintLevel(level);
|
||||
PRF(printf("%s, pos = %6x, size = %6x", name, posBase, size));
|
||||
@@ -1312,7 +1312,7 @@ bool CVolFfsHeader::Parse(const Byte *p)
|
||||
HRESULT CHandler::ParseVolume(
|
||||
int bufIndex, UInt32 posBase,
|
||||
UInt32 exactSize, UInt32 limitSize,
|
||||
int parent, int method, int level)
|
||||
int parent, int method, unsigned level)
|
||||
{
|
||||
if (level > kLevelMax)
|
||||
return S_FALSE;
|
||||
@@ -1333,7 +1333,7 @@ HRESULT CHandler::ParseVolume(
|
||||
if (!Is_FF_Stream(p + kFfsGuidOffset, 16))
|
||||
item.SetGuid(p + kFfsGuidOffset);
|
||||
// if (item.Name.IsEmpty())
|
||||
item.Name += "[VOL]";
|
||||
item.Name += "[VOL]";
|
||||
AddItem(item);
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1512,7 +1512,7 @@ static const char * const kRegionName[] =
|
||||
HRESULT CHandler::ParseIntelMe(
|
||||
int bufIndex, UInt32 posBase,
|
||||
UInt32 exactSize, UInt32 limitSize,
|
||||
int parent, int method, int level)
|
||||
int parent, int method, unsigned level)
|
||||
{
|
||||
UNUSED_VAR(limitSize)
|
||||
level++;
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
#include "HandlerCont.h"
|
||||
|
||||
#define Get16(p) GetUi16(p)
|
||||
#define Get32(p) GetUi32(p)
|
||||
#define Get64(p) GetUi64(p)
|
||||
|
||||
@@ -87,7 +86,7 @@ class CHandler: public CHandlerImg
|
||||
|
||||
Byte Guids[kNumGuids][16];
|
||||
|
||||
HRESULT Seek(UInt64 offset)
|
||||
HRESULT Seek2(UInt64 offset)
|
||||
{
|
||||
_posInArc = offset;
|
||||
return Stream->Seek(offset, STREAM_SEEK_SET, NULL);
|
||||
@@ -96,7 +95,7 @@ class CHandler: public CHandlerImg
|
||||
HRESULT InitAndSeek()
|
||||
{
|
||||
_virtPos = 0;
|
||||
return Seek(0);
|
||||
return Seek2(0);
|
||||
}
|
||||
|
||||
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback);
|
||||
@@ -143,7 +142,7 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
offset += lowBits;
|
||||
if (offset != _posInArc)
|
||||
{
|
||||
RINOK(Seek(offset));
|
||||
RINOK(Seek2(offset));
|
||||
}
|
||||
HRESULT res = Stream->Read(data, size, &size);
|
||||
_posInArc += size;
|
||||
|
||||
@@ -248,7 +248,7 @@ class CHandler: public CHandlerImg
|
||||
}
|
||||
|
||||
void Reset_PosInArc() { _posInArc = (UInt64)0 - 1; }
|
||||
HRESULT Seek(UInt64 offset);
|
||||
HRESULT Seek2(UInt64 offset);
|
||||
HRESULT InitAndSeek();
|
||||
HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size);
|
||||
|
||||
@@ -316,7 +316,7 @@ public:
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
HRESULT CHandler::Seek(UInt64 offset) { return Stream->Seek(_startOffset + offset, STREAM_SEEK_SET, NULL); }
|
||||
HRESULT CHandler::Seek2(UInt64 offset) { return Stream->Seek(_startOffset + offset, STREAM_SEEK_SET, NULL); }
|
||||
|
||||
HRESULT CHandler::InitAndSeek()
|
||||
{
|
||||
@@ -327,7 +327,7 @@ HRESULT CHandler::InitAndSeek()
|
||||
_virtPos = _posInArc = 0;
|
||||
BitMapTag = kUnusedBlock;
|
||||
BitMap.Alloc(Dyn.NumBitMapSectors() << kSectorSize_Log);
|
||||
return Seek(0);
|
||||
return Seek2(0);
|
||||
}
|
||||
|
||||
HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size)
|
||||
@@ -337,7 +337,7 @@ HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size)
|
||||
if (offset != _posInArc)
|
||||
{
|
||||
_posInArc = offset;
|
||||
RINOK(Seek(offset));
|
||||
RINOK(Seek2(offset));
|
||||
}
|
||||
HRESULT res = ReadStream_FALSE(Stream, data, size);
|
||||
if (res == S_OK)
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace NVmdk {
|
||||
static const Byte k_Signature[] = SIGNATURE;
|
||||
|
||||
static const UInt32 k_Flags_NL = (UInt32)1 << 0;
|
||||
static const UInt32 k_Flags_RGD = (UInt32)1 << 1;
|
||||
// static const UInt32 k_Flags_RGD = (UInt32)1 << 1;
|
||||
static const UInt32 k_Flags_ZeroGrain = (UInt32)1 << 2;
|
||||
static const UInt32 k_Flags_Compressed = (UInt32)1 << 16;
|
||||
static const UInt32 k_Flags_Marker = (UInt32)1 << 17;
|
||||
@@ -855,11 +855,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
}
|
||||
|
||||
case kpidId:
|
||||
{
|
||||
if (desc && !desc->CID.IsEmpty())
|
||||
{
|
||||
prop = desc->CID;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidName:
|
||||
{
|
||||
|
||||
@@ -350,7 +350,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
void GetFileTime(const Byte *p, NCOM::CPropVariant &prop)
|
||||
static void GetFileTime(const Byte *p, NCOM::CPropVariant &prop)
|
||||
{
|
||||
prop.vt = VT_FILETIME;
|
||||
prop.filetime.dwLowDateTime = Get32(p);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
#include "../../../Common/IntToString.h"
|
||||
#include "../../../Common/MyBuffer2.h"
|
||||
#include "../../../Common/StringToInt.h"
|
||||
#include "../../../Common/UTFConvert.h"
|
||||
#include "../../../Common/Wildcard.h"
|
||||
@@ -93,9 +94,15 @@ struct CMetaItem
|
||||
CByteBuffer Reparse;
|
||||
|
||||
unsigned GetNumAltStreams() const { return AltStreams.Size() - NumSkipAltStreams; }
|
||||
CMetaItem(): UpdateIndex(-1), HashIndex(-1), SecurityId(-1),
|
||||
FileID(0), VolID(0),
|
||||
Skip(false), NumSkipAltStreams(0) {}
|
||||
CMetaItem():
|
||||
UpdateIndex(-1)
|
||||
, HashIndex(-1)
|
||||
, FileID(0)
|
||||
, VolID(0)
|
||||
, SecurityId(-1)
|
||||
, Skip(false)
|
||||
, NumSkipAltStreams(0)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -320,20 +327,23 @@ class CInStreamWithSha1:
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _size;
|
||||
NCrypto::NSha1::CContext _sha;
|
||||
// NCrypto::NSha1::CContext _sha;
|
||||
CAlignedBuffer _sha;
|
||||
CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; }
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(IInStream)
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
CInStreamWithSha1(): _sha(sizeof(CSha1)) {}
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
void Init()
|
||||
{
|
||||
_size = 0;
|
||||
_sha.Init();
|
||||
Sha1_Init(Sha());
|
||||
}
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
void Final(Byte *digest) { _sha.Final(digest); }
|
||||
void Final(Byte *digest) { Sha1_Final(Sha(), digest); }
|
||||
};
|
||||
|
||||
STDMETHODIMP CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
@@ -341,7 +351,7 @@ STDMETHODIMP CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedS
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->Read(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
_sha.Update((const Byte *)data, realProcessedSize);
|
||||
Sha1_Update(Sha(), (const Byte *)data, realProcessedSize);
|
||||
if (processedSize)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
@@ -427,9 +437,9 @@ static size_t WriteItem(const CStreamInfo *streams, const CMetaItem &item, Byte
|
||||
Set16(p + 0x64, (UInt16)fileNameLen);
|
||||
unsigned i;
|
||||
for (i = 0; i * 2 < fileNameLen; i++)
|
||||
Set16(p + kDirRecordSize + i * 2, item.Name[i]);
|
||||
Set16(p + kDirRecordSize + i * 2, (UInt16)item.Name[i]);
|
||||
for (i = 0; i * 2 < shortNameLen; i++)
|
||||
Set16(p + kDirRecordSize + fileNameLen2 + i * 2, item.ShortName[i]);
|
||||
Set16(p + kDirRecordSize + fileNameLen2 + i * 2, (UInt16)item.ShortName[i]);
|
||||
|
||||
if (item.GetNumAltStreams() == 0)
|
||||
{
|
||||
@@ -468,7 +478,7 @@ static size_t WriteItem(const CStreamInfo *streams, const CMetaItem &item, Byte
|
||||
memcpy(p + 0x10, streams[ss.HashIndex].Hash, kHashSize);
|
||||
Set16(p + 0x24, (UInt16)fileNameLen);
|
||||
for (i = 0; i * 2 < fileNameLen; i++)
|
||||
Set16(p + 0x26 + i * 2, ss.Name[i]);
|
||||
Set16(p + 0x26 + i * 2, (UInt16)ss.Name[i]);
|
||||
totalLen += curLen;
|
||||
p += curLen;
|
||||
}
|
||||
@@ -690,7 +700,7 @@ static void AddTrees(CObjectVector<CDir> &trees, CObjectVector<CMetaItem> &metaI
|
||||
}
|
||||
|
||||
|
||||
#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
|
||||
#define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
|
||||
|
||||
|
||||
|
||||
@@ -1024,7 +1034,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
|
||||
|
||||
imageIndex = (int)val - 1;
|
||||
if (imageIndex < (int)isChangedImage.Size())
|
||||
if (!isChangedImage[imageIndex])
|
||||
if (!isChangedImage[imageIndex])
|
||||
return E_FAIL;
|
||||
|
||||
AddTrees(trees, db.MetaItems, ri, imageIndex);
|
||||
@@ -1079,7 +1089,27 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
|
||||
fileName.Empty();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
#if WCHAR_MAX > 0xffff
|
||||
if (c >= 0x10000)
|
||||
{
|
||||
c -= 0x10000;
|
||||
|
||||
if (c < (1 << 20))
|
||||
{
|
||||
wchar_t c0 = 0xd800 + ((c >> 10) & 0x3FF);
|
||||
fileName += c0;
|
||||
c = 0xdc00 + (c & 0x3FF);
|
||||
}
|
||||
else
|
||||
c = '_'; // we change character unsupported by UTF16
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
fileName += c;
|
||||
}
|
||||
}
|
||||
|
||||
if (isAltStream)
|
||||
@@ -1838,7 +1868,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
|
||||
if (_xmls.Size() == 1)
|
||||
{
|
||||
const CWimXml &_oldXml = _xmls[0];
|
||||
if ((int)i < _oldXml.Images.Size())
|
||||
if (i < _oldXml.Images.Size())
|
||||
{
|
||||
// int ttt = _oldXml.Images[i].ItemIndexInXml;
|
||||
item = _oldXml.Xml.Root.SubItems[_oldXml.Images[i].ItemIndexInXml];
|
||||
@@ -1880,7 +1910,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
|
||||
CByteArr xmlBuf(xmlSize);
|
||||
Set16((Byte *)xmlBuf, 0xFEFF);
|
||||
for (i = 0; i < (unsigned)utf16.Len(); i++)
|
||||
Set16((Byte *)xmlBuf + 2 + i * 2, utf16[i]);
|
||||
Set16((Byte *)xmlBuf + 2 + i * 2, (UInt16)utf16[i]);
|
||||
RINOK(WriteStream(outStream, (const Byte *)xmlBuf, xmlSize));
|
||||
}
|
||||
|
||||
|
||||
@@ -302,12 +302,12 @@ HRESULT CUnpacker::Unpack2(
|
||||
UInt64 packDataSize;
|
||||
size_t numChunks;
|
||||
{
|
||||
UInt64 numChunks64 = (unpackSize + (((UInt32)1 << chunkSizeBits) - 1)) >> chunkSizeBits;
|
||||
UInt64 sizesBufSize64 = (numChunks64 - 1) << entrySizeShifts;
|
||||
const UInt64 numChunks64 = (unpackSize + (((UInt32)1 << chunkSizeBits) - 1)) >> chunkSizeBits;
|
||||
const UInt64 sizesBufSize64 = (numChunks64 - 1) << entrySizeShifts;
|
||||
if (sizesBufSize64 > resource.PackSize)
|
||||
return S_FALSE;
|
||||
packDataSize = resource.PackSize - sizesBufSize64;
|
||||
size_t sizesBufSize = (size_t)sizesBufSize64;
|
||||
const size_t sizesBufSize = (size_t)sizesBufSize64;
|
||||
if (sizesBufSize != sizesBufSize64)
|
||||
return E_OUTOFMEMORY;
|
||||
sizesBuf.AllocAtLeast(sizesBufSize);
|
||||
@@ -639,10 +639,10 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
|
||||
p += dirRecordSize;
|
||||
|
||||
{
|
||||
if (*(const UInt16 *)(p + fileNameLen) != 0)
|
||||
if (*(const UInt16 *)(const void *)(p + fileNameLen) != 0)
|
||||
return S_FALSE;
|
||||
for (UInt32 j = 0; j < fileNameLen; j += 2)
|
||||
if (*(const UInt16 *)(p + j) == 0)
|
||||
if (*(const UInt16 *)(const void *)(p + j) == 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
@@ -652,10 +652,10 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
|
||||
{
|
||||
// empty shortName has no ZERO at the end ?
|
||||
const Byte *p2 = p + fileNameLen2;
|
||||
if (*(const UInt16 *)(p2 + shortNameLen) != 0)
|
||||
if (*(const UInt16 *)(const void *)(p2 + shortNameLen) != 0)
|
||||
return S_FALSE;
|
||||
for (UInt32 j = 0; j < shortNameLen; j += 2)
|
||||
if (*(const UInt16 *)(p2 + j) == 0)
|
||||
if (*(const UInt16 *)(const void *)(p2 + j) == 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
@@ -703,10 +703,10 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
|
||||
|
||||
{
|
||||
const Byte *p3 = p2 + extraOffset + 2;
|
||||
if (*(const UInt16 *)(p3 + fileNameLen111) != 0)
|
||||
if (*(const UInt16 *)(const void *)(p3 + fileNameLen111) != 0)
|
||||
return S_FALSE;
|
||||
for (UInt32 j = 0; j < fileNameLen111; j += 2)
|
||||
if (*(const UInt16 *)(p3 + j) == 0)
|
||||
if (*(const UInt16 *)(const void *)(p3 + j) == 0)
|
||||
return S_FALSE;
|
||||
|
||||
// PRF(printf("\n %S", p3));
|
||||
@@ -1790,7 +1790,8 @@ void CImageInfo::Parse(const CXmlItem &item)
|
||||
{
|
||||
CTimeDefined = ParseTime(item, CTime, "CREATIONTIME");
|
||||
MTimeDefined = ParseTime(item, MTime, "LASTMODIFICATIONTIME");
|
||||
NameDefined = ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name);
|
||||
NameDefined = true;
|
||||
ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name);
|
||||
|
||||
ParseNumber64(item.GetSubStringForTag("DIRCOUNT"), DirCount);
|
||||
ParseNumber64(item.GetSubStringForTag("FILECOUNT"), FileCount);
|
||||
|
||||
@@ -82,11 +82,13 @@ struct CFile
|
||||
|
||||
int Parent;
|
||||
|
||||
CFile(): IsDir(false), HasData(false), ModeDefined(false), Sha1IsDefined(false),
|
||||
/* packSha1IsDefined(false), */
|
||||
Parent(-1),
|
||||
CFile():
|
||||
Size(0), PackSize(0), Offset(0),
|
||||
CTime(0), MTime(0), ATime(0), Mode(0) {}
|
||||
CTime(0), MTime(0), ATime(0), Mode(0),
|
||||
IsDir(false), HasData(false), ModeDefined(false), Sha1IsDefined(false),
|
||||
/* packSha1IsDefined(false), */
|
||||
Parent(-1)
|
||||
{}
|
||||
|
||||
bool IsCopyMethod() const
|
||||
{
|
||||
@@ -435,8 +437,8 @@ static void Utf8StringToProp(const AString &s, NCOM::CPropVariant &prop)
|
||||
if (!s.IsEmpty())
|
||||
{
|
||||
UString us;
|
||||
if (ConvertUTF8ToUnicode(s, us))
|
||||
prop = us;
|
||||
ConvertUTF8ToUnicode(s, us);
|
||||
prop = us;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,20 +61,29 @@ class CHandler:
|
||||
public CCommonMethodProps
|
||||
#endif
|
||||
{
|
||||
CXzStatInfo _stat;
|
||||
SRes MainDecodeSRes;
|
||||
CXzStatInfo _stat; // it's stat from backward parsing
|
||||
CXzStatInfo _stat2; // it's data from forward parsing, if the decoder was called
|
||||
SRes _stat2_decode_SRes;
|
||||
bool _stat_defined;
|
||||
bool _stat2_defined;
|
||||
|
||||
const CXzStatInfo *GetStat() const
|
||||
{
|
||||
if (_stat_defined) return &_stat;
|
||||
if (_stat2_defined) return &_stat2;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool _isArc;
|
||||
bool _needSeekToStart;
|
||||
bool _phySize_Defined;
|
||||
bool _firstBlockWasRead;
|
||||
|
||||
AString _methodsString;
|
||||
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
|
||||
UInt32 _filterId;
|
||||
|
||||
UInt64 _numSolidBytes;
|
||||
|
||||
void InitXz()
|
||||
@@ -85,6 +94,7 @@ class CHandler:
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void Init()
|
||||
{
|
||||
#ifndef EXTRACT_ONLY
|
||||
@@ -109,18 +119,24 @@ class CHandler:
|
||||
#endif
|
||||
decoder._memUsage = _memUsage;
|
||||
|
||||
MainDecodeSRes = SZ_OK;
|
||||
|
||||
RINOK(decoder.Decode(seqInStream, outStream,
|
||||
HRESULT hres = decoder.Decode(seqInStream, outStream,
|
||||
NULL, // *outSizeLimit
|
||||
true, // finishStream
|
||||
progress));
|
||||
progress);
|
||||
|
||||
_stat = decoder.Stat;
|
||||
MainDecodeSRes = decoder.MainDecodeSRes;
|
||||
if (decoder.MainDecodeSRes_wasUsed
|
||||
&& decoder.MainDecodeSRes != SZ_ERROR_MEM
|
||||
&& decoder.MainDecodeSRes != SZ_ERROR_UNSUPPORTED)
|
||||
{
|
||||
// if (!_stat2_defined)
|
||||
{
|
||||
_stat2_decode_SRes = decoder.MainDecodeSRes;
|
||||
_stat2 = decoder.Stat;
|
||||
_stat2_defined = true;
|
||||
}
|
||||
}
|
||||
|
||||
_phySize_Defined = true;
|
||||
return S_OK;
|
||||
return hres;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -143,8 +159,8 @@ public:
|
||||
INTERFACE_IOutArchive(;)
|
||||
#endif
|
||||
|
||||
size_t _blocksArraySize;
|
||||
CBlockInfo *_blocks;
|
||||
size_t _blocksArraySize;
|
||||
UInt64 _maxBlocksSize;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CMyComPtr<ISequentialInStream> _seqStream;
|
||||
@@ -156,7 +172,7 @@ public:
|
||||
|
||||
HRESULT SeekToPackPos(UInt64 pos)
|
||||
{
|
||||
return _stream->Seek(pos, STREAM_SEEK_SET, NULL);
|
||||
return _stream->Seek((Int64)pos, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -325,13 +341,16 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NCOM::CPropVariant prop;
|
||||
|
||||
const CXzStatInfo *stat = GetStat();
|
||||
|
||||
switch (propID)
|
||||
{
|
||||
case kpidPhySize: if (_phySize_Defined) prop = _stat.InSize; break;
|
||||
case kpidNumStreams: if (_stat.NumStreams_Defined) prop = _stat.NumStreams; break;
|
||||
case kpidNumBlocks: if (_stat.NumBlocks_Defined) prop = _stat.NumBlocks; break;
|
||||
case kpidUnpackSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break;
|
||||
case kpidClusterSize: if (_stat.NumBlocks_Defined && _stat.NumBlocks > 1) prop = _maxBlocksSize; break;
|
||||
case kpidPhySize: if (stat) prop = stat->InSize; break;
|
||||
case kpidNumStreams: if (stat && stat->NumStreams_Defined) prop = stat->NumStreams; break;
|
||||
case kpidNumBlocks: if (stat && stat->NumBlocks_Defined) prop = stat->NumBlocks; break;
|
||||
case kpidUnpackSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break;
|
||||
case kpidClusterSize: if (_stat_defined && _stat.NumBlocks_Defined && stat->NumBlocks > 1) prop = _maxBlocksSize; break;
|
||||
case kpidCharacts:
|
||||
if (_firstBlockWasRead)
|
||||
{
|
||||
@@ -350,14 +369,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidErrorFlags:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
SRes sres = MainDecodeSRes; // _stat.DecodeRes2; //
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
if (/*_stat.UnexpectedEnd */ sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
if (_stat.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
|
||||
if (/* _stat.HeadersError */ sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError;
|
||||
if (/* _stat.Unsupported */ sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod;
|
||||
if (/* _stat.DataError */ sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError;
|
||||
if (/* _stat.CrcError */ sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError;
|
||||
SRes sres = _stat2_decode_SRes;
|
||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||
if (sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd;
|
||||
if (_stat2_defined && _stat2.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
|
||||
if (sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError;
|
||||
if (sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod;
|
||||
if (sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError;
|
||||
if (sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError;
|
||||
if (v != 0)
|
||||
prop = v;
|
||||
break;
|
||||
@@ -384,11 +403,12 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const CXzStatInfo *stat = GetStat();
|
||||
NCOM::CPropVariant prop;
|
||||
switch (propID)
|
||||
{
|
||||
case kpidSize: if (_stat.UnpackSize_Defined) prop = _stat.OutSize; break;
|
||||
case kpidPackSize: if (_phySize_Defined) prop = _stat.InSize; break;
|
||||
case kpidSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break;
|
||||
case kpidPackSize: if (stat) prop = stat->InSize; break;
|
||||
case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
@@ -402,7 +422,9 @@ struct COpenCallbackWrap
|
||||
ICompressProgress vt;
|
||||
IArchiveOpenCallback *OpenCallback;
|
||||
HRESULT Res;
|
||||
COpenCallbackWrap(IArchiveOpenCallback *progress);
|
||||
|
||||
// new clang shows "non-POD" warning for offsetof(), if we use constructor instead of Init()
|
||||
void Init(IArchiveOpenCallback *progress);
|
||||
};
|
||||
|
||||
static SRes OpenCallbackProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 /* outSize */)
|
||||
@@ -413,7 +435,7 @@ static SRes OpenCallbackProgress(const ICompressProgress *pp, UInt64 inSize, UIn
|
||||
return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);
|
||||
}
|
||||
|
||||
COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback)
|
||||
void COpenCallbackWrap::Init(IArchiveOpenCallback *callback)
|
||||
{
|
||||
vt.Progress = OpenCallbackProgress;
|
||||
OpenCallback = callback;
|
||||
@@ -482,7 +504,11 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
|
||||
CSeqInStreamWrap inStreamWrap;
|
||||
|
||||
inStreamWrap.Init(inStream);
|
||||
|
||||
SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt);
|
||||
|
||||
if (inStreamWrap.Res != S_OK)
|
||||
return inStreamWrap.Res;
|
||||
if (res != SZ_OK)
|
||||
return SRes_to_Open_HRESULT(res);
|
||||
|
||||
@@ -490,8 +516,27 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
|
||||
CXzBlock block;
|
||||
BoolInt isIndex;
|
||||
UInt32 headerSizeRes;
|
||||
|
||||
SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes);
|
||||
if (res2 == SZ_OK && !isIndex)
|
||||
|
||||
if (inStreamWrap.Res != S_OK)
|
||||
return inStreamWrap.Res;
|
||||
|
||||
if (res2 != SZ_OK)
|
||||
{
|
||||
if (res2 == SZ_ERROR_INPUT_EOF)
|
||||
{
|
||||
_stat2_decode_SRes = res2;
|
||||
_stream = inStream;
|
||||
_seqStream = inStream;
|
||||
_isArc = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (res2 == SZ_ERROR_ARCHIVE)
|
||||
return S_FALSE;
|
||||
}
|
||||
else if (!isIndex)
|
||||
{
|
||||
_firstBlockWasRead = true;
|
||||
_firstBlock = block;
|
||||
@@ -526,7 +571,8 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
|
||||
lookStream.realStream = &inStreamImp.vt;
|
||||
LookToRead2_Init(&lookStream);
|
||||
|
||||
COpenCallbackWrap openWrap(callback);
|
||||
COpenCallbackWrap openWrap;
|
||||
openWrap.Init(callback);
|
||||
|
||||
CXzsCPP xzs;
|
||||
Int64 startPosition;
|
||||
@@ -539,7 +585,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
|
||||
*/
|
||||
if (res == SZ_OK && startPosition == 0)
|
||||
{
|
||||
_phySize_Defined = true;
|
||||
_stat_defined = true;
|
||||
|
||||
_stat.OutSize = Xzs_GetUnpackSize(&xzs.p);
|
||||
_stat.UnpackSize_Defined = true;
|
||||
@@ -615,6 +661,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
|
||||
}
|
||||
|
||||
RINOK(SRes_to_Open_HRESULT(res));
|
||||
|
||||
_stream = inStream;
|
||||
_seqStream = inStream;
|
||||
_isArc = true;
|
||||
@@ -645,12 +692,15 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
XzStatInfo_Clear(&_stat);
|
||||
XzStatInfo_Clear(&_stat2);
|
||||
_stat_defined = false;
|
||||
_stat2_defined = false;
|
||||
_stat2_decode_SRes = SZ_OK;
|
||||
|
||||
_isArc = false;
|
||||
_needSeekToStart = false;
|
||||
_phySize_Defined = false;
|
||||
_firstBlockWasRead = false;
|
||||
|
||||
|
||||
_methodsString.Empty();
|
||||
_stream.Release();
|
||||
_seqStream.Release();
|
||||
@@ -660,8 +710,6 @@ STDMETHODIMP CHandler::Close()
|
||||
_blocksArraySize = 0;
|
||||
_maxBlocksSize = 0;
|
||||
|
||||
MainDecodeSRes = SZ_OK;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -729,7 +777,7 @@ CInStream::~CInStream()
|
||||
}
|
||||
|
||||
|
||||
size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos)
|
||||
static size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos)
|
||||
{
|
||||
size_t left = 0, right = numBlocks;
|
||||
for (;;)
|
||||
@@ -900,9 +948,9 @@ STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPositio
|
||||
}
|
||||
if (offset < 0)
|
||||
return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
|
||||
_virtPos = offset;
|
||||
_virtPos = (UInt64)offset;
|
||||
if (newPosition)
|
||||
*newPosition = offset;
|
||||
*newPosition = (UInt64)offset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -951,7 +999,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
static Int32 Get_Extract_OperationResult(const NCompress::NXz::CDecoder &decoder)
|
||||
{
|
||||
Int32 opRes;
|
||||
SRes sres = decoder.MainDecodeSRes; // decoder.Stat.DecodeRes2;
|
||||
SRes sres = decoder.MainDecodeSRes;
|
||||
if (sres == SZ_ERROR_NO_ARCHIVE) // (!IsArc)
|
||||
opRes = NExtract::NOperationResult::kIsNotArc;
|
||||
else if (sres == SZ_ERROR_INPUT_EOF) // (UnexpectedEnd)
|
||||
@@ -985,8 +1033,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (_phySize_Defined)
|
||||
extractCallback->SetTotal(_stat.InSize);
|
||||
const CXzStatInfo *stat = GetStat();
|
||||
|
||||
if (stat)
|
||||
extractCallback->SetTotal(stat->InSize);
|
||||
|
||||
UInt64 currentTotalPacked = 0;
|
||||
RINOK(extractCallback->SetCompleted(¤tTotalPacked));
|
||||
@@ -1106,7 +1156,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
*/
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
xzProps.numTotalThreads = _numThreads;
|
||||
xzProps.numTotalThreads = (int)_numThreads;
|
||||
#endif
|
||||
|
||||
xzProps.blockSize = _numSolidBytes;
|
||||
@@ -1161,7 +1211,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||
lps->Init(updateCallback, true);
|
||||
|
||||
return encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress);
|
||||
RINOK(encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress));
|
||||
|
||||
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
|
||||
}
|
||||
|
||||
if (indexInArchive != 0)
|
||||
@@ -1176,8 +1228,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
|
||||
if (_stream)
|
||||
{
|
||||
if (_phySize_Defined)
|
||||
RINOK(updateCallback->SetTotal(_stat.InSize));
|
||||
const CXzStatInfo *stat = GetStat();
|
||||
if (stat)
|
||||
RINOK(updateCallback->SetTotal(stat->InSize));
|
||||
RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
|
||||
|
||||
@@ -89,14 +89,18 @@ STDMETHODIMP CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStr
|
||||
}
|
||||
|
||||
|
||||
CAddCommon::CAddCommon(const CCompressionMethodMode &options):
|
||||
_options(options),
|
||||
CAddCommon::CAddCommon():
|
||||
_copyCoderSpec(NULL),
|
||||
_isLzmaEos(false),
|
||||
_cryptoStreamSpec(NULL),
|
||||
_buf(NULL),
|
||||
_isLzmaEos(false)
|
||||
_buf(NULL)
|
||||
{}
|
||||
|
||||
void CAddCommon::SetOptions(const CCompressionMethodMode &options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
CAddCommon::~CAddCommon()
|
||||
{
|
||||
MidFree(_buf);
|
||||
@@ -232,6 +236,11 @@ HRESULT CAddCommon::Compress(
|
||||
unsigned numTestMethods = _options.MethodSequence.Size();
|
||||
|
||||
bool descriptorMode = outSeqMode;
|
||||
|
||||
// ZipCrypto without descriptor requires additional reading pass for
|
||||
// inStream to calculate CRC for password check field.
|
||||
// The descriptor allows to use ZipCrypto check field without CRC (InfoZip's modification).
|
||||
|
||||
if (!outSeqMode)
|
||||
if (inSeqMode && _options.PasswordIsDefined && !_options.IsAesMode)
|
||||
descriptorMode = true;
|
||||
@@ -264,6 +273,15 @@ HRESULT CAddCommon::Compress(
|
||||
RINOK(outStream->SetSize(0));
|
||||
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
|
||||
method = _options.MethodSequence[i];
|
||||
if (method == NCompressionMethod::kStore && descriptorMode)
|
||||
{
|
||||
// we still can create descriptor_mode archives with "Store" method, but they are not good for 100%
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
bool needCode = true;
|
||||
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
@@ -316,23 +334,25 @@ HRESULT CAddCommon::Compress(
|
||||
RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check));
|
||||
}
|
||||
|
||||
RINOK(_cryptoStreamSpec->SetOutStream(outStream));
|
||||
RINOK(_cryptoStreamSpec->InitEncoder());
|
||||
outStreamReleaser.FilterCoder = _cryptoStreamSpec;
|
||||
if (method == NCompressionMethod::kStore)
|
||||
{
|
||||
needCode = false;
|
||||
RINOK(_cryptoStreamSpec->Code(inCrcStream, outStream, NULL, NULL, progress));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(_cryptoStreamSpec->SetOutStream(outStream));
|
||||
RINOK(_cryptoStreamSpec->InitEncoder());
|
||||
outStreamReleaser.FilterCoder = _cryptoStreamSpec;
|
||||
}
|
||||
}
|
||||
|
||||
method = _options.MethodSequence[i];
|
||||
|
||||
switch (method)
|
||||
if (needCode)
|
||||
{
|
||||
switch (method)
|
||||
{
|
||||
case NCompressionMethod::kStore:
|
||||
{
|
||||
if (descriptorMode)
|
||||
{
|
||||
// we still can create descriptor_mode archives with "Store" method, but they are not good for 100%
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
if (!_copyCoderSpec)
|
||||
{
|
||||
_copyCoderSpec = new NCompress::CCopyCoder;
|
||||
@@ -446,15 +466,21 @@ HRESULT CAddCommon::Compress(
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));
|
||||
} catch (...) { return E_FAIL; }
|
||||
break;
|
||||
}
|
||||
} // switch end
|
||||
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
RINOK(_cryptoStreamSpec->OutStreamFinish());
|
||||
}
|
||||
}
|
||||
|
||||
if (_options.PasswordIsDefined)
|
||||
{
|
||||
RINOK(_cryptoStreamSpec->OutStreamFinish());
|
||||
|
||||
if (_options.IsAesMode)
|
||||
{
|
||||
RINOK(_filterAesSpec->WriteFooter(outStream));
|
||||
|
||||
@@ -28,9 +28,15 @@ struct CCompressingResult
|
||||
Byte ExtractVersion;
|
||||
bool DescriptorMode;
|
||||
bool LzmaEos;
|
||||
|
||||
CCompressingResult()
|
||||
{
|
||||
// for GCC:
|
||||
UnpackSize = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class CAddCommon
|
||||
class CAddCommon MY_UNCOPYABLE
|
||||
{
|
||||
CCompressionMethodMode _options;
|
||||
NCompress::CCopyCoder *_copyCoderSpec;
|
||||
@@ -50,7 +56,9 @@ class CAddCommon
|
||||
|
||||
HRESULT CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC);
|
||||
public:
|
||||
CAddCommon(const CCompressionMethodMode &options);
|
||||
// CAddCommon(const CCompressionMethodMode &options);
|
||||
CAddCommon();
|
||||
void SetOptions(const CCompressionMethodMode &options);
|
||||
~CAddCommon();
|
||||
|
||||
HRESULT Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, UInt64 unpackSize,
|
||||
|
||||
@@ -35,7 +35,7 @@ struct CCompressionMethodMode: public CBaseProps
|
||||
{
|
||||
CRecordVector<Byte> MethodSequence;
|
||||
bool PasswordIsDefined;
|
||||
AString Password;
|
||||
AString Password; // _Wipe
|
||||
|
||||
UInt64 _dataSizeReduce;
|
||||
bool _dataSizeReduceDefined;
|
||||
@@ -47,6 +47,8 @@ struct CCompressionMethodMode: public CBaseProps
|
||||
_dataSizeReduceDefined = false;
|
||||
_dataSizeReduce = 0;
|
||||
}
|
||||
|
||||
~CCompressionMethodMode() { Password.Wipe_and_Empty(); }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -18,6 +18,17 @@
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "../../Compress/CopyCoder.h"
|
||||
|
||||
#ifdef EXTERNAL_CODECS
|
||||
#ifndef SUPPORT_LZFSE
|
||||
#define SUPPORT_LZFSE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_LZFSE
|
||||
#include "../../Compress/LzfseDecoder.h"
|
||||
#endif
|
||||
|
||||
#include "../../Compress/LzmaDecoder.h"
|
||||
#include "../../Compress/ImplodeDecoder.h"
|
||||
#include "../../Compress/PpmdZip.h"
|
||||
@@ -82,18 +93,24 @@ const char * const kMethodNames1[kNumMethodNames1] =
|
||||
, "BZip2"
|
||||
, NULL
|
||||
, "LZMA"
|
||||
, NULL
|
||||
, NULL
|
||||
, NULL
|
||||
, NULL
|
||||
, NULL
|
||||
, "zstd-pk"
|
||||
};
|
||||
|
||||
|
||||
const char * const kMethodNames2[kNumMethodNames2] =
|
||||
{
|
||||
"zstd"
|
||||
, NULL
|
||||
, "MP3"
|
||||
, "xz"
|
||||
, "Jpeg"
|
||||
, "WavPack"
|
||||
, "PPMd"
|
||||
, "WzAES"
|
||||
, "LZFSE" // , "WzAES"
|
||||
};
|
||||
|
||||
#define kMethod_AES "AES"
|
||||
@@ -243,6 +260,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
if (m_Archive.IsZip64)
|
||||
s.Add_OptSpaced("Zip64");
|
||||
|
||||
if (m_Archive.IsCdUnsorted)
|
||||
s.Add_OptSpaced("Unsorted_CD");
|
||||
|
||||
if (m_Archive.IsApk)
|
||||
s.Add_OptSpaced("apk");
|
||||
|
||||
if (m_Archive.ExtraMinorError)
|
||||
s.Add_OptSpaced("Minor_Extra_ERROR");
|
||||
|
||||
@@ -315,9 +338,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
|
||||
// case kpidIsAltStream: prop = true; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return prop.Detach(value);
|
||||
COM_TRY_END
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
@@ -339,7 +361,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
{
|
||||
UString res;
|
||||
item.GetUnicodeString(res, item.Name, false, _forceCodePage, _specifiedCodePage);
|
||||
NItemName::ReplaceToOsSlashes_Remove_TailSlash(res);
|
||||
NItemName::ReplaceToOsSlashes_Remove_TailSlash(res,
|
||||
item.Is_MadeBy_Unix() // useBackslashReplacement
|
||||
);
|
||||
/*
|
||||
if (item.ParentOfAltStream >= 0)
|
||||
{
|
||||
@@ -362,7 +386,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidIsDir: prop = item.IsDir(); break;
|
||||
case kpidSize:
|
||||
{
|
||||
if (item.FromCentral || !item.FromLocal || !item.HasDescriptor() || item.DescriptorWasRead)
|
||||
if (!item.IsBadDescriptor())
|
||||
prop = item.Size;
|
||||
break;
|
||||
}
|
||||
@@ -470,23 +494,27 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
|
||||
case kpidMethod:
|
||||
{
|
||||
unsigned id = item.Method;
|
||||
AString m;
|
||||
|
||||
if (item.IsEncrypted())
|
||||
bool isWzAes = false;
|
||||
unsigned id = item.Method;
|
||||
|
||||
if (id == NFileHeader::NCompressionMethod::kWzAES)
|
||||
{
|
||||
if (id == NFileHeader::NCompressionMethod::kWzAES)
|
||||
CWzAesExtra aesField;
|
||||
if (extra.GetWzAes(aesField))
|
||||
{
|
||||
m += kMethod_AES;
|
||||
CWzAesExtra aesField;
|
||||
if (extra.GetWzAes(aesField))
|
||||
{
|
||||
m += '-';
|
||||
m.Add_UInt32(((unsigned)aesField.Strength + 1) * 64);
|
||||
id = aesField.Method;
|
||||
}
|
||||
m += '-';
|
||||
m.Add_UInt32(((unsigned)aesField.Strength + 1) * 64);
|
||||
id = aesField.Method;
|
||||
isWzAes = true;
|
||||
}
|
||||
else if (item.IsStrongEncrypted())
|
||||
}
|
||||
|
||||
if (item.IsEncrypted())
|
||||
if (!isWzAes)
|
||||
{
|
||||
if (item.IsStrongEncrypted())
|
||||
{
|
||||
CStrongCryptoExtra f;
|
||||
f.AlgId = 0;
|
||||
@@ -509,8 +537,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
}
|
||||
else
|
||||
m += kMethod_ZipCrypto;
|
||||
m += ' ';
|
||||
}
|
||||
|
||||
m.Add_Space_if_NotEmpty();
|
||||
|
||||
{
|
||||
const char *s = NULL;
|
||||
@@ -519,7 +548,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
else
|
||||
{
|
||||
int id2 = (int)id - (int)kMethodNames2Start;
|
||||
if (id2 >= 0 && id2 < kNumMethodNames2)
|
||||
if (id2 >= 0 && (unsigned)id2 < kNumMethodNames2)
|
||||
s = kMethodNames2[id2];
|
||||
}
|
||||
if (s)
|
||||
@@ -535,7 +564,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
{
|
||||
if (level & 1)
|
||||
m += ":eos";
|
||||
level &= ~1;
|
||||
level &= ~(unsigned)1;
|
||||
}
|
||||
else if (id == NFileHeader::NCompressionMethod::kDeflate)
|
||||
{
|
||||
@@ -579,7 +608,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
}
|
||||
|
||||
UInt32 flags = item.Flags;
|
||||
flags &= ~(6); // we don't need compression related bits here.
|
||||
flags &= ~(unsigned)6; // we don't need compression related bits here.
|
||||
|
||||
if (flags != 0)
|
||||
{
|
||||
@@ -592,7 +621,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
}
|
||||
}
|
||||
|
||||
if (!item.FromCentral && item.FromLocal && item.HasDescriptor() && !item.DescriptorWasRead)
|
||||
if (item.IsBadDescriptor())
|
||||
s.Add_OptSpaced("Descriptor_ERROR");
|
||||
|
||||
if (!s.IsEmpty())
|
||||
@@ -637,8 +666,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
*/
|
||||
}
|
||||
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
return prop.Detach(value);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
@@ -889,11 +917,14 @@ public:
|
||||
};
|
||||
|
||||
|
||||
static HRESULT SkipStreamData(ISequentialInStream *stream, bool &thereAreData)
|
||||
static HRESULT SkipStreamData(ISequentialInStream *stream,
|
||||
ICompressProgressInfo *progress, UInt64 packSize, UInt64 unpackSize,
|
||||
bool &thereAreData)
|
||||
{
|
||||
thereAreData = false;
|
||||
const size_t kBufSize = 1 << 12;
|
||||
Byte buf[kBufSize];
|
||||
UInt64 prev = packSize;
|
||||
for (;;)
|
||||
{
|
||||
size_t size = kBufSize;
|
||||
@@ -901,10 +932,80 @@ static HRESULT SkipStreamData(ISequentialInStream *stream, bool &thereAreData)
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
thereAreData = true;
|
||||
packSize += size;
|
||||
if ((packSize - prev) >= (1 << 22))
|
||||
{
|
||||
prev = packSize;
|
||||
RINOK(progress->SetRatioInfo(&packSize, &unpackSize));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class COutStreamWithPadPKCS7:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
UInt64 _padPos;
|
||||
UInt32 _padSize;
|
||||
bool _padFailure;
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
|
||||
// padSize == 0 means (no_pad Mode)
|
||||
void Init(UInt64 padPos, UInt32 padSize)
|
||||
{
|
||||
_padPos = padPos;
|
||||
_padSize = padSize;
|
||||
_size = 0;
|
||||
_padFailure = false;
|
||||
}
|
||||
UInt64 GetSize() const { return _size; }
|
||||
bool WasPadFailure() const { return _padFailure; }
|
||||
};
|
||||
|
||||
|
||||
STDMETHODIMP COutStreamWithPadPKCS7::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 written = 0;
|
||||
HRESULT result = S_OK;
|
||||
if (_size < _padPos)
|
||||
{
|
||||
const UInt64 rem = _padPos - _size;
|
||||
UInt32 num = size;
|
||||
if (num > rem)
|
||||
num = (UInt32)rem;
|
||||
result = _stream->Write(data, num, &written);
|
||||
_size += written;
|
||||
if (processedSize)
|
||||
*processedSize = written;
|
||||
if (_size != _padPos || result != S_OK)
|
||||
return result;
|
||||
size -= written;
|
||||
data = ((const Byte *)data) + written;
|
||||
}
|
||||
_size += size;
|
||||
written += size;
|
||||
if (processedSize)
|
||||
*processedSize = written;
|
||||
if (_padSize != 0)
|
||||
for (; size != 0; size--)
|
||||
{
|
||||
if (*(const Byte *)data != _padSize)
|
||||
_padFailure = true;
|
||||
data = ((const Byte *)data) + 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT CZipDecoder::Decode(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CInArchive &archive, const CItemEx &item,
|
||||
@@ -924,9 +1025,32 @@ HRESULT CZipDecoder::Decode(
|
||||
bool needCRC = true;
|
||||
bool wzAesMode = false;
|
||||
bool pkAesMode = false;
|
||||
|
||||
bool badDescriptor = item.IsBadDescriptor();
|
||||
if (badDescriptor)
|
||||
needCRC = false;
|
||||
|
||||
|
||||
unsigned id = item.Method;
|
||||
|
||||
CWzAesExtra aesField;
|
||||
// LZFSE and WinZip's AES use same id - kWzAES.
|
||||
|
||||
if (id == NFileHeader::NCompressionMethod::kWzAES)
|
||||
{
|
||||
if (item.GetMainExtra().GetWzAes(aesField))
|
||||
{
|
||||
if (!item.IsEncrypted())
|
||||
{
|
||||
res = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
return S_OK;
|
||||
}
|
||||
wzAesMode = true;
|
||||
needCRC = aesField.NeedCrc();
|
||||
}
|
||||
}
|
||||
|
||||
if (!wzAesMode)
|
||||
if (item.IsEncrypted())
|
||||
{
|
||||
if (item.IsStrongEncrypted())
|
||||
@@ -939,14 +1063,6 @@ HRESULT CZipDecoder::Decode(
|
||||
}
|
||||
pkAesMode = true;
|
||||
}
|
||||
else if (id == NFileHeader::NCompressionMethod::kWzAES)
|
||||
{
|
||||
CWzAesExtra aesField;
|
||||
if (!item.GetMainExtra().GetWzAes(aesField))
|
||||
return S_OK;
|
||||
wzAesMode = true;
|
||||
needCRC = aesField.NeedCrc();
|
||||
}
|
||||
}
|
||||
|
||||
COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
|
||||
@@ -986,9 +1102,6 @@ HRESULT CZipDecoder::Decode(
|
||||
{
|
||||
if (wzAesMode)
|
||||
{
|
||||
CWzAesExtra aesField;
|
||||
if (!item.GetMainExtra().GetWzAes(aesField))
|
||||
return S_OK;
|
||||
id = aesField.Method;
|
||||
if (!_wzAesDecoder)
|
||||
{
|
||||
@@ -1031,12 +1144,12 @@ HRESULT CZipDecoder::Decode(
|
||||
|
||||
if (getTextPassword)
|
||||
{
|
||||
CMyComBSTR password;
|
||||
CMyComBSTR_Wipe password;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword(&password));
|
||||
AString charPassword;
|
||||
AString_Wipe charPassword;
|
||||
if (password)
|
||||
{
|
||||
UnicodeStringToMultiByte2(charPassword, (const wchar_t *)password, CP_ACP);
|
||||
UnicodeStringToMultiByte2(charPassword, (LPCOLESTR)password, CP_ACP);
|
||||
/*
|
||||
if (wzAesMode || pkAesMode)
|
||||
{
|
||||
@@ -1090,10 +1203,16 @@ HRESULT CZipDecoder::Decode(
|
||||
}
|
||||
else if (id ==NFileHeader::NCompressionMethod::kZstd)
|
||||
mi.Coder = new CZstdDecoder();
|
||||
else if (id ==NFileHeader::NCompressionMethod::kZstdPk)
|
||||
mi.Coder = new CZstdDecoder();
|
||||
else if (id == NFileHeader::NCompressionMethod::kXz)
|
||||
mi.Coder = new NCompress::NXz::CComDecoder;
|
||||
else if (id == NFileHeader::NCompressionMethod::kPPMd)
|
||||
mi.Coder = new NCompress::NPpmdZip::CDecoder(true);
|
||||
#ifdef SUPPORT_LZFSE
|
||||
else if (id == NFileHeader::NCompressionMethod::kWzAES)
|
||||
mi.Coder = new NCompress::NLzfse::CDecoder;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
CMethodId szMethodID;
|
||||
@@ -1120,7 +1239,8 @@ HRESULT CZipDecoder::Decode(
|
||||
m = methodItems.Add(mi);
|
||||
}
|
||||
|
||||
ICompressCoder *coder = methodItems[m].Coder;
|
||||
const CMethodItem &mi = methodItems[m];
|
||||
ICompressCoder *coder = mi.Coder;
|
||||
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
@@ -1154,14 +1274,22 @@ HRESULT CZipDecoder::Decode(
|
||||
}
|
||||
|
||||
|
||||
CMyComPtr<ISequentialInStream> inStreamNew;
|
||||
|
||||
bool isFullStreamExpected = (!item.HasDescriptor() || item.PackSize != 0);
|
||||
bool needReminderCheck = false;
|
||||
|
||||
bool dataAfterEnd = false;
|
||||
bool truncatedError = false;
|
||||
bool lzmaEosError = false;
|
||||
bool headersError = false;
|
||||
bool padError = false;
|
||||
bool readFromFilter = false;
|
||||
|
||||
const bool useUnpackLimit = (id == NFileHeader::NCompressionMethod::kStore
|
||||
|| !item.HasDescriptor()
|
||||
|| item.Size >= ((UInt64)1 << 32)
|
||||
|| item.LocalExtra.IsZip64
|
||||
|| item.CentralExtra.IsZip64
|
||||
);
|
||||
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
@@ -1229,23 +1357,7 @@ HRESULT CZipDecoder::Decode(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result == S_OK)
|
||||
{
|
||||
inStreamReleaser.FilterCoder = filterStreamSpec;
|
||||
RINOK(filterStreamSpec->SetInStream(inStream));
|
||||
|
||||
/* IFilter::Init() does nothing in all zip crypto filters.
|
||||
So we can call any Initialize function in CFilterCoder. */
|
||||
|
||||
RINOK(filterStreamSpec->Init_NoSubFilterInit());
|
||||
// RINOK(filterStreamSpec->SetOutStreamSize(NULL));
|
||||
|
||||
inStreamNew = filterStream;
|
||||
}
|
||||
}
|
||||
else
|
||||
inStreamNew = inStream;
|
||||
|
||||
if (result == S_OK)
|
||||
{
|
||||
@@ -1253,26 +1365,84 @@ HRESULT CZipDecoder::Decode(
|
||||
coder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
|
||||
if (setFinishMode)
|
||||
{
|
||||
RINOK(setFinishMode->SetFinishMode(BoolToInt(true)));
|
||||
RINOK(setFinishMode->SetFinishMode(BoolToUInt(true)));
|
||||
}
|
||||
|
||||
const UInt64 coderPackSize = limitedStreamSpec->GetRem();
|
||||
|
||||
bool useUnpackLimit = (id == 0
|
||||
|| !item.HasDescriptor()
|
||||
|| item.Size >= ((UInt64)1 << 32)
|
||||
|| item.LocalExtra.IsZip64
|
||||
|| item.CentralExtra.IsZip64
|
||||
);
|
||||
|
||||
result = coder->Code(inStreamNew, outStream,
|
||||
isFullStreamExpected ? &coderPackSize : NULL,
|
||||
// NULL,
|
||||
useUnpackLimit ? &item.Size : NULL,
|
||||
compressProgress);
|
||||
|
||||
if (result == S_OK)
|
||||
if (id == NFileHeader::NCompressionMethod::kStore && item.IsEncrypted())
|
||||
{
|
||||
readFromFilter = false;
|
||||
|
||||
COutStreamWithPadPKCS7 *padStreamSpec = NULL;
|
||||
CMyComPtr<ISequentialOutStream> padStream;
|
||||
UInt32 padSize = 0;
|
||||
|
||||
if (pkAesMode)
|
||||
{
|
||||
padStreamSpec = new COutStreamWithPadPKCS7;
|
||||
padStream = padStreamSpec;
|
||||
padSize = _pkAesDecoderSpec->GetPadSize((UInt32)item.Size);
|
||||
padStreamSpec->SetStream(outStream);
|
||||
padStreamSpec->Init(item.Size, padSize);
|
||||
}
|
||||
|
||||
// Here we decode minimal required size, including padding
|
||||
const UInt64 expectedSize = item.Size + padSize;
|
||||
UInt64 size = coderPackSize;
|
||||
if (item.Size > coderPackSize)
|
||||
headersError = true;
|
||||
else if (expectedSize != coderPackSize)
|
||||
{
|
||||
headersError = true;
|
||||
if (coderPackSize > expectedSize)
|
||||
size = expectedSize;
|
||||
}
|
||||
|
||||
result = filterStreamSpec->Code(inStream, padStream ?
|
||||
(ISequentialOutStream *)padStream :
|
||||
(ISequentialOutStream *)outStream,
|
||||
NULL, &size, compressProgress);
|
||||
|
||||
if (outStreamSpec->GetSize() != item.Size)
|
||||
truncatedError = true;
|
||||
|
||||
if (pkAesMode)
|
||||
{
|
||||
if (padStreamSpec->GetSize() != size)
|
||||
truncatedError = true;
|
||||
if (padStreamSpec->WasPadFailure())
|
||||
padError = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.IsEncrypted())
|
||||
{
|
||||
readFromFilter = true;
|
||||
inStreamReleaser.FilterCoder = filterStreamSpec;
|
||||
RINOK(filterStreamSpec->SetInStream(inStream));
|
||||
|
||||
/* IFilter::Init() does nothing in all zip crypto filters.
|
||||
So we can call any Initialize function in CFilterCoder. */
|
||||
|
||||
RINOK(filterStreamSpec->Init_NoSubFilterInit());
|
||||
// RINOK(filterStreamSpec->SetOutStreamSize(NULL));
|
||||
}
|
||||
|
||||
try {
|
||||
result = coder->Code(readFromFilter ?
|
||||
(ISequentialInStream *)filterStream :
|
||||
(ISequentialInStream *)inStream,
|
||||
outStream,
|
||||
isFullStreamExpected ? &coderPackSize : NULL,
|
||||
// NULL,
|
||||
useUnpackLimit ? &item.Size : NULL,
|
||||
compressProgress);
|
||||
} catch (...) { return E_FAIL; }
|
||||
|
||||
if (result == S_OK)
|
||||
{
|
||||
CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;
|
||||
coder->QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize);
|
||||
if (getInStreamProcessedSize && setFinishMode)
|
||||
@@ -1290,7 +1460,32 @@ HRESULT CZipDecoder::Decode(
|
||||
{
|
||||
if (processed + padSize < coderPackSize)
|
||||
dataAfterEnd = true;
|
||||
// also here we can check PKCS7 padding data from reminder (it can be inside stream buffer in coder).
|
||||
else
|
||||
{
|
||||
// here we can PKCS7 padding data from reminder (it can be inside stream buffer in coder).
|
||||
CMyComPtr<ICompressReadUnusedFromInBuf> readInStream;
|
||||
coder->QueryInterface(IID_ICompressReadUnusedFromInBuf, (void **)&readInStream);
|
||||
if (readInStream)
|
||||
{
|
||||
// change pad size, it we support another block size in ZipStron
|
||||
// here we request more to detect error with data after end.
|
||||
const UInt32 kBufSize = NCrypto::NZipStrong::kAesPadAllign + 16;
|
||||
Byte buf[kBufSize];
|
||||
UInt32 processedSize;
|
||||
RINOK(readInStream->ReadUnusedFromInBuf(buf, kBufSize, &processedSize));
|
||||
if (processedSize > padSize)
|
||||
dataAfterEnd = true;
|
||||
else
|
||||
{
|
||||
if (ReadStream_FALSE(filterStream, buf + processedSize, padSize - processedSize) != S_OK)
|
||||
padError = true;
|
||||
else
|
||||
for (unsigned i = 0; i < padSize; i++)
|
||||
if (buf[i] != padSize)
|
||||
padError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1301,11 +1496,15 @@ HRESULT CZipDecoder::Decode(
|
||||
dataAfterEnd = true;
|
||||
}
|
||||
else if (processed > coderPackSize)
|
||||
{
|
||||
// that case is additional check, that can show the bugs in code (coder)
|
||||
truncatedError = true;
|
||||
}
|
||||
needReminderCheck = isFullStreamExpected;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result == S_OK && id == NFileHeader::NCompressionMethod::kLZMA)
|
||||
@@ -1329,19 +1528,33 @@ HRESULT CZipDecoder::Decode(
|
||||
bool authOk = true;
|
||||
if (needCRC)
|
||||
crcOK = (outStreamSpec->GetCRC() == item.Crc);
|
||||
|
||||
if (useUnpackLimit)
|
||||
if (outStreamSpec->GetSize() != item.Size)
|
||||
truncatedError = true;
|
||||
|
||||
if (wzAesMode)
|
||||
{
|
||||
const UInt64 unpackSize = outStreamSpec->GetSize();
|
||||
const UInt64 packSize = limitedStreamSpec->GetSize();
|
||||
bool thereAreData = false;
|
||||
if (SkipStreamData(inStreamNew, thereAreData) != S_OK)
|
||||
// read to the end from filter or from packed stream
|
||||
if (SkipStreamData(readFromFilter ?
|
||||
(ISequentialInStream *)filterStream :
|
||||
(ISequentialInStream *)inStream,
|
||||
compressProgress, packSize, unpackSize, thereAreData) != S_OK)
|
||||
authOk = false;
|
||||
|
||||
if (needReminderCheck && thereAreData)
|
||||
dataAfterEnd = true;
|
||||
|
||||
limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize);
|
||||
if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK)
|
||||
authOk = false;
|
||||
|
||||
if (limitedStreamSpec->GetRem() != 0)
|
||||
truncatedError = true;
|
||||
else
|
||||
{
|
||||
limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize);
|
||||
if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK)
|
||||
authOk = false;
|
||||
}
|
||||
}
|
||||
|
||||
res = NExtract::NOperationResult::kCRCError;
|
||||
@@ -1352,10 +1565,16 @@ HRESULT CZipDecoder::Decode(
|
||||
|
||||
if (dataAfterEnd)
|
||||
res = NExtract::NOperationResult::kDataAfterEnd;
|
||||
else if (padError)
|
||||
res = NExtract::NOperationResult::kCRCError;
|
||||
else if (truncatedError)
|
||||
res = NExtract::NOperationResult::kUnexpectedEnd;
|
||||
else if (headersError)
|
||||
res = NExtract::NOperationResult::kHeadersError;
|
||||
else if (lzmaEosError)
|
||||
res = NExtract::NOperationResult::kHeadersError;
|
||||
else if (badDescriptor)
|
||||
res = NExtract::NOperationResult::kUnexpectedEnd;
|
||||
|
||||
// CheckDescriptor() supports only data descriptor with signature and
|
||||
// it doesn't support "old" pkzip's data descriptor without signature.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace NArchive {
|
||||
namespace NZip {
|
||||
|
||||
const unsigned kNumMethodNames1 = NFileHeader::NCompressionMethod::kLZMA + 1;
|
||||
const unsigned kNumMethodNames1 = NFileHeader::NCompressionMethod::kZstdPk + 1;
|
||||
const unsigned kMethodNames2Start = NFileHeader::NCompressionMethod::kZstd;
|
||||
const unsigned kNumMethodNames2 = NFileHeader::NCompressionMethod::kWzAES + 1 - kMethodNames2Start;
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ static int FindZipMethod(const char *s, const char * const *names, unsigned num)
|
||||
{
|
||||
const char *name = names[i];
|
||||
if (name && StringsAreEqualNoCase_Ascii(s, name))
|
||||
return i;
|
||||
return (int)i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -65,7 +65,7 @@ static int FindZipMethod(const char *s)
|
||||
return k;
|
||||
k = FindZipMethod(s, kMethodNames2, kNumMethodNames2);
|
||||
if (k >= 0)
|
||||
return kMethodNames2Start + k;
|
||||
return (int)kMethodNames2Start + k;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ static int FindZipMethod(const char *s)
|
||||
catch(const CSystemException &e) { return e.ErrorCode; } \
|
||||
catch(...) { return E_OUTOFMEMORY; }
|
||||
|
||||
static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &filetime)
|
||||
static HRESULT GetTime(IArchiveUpdateCallback *callback, unsigned index, PROPID propID, FILETIME &filetime)
|
||||
{
|
||||
filetime.dwHighDateTime = filetime.dwLowDateTime = 0;
|
||||
NCOM::CPropVariant prop;
|
||||
@@ -106,6 +106,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
UInt64 largestSize = 0;
|
||||
bool largestSizeDefined = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
const UINT oemCP = GetOEMCP();
|
||||
#endif
|
||||
|
||||
UString name;
|
||||
CUpdateItem ui;
|
||||
|
||||
@@ -125,7 +129,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
|
||||
ui.NewProps = IntToBool(newProps);
|
||||
ui.NewData = IntToBool(newData);
|
||||
ui.IndexInArc = indexInArc;
|
||||
ui.IndexInArc = (int)indexInArc;
|
||||
ui.IndexInClient = i;
|
||||
|
||||
bool existInArchive = (indexInArc != (UInt32)(Int32)-1);
|
||||
@@ -240,10 +244,25 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (needSlash)
|
||||
name += kSlash;
|
||||
|
||||
UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP;
|
||||
|
||||
const UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP;
|
||||
bool tryUtf8 = true;
|
||||
if ((m_ForceLocal || !m_ForceUtf8) && codePage != CP_UTF8)
|
||||
|
||||
/*
|
||||
Windows 10 allows users to set UTF-8 in Region Settings via option:
|
||||
"Beta: Use Unicode UTF-8 for worldwide language support"
|
||||
In that case Windows uses CP_UTF8 when we use CP_OEMCP.
|
||||
21.02 fixed:
|
||||
we set UTF-8 mark for non-latin files for such UTF-8 mode in Windows.
|
||||
we write additional Info-Zip Utf-8 FileName Extra for non-latin names/
|
||||
*/
|
||||
|
||||
if ((codePage != CP_UTF8) &&
|
||||
#ifdef _WIN32
|
||||
(m_ForceLocal || !m_ForceUtf8) && (oemCP != CP_UTF8)
|
||||
#else
|
||||
(m_ForceLocal && !m_ForceUtf8)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
bool defaultCharWasUsed;
|
||||
ui.Name = UnicodeStringToMultiByte(name, codePage, '_', defaultCharWasUsed);
|
||||
@@ -251,13 +270,26 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
MultiByteToUnicodeString(ui.Name, codePage) != name));
|
||||
}
|
||||
|
||||
const bool isNonLatin = !name.IsAscii();
|
||||
|
||||
if (tryUtf8)
|
||||
{
|
||||
ui.IsUtf8 = !name.IsAscii();
|
||||
ui.IsUtf8 = isNonLatin;
|
||||
ConvertUnicodeToUTF8(name, ui.Name);
|
||||
}
|
||||
|
||||
if (ui.Name.Len() >= (1 << 16))
|
||||
#ifndef _WIN32
|
||||
if (ui.IsUtf8 && !CheckUTF8_AString(ui.Name))
|
||||
{
|
||||
// if it's non-Windows and there are non-UTF8 characters we clear UTF8-flag
|
||||
ui.IsUtf8 = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (isNonLatin)
|
||||
Convert_Unicode_To_UTF8_Buf(name, ui.Name_Utf);
|
||||
|
||||
if (ui.Name.Len() >= (1 << 16)
|
||||
|| ui.Name_Utf.Size() >= (1 << 16) - 128)
|
||||
return E_INVALIDARG;
|
||||
|
||||
{
|
||||
@@ -337,10 +369,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
options._dataSizeReduceDefined = largestSizeDefined;
|
||||
|
||||
options.PasswordIsDefined = false;
|
||||
options.Password.Empty();
|
||||
options.Password.Wipe_and_Empty();
|
||||
if (getTextPassword)
|
||||
{
|
||||
CMyComBSTR password;
|
||||
CMyComBSTR_Wipe password;
|
||||
Int32 passwordIsDefined;
|
||||
RINOK(getTextPassword->CryptoGetTextPassword2(&passwordIsDefined, &password));
|
||||
options.PasswordIsDefined = IntToBool(passwordIsDefined);
|
||||
@@ -352,7 +384,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (!IsSimpleAsciiString(password))
|
||||
return E_INVALIDARG;
|
||||
if (password)
|
||||
options.Password = UnicodeStringToMultiByte((LPCOLESTR)password, CP_OEMCP);
|
||||
UnicodeStringToMultiByte2(options.Password, (LPCOLESTR)password, CP_OEMCP);
|
||||
if (options.IsAesMode)
|
||||
{
|
||||
if (options.Password.Len() > NCrypto::NWzAes::kPasswordSizeMax)
|
||||
@@ -496,7 +528,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
|
||||
UInt32 id = prop.ulVal;
|
||||
if (id > 0xFF)
|
||||
return E_INVALIDARG;
|
||||
m_MainMethod = id;
|
||||
m_MainMethod = (int)id;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -518,7 +550,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
|
||||
const char *end;
|
||||
UInt32 id = ConvertStringToUInt32(methodName, &end);
|
||||
if (*end == 0 && id <= 0xFF)
|
||||
m_MainMethod = id;
|
||||
m_MainMethod = (int)id;
|
||||
else if (methodName.IsEqualTo_Ascii_NoCase("Copy")) // it's alias for "Store"
|
||||
m_MainMethod = 0;
|
||||
}
|
||||
|
||||
@@ -49,24 +49,25 @@ namespace NFileHeader
|
||||
kDeflate = 8,
|
||||
kDeflate64 = 9,
|
||||
kPKImploding = 10,
|
||||
|
||||
kBZip2 = 12,
|
||||
|
||||
kLZMA = 14,
|
||||
|
||||
kTerse = 18,
|
||||
kLz77 = 19,
|
||||
|
||||
kZstd = 93,
|
||||
kXz = 95,
|
||||
kJpeg = 96,
|
||||
kWavPack = 97,
|
||||
kPPMd = 98,
|
||||
kWzAES = 99
|
||||
|
||||
kBZip2 = 12, // File is compressed using BZIP2 algorithm
|
||||
|
||||
kLZMA = 14, // LZMA
|
||||
|
||||
kTerse = 18, // File is compressed using IBM TERSE (new)
|
||||
kLz77 = 19, // IBM LZ77 z Architecture
|
||||
kZstdPk = 20, // deprecated (use method 93 for zstd)
|
||||
|
||||
kZstd = 93, // Zstandard (zstd) Compression
|
||||
kMP3 = 94, // MP3 Compression
|
||||
kXz = 95, // XZ Compression
|
||||
kJpeg = 96, // JPEG variant
|
||||
kWavPack = 97, // WavPack compressed data
|
||||
kPPMd = 98, // PPMd version I, Rev 1
|
||||
kWzAES = 99 // AE-x encryption marker (see APPENDIX E)
|
||||
};
|
||||
|
||||
const Byte kMadeByProgramVersion = 63;
|
||||
|
||||
const Byte kExtractVersion_Default = 10;
|
||||
const Byte kExtractVersion_Dir = 20;
|
||||
const Byte kExtractVersion_ZipCrypto = 20;
|
||||
@@ -77,7 +78,7 @@ namespace NFileHeader
|
||||
const Byte kExtractVersion_Aes = 51;
|
||||
const Byte kExtractVersion_LZMA = 63;
|
||||
const Byte kExtractVersion_PPMd = 63;
|
||||
const Byte kExtractVersion_Xz = 20; // test it
|
||||
const Byte kExtractVersion_Xz = 20; // test it
|
||||
const Byte kExtractVersion_Zstd = 20; // WinZip mark it
|
||||
}
|
||||
|
||||
@@ -92,7 +93,10 @@ namespace NFileHeader
|
||||
kUnixExtra = 0x5855,
|
||||
kIzUnicodeComment = 0x6375,
|
||||
kIzUnicodeName = 0x7075,
|
||||
kWzAES = 0x9901
|
||||
kUnix2Extra = 0x7855,
|
||||
kUnix3Extra = 0x7875,
|
||||
kWzAES = 0x9901,
|
||||
kApkAlign = 0xD935
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -152,6 +152,9 @@ void CInArchive::Close()
|
||||
IsArc = false;
|
||||
IsZip64 = false;
|
||||
|
||||
IsApk = false;
|
||||
IsCdUnsorted = false;
|
||||
|
||||
HeadersError = false;
|
||||
HeadersWarning = false;
|
||||
ExtraMinorError = false;
|
||||
@@ -169,7 +172,7 @@ void CInArchive::Close()
|
||||
IsMultiVol = false;
|
||||
UseDisk_in_SingleVol = false;
|
||||
EcdVolIndex = 0;
|
||||
|
||||
|
||||
ArcInfo.Clear();
|
||||
|
||||
ClearRefs();
|
||||
@@ -181,7 +184,7 @@ HRESULT CInArchive::Seek_SavePos(UInt64 offset)
|
||||
{
|
||||
// InitBuf();
|
||||
// if (!Stream) return S_FALSE;
|
||||
return Stream->Seek(offset, STREAM_SEEK_SET, &_streamPos);
|
||||
return Stream->Seek((Int64)offset, STREAM_SEEK_SET, &_streamPos);
|
||||
}
|
||||
|
||||
HRESULT CInArchive::SeekToVol(int volIndex, UInt64 offset)
|
||||
@@ -193,9 +196,9 @@ HRESULT CInArchive::SeekToVol(int volIndex, UInt64 offset)
|
||||
{
|
||||
if ((unsigned)volIndex >= Vols.Streams.Size())
|
||||
return S_FALSE;
|
||||
if (!Vols.Streams[volIndex].Stream)
|
||||
if (!Vols.Streams[(unsigned)volIndex].Stream)
|
||||
return S_FALSE;
|
||||
Stream = Vols.Streams[volIndex].Stream;
|
||||
Stream = Vols.Streams[(unsigned)volIndex].Stream;
|
||||
}
|
||||
else if (volIndex == -2)
|
||||
{
|
||||
@@ -277,11 +280,11 @@ HRESULT CInArchive::ReadFromCache(Byte *data, unsigned size, unsigned &processed
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 cur = 0;
|
||||
result = Stream->Read(data, size, &cur);
|
||||
size_t cur = size;
|
||||
result = ReadStream(Stream, data, &cur);
|
||||
data += cur;
|
||||
size -= cur;
|
||||
processed += cur;
|
||||
size -= (unsigned)cur;
|
||||
processed += (unsigned)cur;
|
||||
_streamPos += cur;
|
||||
_cnt += cur;
|
||||
if (cur != 0)
|
||||
@@ -299,7 +302,7 @@ HRESULT CInArchive::ReadFromCache(Byte *data, unsigned size, unsigned &processed
|
||||
|| (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size())
|
||||
break;
|
||||
|
||||
const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1];
|
||||
const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex + 1];
|
||||
if (!s.Stream)
|
||||
break;
|
||||
result = s.SeekToStart();
|
||||
@@ -316,6 +319,16 @@ HRESULT CInArchive::ReadFromCache(Byte *data, unsigned size, unsigned &processed
|
||||
}
|
||||
|
||||
|
||||
HRESULT CInArchive::ReadFromCache_FALSE(Byte *data, unsigned size)
|
||||
{
|
||||
unsigned processed;
|
||||
HRESULT res = ReadFromCache(data, size, processed);
|
||||
if (res == S_OK && size != processed)
|
||||
return S_FALSE;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static bool CheckDosTime(UInt32 dosTime)
|
||||
{
|
||||
if (dosTime == 0)
|
||||
@@ -412,8 +425,12 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size)
|
||||
const unsigned nameSize = Get16(p + 22);
|
||||
unsigned extraSize = Get16(p + 24);
|
||||
const UInt32 extraOffset = kLocalHeaderSize + (UInt32)nameSize;
|
||||
|
||||
/*
|
||||
// 21.02: fixed. we don't use the following check
|
||||
if (extraOffset + extraSize > (1 << 16))
|
||||
return k_IsArc_Res_NO;
|
||||
*/
|
||||
|
||||
p -= 4;
|
||||
|
||||
@@ -498,12 +515,9 @@ static const Byte *FindPK(const Byte *p, const Byte *limit)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
Byte b0 = p[0];
|
||||
if (p >= limit)
|
||||
return p;
|
||||
p++;
|
||||
if (b0 == 0x50)
|
||||
break;
|
||||
Byte b0;
|
||||
b0 = p[0]; if (p >= limit) return p; p++; if (b0 == 0x50) break;
|
||||
b0 = p[0]; if (p >= limit) return p; p++; if (b0 == 0x50) break;
|
||||
}
|
||||
if (p[0] == 0x4B)
|
||||
return p - 1;
|
||||
@@ -540,10 +554,7 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit)
|
||||
if (searchLimit && *searchLimit == 0)
|
||||
{
|
||||
Byte startBuf[kMarkerSize];
|
||||
unsigned processed;
|
||||
RINOK(ReadFromCache(startBuf, kMarkerSize, processed));
|
||||
if (processed != kMarkerSize)
|
||||
return S_FALSE;
|
||||
RINOK(ReadFromCache_FALSE(startBuf, kMarkerSize));
|
||||
|
||||
UInt32 marker = Get32(startBuf);
|
||||
_signature = marker;
|
||||
@@ -551,9 +562,7 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit)
|
||||
if ( marker == NSignature::kNoSpan
|
||||
|| marker == NSignature::kSpan)
|
||||
{
|
||||
RINOK(ReadFromCache(startBuf, kMarkerSize, processed));
|
||||
if (processed != kMarkerSize)
|
||||
return S_FALSE;
|
||||
RINOK(ReadFromCache_FALSE(startBuf, kMarkerSize));
|
||||
_signature = Get32(startBuf);
|
||||
}
|
||||
|
||||
@@ -605,7 +614,7 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit)
|
||||
|
||||
SkipLookahed(avail);
|
||||
|
||||
const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1];
|
||||
const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex + 1];
|
||||
if (!s.Stream)
|
||||
break;
|
||||
|
||||
@@ -645,14 +654,14 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit)
|
||||
p = FindPK(p, limit);
|
||||
if (p >= limit)
|
||||
break;
|
||||
const size_t rem = pStart + avail - p;
|
||||
const size_t rem = (size_t)(pStart + avail - p);
|
||||
UInt32 res = IsArc_Zip_2(p, rem, isFinished);
|
||||
if (res != k_IsArc_Res_NO)
|
||||
{
|
||||
if (rem < kMarkerSize)
|
||||
return S_FALSE;
|
||||
_signature = Get32(p);
|
||||
SkipLookahed(p - pStart);
|
||||
SkipLookahed((size_t)(p - pStart));
|
||||
ArcInfo.MarkerVolIndex = Vols.StreamIndex;
|
||||
ArcInfo.MarkerPos = GetVirtStreamPos();
|
||||
ArcInfo.MarkerPos2 = ArcInfo.MarkerPos;
|
||||
@@ -674,7 +683,7 @@ HRESULT CInArchive::FindMarker(const UInt64 *searchLimit)
|
||||
if (!IsMultiVol && isFinished)
|
||||
break;
|
||||
|
||||
SkipLookahed(p - pStart);
|
||||
SkipLookahed((size_t)(p - pStart));
|
||||
|
||||
if (Callback && (_cnt - progressPrev) >= ((UInt32)1 << 23))
|
||||
{
|
||||
@@ -728,7 +737,7 @@ HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished)
|
||||
if (!IsMultiVol)
|
||||
{
|
||||
_cnt += offset;
|
||||
return Stream->Seek(offset, STREAM_SEEK_CUR, &_streamPos);
|
||||
return Stream->Seek((Int64)offset, STREAM_SEEK_CUR, &_streamPos);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
@@ -744,7 +753,7 @@ HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished)
|
||||
return S_OK;
|
||||
}
|
||||
{
|
||||
const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex];
|
||||
const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex];
|
||||
if (!s.Stream)
|
||||
{
|
||||
isFinished = true;
|
||||
@@ -756,7 +765,7 @@ HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished)
|
||||
if ((UInt64)offset <= rem)
|
||||
{
|
||||
_cnt += offset;
|
||||
return Stream->Seek(offset, STREAM_SEEK_CUR, &_streamPos);
|
||||
return Stream->Seek((Int64)offset, STREAM_SEEK_CUR, &_streamPos);
|
||||
}
|
||||
RINOK(Seek_SavePos(s.Size));
|
||||
offset -= rem;
|
||||
@@ -771,7 +780,7 @@ HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished)
|
||||
isFinished = true;
|
||||
return S_OK;
|
||||
}
|
||||
const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex];
|
||||
const CVols::CSubStreamInfo &s2 = Vols.Streams[(unsigned)Vols.StreamIndex];
|
||||
if (!s2.Stream)
|
||||
{
|
||||
isFinished = true;
|
||||
@@ -834,7 +843,7 @@ HRESULT CInArchive::LookAhead(size_t minRequired)
|
||||
|| (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size())
|
||||
return S_OK;
|
||||
|
||||
const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1];
|
||||
const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex + 1];
|
||||
if (!s.Stream)
|
||||
return S_OK;
|
||||
|
||||
@@ -979,7 +988,7 @@ bool CInArchive::ReadFileName(unsigned size, AString &s)
|
||||
#define ZIP64_IS_16_MAX(n) ((n) == 0xFFFF)
|
||||
|
||||
|
||||
bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extra,
|
||||
bool CInArchive::ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlock &extra,
|
||||
UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk)
|
||||
{
|
||||
extra.Clear();
|
||||
@@ -1010,16 +1019,16 @@ bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extra,
|
||||
bool isOK = true;
|
||||
|
||||
if (ZIP64_IS_32_MAX(unpackSize))
|
||||
if (size < 8) isOK = false; else { size -= 8; unpackSize = ReadUInt64(); }
|
||||
{ if (size < 8) isOK = false; else { size -= 8; unpackSize = ReadUInt64(); }}
|
||||
|
||||
if (isOK && ZIP64_IS_32_MAX(packSize))
|
||||
if (size < 8) isOK = false; else { size -= 8; packSize = ReadUInt64(); }
|
||||
{ if (size < 8) isOK = false; else { size -= 8; packSize = ReadUInt64(); }}
|
||||
|
||||
if (isOK && ZIP64_IS_32_MAX(localOffset))
|
||||
if (size < 8) isOK = false; else { size -= 8; localOffset = ReadUInt64(); }
|
||||
{ if (size < 8) isOK = false; else { size -= 8; localOffset = ReadUInt64(); }}
|
||||
|
||||
if (isOK && ZIP64_IS_16_MAX(disk))
|
||||
if (size < 4) isOK = false; else { size -= 4; disk = ReadUInt32(); }
|
||||
{ if (size < 4) isOK = false; else { size -= 4; disk = ReadUInt32(); }}
|
||||
|
||||
if (!isOK || size != 0)
|
||||
{
|
||||
@@ -1033,6 +1042,11 @@ bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extra,
|
||||
{
|
||||
ReadBuffer(subBlock.Data, size);
|
||||
extra.SubBlocks.Add(subBlock);
|
||||
if (subBlock.ID == NFileHeader::NExtraID::kIzUnicodeName)
|
||||
{
|
||||
if (!subBlock.CheckIzUnicode(item.Name))
|
||||
extra.Error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1054,7 +1068,7 @@ bool CInArchive::ReadLocalItem(CItemEx &item)
|
||||
{
|
||||
item.Disk = 0;
|
||||
if (IsMultiVol && Vols.StreamIndex >= 0)
|
||||
item.Disk = Vols.StreamIndex;
|
||||
item.Disk = (UInt32)Vols.StreamIndex;
|
||||
const unsigned kPureHeaderSize = kLocalHeaderSize - 4;
|
||||
Byte p[kPureHeaderSize];
|
||||
SafeRead(p, kPureHeaderSize);
|
||||
@@ -1088,7 +1102,7 @@ bool CInArchive::ReadLocalItem(CItemEx &item)
|
||||
{
|
||||
UInt64 localOffset = 0;
|
||||
UInt32 disk = 0;
|
||||
if (!ReadExtra(extraSize, item.LocalExtra, item.Size, item.PackSize, localOffset, disk))
|
||||
if (!ReadExtra(item, extraSize, item.LocalExtra, item.Size, item.PackSize, localOffset, disk))
|
||||
{
|
||||
/* Most of archives are OK for Extra. But there are some rare cases
|
||||
that have error. And if error in first item, it can't open archive.
|
||||
@@ -1111,33 +1125,39 @@ bool CInArchive::ReadLocalItem(CItemEx &item)
|
||||
HeadersWarning = true;
|
||||
}
|
||||
|
||||
return item.LocalFullHeaderSize <= ((UInt32)1 << 16);
|
||||
// return item.LocalFullHeaderSize <= ((UInt32)1 << 16);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool FlagsAreSame(const CItem &i1, const CItem &i2)
|
||||
static bool FlagsAreSame(const CItem &i1, const CItem &i2_cd)
|
||||
{
|
||||
if (i1.Method != i2.Method)
|
||||
if (i1.Method != i2_cd.Method)
|
||||
return false;
|
||||
if (i1.Flags == i2.Flags)
|
||||
|
||||
UInt32 mask = i1.Flags ^ i2_cd.Flags;
|
||||
if (mask == 0)
|
||||
return true;
|
||||
UInt32 mask = 0xFFFF;
|
||||
switch (i1.Method)
|
||||
{
|
||||
case NFileHeader::NCompressionMethod::kDeflate:
|
||||
mask = 0x7FF9;
|
||||
mask &= 0x7FF9;
|
||||
break;
|
||||
default:
|
||||
if (i1.Method <= NFileHeader::NCompressionMethod::kImplode)
|
||||
mask = 0x7FFF;
|
||||
mask &= 0x7FFF;
|
||||
}
|
||||
|
||||
// we can ignore utf8 flag, if name is ascii
|
||||
if ((i1.Flags ^ i2.Flags) & NFileHeader::NFlags::kUtf8)
|
||||
if (i1.Name.IsAscii() && i2.Name.IsAscii())
|
||||
if (mask & NFileHeader::NFlags::kUtf8)
|
||||
if (i1.Name.IsAscii() && i2_cd.Name.IsAscii())
|
||||
mask &= ~NFileHeader::NFlags::kUtf8;
|
||||
|
||||
// some bad archive in rare case can use descriptor without descriptor flag in Central Dir
|
||||
// if (i1.HasDescriptor())
|
||||
mask &= ~NFileHeader::NFlags::kDescriptorUsedMask;
|
||||
|
||||
return ((i1.Flags & mask) == (i2.Flags & mask));
|
||||
return (mask == 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1167,13 +1187,13 @@ static bool AreEqualPaths_IgnoreSlashes(const char *s1, const char *s2)
|
||||
|
||||
static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
|
||||
{
|
||||
if (!FlagsAreSame(cdItem, localItem))
|
||||
if (!FlagsAreSame(localItem, cdItem))
|
||||
return false;
|
||||
if (!localItem.HasDescriptor())
|
||||
{
|
||||
if (cdItem.PackSize != localItem.PackSize
|
||||
|| cdItem.Size != localItem.Size
|
||||
|| cdItem.Crc != localItem.Crc && cdItem.Crc != 0) // some program writes 0 to crc field in central directory
|
||||
|| (cdItem.Crc != localItem.Crc && cdItem.Crc != 0)) // some program writes 0 to crc field in central directory
|
||||
return false;
|
||||
}
|
||||
/* pkzip 2.50 creates incorrect archives. It uses
|
||||
@@ -1235,7 +1255,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool
|
||||
return S_FALSE;
|
||||
}
|
||||
Stream = Vols.Streams[item.Disk].Stream;
|
||||
Vols.StreamIndex = item.Disk;
|
||||
Vols.StreamIndex = (int)item.Disk;
|
||||
if (!Stream)
|
||||
{
|
||||
isAvail = false;
|
||||
@@ -1251,7 +1271,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool
|
||||
}
|
||||
Stream = StreamRef;
|
||||
|
||||
offset += ArcInfo.Base;
|
||||
offset = (UInt64)((Int64)offset + ArcInfo.Base);
|
||||
if (ArcInfo.Base < 0 && (Int64)offset < 0)
|
||||
{
|
||||
isAvail = false;
|
||||
@@ -1281,6 +1301,11 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool
|
||||
item.Crc = localItem.Crc;
|
||||
headersError = true;
|
||||
}
|
||||
if ((item.Flags ^ localItem.Flags) & NFileHeader::NFlags::kDescriptorUsedMask)
|
||||
{
|
||||
item.Flags = (UInt16)(item.Flags ^ NFileHeader::NFlags::kDescriptorUsedMask);
|
||||
headersError = true;
|
||||
}
|
||||
item.FromLocal = true;
|
||||
}
|
||||
catch(...) { return S_FALSE; }
|
||||
@@ -1351,8 +1376,11 @@ HRESULT CInArchive::FindDescriptor(CItemEx &item, unsigned numFiles)
|
||||
{
|
||||
// we write to packSize all these available bytes.
|
||||
// later it's simpler to work with such value than with 0
|
||||
if (item.PackSize == 0)
|
||||
// if (item.PackSize == 0)
|
||||
item.PackSize = packedSize + avail;
|
||||
if (item.Method == 0)
|
||||
item.Size = item.PackSize;
|
||||
SkipLookahed(avail);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1384,7 +1412,7 @@ HRESULT CInArchive::FindDescriptor(CItemEx &item, unsigned numFiles)
|
||||
&& sig != NSignature::kCentralFileHeader)
|
||||
continue;
|
||||
|
||||
const UInt64 packSizeCur = packedSize + (p - pStart);
|
||||
const UInt64 packSizeCur = packedSize + (size_t)(p - pStart);
|
||||
if (descriptorSize4 == kDataDescriptorSize64 + kNextSignatureSize) // if (item.LocalExtra.IsZip64)
|
||||
{
|
||||
const UInt64 descriptorPackSize = Get64(p + 8);
|
||||
@@ -1406,14 +1434,14 @@ HRESULT CInArchive::FindDescriptor(CItemEx &item, unsigned numFiles)
|
||||
item.DescriptorWasRead = true;
|
||||
item.Crc = Get32(p + 4);
|
||||
|
||||
const size_t skip = (p - pStart) + descriptorSize4 - kNextSignatureSize;
|
||||
const size_t skip = (size_t)(p - pStart) + descriptorSize4 - kNextSignatureSize;
|
||||
|
||||
SkipLookahed(skip);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
const size_t skip = (p - pStart);
|
||||
const size_t skip = (size_t)(p - pStart);
|
||||
SkipLookahed(skip);
|
||||
|
||||
packedSize += skip;
|
||||
@@ -1529,7 +1557,7 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item)
|
||||
ReadFileName(nameSize, item.Name);
|
||||
|
||||
if (extraSize > 0)
|
||||
ReadExtra(extraSize, item.CentralExtra, item.Size, item.PackSize, item.LocalHeaderPos, item.Disk);
|
||||
ReadExtra(item, extraSize, item.CentralExtra, item.Size, item.PackSize, item.LocalHeaderPos, item.Disk);
|
||||
|
||||
// May be these strings must be deleted
|
||||
/*
|
||||
@@ -1549,11 +1577,7 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo)
|
||||
Byte buf[kEcd64_FullSize];
|
||||
|
||||
RINOK(SeekToVol(Vols.StreamIndex, offset));
|
||||
unsigned processed = 0;
|
||||
ReadFromCache(buf, kEcd64_FullSize, processed);
|
||||
|
||||
if (processed != kEcd64_FullSize)
|
||||
return S_FALSE;
|
||||
RINOK(ReadFromCache_FALSE(buf, kEcd64_FullSize));
|
||||
|
||||
if (Get32(buf) != NSignature::kEcd64)
|
||||
return S_FALSE;
|
||||
@@ -1636,8 +1660,12 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode)
|
||||
{
|
||||
CLocator locator;
|
||||
locator.Parse(buf + locatorIndex + 4);
|
||||
if ((cdInfo.ThisDisk == locator.NumDisks - 1 || ZIP64_IS_16_MAX(cdInfo.ThisDisk))
|
||||
&& locator.Ecd64Disk < locator.NumDisks)
|
||||
UInt32 numDisks = locator.NumDisks;
|
||||
// we ignore the error, where some zip creators use (NumDisks == 0)
|
||||
if (numDisks == 0)
|
||||
numDisks = 1;
|
||||
if ((cdInfo.ThisDisk == numDisks - 1 || ZIP64_IS_16_MAX(cdInfo.ThisDisk))
|
||||
&& locator.Ecd64Disk < numDisks)
|
||||
{
|
||||
if (locator.Ecd64Disk != cdInfo.ThisDisk && !ZIP64_IS_16_MAX(cdInfo.ThisDisk))
|
||||
return E_NOTIMPL;
|
||||
@@ -1657,7 +1685,7 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode)
|
||||
if (mainEcd64Size == kEcd64_MainSize)
|
||||
{
|
||||
cdInfo.ParseEcd64e(ecd64 + 12);
|
||||
ArcInfo.Base = absEcd64 - locator.Ecd64Offset;
|
||||
ArcInfo.Base = (Int64)(absEcd64 - locator.Ecd64Offset);
|
||||
// ArcInfo.BaseVolIndex = cdInfo.ThisDisk;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1685,7 +1713,7 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode)
|
||||
{
|
||||
if (TryEcd64(ArcInfo.MarkerPos + locator.Ecd64Offset, cdInfo) == S_OK)
|
||||
{
|
||||
ArcInfo.Base = ArcInfo.MarkerPos;
|
||||
ArcInfo.Base = (Int64)ArcInfo.MarkerPos;
|
||||
// ArcInfo.BaseVolIndex = cdInfo.ThisDisk;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1719,7 +1747,7 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode)
|
||||
}
|
||||
else
|
||||
*/
|
||||
ArcInfo.Base = absEcdPos - cdEnd;
|
||||
ArcInfo.Base = (Int64)(absEcdPos - cdEnd);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1730,11 +1758,12 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode)
|
||||
HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize)
|
||||
{
|
||||
items.Clear();
|
||||
IsCdUnsorted = false;
|
||||
|
||||
// _startLocalFromCd_Disk = (UInt32)(Int32)-1;
|
||||
// _startLocalFromCd_Offset = (UInt64)(Int64)-1;
|
||||
|
||||
RINOK(SeekToVol(IsMultiVol ? cdInfo.CdDisk : -1, cdOffset));
|
||||
RINOK(SeekToVol(IsMultiVol ? (int)cdInfo.CdDisk : -1, cdOffset));
|
||||
|
||||
_inBufMode = true;
|
||||
_cnt = 0;
|
||||
@@ -1767,6 +1796,15 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn
|
||||
}
|
||||
*/
|
||||
|
||||
if (items.Size() > 0 && !IsCdUnsorted)
|
||||
{
|
||||
const CItemEx &prev = items.Back();
|
||||
if (cdItem.Disk < prev.Disk
|
||||
|| (cdItem.Disk == prev.Disk &&
|
||||
cdItem.LocalHeaderPos < prev.LocalHeaderPos))
|
||||
IsCdUnsorted = true;
|
||||
}
|
||||
|
||||
items.Add(cdItem);
|
||||
}
|
||||
if (Callback && (items.Size() & 0xFFF) == 0)
|
||||
@@ -1793,6 +1831,22 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static int CompareCdItems(void *const *elem1, void *const *elem2, void *)
|
||||
{
|
||||
const CItemEx *i1 = *(const CItemEx **)elem1;
|
||||
const CItemEx *i2 = *(const CItemEx **)elem2;
|
||||
|
||||
if (i1->Disk < i2->Disk) return -1;
|
||||
if (i1->Disk > i2->Disk) return 1;
|
||||
if (i1->LocalHeaderPos < i2->LocalHeaderPos) return -1;
|
||||
if (i1->LocalHeaderPos > i2->LocalHeaderPos) return 1;
|
||||
if (i1 < i2) return -1;
|
||||
if (i1 > i2) return 1;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize)
|
||||
{
|
||||
bool checkOffsetMode = true;
|
||||
@@ -1801,7 +1855,7 @@ HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64
|
||||
{
|
||||
if (Vols.EndVolIndex == -1)
|
||||
return S_FALSE;
|
||||
Stream = Vols.Streams[Vols.EndVolIndex].Stream;
|
||||
Stream = Vols.Streams[(unsigned)Vols.EndVolIndex].Stream;
|
||||
if (!Vols.StartIsZip)
|
||||
checkOffsetMode = false;
|
||||
}
|
||||
@@ -1827,7 +1881,7 @@ HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
const UInt64 base = (IsMultiVol ? 0 : ArcInfo.Base);
|
||||
const UInt64 base = (IsMultiVol ? 0 : (UInt64)ArcInfo.Base);
|
||||
res = TryReadCd(items, cdInfo, base + cdOffset, cdSize);
|
||||
|
||||
if (res == S_FALSE && !IsMultiVol && base != ArcInfo.MarkerPos)
|
||||
@@ -1835,9 +1889,11 @@ HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64
|
||||
// do we need that additional attempt to read cd?
|
||||
res = TryReadCd(items, cdInfo, ArcInfo.MarkerPos + cdOffset, cdSize);
|
||||
if (res == S_OK)
|
||||
ArcInfo.Base = ArcInfo.MarkerPos;
|
||||
ArcInfo.Base = (Int64)ArcInfo.MarkerPos;
|
||||
}
|
||||
|
||||
// Some rare case files are unsorted
|
||||
// items.Sort(CompareCdItems, NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1849,14 +1905,14 @@ static int FindItem(const CObjectVector<CItemEx> &items, const CItemEx &item)
|
||||
{
|
||||
if (left >= right)
|
||||
return -1;
|
||||
unsigned index = (left + right) / 2;
|
||||
const unsigned index = (left + right) / 2;
|
||||
const CItemEx &item2 = items[index];
|
||||
if (item.Disk < item2.Disk)
|
||||
right = index;
|
||||
else if (item.Disk > item2.Disk)
|
||||
left = index + 1;
|
||||
else if (item.LocalHeaderPos == item2.LocalHeaderPos)
|
||||
return index;
|
||||
return (int)index;
|
||||
else if (item.LocalHeaderPos < item2.LocalHeaderPos)
|
||||
right = index;
|
||||
else
|
||||
@@ -1921,7 +1977,7 @@ HRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items)
|
||||
|
||||
item.LocalHeaderPos = GetVirtStreamPos() - 4;
|
||||
if (!IsMultiVol)
|
||||
item.LocalHeaderPos -= ArcInfo.Base;
|
||||
item.LocalHeaderPos = (UInt64)((Int64)item.LocalHeaderPos - ArcInfo.Base);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -1950,7 +2006,7 @@ HRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items)
|
||||
}
|
||||
catch (CUnexpectEnd &)
|
||||
{
|
||||
if (items.IsEmpty() || items.Size() == 1 && IsStrangeItem(items[0]))
|
||||
if (items.IsEmpty() || (items.Size() == 1 && IsStrangeItem(items[0])))
|
||||
return S_FALSE;
|
||||
throw;
|
||||
}
|
||||
@@ -1986,11 +2042,11 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
|
||||
name = prop.bstrVal;
|
||||
}
|
||||
|
||||
int dotPos = name.ReverseFind_Dot();
|
||||
const int dotPos = name.ReverseFind_Dot();
|
||||
if (dotPos < 0)
|
||||
return S_OK;
|
||||
const UString ext = name.Ptr(dotPos + 1);
|
||||
name.DeleteFrom(dotPos + 1);
|
||||
const UString ext = name.Ptr((unsigned)(dotPos + 1));
|
||||
name.DeleteFrom((unsigned)(dotPos + 1));
|
||||
|
||||
StartVolIndex = (Int32)(-1);
|
||||
|
||||
@@ -2047,7 +2103,7 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
|
||||
UInt32 volNum = ConvertStringToUInt32(ext.Ptr(1), &end);
|
||||
if (*end != 0 || volNum < 1 || volNum > ((UInt32)1 << 30))
|
||||
return S_OK;
|
||||
StartVolIndex = volNum - 1;
|
||||
StartVolIndex = (Int32)(volNum - 1);
|
||||
BaseName = name;
|
||||
StartIsZ = true;
|
||||
}
|
||||
@@ -2147,7 +2203,7 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback,
|
||||
UInt64 pos;
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &pos));
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &size));
|
||||
RINOK(stream->Seek(pos, STREAM_SEEK_SET, NULL));
|
||||
RINOK(stream->Seek((Int64)pos, STREAM_SEEK_SET, NULL));
|
||||
|
||||
while (i >= Vols.Streams.Size())
|
||||
Vols.Streams.AddNew();
|
||||
@@ -2161,7 +2217,7 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback,
|
||||
|
||||
if ((int)i == zipDisk)
|
||||
{
|
||||
Vols.EndVolIndex = Vols.Streams.Size() - 1;
|
||||
Vols.EndVolIndex = (int)(Vols.Streams.Size() - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2211,7 +2267,7 @@ HRESULT CInArchive::ReadVols()
|
||||
CCdInfo &ecd = Vols.ecd;
|
||||
if (res == S_OK)
|
||||
{
|
||||
zipDisk = ecd.ThisDisk;
|
||||
zipDisk = (int)ecd.ThisDisk;
|
||||
Vols.ecd_wasRead = true;
|
||||
|
||||
// if is not multivol or bad multivol, we return to main single stream code
|
||||
@@ -2220,9 +2276,9 @@ HRESULT CInArchive::ReadVols()
|
||||
|| ecd.ThisDisk < ecd.CdDisk)
|
||||
return S_OK;
|
||||
|
||||
cdDisk = ecd.CdDisk;
|
||||
cdDisk = (int)ecd.CdDisk;
|
||||
if (Vols.StartVolIndex < 0)
|
||||
Vols.StartVolIndex = ecd.ThisDisk;
|
||||
Vols.StartVolIndex = (Int32)ecd.ThisDisk;
|
||||
else if ((UInt32)Vols.StartVolIndex >= ecd.ThisDisk)
|
||||
return S_OK;
|
||||
|
||||
@@ -2232,7 +2288,7 @@ HRESULT CInArchive::ReadVols()
|
||||
if (cdDisk != zipDisk)
|
||||
{
|
||||
// get volumes required for cd.
|
||||
RINOK(ReadVols2(volCallback, cdDisk, zipDisk, zipDisk, 0, numMissingVols));
|
||||
RINOK(ReadVols2(volCallback, (unsigned)cdDisk, zipDisk, zipDisk, 0, numMissingVols));
|
||||
if (numMissingVols != 0)
|
||||
{
|
||||
// cdOK = false;
|
||||
@@ -2269,10 +2325,10 @@ HRESULT CInArchive::ReadVols()
|
||||
if (Vols.StartVolIndex > (1 << 20))
|
||||
return S_OK;
|
||||
if ((unsigned)Vols.StartVolIndex >= Vols.Streams.Size()
|
||||
|| !Vols.Streams[Vols.StartVolIndex].Stream)
|
||||
|| !Vols.Streams[(unsigned)Vols.StartVolIndex].Stream)
|
||||
{
|
||||
// we get volumes starting from StartVolIndex, if they we not requested before know the volume index (if FindCd() was ok)
|
||||
RINOK(ReadVols2(volCallback, Vols.StartVolIndex, zipDisk, zipDisk, 0, numMissingVols));
|
||||
RINOK(ReadVols2(volCallback, (unsigned)Vols.StartVolIndex, zipDisk, zipDisk, 0, numMissingVols));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2285,7 +2341,7 @@ HRESULT CInArchive::ReadVols()
|
||||
if (zipDisk >= 0)
|
||||
{
|
||||
// we create item in Streams for ZipStream, if we know the volume index (if FindCd() was ok)
|
||||
RINOK(ReadVols2(volCallback, zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols));
|
||||
RINOK(ReadVols2(volCallback, (unsigned)zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2331,7 +2387,7 @@ HRESULT CVols::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
return S_OK;
|
||||
if ((unsigned)StreamIndex >= Streams.Size())
|
||||
return S_OK;
|
||||
const CVols::CSubStreamInfo &s = Streams[StreamIndex];
|
||||
const CVols::CSubStreamInfo &s = Streams[(unsigned)StreamIndex];
|
||||
if (!s.Stream)
|
||||
return S_FALSE;
|
||||
if (NeedSeek)
|
||||
@@ -2473,7 +2529,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
if (!ecd.IsEmptyArc())
|
||||
return S_FALSE;
|
||||
|
||||
ArcInfo.Base = ArcInfo.MarkerPos;
|
||||
ArcInfo.Base = (Int64)ArcInfo.MarkerPos;
|
||||
IsArc = true; // check it: we need more tests?
|
||||
|
||||
RINOK(SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2));
|
||||
@@ -2514,16 +2570,44 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
res = S_FALSE;
|
||||
else
|
||||
{
|
||||
firstItem.LocalHeaderPos = ArcInfo.MarkerPos2 - ArcInfo.Base;
|
||||
int index = FindItem(items, firstItem);
|
||||
firstItem.LocalHeaderPos = (UInt64)((Int64)ArcInfo.MarkerPos2 - ArcInfo.Base);
|
||||
int index = -1;
|
||||
|
||||
UInt32 min_Disk = (UInt32)(Int32)-1;
|
||||
UInt64 min_LocalHeaderPos = (UInt64)(Int64)-1;
|
||||
|
||||
if (!IsCdUnsorted)
|
||||
index = FindItem(items, firstItem);
|
||||
else
|
||||
{
|
||||
FOR_VECTOR (i, items)
|
||||
{
|
||||
const CItemEx &cdItem = items[i];
|
||||
if (cdItem.Disk == firstItem.Disk
|
||||
&& (cdItem.LocalHeaderPos == firstItem.LocalHeaderPos))
|
||||
index = (int)i;
|
||||
|
||||
if (i == 0
|
||||
|| cdItem.Disk < min_Disk
|
||||
|| (cdItem.Disk == min_Disk && cdItem.LocalHeaderPos < min_LocalHeaderPos))
|
||||
{
|
||||
min_Disk = cdItem.Disk;
|
||||
min_LocalHeaderPos = cdItem.LocalHeaderPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1)
|
||||
res = S_FALSE;
|
||||
else if (!AreItemsEqual(firstItem, items[index]))
|
||||
else if (!AreItemsEqual(firstItem, items[(unsigned)index]))
|
||||
res = S_FALSE;
|
||||
else
|
||||
{
|
||||
ArcInfo.CdWasRead = true;
|
||||
ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos;
|
||||
if (IsCdUnsorted)
|
||||
ArcInfo.FirstItemRelatOffset = min_LocalHeaderPos;
|
||||
else
|
||||
ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos;
|
||||
|
||||
// ArcInfo.FirstItemRelatOffset = _startLocalFromCd_Offset;
|
||||
}
|
||||
@@ -2588,7 +2672,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
The (Base) can be corrected later after ECD reading.
|
||||
But sfx volume with stub and (No)Span-marker in (!IsMultiVol) mode will have incorrect (Base) here.
|
||||
*/
|
||||
ArcInfo.Base = ArcInfo.MarkerPos2;
|
||||
ArcInfo.Base = (Int64)ArcInfo.MarkerPos2;
|
||||
}
|
||||
|
||||
RINOK(SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2));
|
||||
@@ -2607,15 +2691,42 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
// GetVirtStreamPos() - 4
|
||||
if (items.IsEmpty())
|
||||
return S_FALSE;
|
||||
NoCentralDir = true;
|
||||
HeadersError = true;
|
||||
return S_OK;
|
||||
|
||||
bool isError = true;
|
||||
|
||||
const UInt32 apkSize = _signature;
|
||||
const unsigned kApkFooterSize = 16 + 8;
|
||||
if (apkSize >= kApkFooterSize && apkSize <= (1 << 20))
|
||||
{
|
||||
if (ReadUInt32() == 0)
|
||||
{
|
||||
CByteBuffer apk;
|
||||
apk.Alloc(apkSize);
|
||||
SafeRead(apk, apkSize);
|
||||
ReadSignature();
|
||||
const Byte *footer = apk + apkSize - kApkFooterSize;
|
||||
if (_signature == NSignature::kCentralFileHeader)
|
||||
if (GetUi64(footer) == apkSize)
|
||||
if (memcmp(footer + 8, "APK Sig Block 42", 16) == 0)
|
||||
{
|
||||
isError = false;
|
||||
IsApk = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isError)
|
||||
{
|
||||
NoCentralDir = true;
|
||||
HeadersError = true;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
_inBufMode = true;
|
||||
|
||||
cdAbsOffset = GetVirtStreamPos() - 4;
|
||||
cdDisk = Vols.StreamIndex;
|
||||
cdDisk = (UInt32)Vols.StreamIndex;
|
||||
|
||||
#ifdef ZIP_SELF_CHECK
|
||||
if (!IsMultiVol && _cnt != GetVirtStreamPos() - ArcInfo.MarkerPos2)
|
||||
@@ -2656,7 +2767,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
|
||||
needSetBase = true;
|
||||
numCdItems = cdItems.Size();
|
||||
cdRelatOffset = cdAbsOffset - ArcInfo.Base;
|
||||
cdRelatOffset = (UInt64)((Int64)cdAbsOffset - ArcInfo.Base);
|
||||
|
||||
if (!cdItems.IsEmpty())
|
||||
{
|
||||
@@ -2712,6 +2823,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
Byte buf[kBufSize];
|
||||
SafeRead(buf, kBufSize);
|
||||
locator.Parse(buf);
|
||||
// we ignore the error, where some zip creators use (NumDisks == 0)
|
||||
// if (locator.NumDisks == 0) HeadersWarning = true;
|
||||
}
|
||||
|
||||
ReadSignature();
|
||||
@@ -2764,12 +2877,12 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
|
||||
if (IsMultiVol)
|
||||
{
|
||||
if (cdDisk != (int)cdInfo.CdDisk)
|
||||
if (cdDisk != cdInfo.CdDisk)
|
||||
HeadersError = true;
|
||||
}
|
||||
else if (needSetBase && cdOK)
|
||||
{
|
||||
const UInt64 oldBase = ArcInfo.Base;
|
||||
const UInt64 oldBase = (UInt64)ArcInfo.Base;
|
||||
// localsWereRead == true
|
||||
// ArcInfo.Base == ArcInfo.MarkerPos2
|
||||
// cdRelatOffset == (cdAbsOffset - ArcInfo.Base)
|
||||
@@ -2778,13 +2891,13 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
{
|
||||
if (ecd64Disk == Vols.StartVolIndex)
|
||||
{
|
||||
const Int64 newBase = (Int64)ecd64AbsOffset - locator.Ecd64Offset;
|
||||
const Int64 newBase = (Int64)ecd64AbsOffset - (Int64)locator.Ecd64Offset;
|
||||
if (newBase <= (Int64)ecd64AbsOffset)
|
||||
{
|
||||
if (!localsWereRead || newBase <= (Int64)ArcInfo.MarkerPos2)
|
||||
{
|
||||
ArcInfo.Base = newBase;
|
||||
cdRelatOffset = cdAbsOffset - newBase;
|
||||
cdRelatOffset = (UInt64)((Int64)cdAbsOffset - newBase);
|
||||
}
|
||||
else
|
||||
cdOK = false;
|
||||
@@ -2795,7 +2908,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
{
|
||||
if ((int)cdDisk == Vols.StartVolIndex)
|
||||
{
|
||||
const Int64 newBase = (Int64)cdAbsOffset - cdInfo.Offset;
|
||||
const Int64 newBase = (Int64)cdAbsOffset - (Int64)cdInfo.Offset;
|
||||
if (newBase <= (Int64)cdAbsOffset)
|
||||
{
|
||||
if (!localsWereRead || newBase <= (Int64)ArcInfo.MarkerPos2)
|
||||
@@ -2828,7 +2941,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
|
||||
if (localsWereRead)
|
||||
{
|
||||
const UInt64 delta = oldBase - ArcInfo.Base;
|
||||
const UInt64 delta = (UInt64)((Int64)oldBase - ArcInfo.Base);
|
||||
if (delta != 0)
|
||||
{
|
||||
FOR_VECTOR (i, items)
|
||||
@@ -2864,7 +2977,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
|
||||
if (isZip64)
|
||||
{
|
||||
if (cdInfo.ThisDisk == 0 && ecd64AbsOffset != ArcInfo.Base + locator.Ecd64Offset
|
||||
if ((cdInfo.ThisDisk == 0 && ecd64AbsOffset != (UInt64)(ArcInfo.Base + (Int64)locator.Ecd64Offset))
|
||||
// || cdInfo.NumEntries_in_ThisDisk != numCdItems
|
||||
|| cdInfo.NumEntries != numCdItems
|
||||
|| cdInfo.Size != cdSize
|
||||
@@ -2902,10 +3015,10 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
{
|
||||
if ((unsigned)nextLocalIndex < items.Size())
|
||||
{
|
||||
CItemEx &item = items[nextLocalIndex];
|
||||
CItemEx &item = items[(unsigned)nextLocalIndex];
|
||||
if (item.Disk == cdItem.Disk &&
|
||||
(item.LocalHeaderPos == cdItem.LocalHeaderPos
|
||||
|| Overflow32bit && (UInt32)item.LocalHeaderPos == cdItem.LocalHeaderPos))
|
||||
|| (Overflow32bit && (UInt32)item.LocalHeaderPos == cdItem.LocalHeaderPos)))
|
||||
index = nextLocalIndex++;
|
||||
else
|
||||
nextLocalIndex = -1;
|
||||
@@ -2924,7 +3037,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
continue;
|
||||
}
|
||||
|
||||
CItemEx &item = items[index];
|
||||
CItemEx &item = items[(unsigned)index];
|
||||
if (item.Name != cdItem.Name
|
||||
// || item.Name.Len() != cdItem.Name.Len()
|
||||
|| item.PackSize != cdItem.PackSize
|
||||
@@ -2965,7 +3078,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
|
||||
if (isZip64)
|
||||
{
|
||||
if (cdInfo.NumEntries != items.Size()
|
||||
|| ecd.NumEntries != items.Size() && ecd.NumEntries != 0xFFFF)
|
||||
|| (ecd.NumEntries != items.Size() && ecd.NumEntries != 0xFFFF))
|
||||
HeadersError = true;
|
||||
}
|
||||
else
|
||||
@@ -3069,7 +3182,9 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit,
|
||||
else
|
||||
{
|
||||
// printf("\nOpen offset = %u\n", (unsigned)startPos);
|
||||
if (IsMultiVol && (unsigned)Vols.StartParsingVol < Vols.Streams.Size() && Vols.Streams[Vols.StartParsingVol].Stream)
|
||||
if (IsMultiVol
|
||||
&& (unsigned)Vols.StartParsingVol < Vols.Streams.Size()
|
||||
&& Vols.Streams[(unsigned)Vols.StartParsingVol].Stream)
|
||||
{
|
||||
RINOK(SeekToVol(Vols.StartParsingVol, Vols.StreamIndex == Vols.StartVolIndex ? startPos : 0));
|
||||
}
|
||||
@@ -3117,7 +3232,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit,
|
||||
{
|
||||
if ((unsigned)Vols.StartVolIndex < Vols.Streams.Size())
|
||||
{
|
||||
Stream = Vols.Streams[Vols.StartVolIndex].Stream;
|
||||
Stream = Vols.Streams[(unsigned)Vols.StartVolIndex].Stream;
|
||||
if (Stream)
|
||||
{
|
||||
RINOK(Seek_SavePos(curPos));
|
||||
@@ -3173,7 +3288,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit,
|
||||
{
|
||||
ArcInfo.FinishPos = ArcInfo.FileEndPos;
|
||||
if ((unsigned)Vols.StreamIndex < Vols.Streams.Size())
|
||||
if (GetVirtStreamPos() < Vols.Streams[Vols.StreamIndex].Size)
|
||||
if (GetVirtStreamPos() < Vols.Streams[(unsigned)Vols.StreamIndex].Size)
|
||||
ArcInfo.ThereIsTail = true;
|
||||
}
|
||||
else
|
||||
@@ -3204,8 +3319,8 @@ HRESULT CInArchive::GetItemStream(const CItemEx &item, bool seekPackData, CMyCom
|
||||
{
|
||||
if (UseDisk_in_SingleVol && item.Disk != EcdVolIndex)
|
||||
return S_OK;
|
||||
pos += ArcInfo.Base;
|
||||
RINOK(StreamRef->Seek(pos, STREAM_SEEK_SET, NULL));
|
||||
pos = (UInt64)((Int64)pos + ArcInfo.Base);
|
||||
RINOK(StreamRef->Seek((Int64)pos, STREAM_SEEK_SET, NULL));
|
||||
stream = StreamRef;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -3216,10 +3331,10 @@ HRESULT CInArchive::GetItemStream(const CItemEx &item, bool seekPackData, CMyCom
|
||||
IInStream *str2 = Vols.Streams[item.Disk].Stream;
|
||||
if (!str2)
|
||||
return S_OK;
|
||||
RINOK(str2->Seek(pos, STREAM_SEEK_SET, NULL));
|
||||
RINOK(str2->Seek((Int64)pos, STREAM_SEEK_SET, NULL));
|
||||
|
||||
Vols.NeedSeek = false;
|
||||
Vols.StreamIndex = item.Disk;
|
||||
Vols.StreamIndex = (int)item.Disk;
|
||||
|
||||
CVolStream *volsStreamSpec = new CVolStream;
|
||||
volsStreamSpec->Vols = &Vols;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user