mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-13 06:11:32 -06:00
16.00
This commit is contained in:
committed by
Kornel Lesiński
parent
c20d013055
commit
66ac98bb02
@@ -12,6 +12,7 @@
|
||||
#include "../../IPassword.h"
|
||||
|
||||
#include "../../Common/FilterCoder.h"
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/StreamObjects.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
@@ -142,14 +143,19 @@ static const Byte kProps[] =
|
||||
kpidCRC,
|
||||
kpidMethod,
|
||||
kpidHostOS,
|
||||
kpidUnpackVer
|
||||
kpidUnpackVer,
|
||||
kpidVolumeIndex
|
||||
};
|
||||
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidEmbeddedStubSize,
|
||||
kpidBit64,
|
||||
kpidComment
|
||||
kpidComment,
|
||||
kpidTotalPhySize,
|
||||
kpidIsVolume,
|
||||
kpidVolumeIndex,
|
||||
kpidNumVolumes
|
||||
};
|
||||
|
||||
CHandler::CHandler()
|
||||
@@ -175,18 +181,23 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
case kpidBit64: if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break;
|
||||
case kpidComment: if (m_Archive.ArcInfo.Comment.Size() != 0) prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break;
|
||||
case kpidPhySize: prop = m_Archive.ArcInfo.GetPhySize(); break;
|
||||
case kpidOffset: /* if (m_Archive.ArcInfo.Base != 0) */
|
||||
prop = m_Archive.ArcInfo.Base; break;
|
||||
|
||||
case kpidPhySize: prop = m_Archive.GetPhySize(); break;
|
||||
case kpidOffset: prop = m_Archive.GetOffset(); break;
|
||||
|
||||
case kpidEmbeddedStubSize:
|
||||
{
|
||||
UInt64 stubSize = m_Archive.ArcInfo.GetEmbeddedStubSize();
|
||||
UInt64 stubSize = m_Archive.GetEmbeddedStubSize();
|
||||
if (stubSize != 0)
|
||||
prop = stubSize;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidTotalPhySize: if (m_Archive.IsMultiVol) prop = m_Archive.Vols.GetTotalSize(); break;
|
||||
case kpidVolumeIndex: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.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:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
@@ -197,6 +208,18 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
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:
|
||||
{
|
||||
UInt32 v = 0;
|
||||
@@ -209,7 +232,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
but the stream has access only to zip part.
|
||||
In that case we ignore UnavailableStart error.
|
||||
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)
|
||||
v |= kpv_ErrorFlags_UnavailableStart;
|
||||
}
|
||||
@@ -429,6 +452,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
case kpidUnpackVer:
|
||||
prop = (UInt32)item.ExtractVersion.Version;
|
||||
break;
|
||||
|
||||
case kpidVolumeIndex:
|
||||
prop = item.Disk;
|
||||
break;
|
||||
}
|
||||
|
||||
prop.Detach(value);
|
||||
@@ -436,30 +463,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
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,
|
||||
const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)
|
||||
@@ -468,9 +471,13 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
try
|
||||
{
|
||||
Close();
|
||||
RINOK(m_Archive.Open(inStream, maxCheckStartPosition));
|
||||
CProgressImp progressImp(callback);
|
||||
return m_Archive.ReadHeaders(m_Items, callback ? &progressImp : NULL);
|
||||
HRESULT res = m_Archive.Open(inStream, maxCheckStartPosition, callback, m_Items);
|
||||
if (res != S_OK)
|
||||
{
|
||||
m_Items.Clear();
|
||||
m_Archive.ClearRefs();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
catch(...) { Close(); throw; }
|
||||
COM_TRY_END
|
||||
@@ -483,8 +490,6 @@ STDMETHODIMP CHandler::Close()
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// CHandler::DecompressItems
|
||||
|
||||
class CLzmaDecoder:
|
||||
public ICompressCoder,
|
||||
@@ -550,6 +555,8 @@ struct CMethodItem
|
||||
CMyComPtr<ICompressCoder> Coder;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CZipDecoder
|
||||
{
|
||||
NCrypto::NZip::CDecoder *_zipCryptoDecoderSpec;
|
||||
@@ -584,6 +591,24 @@ public:
|
||||
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(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CInArchive &archive, const CItemEx &item,
|
||||
@@ -634,9 +659,11 @@ HRESULT CZipDecoder::Decode(
|
||||
outStreamSpec->SetStream(realOutStream);
|
||||
outStreamSpec->Init(needCRC);
|
||||
|
||||
UInt64 authenticationPos;
|
||||
|
||||
CMyComPtr<ISequentialInStream> inStream;
|
||||
CMyComPtr<ISequentialInStream> packStream;
|
||||
|
||||
CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(limitedStreamSpec);
|
||||
|
||||
{
|
||||
UInt64 packSize = item.PackSize;
|
||||
if (wzAesMode)
|
||||
@@ -645,9 +672,14 @@ HRESULT CZipDecoder::Decode(
|
||||
return S_OK;
|
||||
packSize -= NCrypto::NWzAes::kMacSize;
|
||||
}
|
||||
UInt64 dataPos = item.GetDataPosition();
|
||||
inStream.Attach(archive.CreateLimitedStream(dataPos, packSize));
|
||||
authenticationPos = dataPos + packSize;
|
||||
RINOK(archive.GetItemStream(item, true, packStream));
|
||||
if (!packStream)
|
||||
{
|
||||
res = NExtract::NOperationResult::kUnavailable;
|
||||
return S_OK;
|
||||
}
|
||||
limitedStreamSpec->SetStream(packStream);
|
||||
limitedStreamSpec->Init(packSize);
|
||||
}
|
||||
|
||||
CMyComPtr<ICompressFilter> cryptoFilter;
|
||||
@@ -912,9 +944,15 @@ HRESULT CZipDecoder::Decode(
|
||||
bool authOk = true;
|
||||
if (needCRC)
|
||||
crcOK = (outStreamSpec->GetCRC() == item.Crc);
|
||||
|
||||
if (wzAesMode)
|
||||
{
|
||||
inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAes::kMacSize));
|
||||
const UInt64 rem = limitedStreamSpec->GetRem();
|
||||
if (rem != 0)
|
||||
if (SkipStreamData(inStream, rem) != S_OK)
|
||||
authOk = false;
|
||||
|
||||
limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize);
|
||||
if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK)
|
||||
authOk = false;
|
||||
}
|
||||
@@ -988,16 +1026,21 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnavailable));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!item.FromLocal)
|
||||
{
|
||||
HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item);
|
||||
bool isAvail = true;
|
||||
HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item, isAvail);
|
||||
if (res == S_FALSE)
|
||||
{
|
||||
if (item.IsDir() || realOutStream || testMode)
|
||||
{
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kHeadersError));
|
||||
RINOK(extractCallback->SetOperationResult(
|
||||
isAvail ?
|
||||
NExtract::NOperationResult::kHeadersError :
|
||||
NExtract::NOperationResult::kUnavailable));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1034,6 +1077,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
RINOK(extractCallback->SetOperationResult(res))
|
||||
}
|
||||
|
||||
lps->InSize = currentTotalPacked;
|
||||
lps->OutSize = currentTotalUnPacked;
|
||||
return lps->SetCur();
|
||||
|
||||
Reference in New Issue
Block a user