ZipHandler.cpp (p7zip_15.14.1_src_all) | : | ZipHandler.cpp (p7zip_16.02_src_all) | ||
---|---|---|---|---|
skipping to change at line 15 | skipping to change at line 15 | |||
#include "../../../Common/ComTry.h" | #include "../../../Common/ComTry.h" | |||
#include "../../../Common/IntToString.h" | #include "../../../Common/IntToString.h" | |||
#include "../../../Common/StringConvert.h" | #include "../../../Common/StringConvert.h" | |||
#include "../../../Windows/PropVariant.h" | #include "../../../Windows/PropVariant.h" | |||
#include "../../../Windows/TimeUtils.h" | #include "../../../Windows/TimeUtils.h" | |||
#include "../../IPassword.h" | #include "../../IPassword.h" | |||
#include "../../Common/FilterCoder.h" | #include "../../Common/FilterCoder.h" | |||
#include "../../Common/LimitedStreams.h" | ||||
#include "../../Common/ProgressUtils.h" | #include "../../Common/ProgressUtils.h" | |||
#include "../../Common/StreamObjects.h" | #include "../../Common/StreamObjects.h" | |||
#include "../../Common/StreamUtils.h" | #include "../../Common/StreamUtils.h" | |||
#include "../../Compress/CopyCoder.h" | #include "../../Compress/CopyCoder.h" | |||
#include "../../Compress/LzmaDecoder.h" | #include "../../Compress/LzmaDecoder.h" | |||
#include "../../Compress/ImplodeDecoder.h" | #include "../../Compress/ImplodeDecoder.h" | |||
#include "../../Compress/PpmdZip.h" | #include "../../Compress/PpmdZip.h" | |||
#include "../../Compress/ShrinkDecoder.h" | #include "../../Compress/ShrinkDecoder.h" | |||
skipping to change at line 145 | skipping to change at line 146 | |||
kpidMTime, | kpidMTime, | |||
kpidCTime, | kpidCTime, | |||
kpidATime, | kpidATime, | |||
kpidAttrib, | kpidAttrib, | |||
// kpidPosixAttrib, | // kpidPosixAttrib, | |||
kpidEncrypted, | kpidEncrypted, | |||
kpidComment, | kpidComment, | |||
kpidCRC, | kpidCRC, | |||
kpidMethod, | kpidMethod, | |||
kpidHostOS, | kpidHostOS, | |||
kpidUnpackVer | kpidUnpackVer, | |||
kpidVolumeIndex | ||||
}; | }; | |||
static const Byte kArcProps[] = | static const Byte kArcProps[] = | |||
{ | { | |||
kpidEmbeddedStubSize, | kpidEmbeddedStubSize, | |||
kpidBit64, | kpidBit64, | |||
kpidComment | kpidComment, | |||
kpidTotalPhySize, | ||||
kpidIsVolume, | ||||
kpidVolumeIndex, | ||||
kpidNumVolumes | ||||
}; | }; | |||
CHandler::CHandler() | CHandler::CHandler() | |||
{ | { | |||
InitMethodProps(); | InitMethodProps(); | |||
} | } | |||
static AString BytesToString(const CByteBuffer &data) | static AString BytesToString(const CByteBuffer &data) | |||
{ | { | |||
AString s; | AString s; | |||
skipping to change at line 178 | skipping to change at line 184 | |||
IMP_IInArchive_ArcProps | IMP_IInArchive_ArcProps | |||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
{ | { | |||
COM_TRY_BEGIN | COM_TRY_BEGIN | |||
NWindows::NCOM::CPropVariant prop; | NWindows::NCOM::CPropVariant prop; | |||
switch (propID) | switch (propID) | |||
{ | { | |||
case kpidBit64: if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break; | case kpidBit64: if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break; | |||
case kpidComment: if (m_Archive.ArcInfo.Comment.Size() != 0) prop = MultiBy teToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break; | case kpidComment: if (m_Archive.ArcInfo.Comment.Size() != 0) prop = MultiBy teToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break; | |||
case kpidPhySize: prop = m_Archive.ArcInfo.GetPhySize(); break; | ||||
case kpidOffset: /* if (m_Archive.ArcInfo.Base != 0) */ | case kpidPhySize: prop = m_Archive.GetPhySize(); break; | |||
prop = m_Archive.ArcInfo.Base; break; | case kpidOffset: prop = m_Archive.GetOffset(); break; | |||
case kpidEmbeddedStubSize: | case kpidEmbeddedStubSize: | |||
{ | { | |||
UInt64 stubSize = m_Archive.ArcInfo.GetEmbeddedStubSize(); | UInt64 stubSize = m_Archive.GetEmbeddedStubSize(); | |||
if (stubSize != 0) | if (stubSize != 0) | |||
prop = stubSize; | prop = stubSize; | |||
break; | break; | |||
} | } | |||
case kpidTotalPhySize: if (m_Archive.IsMultiVol) prop = m_Archive.Vols.GetTo | ||||
talSize(); break; | ||||
case kpidVolumeIndex: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vol | ||||
s.StartVolIndex; break; | ||||
case kpidIsVolume: if (m_Archive.IsMultiVol) prop = true; break; | ||||
case kpidNumVolumes: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols | ||||
.Streams.Size(); break; | ||||
case kpidWarningFlags: | case kpidWarningFlags: | |||
{ | { | |||
UInt32 v = 0; | UInt32 v = 0; | |||
// if (m_Archive.ExtraMinorError) v |= kpv_ErrorFlags_HeadersError; | // if (m_Archive.ExtraMinorError) v |= kpv_ErrorFlags_HeadersError; | |||
if (m_Archive.HeadersWarning) v |= kpv_ErrorFlags_HeadersError; | if (m_Archive.HeadersWarning) v |= kpv_ErrorFlags_HeadersError; | |||
if (v != 0) | if (v != 0) | |||
prop = v; | prop = v; | |||
break; | break; | |||
} | } | |||
case kpidError: | ||||
{ | ||||
if (!m_Archive.Vols.MissingName.IsEmpty()) | ||||
{ | ||||
UString s; | ||||
s.SetFromAscii("Missing volume : "); | ||||
s += m_Archive.Vols.MissingName; | ||||
prop = s; | ||||
} | ||||
break; | ||||
} | ||||
case kpidErrorFlags: | case kpidErrorFlags: | |||
{ | { | |||
UInt32 v = 0; | UInt32 v = 0; | |||
if (!m_Archive.IsArc) v |= kpv_ErrorFlags_IsNotArc; | if (!m_Archive.IsArc) v |= kpv_ErrorFlags_IsNotArc; | |||
if (m_Archive.HeadersError) v |= kpv_ErrorFlags_HeadersError; | if (m_Archive.HeadersError) v |= kpv_ErrorFlags_HeadersError; | |||
if (m_Archive.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; | if (m_Archive.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; | |||
if (m_Archive.ArcInfo.Base < 0) | if (m_Archive.ArcInfo.Base < 0) | |||
{ | { | |||
/* We try to support case when we have sfx-zip with embedded stub, | /* We try to support case when we have sfx-zip with embedded stub, | |||
but the stream has access only to zip part. | but the stream has access only to zip part. | |||
In that case we ignore UnavailableStart error. | In that case we ignore UnavailableStart error. | |||
maybe we must show warning in that case. */ | maybe we must show warning in that case. */ | |||
UInt64 stubSize = m_Archive.ArcInfo.GetEmbeddedStubSize(); | UInt64 stubSize = m_Archive.GetEmbeddedStubSize(); | |||
if (stubSize < (UInt64)-m_Archive.ArcInfo.Base) | if (stubSize < (UInt64)-m_Archive.ArcInfo.Base) | |||
v |= kpv_ErrorFlags_UnavailableStart; | v |= kpv_ErrorFlags_UnavailableStart; | |||
} | } | |||
if (m_Archive.NoCentralDir) v |= kpv_ErrorFlags_UnconfirmedStart; | if (m_Archive.NoCentralDir) v |= kpv_ErrorFlags_UnconfirmedStart; | |||
prop = v; | prop = v; | |||
break; | break; | |||
} | } | |||
case kpidReadOnly: | case kpidReadOnly: | |||
{ | { | |||
skipping to change at line 432 | skipping to change at line 455 | |||
ConvertUInt32ToString(hostOS, temp); | ConvertUInt32ToString(hostOS, temp); | |||
s = temp; | s = temp; | |||
} | } | |||
prop = s; | prop = s; | |||
break; | break; | |||
} | } | |||
case kpidUnpackVer: | case kpidUnpackVer: | |||
prop = (UInt32)item.ExtractVersion.Version; | prop = (UInt32)item.ExtractVersion.Version; | |||
break; | break; | |||
case kpidVolumeIndex: | ||||
prop = item.Disk; | ||||
break; | ||||
} | } | |||
prop.Detach(value); | prop.Detach(value); | |||
return S_OK; | return S_OK; | |||
COM_TRY_END | COM_TRY_END | |||
} | } | |||
class CProgressImp: public CProgressVirt | ||||
{ | ||||
CMyComPtr<IArchiveOpenCallback> _callback; | ||||
public: | ||||
virtual HRESULT SetCompletedLocal(UInt64 numFiles, UInt64 numBytes); | ||||
virtual HRESULT SetTotalCD(UInt64 numFiles); | ||||
virtual HRESULT SetCompletedCD(UInt64 numFiles); | ||||
CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {} | ||||
}; | ||||
HRESULT CProgressImp::SetCompletedLocal(UInt64 numFiles, UInt64 numBytes) | ||||
{ | ||||
return _callback->SetCompleted(&numFiles, &numBytes); | ||||
} | ||||
HRESULT CProgressImp::SetTotalCD(UInt64 numFiles) | ||||
{ | ||||
return _callback->SetTotal(&numFiles, NULL); | ||||
} | ||||
HRESULT CProgressImp::SetCompletedCD(UInt64 numFiles) | ||||
{ | ||||
return _callback->SetCompleted(&numFiles, NULL); | ||||
} | ||||
STDMETHODIMP CHandler::Open(IInStream *inStream, | STDMETHODIMP CHandler::Open(IInStream *inStream, | |||
const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) | const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback) | |||
{ | { | |||
COM_TRY_BEGIN | COM_TRY_BEGIN | |||
try | try | |||
{ | { | |||
Close(); | Close(); | |||
RINOK(m_Archive.Open(inStream, maxCheckStartPosition)); | HRESULT res = m_Archive.Open(inStream, maxCheckStartPosition, callback, m_It | |||
CProgressImp progressImp(callback); | ems); | |||
return m_Archive.ReadHeaders(m_Items, callback ? &progressImp : NULL); | if (res != S_OK) | |||
{ | ||||
m_Items.Clear(); | ||||
m_Archive.ClearRefs(); | ||||
} | ||||
return res; | ||||
} | } | |||
catch(...) { Close(); throw; } | catch(...) { Close(); throw; } | |||
COM_TRY_END | COM_TRY_END | |||
} | } | |||
STDMETHODIMP CHandler::Close() | STDMETHODIMP CHandler::Close() | |||
{ | { | |||
m_Items.Clear(); | m_Items.Clear(); | |||
m_Archive.Close(); | m_Archive.Close(); | |||
return S_OK; | return S_OK; | |||
} | } | |||
////////////////////////////////////// | ||||
// CHandler::DecompressItems | ||||
class CLzmaDecoder: | class CLzmaDecoder: | |||
public ICompressCoder, | public ICompressCoder, | |||
public CMyUnknownImp | public CMyUnknownImp | |||
{ | { | |||
NCompress::NLzma::CDecoder *DecoderSpec; | NCompress::NLzma::CDecoder *DecoderSpec; | |||
CMyComPtr<ICompressCoder> Decoder; | CMyComPtr<ICompressCoder> Decoder; | |||
public: | public: | |||
CLzmaDecoder(); | CLzmaDecoder(); | |||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream , | STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream , | |||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progre ss); | const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progre ss); | |||
skipping to change at line 585 | skipping to change at line 588 | |||
CInArchive &archive, const CItemEx &item, | CInArchive &archive, const CItemEx &item, | |||
ISequentialOutStream *realOutStream, | ISequentialOutStream *realOutStream, | |||
IArchiveExtractCallback *extractCallback, | IArchiveExtractCallback *extractCallback, | |||
ICompressProgressInfo *compressProgress, | ICompressProgressInfo *compressProgress, | |||
#ifndef _7ZIP_ST | #ifndef _7ZIP_ST | |||
UInt32 numThreads, | UInt32 numThreads, | |||
#endif | #endif | |||
Int32 &res); | Int32 &res); | |||
}; | }; | |||
static HRESULT SkipStreamData(ISequentialInStream *stream, UInt64 size) | ||||
{ | ||||
const size_t kBufSize = 1 << 12; | ||||
Byte buf[kBufSize]; | ||||
for (;;) | ||||
{ | ||||
if (size == 0) | ||||
return S_OK; | ||||
size_t curSize = kBufSize; | ||||
if (curSize > size) | ||||
curSize = (size_t)size; | ||||
RINOK(ReadStream_FALSE(stream, buf, curSize)); | ||||
size -= curSize; | ||||
} | ||||
} | ||||
HRESULT CZipDecoder::Decode( | HRESULT CZipDecoder::Decode( | |||
DECL_EXTERNAL_CODECS_LOC_VARS | DECL_EXTERNAL_CODECS_LOC_VARS | |||
CInArchive &archive, const CItemEx &item, | CInArchive &archive, const CItemEx &item, | |||
ISequentialOutStream *realOutStream, | ISequentialOutStream *realOutStream, | |||
IArchiveExtractCallback *extractCallback, | IArchiveExtractCallback *extractCallback, | |||
ICompressProgressInfo *compressProgress, | ICompressProgressInfo *compressProgress, | |||
#ifndef _7ZIP_ST | #ifndef _7ZIP_ST | |||
UInt32 numThreads, | UInt32 numThreads, | |||
#endif | #endif | |||
Int32 &res) | Int32 &res) | |||
skipping to change at line 635 | skipping to change at line 654 | |||
needCRC = aesField.NeedCrc(); | needCRC = aesField.NeedCrc(); | |||
} | } | |||
} | } | |||
} | } | |||
COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; | COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; | |||
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; | CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; | |||
outStreamSpec->SetStream(realOutStream); | outStreamSpec->SetStream(realOutStream); | |||
outStreamSpec->Init(needCRC); | outStreamSpec->Init(needCRC); | |||
UInt64 authenticationPos; | CMyComPtr<ISequentialInStream> packStream; | |||
CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream | ||||
; | ||||
CMyComPtr<ISequentialInStream> inStream(limitedStreamSpec); | ||||
CMyComPtr<ISequentialInStream> inStream; | ||||
{ | { | |||
UInt64 packSize = item.PackSize; | UInt64 packSize = item.PackSize; | |||
if (wzAesMode) | if (wzAesMode) | |||
{ | { | |||
if (packSize < NCrypto::NWzAes::kMacSize) | if (packSize < NCrypto::NWzAes::kMacSize) | |||
return S_OK; | return S_OK; | |||
packSize -= NCrypto::NWzAes::kMacSize; | packSize -= NCrypto::NWzAes::kMacSize; | |||
} | } | |||
UInt64 dataPos = item.GetDataPosition(); | RINOK(archive.GetItemStream(item, true, packStream)); | |||
inStream.Attach(archive.CreateLimitedStream(dataPos, packSize)); | if (!packStream) | |||
authenticationPos = dataPos + packSize; | { | |||
res = NExtract::NOperationResult::kUnavailable; | ||||
return S_OK; | ||||
} | ||||
limitedStreamSpec->SetStream(packStream); | ||||
limitedStreamSpec->Init(packSize); | ||||
} | } | |||
CMyComPtr<ICompressFilter> cryptoFilter; | CMyComPtr<ICompressFilter> cryptoFilter; | |||
if (item.IsEncrypted()) | if (item.IsEncrypted()) | |||
{ | { | |||
if (wzAesMode) | if (wzAesMode) | |||
{ | { | |||
CWzAesExtra aesField; | CWzAesExtra aesField; | |||
if (!item.GetMainExtra().GetWzAes(aesField)) | if (!item.GetMainExtra().GetWzAes(aesField)) | |||
skipping to change at line 913 | skipping to change at line 939 | |||
return S_OK; | return S_OK; | |||
} | } | |||
RINOK(result); | RINOK(result); | |||
} | } | |||
bool crcOK = true; | bool crcOK = true; | |||
bool authOk = true; | bool authOk = true; | |||
if (needCRC) | if (needCRC) | |||
crcOK = (outStreamSpec->GetCRC() == item.Crc); | crcOK = (outStreamSpec->GetCRC() == item.Crc); | |||
if (wzAesMode) | if (wzAesMode) | |||
{ | { | |||
inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzA | const UInt64 rem = limitedStreamSpec->GetRem(); | |||
es::kMacSize)); | if (rem != 0) | |||
if (SkipStreamData(inStream, rem) != S_OK) | ||||
authOk = false; | ||||
limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize); | ||||
if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK) | if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK) | |||
authOk = false; | authOk = false; | |||
} | } | |||
res = ((crcOK && authOk) ? | res = ((crcOK && authOk) ? | |||
NExtract::NOperationResult::kOK : | NExtract::NOperationResult::kOK : | |||
NExtract::NOperationResult::kCRCError); | NExtract::NOperationResult::kCRCError); | |||
return S_OK; | return S_OK; | |||
} | } | |||
skipping to change at line 988 | skipping to change at line 1020 | |||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); | |||
if (!isLocalOffsetOK) | if (!isLocalOffsetOK) | |||
{ | { | |||
RINOK(extractCallback->PrepareOperation(askMode)); | RINOK(extractCallback->PrepareOperation(askMode)); | |||
realOutStream.Release(); | realOutStream.Release(); | |||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUna vailable)); | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUna vailable)); | |||
continue; | continue; | |||
} | } | |||
if (!item.FromLocal) | if (!item.FromLocal) | |||
{ | { | |||
HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item); | bool isAvail = true; | |||
HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item, isAvail); | ||||
if (res == S_FALSE) | if (res == S_FALSE) | |||
{ | { | |||
if (item.IsDir() || realOutStream || testMode) | if (item.IsDir() || realOutStream || testMode) | |||
{ | { | |||
RINOK(extractCallback->PrepareOperation(askMode)); | RINOK(extractCallback->PrepareOperation(askMode)); | |||
realOutStream.Release(); | realOutStream.Release(); | |||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult:: | RINOK(extractCallback->SetOperationResult( | |||
kHeadersError)); | isAvail ? | |||
NExtract::NOperationResult::kHeadersError : | ||||
NExtract::NOperationResult::kUnavailable)); | ||||
} | } | |||
continue; | continue; | |||
} | } | |||
RINOK(res); | RINOK(res); | |||
} | } | |||
if (item.IsDir()) | if (item.IsDir()) | |||
{ | { | |||
// if (!testMode) | // if (!testMode) | |||
{ | { | |||
skipping to change at line 1034 | skipping to change at line 1071 | |||
progress, | progress, | |||
#ifndef _7ZIP_ST | #ifndef _7ZIP_ST | |||
_props.NumThreads, | _props.NumThreads, | |||
#endif | #endif | |||
res); | res); | |||
RINOK(hres); | RINOK(hres); | |||
realOutStream.Release(); | realOutStream.Release(); | |||
RINOK(extractCallback->SetOperationResult(res)) | RINOK(extractCallback->SetOperationResult(res)) | |||
} | } | |||
lps->InSize = currentTotalPacked; | lps->InSize = currentTotalPacked; | |||
lps->OutSize = currentTotalUnPacked; | lps->OutSize = currentTotalUnPacked; | |||
return lps->SetCur(); | return lps->SetCur(); | |||
COM_TRY_END | COM_TRY_END | |||
} | } | |||
IMPL_ISetCompressCodecsInfo | IMPL_ISetCompressCodecsInfo | |||
}} | }} | |||
End of changes. 22 change blocks. | ||||
48 lines changed or deleted | 89 lines changed or added |