Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2009-08-29 04:00:00 +0400
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:01 +0300
commit2fed8721946901375d21d4a506fe8b114045b397 (patch)
tree30c688bd7e1c59c31081a4fe4bb5fc3a6497f066 /CPP/7zip/Archive/Zip
parentc99f3ebdd639c2adb03d8b44001b10af18516504 (diff)
9.07 beta
Diffstat (limited to 'CPP/7zip/Archive/Zip')
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipIn.cpp86
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipIn.h3
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipUpdate.cpp2
3 files changed, 59 insertions, 32 deletions
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
index 6943c9ed..a311e7f3 100755
--- a/CPP/7zip/Archive/Zip/ZipIn.cpp
+++ b/CPP/7zip/Archive/Zip/ZipIn.cpp
@@ -305,6 +305,27 @@ HRESULT CInArchive::ReadLocalItem(CItemEx &item)
return S_OK;
}
+static bool FlagsAreSame(CItem &i1, CItem &i2)
+{
+ if (i1.CompressionMethod != i2.CompressionMethod)
+ return false;
+ // i1.Time
+
+ if (i1.Flags == i2.Flags)
+ return true;
+ UInt32 mask = 0xFFFF;
+ switch(i1.CompressionMethod)
+ {
+ case NFileHeader::NCompressionMethod::kDeflated:
+ mask = 0x7FF9;
+ break;
+ default:
+ if (i1.CompressionMethod <= NFileHeader::NCompressionMethod::kImploded)
+ mask = 0x7FFF;
+ }
+ return ((i1.Flags & mask) == (i2.Flags & mask));
+}
+
HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item)
{
if (item.FromLocal)
@@ -316,25 +337,10 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item)
if (ReadUInt32() != NSignature::kLocalFileHeader)
return S_FALSE;
RINOK(ReadLocalItem(localItem));
- if (item.Flags != localItem.Flags)
- {
- UInt32 mask = 0xFFFF;
- switch(item.CompressionMethod)
- {
- case NFileHeader::NCompressionMethod::kDeflated:
- mask = 0x7FF9;
- break;
- default:
- if (item.CompressionMethod <= NFileHeader::NCompressionMethod::kImploded)
- mask = 0x7FFF;
- }
- if ((item.Flags & mask) != (localItem.Flags & mask))
- return S_FALSE;
- }
+ if (!FlagsAreSame(item, localItem))
+ return S_FALSE;
- if (item.CompressionMethod != localItem.CompressionMethod ||
- // item.Time != localItem.Time ||
- (!localItem.HasDescriptor() &&
+ if ((!localItem.HasDescriptor() &&
(
item.FileCRC != localItem.FileCRC ||
item.PackSize != localItem.PackSize ||
@@ -597,9 +603,10 @@ HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt
return res;
}
-HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset)
+HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems)
{
items.Clear();
+ numCdItems = 0;
while (m_Signature == NSignature::kLocalFileHeader)
{
// FSeek points to next byte after signature
@@ -616,10 +623,14 @@ HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt
break;
}
cdOffset = m_Position - 4;
- for (int i = 0; i < items.Size(); i++)
+ int i;
+ for (i = 0; i < items.Size(); i++, numCdItems++)
{
if (progress && i % 1000 == 0)
RINOK(progress->SetCompleted(items.Size()));
+ if (m_Signature == NSignature::kEndOfCentralDir)
+ break;
+
if (m_Signature != NSignature::kCentralFileHeader)
return S_FALSE;
@@ -627,7 +638,20 @@ HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt
RINOK(ReadCdItem(cdItem));
if (i == 0)
- m_ArchiveInfo.Base = items[i].LocalHeaderPosition - cdItem.LocalHeaderPosition;
+ {
+ int j;
+ for (j = 0; j < items.Size(); j++)
+ {
+ CItemEx &item = items[j];
+ if (item.Name == cdItem.Name)
+ {
+ m_ArchiveInfo.Base = item.LocalHeaderPosition - cdItem.LocalHeaderPosition;
+ break;
+ }
+ }
+ if (j == items.Size())
+ return S_FALSE;
+ }
int index;
int left = 0, right = items.Size();
@@ -645,15 +669,13 @@ HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt
left = index + 1;
}
CItemEx &item = items[index];
- item.LocalHeaderPosition = cdItem.LocalHeaderPosition;
+ // item.LocalHeaderPosition = cdItem.LocalHeaderPosition;
item.MadeByVersion = cdItem.MadeByVersion;
item.CentralExtra = cdItem.CentralExtra;
if (
// item.ExtractVersion != cdItem.ExtractVersion ||
- item.Flags != cdItem.Flags ||
- item.CompressionMethod != cdItem.CompressionMethod ||
- // item.Time != cdItem.Time ||
+ !FlagsAreSame(item, cdItem) ||
item.FileCRC != cdItem.FileCRC)
return S_FALSE;
@@ -670,6 +692,8 @@ HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt
if (!ReadUInt32(m_Signature))
return S_FALSE;
}
+ for (i = 0; i < items.Size(); i++)
+ items[i].LocalHeaderPosition -= m_ArchiveInfo.Base;
return S_OK;
}
@@ -753,6 +777,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
res = S_FALSE;
*/
+ int numCdItems = items.Size();
if (res == S_FALSE)
{
_inBufMode = false;
@@ -762,7 +787,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
return S_FALSE;
if (!ReadUInt32(m_Signature))
return S_FALSE;
- RINOK(ReadLocalsAndCd(items, progress, cdStartOffset));
+ RINOK(ReadLocalsAndCd(items, progress, cdStartOffset, numCdItems));
cdSize = (m_Position - 4) - cdStartOffset;
cdStartOffset -= m_ArchiveInfo.Base;
}
@@ -785,8 +810,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
return S_FALSE;
if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
- if (ecd64.numEntriesInCDOnThisDisk != items.Size() ||
- ecd64.numEntriesInCD != items.Size() ||
+ if (ecd64.numEntriesInCDOnThisDisk != numCdItems ||
+ ecd64.numEntriesInCD != numCdItems ||
ecd64.cdSize != cdSize ||
(ecd64.cdStartOffset != cdStartOffset &&
(!items.IsEmpty())))
@@ -822,8 +847,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
- if ((UInt16)ecd64.numEntriesInCDOnThisDisk != ((UInt16)items.Size()) ||
- (UInt16)ecd64.numEntriesInCD != ((UInt16)items.Size()) ||
+ if ((UInt16)ecd64.numEntriesInCDOnThisDisk != ((UInt16)numCdItems) ||
+ (UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) ||
(UInt32)ecd64.cdSize != (UInt32)cdSize ||
((UInt32)(ecd64.cdStartOffset) != (UInt32)cdStartOffset &&
(!items.IsEmpty())))
@@ -831,6 +856,7 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
_inBufMode = false;
_inBuffer.Free();
+ IsOkHeaders = (numCdItems == items.Size());
return S_OK;
}
diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h
index 5f4fe143..f0e88b03 100755
--- a/CPP/7zip/Archive/Zip/ZipIn.h
+++ b/CPP/7zip/Archive/Zip/ZipIn.h
@@ -99,10 +99,11 @@ class CInArchive
HRESULT FindCd(CCdInfo &cdInfo);
HRESULT TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress);
HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress);
- HRESULT ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset);
+ HRESULT ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems);
public:
CInArchiveInfo m_ArchiveInfo;
bool IsZip64;
+ bool IsOkHeaders;
HRESULT ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress);
HRESULT ReadLocalItemAfterCdItem(CItemEx &item);
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index c76ee488..056a8cd2 100755
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -817,7 +817,7 @@ HRESULT Update(
if(inArchive != 0)
{
inArchive->GetArchiveInfo(archiveInfo);
- if (archiveInfo.Base != 0)
+ if (archiveInfo.Base != 0 || !inArchive->IsOkHeaders)
return E_NOTIMPL;
}
else