From 051769bbc577aeede90558b6ab5c9be187940ca0 Mon Sep 17 00:00:00 2001 From: Igor Pavlov Date: Mon, 27 Aug 2007 00:00:00 +0000 Subject: 4.53 beta --- CPP/7zip/Archive/Zip/ZipHandler.cpp | 108 +++++++++------------------- CPP/7zip/Archive/Zip/ZipIn.cpp | 4 ++ CPP/7zip/Archive/Zip/ZipItem.h | 2 +- CPP/7zip/Archive/Zip/ZipUpdate.cpp | 139 ++++++++++++++++++++++++++++-------- 4 files changed, 146 insertions(+), 107 deletions(-) (limited to 'CPP/7zip/Archive/Zip') diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index 84269599..c3576eeb 100755 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -74,15 +74,7 @@ static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); static const wchar_t *kUnknownOS = L"Unknown"; - -/* -enum // PropID -{ - kpidUnPackVersion, -}; -*/ - -STATPROPSTG kProperties[] = +STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsFolder, VT_BOOL}, @@ -99,7 +91,7 @@ STATPROPSTG kProperties[] = { NULL, kpidMethod, VT_BSTR}, { NULL, kpidHostOS, VT_BSTR} - // { L"UnPack Version", kpidUnPackVersion, VT_UI1}, + // { NULL, kpidUnpackVer, VT_UI1}, }; const wchar_t *kMethods[] = @@ -147,7 +139,7 @@ CStrongCryptoPair g_StrongCryptoPairs[] = { NStrongCryptoFlags::kRC4, L"RC4" } }; -STATPROPSTG kArcProperties[] = +STATPROPSTG kArcProps[] = { { NULL, kpidComment, VT_BSTR} }; @@ -158,7 +150,7 @@ CHandler::CHandler(): InitMethodProperties(); } -static void StringToProp(const CByteBuffer &data, UINT codePage, NWindows::NCOM::CPropVariant &propVariant) +static void StringToProp(const CByteBuffer &data, UINT codePage, NWindows::NCOM::CPropVariant &prop) { int size = (int)data.GetCapacity(); if (size <= 0) @@ -168,62 +160,29 @@ static void StringToProp(const CByteBuffer &data, UINT codePage, NWindows::NCOM: memcpy(p, (const Byte *)data, size); p[size] = '\0'; s.ReleaseBuffer(); - propVariant = MultiByteToUnicodeString(s, codePage); + prop = MultiByteToUnicodeString(s, codePage); } +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant propVariant; + NWindows::NCOM::CPropVariant prop; switch(propID) { case kpidComment: { - StringToProp(m_Archive.m_ArchiveInfo.Comment, CP_ACP, propVariant); + StringToProp(m_Archive.m_ArchiveInfo.Comment, CP_ACP, prop); break; } } - propVariant.Detach(value); + prop.Detach(value); COM_TRY_END return S_OK; } -STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) -{ - *numProperties = sizeof(kProperties) / sizeof(kProperties[0]); - return S_OK; -} - -STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, - BSTR *name, PROPID *propID, VARTYPE *varType) -{ - if (index >= sizeof(kProperties) / sizeof(kProperties[0])) - return E_INVALIDARG; - const STATPROPSTG &srcItem = kProperties[index]; - *propID = srcItem.propid; - *varType = srcItem.vt; - *name = 0; - return S_OK; -} - -STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) -{ - *numProperties = sizeof(kArcProperties) / sizeof(kArcProperties[0]); - return S_OK; -} - -STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index, - BSTR * name, PROPID * propID, VARTYPE *varType) -{ - if (index >= sizeof(kArcProperties) / sizeof(kArcProperties[0])) - return E_INVALIDARG; - const STATPROPSTG &srcItem = kArcProperties[index]; - *propID = srcItem.propid; - *varType = srcItem.vt; - *name = 0; - return S_OK; -} - STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = m_Items.Size(); @@ -233,22 +192,22 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN - NWindows::NCOM::CPropVariant propVariant; + NWindows::NCOM::CPropVariant prop; const CItemEx &item = m_Items[index]; switch(propID) { case kpidPath: - propVariant = NItemName::GetOSName2( + prop = NItemName::GetOSName2( MultiByteToUnicodeString(item.Name, item.GetCodePage())); break; case kpidIsFolder: - propVariant = item.IsDirectory(); + prop = item.IsDirectory(); break; case kpidSize: - propVariant = item.UnPackSize; + prop = item.UnPackSize; break; case kpidPackedSize: - propVariant = item.PackSize; + prop = item.PackSize; break; case kpidLastWriteTime: { @@ -260,23 +219,23 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } else utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; - propVariant = utcFileTime; + prop = utcFileTime; break; } case kpidAttributes: - propVariant = item.GetWinAttributes(); + prop = item.GetWinAttributes(); break; case kpidEncrypted: - propVariant = item.IsEncrypted(); + prop = item.IsEncrypted(); break; case kpidComment: { - StringToProp(item.Comment, item.GetCodePage(), propVariant); + StringToProp(item.Comment, item.GetCodePage(), prop); break; } case kpidCRC: if (item.IsThereCrc()) - propVariant = item.FileCRC; + prop = item.FileCRC; break; case kpidMethod: { @@ -335,15 +294,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val ConvertUInt64ToString(methodId, s); method += s; } - propVariant = method; + prop = method; break; } case kpidHostOS: - propVariant = (item.MadeByVersion.HostOS < kNumHostOSes) ? + prop = (item.MadeByVersion.HostOS < kNumHostOSes) ? (kHostOS[item.MadeByVersion.HostOS]) : kUnknownOS; break; } - propVariant.Detach(value); + prop.Detach(value); return S_OK; COM_TRY_END } @@ -731,15 +690,14 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, totalUnPacked += item.UnPackSize; totalPacked += item.PackSize; } - extractCallback->SetTotal(totalUnPacked); + RINOK(extractCallback->SetTotal(totalUnPacked)); UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0; UInt64 currentItemUnPacked, currentItemPacked; - CLocalProgress *localProgressSpec = new CLocalProgress; - CMyComPtr progress = localProgressSpec; - CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo; - CMyComPtr compressProgress = localCompressProgressSpec; + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, currentTotalPacked += currentItemPacked) @@ -747,7 +705,10 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, currentItemUnPacked = 0; currentItemPacked = 0; - RINOK(extractCallback->SetCompleted(¤tTotalUnPacked)); + lps->InSize = currentTotalPacked; + lps->OutSize = currentTotalUnPacked; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : @@ -792,14 +753,11 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, RINOK(extractCallback->PrepareOperation(askMode)); - localProgressSpec->Init(extractCallback, false); - localCompressProgressSpec->Init(progress, ¤tTotalPacked, ¤tTotalUnPacked); - Int32 res; RINOK(myDecoder.Decode( EXTERNAL_CODECS_VARS m_Archive, item, realOutStream, extractCallback, - compressProgress, _numThreads, res)); + progress, _numThreads, res)); realOutStream.Release(); RINOK(extractCallback->SetOperationResult(res)) diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index bb45d1d1..bf3764f7 100755 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -542,6 +542,10 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo) // cdInfo.NumEntries = GetUInt16(buf + i + 10); cdInfo.Size = GetUInt32(buf + i + 12); cdInfo.Offset = GetUInt32(buf + i + 16); + UInt64 curPos = endPosition - bufSize + i; + UInt64 cdEnd = cdInfo.Size + cdInfo.Offset; + if (curPos > cdEnd) + m_ArchiveInfo.Base = curPos - cdEnd; return S_OK; } } diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index 2395a37a..350e81b6 100755 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -226,7 +226,7 @@ public: if (CentralExtra.GetWzAesField(aesField)) return aesField.NeedCrc(); } - return true; + return (FileCRC != 0 || !IsDirectory()); } WORD GetCodePage() const diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index 27284953..b08545c6 100755 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -237,12 +237,93 @@ public: } }; +class CMtProgressMixer2: + public ICompressProgressInfo, + public CMyUnknownImp +{ + UInt64 ProgressOffset; + UInt64 InSizes[2]; + UInt64 OutSizes[2]; + CMyComPtr Progress; + CMyComPtr RatioProgress; + bool _inSizeIsMain; +public: + NWindows::NSynchronization::CCriticalSection CriticalSection; + MY_UNKNOWN_IMP + void Create(IProgress *progress, bool inSizeIsMain); + void SetProgressOffset(UInt64 progressOffset); + HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize); + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +void CMtProgressMixer2::Create(IProgress *progress, bool inSizeIsMain) +{ + Progress = progress; + Progress.QueryInterface(IID_ICompressProgressInfo, &RatioProgress); + _inSizeIsMain = inSizeIsMain; + ProgressOffset = InSizes[0] = InSizes[1] = OutSizes[0] = OutSizes[1] = 0; +} + +void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset) +{ + CriticalSection.Enter(); + ProgressOffset = progressOffset; + CriticalSection.Leave(); +} + +HRESULT CMtProgressMixer2::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize) +{ + NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); + if (index == 0 && RatioProgress) + { + RINOK(RatioProgress->SetRatioInfo(inSize, outSize)); + } + if (inSize != 0) + InSizes[index] = *inSize; + if (outSize != 0) + OutSizes[index] = *outSize; + UInt64 v = ProgressOffset + (_inSizeIsMain ? + (InSizes[0] + InSizes[1]) : + (OutSizes[0] + OutSizes[1])); + return Progress->SetCompleted(&v); +} + +STDMETHODIMP CMtProgressMixer2::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + return SetRatioInfo(0, inSize, outSize); +} + +class CMtProgressMixer: + public ICompressProgressInfo, + public CMyUnknownImp +{ +public: + CMtProgressMixer2 *Mixer2; + CMyComPtr RatioProgress; + void Create(IProgress *progress, bool inSizeIsMain); + MY_UNKNOWN_IMP + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +void CMtProgressMixer::Create(IProgress *progress, bool inSizeIsMain) +{ + Mixer2 = new CMtProgressMixer2; + RatioProgress = Mixer2; + Mixer2->Create(progress, inSizeIsMain); +} + +STDMETHODIMP CMtProgressMixer::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + return Mixer2->SetRatioInfo(1, inSize, outSize); +} + + #endif static HRESULT UpdateItemOldData(COutArchive &archive, IInStream *inStream, - const CUpdateItem &updateItem, CItemEx &item, ICompressProgressInfo *progress, + const CUpdateItem &updateItem, CItemEx &item, ICompressProgressInfo *progress, UInt64 &complexity) { if (updateItem.NewProperties) @@ -301,21 +382,20 @@ static HRESULT Update2St( const CByteBuffer &comment, IArchiveUpdateCallback *updateCallback) { - CLocalProgress *localProgressSpec = new CLocalProgress; - CMyComPtr localProgress = localProgressSpec; - localProgressSpec->Init(updateCallback, true); - - CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo; - CMyComPtr compressProgress = localCompressProgressSpec; + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(updateCallback, true); CAddCommon compressor(*options); CObjectVector items; - UInt64 complexity = 0; + UInt64 unpackSizeTotal = 0, packSizeTotal = 0; for (int itemIndex = 0; itemIndex < updateItems.Size(); itemIndex++) { - RINOK(updateCallback->SetCompleted(&complexity)); + lps->InSize = unpackSizeTotal; + lps->OutSize = packSizeTotal; + RINOK(lps->SetCur()); const CUpdateItem &updateItem = updateItems[itemIndex]; CItemEx item; if (!updateItem.NewProperties || !updateItem.NewData) @@ -338,7 +418,7 @@ static HRESULT Update2St( HRESULT res = updateCallback->GetStream(updateItem.IndexInClient, &fileInStream); if (res == S_FALSE) { - complexity += updateItem.Size + NFileHeader::kLocalBlockSize; + lps->ProgressOffset += updateItem.Size; RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); continue; } @@ -350,23 +430,26 @@ static HRESULT Update2St( CCompressingResult compressingResult; CMyComPtr outStream; archive.CreateStreamForCompressing(&outStream); - localCompressProgressSpec->Init(localProgress, &complexity, NULL); RINOK(compressor.Compress( EXTERNAL_CODECS_LOC_VARS - fileInStream, outStream, compressProgress, compressingResult)); + fileInStream, outStream, progress, compressingResult)); SetItemInfoFromCompressingResult(compressingResult, options->IsAesMode, options->AesKeyMode, item); archive.WriteLocalHeader(item); RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); - complexity += item.UnPackSize; + unpackSizeTotal += item.UnPackSize; + packSizeTotal += item.PackSize; } } else { - localCompressProgressSpec->Init(localProgress, &complexity, NULL); - RINOK(UpdateItemOldData(archive, inStream, updateItem, item, compressProgress, complexity)); + UInt64 complexity = 0; + lps->SendRatio = false; + RINOK(UpdateItemOldData(archive, inStream, updateItem, item, progress, complexity)); + lps->SendRatio = true; + lps->ProgressOffset += complexity; } items.Add(item); - complexity += NFileHeader::kLocalBlockSize; + lps->ProgressOffset += NFileHeader::kLocalBlockSize; } archive.WriteCentralDir(items, comment); return S_OK; @@ -477,17 +560,12 @@ static HRESULT Update2( CObjectVector items; - CLocalProgress *localProgressSpec = new CLocalProgress; - CMyComPtr localProgress = localProgressSpec; - localProgressSpec->Init(updateCallback, true); + CMtProgressMixer *mtProgressMixerSpec = new CMtProgressMixer; + CMyComPtr progress = mtProgressMixerSpec; + mtProgressMixerSpec->Create(updateCallback, true); CMtCompressProgressMixer mtCompressProgressMixer; - mtCompressProgressMixer.Init(numThreads + 1, localProgress); - - // we need one item for main stream - CMtCompressProgress *progressMainSpec = new CMtCompressProgress(); - CMyComPtr progressMain = progressMainSpec; - progressMainSpec->Init(&mtCompressProgressMixer, (int)numThreads); + mtCompressProgressMixer.Init(numThreads, mtProgressMixerSpec->RatioProgress); CMemBlockManagerMt memManager(kBlockSize); CMemRefs refs(&memManager); @@ -551,12 +629,13 @@ static HRESULT Update2( } CMyComPtr fileInStream; { - NWindows::NSynchronization::CCriticalSectionLock lock(mtCompressProgressMixer.CriticalSection); + NWindows::NSynchronization::CCriticalSectionLock lock(mtProgressMixerSpec->Mixer2->CriticalSection); HRESULT res = updateCallback->GetStream(updateItem.IndexInClient, &fileInStream); if (res == S_FALSE) { complexity += updateItem.Size; - complexity++; + complexity += NFileHeader::kLocalBlockSize; + mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); refs.Refs[mtItemIndex - 1].Skip = true; continue; @@ -633,7 +712,6 @@ static HRESULT Update2( options->IsAesMode, options->AesKeyMode, item); SetFileHeader(archive, *options, updateItem, item); archive.WriteLocalHeader(item); - complexity += item.UnPackSize; // RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); memRef.FreeOpt(&memManager); } @@ -667,7 +745,6 @@ static HRESULT Update2( options->IsAesMode, options->AesKeyMode, item); SetFileHeader(archive, *options, updateItem, item); archive.WriteLocalHeader(item); - complexity += item.UnPackSize; } else { @@ -682,11 +759,11 @@ static HRESULT Update2( } else { - progressMainSpec->Reinit(); - RINOK(UpdateItemOldData(archive, inStream, updateItem, item, progressMain, complexity)); + RINOK(UpdateItemOldData(archive, inStream, updateItem, item, progress, complexity)); } items.Add(item); complexity += NFileHeader::kLocalBlockSize; + mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity); itemIndex++; } archive.WriteCentralDir(items, comment); -- cgit v1.2.3