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>2014-11-23 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:51 +0300
commitf08f4dcc3c02464c17753b3feafcfe5243b9e236 (patch)
treeb0e1b15bc5368d92dff422e8ec0818564a2b00b8 /CPP/7zip/Archive/Zip
parent83f8ddcc5b2161e1e3c49666265257fca8aeb12c (diff)
9.349.34
Diffstat (limited to 'CPP/7zip/Archive/Zip')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/StdAfx.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipAddCommon.cpp49
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipAddCommon.h0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipCompressionMode.h2
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipHandler.cpp531
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipHandler.h10
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipHandlerOut.cpp151
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHeader.cpp36
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipHeader.h264
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipIn.cpp1323
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipIn.h178
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipItem.cpp109
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipItem.h226
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipItemEx.h34
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipOut.cpp331
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipOut.h68
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipRegister.cpp27
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipUpdate.cpp296
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Zip/ZipUpdate.h19
19 files changed, 2130 insertions, 1526 deletions
diff --git a/CPP/7zip/Archive/Zip/StdAfx.h b/CPP/7zip/Archive/Zip/StdAfx.h
index e7fb6986..2854ff3e 100755..100644
--- a/CPP/7zip/Archive/Zip/StdAfx.h
+++ b/CPP/7zip/Archive/Zip/StdAfx.h
@@ -3,6 +3,6 @@
#ifndef __STDAFX_H
#define __STDAFX_H
-#include "../../../Common/MyWindows.h"
+#include "../../../Common/Common.h"
#endif
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
index f77e4f23..9a0d7515 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
@@ -4,7 +4,7 @@
#include "../../../../C/7zCrc.h"
-#include "Windows/PropVariant.h"
+#include "../../../Windows/PropVariant.h"
#include "../../ICoder.h"
#include "../../IPassword.h"
@@ -85,18 +85,18 @@ CAddCommon::CAddCommon(const CCompressionMethodMode &options):
static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
{
UInt32 crc = CRC_INIT_VAL;
- const UInt32 kBufferSize = (1 << 14);
- Byte buffer[kBufferSize];
+ const UInt32 kBufSize = (1 << 14);
+ Byte buf[kBufSize];
for (;;)
{
- UInt32 realProcessedSize;
- RINOK(inStream->Read(buffer, kBufferSize, &realProcessedSize));
- if (realProcessedSize == 0)
+ UInt32 processed;
+ RINOK(inStream->Read(buf, kBufSize, &processed));
+ if (processed == 0)
{
resultCRC = CRC_GET_DIGEST(crc);
return S_OK;
}
- crc = CrcUpdate(crc, buffer, (size_t)realProcessedSize);
+ crc = CrcUpdate(crc, buf, (size_t)processed);
}
}
@@ -105,8 +105,14 @@ HRESULT CAddCommon::Compress(
ISequentialInStream *inStream, IOutStream *outStream,
ICompressProgressInfo *progress, CCompressingResult &opRes)
{
- CSequentialInStreamWithCRC *inSecCrcStreamSpec = 0;
- CInStreamWithCRC *inCrcStreamSpec = 0;
+ if (!inStream)
+ {
+ // We can create empty stream here. But it was already implemented in caller code in 9.33+
+ return E_INVALIDARG;
+ }
+
+ CSequentialInStreamWithCRC *inSecCrcStreamSpec = NULL;
+ CInStreamWithCRC *inCrcStreamSpec = NULL;
CMyComPtr<ISequentialInStream> inCrcStream;
{
CMyComPtr<IInStream> inStream2;
@@ -128,26 +134,30 @@ HRESULT CAddCommon::Compress(
}
}
- int numTestMethods = _options.MethodSequence.Size();
+ unsigned numTestMethods = _options.MethodSequence.Size();
+
if (numTestMethods > 1 || _options.PasswordIsDefined)
{
- if (inCrcStreamSpec == 0)
+ if (!inCrcStreamSpec)
{
if (_options.PasswordIsDefined)
return E_NOTIMPL;
numTestMethods = 1;
}
}
+
Byte method = 0;
COutStreamReleaser outStreamReleaser;
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
- for (int i = 0; i < numTestMethods; i++)
+
+ for (unsigned i = 0; i < numTestMethods; i++)
{
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
- if (inCrcStreamSpec != 0)
+ if (inCrcStreamSpec)
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
RINOK(outStream->SetSize(0));
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
+
if (_options.PasswordIsDefined)
{
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_ZipCrypto;
@@ -157,6 +167,7 @@ HRESULT CAddCommon::Compress(
_cryptoStreamSpec = new CFilterCoder;
_cryptoStream = _cryptoStreamSpec;
}
+
if (_options.IsAesMode)
{
opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Aes;
@@ -164,7 +175,7 @@ HRESULT CAddCommon::Compress(
{
_cryptoStreamSpec->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder;
_filterAesSpec->SetKeyMode(_options.AesKeyMode);
- RINOK(_filterAesSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length()));
+ RINOK(_filterAesSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len()));
}
RINOK(_filterAesSpec->WriteHeader(outStream));
}
@@ -173,19 +184,21 @@ HRESULT CAddCommon::Compress(
if (!_cryptoStreamSpec->Filter)
{
_cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder;
- _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length());
+ _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len());
}
UInt32 crc = 0;
RINOK(GetStreamCRC(inStream, crc));
RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
RINOK(_filterSpec->WriteHeader(outStream, crc));
}
+
RINOK(_cryptoStreamSpec->SetOutStream(outStream));
outStreamReleaser.FilterCoder = _cryptoStreamSpec;
}
method = _options.MethodSequence[i];
- switch(method)
+
+ switch (method)
{
case NFileHeader::NCompressionMethod::kStored:
{
@@ -202,6 +215,7 @@ HRESULT CAddCommon::Compress(
RINOK(_copyCoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));
break;
}
+
default:
{
if (!_compressEncoder)
@@ -272,7 +286,7 @@ HRESULT CAddCommon::Compress(
RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));
- if (inCrcStreamSpec != 0)
+ if (inCrcStreamSpec)
{
opRes.CRC = inCrcStreamSpec->GetCRC();
opRes.UnpackSize = inCrcStreamSpec->GetSize();
@@ -292,6 +306,7 @@ HRESULT CAddCommon::Compress(
else if (opRes.PackSize < opRes.UnpackSize)
break;
}
+
if (_options.PasswordIsDefined && _options.IsAesMode)
{
RINOK(_filterAesSpec->WriteFooter(outStream));
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h
index e4c02db3..e4c02db3 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.h
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h
diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h
index 893daaab..86548d95 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipCompressionMode.h
+++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h
@@ -3,7 +3,7 @@
#ifndef __ZIP_COMPRESSION_MODE_H
#define __ZIP_COMPRESSION_MODE_H
-#include "Common/MyString.h"
+#include "../../../Common/MyString.h"
#ifndef _7ZIP_ST
#include "../../../Windows/System.h"
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp
index 2281ed5b..f556068c 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipHandler.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp
@@ -2,11 +2,11 @@
#include "StdAfx.h"
-#include "Common/ComTry.h"
-#include "Common/IntToString.h"
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
-#include "Windows/PropVariant.h"
-#include "Windows/Time.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/TimeUtils.h"
#include "../../IPassword.h"
@@ -40,98 +40,112 @@ static const CMethodId kMethodId_BZip2 = 0x040202;
static const char *kHostOS[] =
{
- "FAT",
- "AMIGA",
- "VMS",
- "Unix",
- "VM/CMS",
- "Atari",
- "HPFS",
- "Macintosh",
- "Z-System",
- "CP/M",
- "TOPS-20",
- "NTFS",
- "SMS/QDOS",
- "Acorn",
- "VFAT",
- "MVS",
- "BeOS",
- "Tandem",
- "OS/400",
- "OS/X"
+ "FAT"
+ , "AMIGA"
+ , "VMS"
+ , "Unix"
+ , "VM/CMS"
+ , "Atari"
+ , "HPFS"
+ , "Macintosh"
+ , "Z-System"
+ , "CP/M"
+ , "TOPS-20"
+ , "NTFS"
+ , "SMS/QDOS"
+ , "Acorn"
+ , "VFAT"
+ , "MVS"
+ , "BeOS"
+ , "Tandem"
+ , "OS/400"
+ , "OS/X"
};
-static const char *kUnknownOS = "Unknown";
-
static const char *kMethods[] =
{
- "Store",
- "Shrink",
- "Reduced1",
- "Reduced2",
- "Reduced3",
- "Reduced4",
- "Implode",
- "Tokenizing",
- "Deflate",
- "Deflate64",
- "PKImploding"
+ "Store"
+ , "Shrink"
+ , "Reduced1"
+ , "Reduced2"
+ , "Reduced3"
+ , "Reduced4"
+ , "Implode"
+ , "Tokenizing"
+ , "Deflate"
+ , "Deflate64"
+ , "PKImploding"
};
-static const char *kBZip2Method = "BZip2";
-static const char *kLZMAMethod = "LZMA";
-static const char *kJpegMethod = "Jpeg";
-static const char *kWavPackMethod = "WavPack";
-static const char *kPPMdMethod = "PPMd";
-static const char *kAESMethod = "AES";
-static const char *kZipCryptoMethod = "ZipCrypto";
-static const char *kStrongCryptoMethod = "StrongCrypto";
+static const char *kMethod_AES = "AES";
+static const char *kMethod_ZipCrypto = "ZipCrypto";
+static const char *kMethod_StrongCrypto = "StrongCrypto";
-static struct CStrongCryptoPair
+struct CIdToNamePair
{
- UInt16 Id;
+ unsigned Id;
const char *Name;
-} g_StrongCryptoPairs[] =
+};
+
+static const CIdToNamePair k_MethodIdNamePairs[] =
+{
+ { NFileHeader::NCompressionMethod::kBZip2, "BZip2" },
+ { NFileHeader::NCompressionMethod::kLZMA, "LZMA" },
+ { NFileHeader::NCompressionMethod::kJpeg, "Jpeg" },
+ { NFileHeader::NCompressionMethod::kWavPack, "WavPack" },
+ { NFileHeader::NCompressionMethod::kPPMd, "PPMd" }
+};
+
+static const CIdToNamePair k_StrongCryptoPairs[] =
{
- { NStrongCryptoFlags::kDES, "DES" },
- { NStrongCryptoFlags::kRC2old, "RC2a" },
- { NStrongCryptoFlags::k3DES168, "3DES-168" },
- { NStrongCryptoFlags::k3DES112, "3DES-112" },
- { NStrongCryptoFlags::kAES128, "pkAES-128" },
- { NStrongCryptoFlags::kAES192, "pkAES-192" },
- { NStrongCryptoFlags::kAES256, "pkAES-256" },
- { NStrongCryptoFlags::kRC2, "RC2" },
- { NStrongCryptoFlags::kBlowfish, "Blowfish" },
- { NStrongCryptoFlags::kTwofish, "Twofish" },
- { NStrongCryptoFlags::kRC4, "RC4" }
+ { NStrongCrypto_AlgId::kDES, "DES" },
+ { NStrongCrypto_AlgId::kRC2old, "RC2a" },
+ { NStrongCrypto_AlgId::k3DES168, "3DES-168" },
+ { NStrongCrypto_AlgId::k3DES112, "3DES-112" },
+ { NStrongCrypto_AlgId::kAES128, "pkAES-128" },
+ { NStrongCrypto_AlgId::kAES192, "pkAES-192" },
+ { NStrongCrypto_AlgId::kAES256, "pkAES-256" },
+ { NStrongCrypto_AlgId::kRC2, "RC2" },
+ { NStrongCrypto_AlgId::kBlowfish, "Blowfish" },
+ { NStrongCrypto_AlgId::kTwofish, "Twofish" },
+ { NStrongCrypto_AlgId::kRC4, "RC4" }
};
-static const STATPROPSTG kProps[] =
+const char *FindNameForId(const CIdToNamePair *pairs, unsigned num, unsigned id)
+{
+ for (unsigned i = 0; i < num; i++)
+ {
+ const CIdToNamePair &pair = pairs[i];
+ if (id == pair.Id)
+ return pair.Name;
+ }
+ return NULL;
+}
+
+static const Byte kProps[] =
{
- { NULL, kpidPath, VT_BSTR},
- { NULL, kpidIsDir, VT_BOOL},
- { NULL, kpidSize, VT_UI8},
- { NULL, kpidPackSize, VT_UI8},
- { NULL, kpidMTime, VT_FILETIME},
- { NULL, kpidCTime, VT_FILETIME},
- { NULL, kpidATime, VT_FILETIME},
- { NULL, kpidAttrib, VT_UI4},
- // { NULL, kpidPosixAttrib, VT_UI4},
- { NULL, kpidEncrypted, VT_BOOL},
- { NULL, kpidComment, VT_BSTR},
- { NULL, kpidCRC, VT_UI4},
- { NULL, kpidMethod, VT_BSTR},
- { NULL, kpidHostOS, VT_BSTR},
- { NULL, kpidUnpackVer, VT_UI4}
+ kpidPath,
+ kpidIsDir,
+ kpidSize,
+ kpidPackSize,
+ kpidMTime,
+ kpidCTime,
+ kpidATime,
+ kpidAttrib,
+ // kpidPosixAttrib,
+ kpidEncrypted,
+ kpidComment,
+ kpidCRC,
+ kpidMethod,
+ kpidHostOS,
+ kpidUnpackVer
};
-static const STATPROPSTG kArcProps[] =
+static const Byte kArcProps[] =
{
- { NULL, kpidBit64, VT_BOOL},
- { NULL, kpidComment, VT_BSTR},
- { NULL, kpidPhySize, VT_UI8},
- { NULL, kpidOffset, VT_UI8}
+ kpidEmbeddedStubSize,
+ kpidBit64,
+ kpidComment
};
CHandler::CHandler()
@@ -142,12 +156,12 @@ CHandler::CHandler()
static AString BytesToString(const CByteBuffer &data)
{
AString s;
- int size = (int)data.GetCapacity();
+ unsigned size = (unsigned)data.Size();
if (size > 0)
{
- char *p = s.GetBuffer(size + 1);
+ char *p = s.GetBuffer(size);
memcpy(p, (const Byte *)data, size);
- p[size] = '\0';
+ p[size] = 0;
s.ReleaseBuffer();
}
return s;
@@ -160,13 +174,52 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
- switch(propID)
+ switch (propID)
{
case kpidBit64: if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break;
- case kpidComment: prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); 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.StartPosition != 0) prop = m_Archive.ArcInfo.StartPosition; break;
- case kpidError: if (!m_Archive.IsOkHeaders) prop = "Incorrect headers"; break;
+ case kpidOffset: /* if (m_Archive.ArcInfo.Base != 0) */
+ prop = m_Archive.ArcInfo.Base; break;
+
+ case kpidEmbeddedStubSize:
+ {
+ UInt64 stubSize = m_Archive.ArcInfo.GetEmbeddedStubSize();
+ if (stubSize != 0)
+ prop = stubSize;
+ break;
+ }
+
+ case kpidWarningFlags:
+ {
+ UInt32 v = 0;
+ // if (m_Archive.ExtraMinorError) v |= kpv_ErrorFlags_HeadersError;
+ if (m_Archive.HeadersWarning) v |= kpv_ErrorFlags_HeadersError;
+ if (v != 0)
+ prop = v;
+ break;
+ }
+
+ case kpidErrorFlags:
+ {
+ UInt32 v = 0;
+ if (!m_Archive.IsArc) v |= kpv_ErrorFlags_IsNotArc;
+ if (m_Archive.HeadersError) v |= kpv_ErrorFlags_HeadersError;
+ if (m_Archive.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
+ if (m_Archive.ArcInfo.Base < 0)
+ {
+ /* We try to support case when we have sfx-zip with embedded stub,
+ 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();
+ if (stubSize < (UInt64)-m_Archive.ArcInfo.Base)
+ v |= kpv_ErrorFlags_UnavailableStart;
+ }
+ if (m_Archive.NoCentralDir) v |= kpv_ErrorFlags_UnconfirmedStart;
+ prop = v;
+ break;
+ }
}
prop.Detach(value);
COM_TRY_END
@@ -184,24 +237,36 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
const CItemEx &item = m_Items[index];
- switch(propID)
+ switch (propID)
{
- case kpidPath: prop = NItemName::GetOSName2(item.GetUnicodeString(item.Name)); break;
+ case kpidPath:
+ {
+ UString res;
+ item.GetUnicodeString(item.Name, res, _forceCodePage, _specifiedCodePage);
+ NItemName::ConvertToOSName2(res);
+ prop = res;
+ break;
+ }
+
case kpidIsDir: prop = item.IsDir(); break;
- case kpidSize: prop = item.UnPackSize; break;
+ case kpidSize: prop = item.Size; break;
case kpidPackSize: prop = item.PackSize; break;
+
case kpidTimeType:
{
FILETIME ft;
UInt32 unixTime;
+ UInt32 type;
if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft))
- prop = (UInt32)NFileTimeType::kWindows;
+ type = NFileTimeType::kWindows;
else if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime))
- prop = (UInt32)NFileTimeType::kUnix;
+ type = NFileTimeType::kUnix;
else
- prop = (UInt32)NFileTimeType::kDOS;
+ type = NFileTimeType::kDOS;
+ prop = type;
break;
}
+
case kpidCTime:
{
FILETIME ft;
@@ -209,6 +274,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = ft;
break;
}
+
case kpidATime:
{
FILETIME ft;
@@ -216,26 +282,33 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = ft;
break;
}
+
case kpidMTime:
{
FILETIME utc;
+ bool defined = true;
if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc))
{
- UInt32 unixTime;
+ UInt32 unixTime = 0;
if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime))
NTime::UnixTimeToFileTime(unixTime, utc);
else
{
FILETIME localFileTime;
- if (!NTime::DosTimeToFileTime(item.Time, localFileTime) ||
+ if (item.Time == 0)
+ defined = false;
+ else if (!NTime::DosTimeToFileTime(item.Time, localFileTime) ||
!LocalFileTimeToFileTime(&localFileTime, &utc))
utc.dwHighDateTime = utc.dwLowDateTime = 0;
}
}
- prop = utc;
+ if (defined)
+ prop = utc;
break;
}
+
case kpidAttrib: prop = item.GetWinAttrib(); break;
+
case kpidPosixAttrib:
{
UInt32 attrib;
@@ -243,83 +316,107 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = attrib;
break;
}
+
case kpidEncrypted: prop = item.IsEncrypted(); break;
- case kpidComment: prop = item.GetUnicodeString(BytesToString(item.Comment)); break;
- case kpidCRC: if (item.IsThereCrc()) prop = item.FileCRC; break;
+
+ case kpidComment:
+ {
+ if (item.Comment.Size() != 0)
+ {
+ UString res;
+ item.GetUnicodeString(BytesToString(item.Comment), res, _forceCodePage, _specifiedCodePage);
+ prop = res;
+ }
+ break;
+ }
+
+ case kpidCRC: if (item.IsThereCrc()) prop = item.Crc; break;
+
case kpidMethod:
{
- UInt16 methodId = item.CompressionMethod;
- AString method;
+ UInt16 methodId = item.Method;
+ AString m;
+
if (item.IsEncrypted())
{
if (methodId == NFileHeader::NCompressionMethod::kWzAES)
{
- method = kAESMethod;
- CWzAesExtraField aesField;
- if (item.CentralExtra.GetWzAesField(aesField))
+ m += kMethod_AES;
+ CWzAesExtra aesField;
+ if (item.CentralExtra.GetWzAes(aesField))
{
- method += '-';
- char s[32];
- ConvertUInt64ToString((aesField.Strength + 1) * 64 , s);
- method += s;
- method += ' ';
+ char s[16];
+ s[0] = '-';
+ ConvertUInt32ToString(((unsigned)aesField.Strength + 1) * 64 , s + 1);
+ m += s;
methodId = aesField.Method;
}
}
- else
+ else if (item.IsStrongEncrypted())
{
- if (item.IsStrongEncrypted())
+ CStrongCryptoExtra f;
+ f.AlgId = 0;
+ if (item.CentralExtra.GetStrongCrypto(f))
{
- CStrongCryptoField f;
- bool finded = false;
- if (item.CentralExtra.GetStrongCryptoField(f))
+ const char *s = FindNameForId(k_StrongCryptoPairs, ARRAY_SIZE(k_StrongCryptoPairs), f.AlgId);
+ if (s)
+ m += s;
+ else
{
- for (int i = 0; i < sizeof(g_StrongCryptoPairs) / sizeof(g_StrongCryptoPairs[0]); i++)
- {
- const CStrongCryptoPair &pair = g_StrongCryptoPairs[i];
- if (f.AlgId == pair.Id)
- {
- method += pair.Name;
- finded = true;
- break;
- }
- }
+ m += kMethod_StrongCrypto;
+ char temp[16];
+ temp[0] = ':';
+ ConvertUInt32ToString(f.AlgId, temp + 1);
+ m += temp;
}
- if (!finded)
- method += kStrongCryptoMethod;
}
else
- method += kZipCryptoMethod;
- method += ' ';
+ m += kMethod_StrongCrypto;
}
+ else
+ m += kMethod_ZipCrypto;
+ m += ' ';
}
- if (methodId < sizeof(kMethods) / sizeof(kMethods[0]))
- method += kMethods[methodId];
- else switch (methodId)
+
{
- case NFileHeader::NCompressionMethod::kLZMA:
- method += kLZMAMethod;
- if (item.IsLzmaEOS())
- method += ":EOS";
- break;
- case NFileHeader::NCompressionMethod::kBZip2: method += kBZip2Method; break;
- case NFileHeader::NCompressionMethod::kJpeg: method += kJpegMethod; break;
- case NFileHeader::NCompressionMethod::kWavPack: method += kWavPackMethod; break;
- case NFileHeader::NCompressionMethod::kPPMd: method += kPPMdMethod; break;
- default:
+ char temp[16];
+ const char *s = NULL;
+ if (methodId < ARRAY_SIZE(kMethods))
+ s = kMethods[methodId];
+ else
{
- char s[32];
- ConvertUInt64ToString(methodId, s);
- method += s;
+ s = FindNameForId(k_MethodIdNamePairs, ARRAY_SIZE(k_MethodIdNamePairs), methodId);
+ if (!s)
+ {
+ ConvertUInt32ToString(methodId, temp);
+ s = temp;
+ }
}
+ m += s;
+ if (methodId == NFileHeader::NCompressionMethod::kLZMA && item.IsLzmaEOS())
+ m += ":EOS";
}
- prop = method;
+
+ prop = m;
break;
}
+
case kpidHostOS:
- prop = (item.MadeByVersion.HostOS < sizeof(kHostOS) / sizeof(kHostOS[0])) ?
- (kHostOS[item.MadeByVersion.HostOS]) : kUnknownOS;
+ {
+ Byte hostOS = item.GetHostOS();
+ char temp[16];
+ const char *s = NULL;
+ if (hostOS < ARRAY_SIZE(kHostOS))
+ s = kHostOS[hostOS];
+ else
+ {
+ ConvertUInt32ToString(hostOS, temp);
+ s = temp;
+ }
+ prop = s;
break;
+ }
+
case kpidUnpackVer:
prop = (UInt32)item.ExtractVersion.Version;
break;
@@ -333,23 +430,25 @@ class CProgressImp: public CProgressVirt
{
CMyComPtr<IArchiveOpenCallback> _callback;
public:
- STDMETHOD(SetTotal)(UInt64 numFiles);
- STDMETHOD(SetCompleted)(UInt64 numFiles);
+ virtual HRESULT SetCompletedLocal(UInt64 numFiles, UInt64 numBytes);
+ virtual HRESULT SetTotalCD(UInt64 numFiles);
+ virtual HRESULT SetCompletedCD(UInt64 numFiles);
CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {}
};
-STDMETHODIMP CProgressImp::SetTotal(UInt64 numFiles)
+HRESULT CProgressImp::SetCompletedLocal(UInt64 numFiles, UInt64 numBytes)
{
- if (_callback)
- return _callback->SetTotal(&numFiles, NULL);
- return S_OK;
+ return _callback->SetCompleted(&numFiles, &numBytes);
}
-STDMETHODIMP CProgressImp::SetCompleted(UInt64 numFiles)
+HRESULT CProgressImp::SetTotalCD(UInt64 numFiles)
{
- if (_callback)
- return _callback->SetCompleted(&numFiles, NULL);
- return S_OK;
+ return _callback->SetTotal(&numFiles, NULL);
+}
+
+HRESULT CProgressImp::SetCompletedCD(UInt64 numFiles)
+{
+ return _callback->SetCompleted(&numFiles, NULL);
}
STDMETHODIMP CHandler::Open(IInStream *inStream,
@@ -359,12 +458,10 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
try
{
Close();
- RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
RINOK(m_Archive.Open(inStream, maxCheckStartPosition));
CProgressImp progressImp(callback);
- return m_Archive.ReadHeaders(m_Items, &progressImp);
+ return m_Archive.ReadHeaders(m_Items, callback ? &progressImp : NULL);
}
- catch(const CInArchiveException &) { Close(); return S_FALSE; }
catch(...) { Close(); throw; }
COM_TRY_END
}
@@ -467,26 +564,26 @@ HRESULT CZipDecoder::Decode(
bool needCRC = true;
bool wzAesMode = false;
bool pkAesMode = false;
- UInt16 methodId = item.CompressionMethod;
+ UInt16 methodId = item.Method;
if (item.IsEncrypted())
{
if (item.IsStrongEncrypted())
{
- CStrongCryptoField f;
- if (item.CentralExtra.GetStrongCryptoField(f))
+ CStrongCryptoExtra f;
+ if (item.CentralExtra.GetStrongCrypto(f))
{
pkAesMode = true;
}
if (!pkAesMode)
{
- res = NExtract::NOperationResult::kUnSupportedMethod;
+ res = NExtract::NOperationResult::kUnsupportedMethod;
return S_OK;
}
}
- if (methodId == NFileHeader::NCompressionMethod::kWzAES)
+ if (!pkAesMode && methodId == NFileHeader::NCompressionMethod::kWzAES)
{
- CWzAesExtraField aesField;
- if (item.CentralExtra.GetWzAesField(aesField))
+ CWzAesExtra aesField;
+ if (item.CentralExtra.GetWzAes(aesField))
{
wzAesMode = true;
needCRC = aesField.NeedCrc();
@@ -520,8 +617,8 @@ HRESULT CZipDecoder::Decode(
{
if (wzAesMode)
{
- CWzAesExtraField aesField;
- if (!item.CentralExtra.GetWzAesField(aesField))
+ CWzAesExtra aesField;
+ if (!item.CentralExtra.GetWzAes(aesField))
return S_OK;
methodId = aesField.Method;
if (!_wzAesDecoder)
@@ -562,31 +659,35 @@ HRESULT CZipDecoder::Decode(
CMyComBSTR password;
RINOK(getTextPassword->CryptoGetTextPassword(&password));
AString charPassword;
- if (wzAesMode || pkAesMode)
+ if (password)
{
- charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP);
- /*
- for (int i = 0;; i++)
+ if (wzAesMode || pkAesMode)
{
- wchar_t c = password[i];
- if (c == 0)
- break;
- if (c >= 0x80)
+ charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP);
+ /*
+ for (unsigned i = 0;; i++)
{
- res = NExtract::NOperationResult::kDataError;
- return S_OK;
+ wchar_t c = password[i];
+ if (c == 0)
+ break;
+ if (c >= 0x80)
+ {
+ res = NExtract::NOperationResult::kDataError;
+ return S_OK;
+ }
+ charPassword += (char)c;
}
- charPassword += (char)c;
+ */
+ }
+ else
+ {
+ /* pkzip25 / WinZip / Windows probably use ANSI for some files
+ We use OEM for compatibility with previous versions of 7-Zip? */
+ charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);
}
- */
- }
- else
- {
- // we use OEM. WinZip/Windows probably use ANSI for some files
- charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);
}
HRESULT result = cryptoSetPassword->CryptoSetPassword(
- (const Byte *)(const char *)charPassword, charPassword.Length());
+ (const Byte *)(const char *)charPassword, charPassword.Len());
if (result != S_OK)
return S_OK;
}
@@ -596,7 +697,7 @@ HRESULT CZipDecoder::Decode(
}
}
- int m;
+ unsigned m;
for (m = 0; m < methodItems.Size(); m++)
if (methodItems[m].ZipMethod == methodId)
break;
@@ -624,7 +725,7 @@ HRESULT CZipDecoder::Decode(
{
if (methodId > 0xFF)
{
- res = NExtract::NOperationResult::kUnSupportedMethod;
+ res = NExtract::NOperationResult::kUnsupportedMethod;
return S_OK;
}
szMethodID = kMethodId_ZipBase + (Byte)methodId;
@@ -634,7 +735,7 @@ HRESULT CZipDecoder::Decode(
if (mi.Coder == 0)
{
- res = NExtract::NOperationResult::kUnSupportedMethod;
+ res = NExtract::NOperationResult::kUnsupportedMethod;
return S_OK;
}
}
@@ -680,7 +781,7 @@ HRESULT CZipDecoder::Decode(
}
else if (pkAesMode)
{
- result =_pkAesDecoderSpec->ReadHeader(inStream, item.FileCRC, item.UnPackSize);
+ result =_pkAesDecoderSpec->ReadHeader(inStream, item.Crc, item.Size);
if (result == S_OK)
{
bool passwOK;
@@ -696,7 +797,16 @@ HRESULT CZipDecoder::Decode(
if (result == S_OK)
{
- RINOK(filterStreamSpec->SetInStream(inStream));
+ if (pkAesMode)
+ {
+ /* 9.31: The BUG in 9.24-9.30 was fixed. pkAes archives didn't work.
+ We don't need to call CAesCbcCoder::Init() to reset IV for data. */
+ filterStreamSpec->SetInStream_NoSubFilterInit(inStream);
+ }
+ else
+ {
+ RINOK(filterStreamSpec->SetInStream(inStream));
+ }
inStreamReleaser.FilterCoder = filterStreamSpec;
inStreamNew = filterStream;
if (wzAesMode)
@@ -709,12 +819,12 @@ HRESULT CZipDecoder::Decode(
else
inStreamNew = inStream;
if (result == S_OK)
- result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress);
+ result = coder->Code(inStreamNew, outStream, NULL, &item.Size, compressProgress);
if (result == S_FALSE)
return S_OK;
if (result == E_NOTIMPL)
{
- res = NExtract::NOperationResult::kUnSupportedMethod;
+ res = NExtract::NOperationResult::kUnsupportedMethod;
return S_OK;
}
@@ -723,7 +833,7 @@ HRESULT CZipDecoder::Decode(
bool crcOK = true;
bool authOk = true;
if (needCRC)
- crcOK = (outStreamSpec->GetCRC() == item.FileCRC);
+ crcOK = (outStreamSpec->GetCRC() == item.Crc);
if (wzAesMode)
{
inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAes::kMacSize));
@@ -744,7 +854,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_BEGIN
CZipDecoder myDecoder;
UInt64 totalUnPacked = 0, totalPacked = 0;
- bool allFilesMode = (numItems == (UInt32)-1);
+ bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
numItems = m_Items.Size();
if(numItems == 0)
@@ -753,7 +863,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
for (i = 0; i < numItems; i++)
{
const CItemEx &item = m_Items[allFilesMode ? i : indices[i]];
- totalUnPacked += item.UnPackSize;
+ totalUnPacked += item.Size;
totalPacked += item.PackSize;
}
RINOK(extractCallback->SetTotal(totalUnPacked));
@@ -765,7 +875,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
- for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked,
+ for (i = 0; i < numItems; i++,
+ currentTotalUnPacked += currentItemUnPacked,
currentTotalPacked += currentItemPacked)
{
currentItemUnPacked = 0;
@@ -779,11 +890,26 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
- Int32 index = allFilesMode ? i : indices[i];
+ UInt32 index = allFilesMode ? i : indices[i];
+
+ CItemEx item = m_Items[index];
+ bool isLocalOffsetOK = m_Archive.IsLocalOffsetOK(item);
+ bool skip = !isLocalOffsetOK && !item.IsDir();
+ if (skip)
+ askMode = NExtract::NAskMode::kSkip;
+
+ currentItemUnPacked = item.Size;
+ currentItemPacked = item.PackSize;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
- CItemEx item = m_Items[index];
+ if (!isLocalOffsetOK)
+ {
+ RINOK(extractCallback->PrepareOperation(askMode));
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnavailable));
+ continue;
+ }
if (!item.FromLocal)
{
HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item);
@@ -793,14 +919,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
RINOK(extractCallback->PrepareOperation(askMode));
realOutStream.Release();
- RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
+ RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kHeadersError));
}
continue;
}
RINOK(res);
}
- if (item.IsDir() || item.IgnoreItem())
+ if (item.IsDir())
{
// if (!testMode)
{
@@ -811,9 +937,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
continue;
}
- currentItemUnPacked = item.UnPackSize;
- currentItemPacked = item.PackSize;
-
if (!testMode && !realOutStream)
continue;
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h
index 33cf6fdc..7f1d2eba 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipHandler.h
+++ b/CPP/7zip/Archive/Zip/ZipHandler.h
@@ -3,7 +3,7 @@
#ifndef __ZIP_HANDLER_H
#define __ZIP_HANDLER_H
-#include "Common/DynamicBuffer.h"
+#include "../../../Common/DynamicBuffer.h"
#include "../../ICoder.h"
#include "../IArchive.h"
@@ -33,7 +33,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IOutArchive(;)
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);
+ STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
DECL_ISetCompressCodecsInfo
@@ -47,8 +47,11 @@ private:
int m_MainMethod;
bool m_ForceAesMode;
bool m_WriteNtfsTimeExtra;
+ bool _removeSfxBlock;
bool m_ForceLocal;
bool m_ForceUtf8;
+ bool _forceCodePage;
+ UInt32 _specifiedCodePage;
DECL_EXTERNAL_CODECS_VARS
@@ -58,8 +61,11 @@ private:
m_MainMethod = -1;
m_ForceAesMode = false;
m_WriteNtfsTimeExtra = true;
+ _removeSfxBlock = false;
m_ForceLocal = false;
m_ForceUtf8 = false;
+ _forceCodePage = false;
+ _specifiedCodePage = CP_OEMCP;
}
};
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index dd1ca136..ae58cbe2 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -2,12 +2,12 @@
#include "StdAfx.h"
-#include "Common/ComTry.h"
-#include "Common/StringConvert.h"
-#include "Common/StringToInt.h"
+#include "../../../Common/ComTry.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/StringToInt.h"
-#include "Windows/PropVariant.h"
-#include "Windows/Time.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/TimeUtils.h"
#include "../../IPassword.h"
@@ -36,7 +36,7 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
static bool IsAsciiString(const UString &s)
{
- for (int i = 0; i < s.Length(); i++)
+ for (unsigned i = 0; i < s.Len(); i++)
{
wchar_t c = s[i];
if (c < 0x20 || c > 0x7F)
@@ -66,40 +66,48 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
IArchiveUpdateCallback *callback)
{
COM_TRY_BEGIN2
+
+ if (m_Archive.IsOpen())
+ {
+ if (!m_Archive.CanUpdate())
+ return E_NOTIMPL;
+ }
+
CObjectVector<CUpdateItem> updateItems;
bool thereAreAesUpdates = false;
UInt64 largestSize = 0;
bool largestSizeDefined = false;
+
for (UInt32 i = 0; i < numItems; i++)
{
CUpdateItem ui;
Int32 newData;
- Int32 newProperties;
+ Int32 newProps;
UInt32 indexInArchive;
if (!callback)
return E_FAIL;
- RINOK(callback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive));
- ui.NewProperties = IntToBool(newProperties);
+ RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
+ ui.NewProps = IntToBool(newProps);
ui.NewData = IntToBool(newData);
- ui.IndexInArchive = indexInArchive;
+ ui.IndexInArc = indexInArchive;
ui.IndexInClient = i;
- bool existInArchive = (indexInArchive != (UInt32)-1);
+ bool existInArchive = (indexInArchive != (UInt32)(Int32)-1);
if (existInArchive && newData)
if (m_Items[indexInArchive].IsAesEncrypted())
thereAreAesUpdates = true;
- if (IntToBool(newProperties))
+ if (IntToBool(newProps))
{
UString name;
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidAttrib, &prop));
if (prop.vt == VT_EMPTY)
- ui.Attributes = 0;
+ ui.Attrib = 0;
else if (prop.vt != VT_UI4)
return E_INVALIDARG;
else
- ui.Attributes = prop.ulVal;
+ ui.Attrib = prop.ulVal;
}
{
@@ -131,15 +139,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
else
ui.NtfsTimeIsDefined = m_WriteNtfsTimeExtra;
}
- RINOK(GetTime(callback, i, kpidMTime, ui.NtfsMTime));
- RINOK(GetTime(callback, i, kpidATime, ui.NtfsATime));
- RINOK(GetTime(callback, i, kpidCTime, ui.NtfsCTime));
+ RINOK(GetTime(callback, i, kpidMTime, ui.Ntfs_MTime));
+ RINOK(GetTime(callback, i, kpidATime, ui.Ntfs_ATime));
+ RINOK(GetTime(callback, i, kpidCTime, ui.Ntfs_CTime));
{
FILETIME localFileTime = { 0, 0 };
- if (ui.NtfsMTime.dwHighDateTime != 0 ||
- ui.NtfsMTime.dwLowDateTime != 0)
- if (!FileTimeToLocalFileTime(&ui.NtfsMTime, &localFileTime))
+ if (ui.Ntfs_MTime.dwHighDateTime != 0 ||
+ ui.Ntfs_MTime.dwLowDateTime != 0)
+ if (!FileTimeToLocalFileTime(&ui.Ntfs_MTime, &localFileTime))
return E_INVALIDARG;
FileTimeToDosTime(localFileTime, ui.Time);
}
@@ -159,25 +167,27 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (needSlash)
name += kSlash;
+ UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP;
+
bool tryUtf8 = true;
- if (m_ForceLocal || !m_ForceUtf8)
+ if ((m_ForceLocal || !m_ForceUtf8) && codePage != CP_UTF8)
{
bool defaultCharWasUsed;
- ui.Name = UnicodeStringToMultiByte(name, CP_OEMCP, '_', defaultCharWasUsed);
+ ui.Name = UnicodeStringToMultiByte(name, codePage, '_', defaultCharWasUsed);
tryUtf8 = (!m_ForceLocal && (defaultCharWasUsed ||
- MultiByteToUnicodeString(ui.Name, CP_OEMCP) != name));
+ MultiByteToUnicodeString(ui.Name, codePage) != name));
}
if (tryUtf8)
{
- int i;
- for (i = 0; i < name.Length() && (unsigned)name[i] < 0x80; i++);
- ui.IsUtf8 = (i != name.Length());
+ unsigned i;
+ for (i = 0; i < name.Len() && (unsigned)name[i] < 0x80; i++);
+ ui.IsUtf8 = (i != name.Len());
if (!ConvertUnicodeToUTF8(name, ui.Name))
return E_INVALIDARG;
}
- if (ui.Name.Length() >= (1 << 16))
+ if (ui.Name.Len() >= (1 << 16))
return E_INVALIDARG;
ui.IndexInClient = i;
@@ -211,6 +221,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
largestSizeDefined = true;
}
ui.Size = size;
+ // ui.Size -= ui.Size / 2;
}
updateItems.Add(ui);
}
@@ -225,6 +236,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options._dataSizeReduce = largestSize;
options._dataSizeReduceDefined = largestSizeDefined;
+ options.PasswordIsDefined = false;
+ options.Password.Empty();
if (getTextPassword)
{
CMyComBSTR password;
@@ -236,18 +249,17 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (!m_ForceAesMode)
options.IsAesMode = thereAreAesUpdates;
- if (!IsAsciiString((const wchar_t *)password))
+ if (!IsAsciiString((BSTR)password))
return E_INVALIDARG;
+ if (password)
+ options.Password = UnicodeStringToMultiByte((BSTR)password, CP_OEMCP);
if (options.IsAesMode)
{
- if (options.Password.Length() > NCrypto::NWzAes::kPasswordSizeMax)
+ if (options.Password.Len() > NCrypto::NWzAes::kPasswordSizeMax)
return E_INVALIDARG;
}
- options.Password = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);
}
}
- else
- options.PasswordIsDefined = false;
Byte mainMethod;
if (m_MainMethod < 0)
@@ -263,68 +275,68 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return Update(
EXTERNAL_CODECS_VARS
m_Items, updateItems, outStream,
- m_Archive.IsOpen() ? &m_Archive : NULL, &options, callback);
+ m_Archive.IsOpen() ? &m_Archive : NULL, _removeSfxBlock,
+ &options, callback);
+
COM_TRY_END2
}
struct CMethodIndexToName
{
unsigned Method;
- const wchar_t *Name;
+ const char *Name;
};
static const CMethodIndexToName k_SupportedMethods[] =
{
- { NFileHeader::NCompressionMethod::kStored, L"COPY" },
- { NFileHeader::NCompressionMethod::kDeflated, L"DEFLATE" },
- { NFileHeader::NCompressionMethod::kDeflated64, L"DEFLATE64" },
- { NFileHeader::NCompressionMethod::kBZip2, L"BZIP2" },
- { NFileHeader::NCompressionMethod::kLZMA, L"LZMA" },
- { NFileHeader::NCompressionMethod::kPPMd, L"PPMD" }
+ { NFileHeader::NCompressionMethod::kStored, "copy" },
+ { NFileHeader::NCompressionMethod::kDeflated, "deflate" },
+ { NFileHeader::NCompressionMethod::kDeflated64, "deflate64" },
+ { NFileHeader::NCompressionMethod::kBZip2, "bzip2" },
+ { NFileHeader::NCompressionMethod::kLZMA, "lzma" },
+ { NFileHeader::NCompressionMethod::kPPMd, "ppmd" }
};
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
-
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
{
InitMethodProps();
#ifndef _7ZIP_ST
const UInt32 numProcessors = _props.NumThreads;
#endif
- for (int i = 0; i < numProps; i++)
+ for (UInt32 i = 0; i < numProps; i++)
{
UString name = names[i];
- name.MakeUpper();
+ name.MakeLower_Ascii();
if (name.IsEmpty())
return E_INVALIDARG;
const PROPVARIANT &prop = values[i];
- if (name[0] == L'X')
+ if (name[0] == L'x')
{
UInt32 level = 9;
- RINOK(ParsePropToUInt32(name.Mid(1), prop, level));
+ RINOK(ParsePropToUInt32(name.Ptr(1), prop, level));
_props.Level = level;
_props.MethodInfo.AddLevelProp(level);
}
- else if (name == L"M")
+ else if (name == L"m")
{
if (prop.vt == VT_BSTR)
{
UString m = prop.bstrVal, m2;
- m.MakeUpper();
+ m.MakeLower_Ascii();
int colonPos = m.Find(L':');
if (colonPos >= 0)
{
- m2 = m.Mid(colonPos + 1);
- m = m.Left(colonPos);
+ m2 = m.Ptr(colonPos + 1);
+ m.DeleteFrom(colonPos);
}
- int k;
+ unsigned k;
for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
{
const CMethodIndexToName &pair = k_SupportedMethods[k];
- if (m == pair.Name)
+ if (m.IsEqualTo(pair.Name))
{
if (!m2.IsEmpty())
{
@@ -339,7 +351,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
}
else if (prop.vt == VT_UI4)
{
- int k;
+ unsigned k;
for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
{
unsigned method = k_SupportedMethods[k].Method;
@@ -355,16 +367,16 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
else
return E_INVALIDARG;
}
- else if (name.Left(2) == L"EM")
+ else if (name.IsPrefixedBy(L"em"))
{
if (prop.vt != VT_BSTR)
return E_INVALIDARG;
{
UString m = prop.bstrVal;
- m.MakeUpper();
- if (m.Left(3) == L"AES")
+ m.MakeLower_Ascii();
+ if (m.IsPrefixedBy(L"aes"))
{
- m = m.Mid(3);
+ m.DeleteFrontal(3);
if (m == L"128")
_props.AesKeyMode = 1;
else if (m == L"192")
@@ -376,7 +388,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
_props.IsAesMode = true;
m_ForceAesMode = true;
}
- else if (m == L"ZIPCRYPTO")
+ else if (m == L"zipcrypto")
{
_props.IsAesMode = false;
m_ForceAesMode = true;
@@ -385,29 +397,40 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
return E_INVALIDARG;
}
}
- else if (name.Left(2) == L"MT")
+ else if (name.IsPrefixedBy(L"mt"))
{
#ifndef _7ZIP_ST
- RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _props.NumThreads));
+ RINOK(ParseMtProp(name.Ptr(2), prop, numProcessors, _props.NumThreads));
_props.NumThreadsWasChanged = true;
#endif
}
- else if (name.CompareNoCase(L"TC") == 0)
+ else if (name.IsEqualTo("tc"))
{
RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra));
}
- else if (name.CompareNoCase(L"CL") == 0)
+ else if (name.IsEqualTo("cl"))
{
RINOK(PROPVARIANT_to_bool(prop, m_ForceLocal));
if (m_ForceLocal)
m_ForceUtf8 = false;
}
- else if (name.CompareNoCase(L"CU") == 0)
+ else if (name.IsEqualTo("cu"))
{
RINOK(PROPVARIANT_to_bool(prop, m_ForceUtf8));
if (m_ForceUtf8)
m_ForceLocal = false;
}
+ else if (name.IsEqualTo("cp"))
+ {
+ UInt32 cp = CP_OEMCP;
+ RINOK(ParsePropToUInt32(L"", prop, cp));
+ _forceCodePage = true;
+ _specifiedCodePage = cp;
+ }
+ else if (name.IsEqualTo("rsfx"))
+ {
+ RINOK(PROPVARIANT_to_bool(prop, _removeSfxBlock));
+ }
else
{
RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop));
diff --git a/CPP/7zip/Archive/Zip/ZipHeader.cpp b/CPP/7zip/Archive/Zip/ZipHeader.cpp
deleted file mode 100755
index 582187b5..00000000
--- a/CPP/7zip/Archive/Zip/ZipHeader.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// Archive/Zip/Header.h
-
-#include "StdAfx.h"
-
-#include "ZipHeader.h"
-
-namespace NArchive {
-namespace NZip {
-
-namespace NSignature
-{
- UInt32 kLocalFileHeader = 0x04034B50 + 1;
- UInt32 kDataDescriptor = 0x08074B50 + 1;
- UInt32 kCentralFileHeader = 0x02014B50 + 1;
- UInt32 kEndOfCentralDir = 0x06054B50 + 1;
- UInt32 kZip64EndOfCentralDir = 0x06064B50 + 1;
- UInt32 kZip64EndOfCentralDirLocator = 0x07064B50 + 1;
-
- class CMarkersInitializer
- {
- public:
- CMarkersInitializer()
- {
- kLocalFileHeader--;
- kDataDescriptor--;
- kCentralFileHeader--;
- kEndOfCentralDir--;
- kZip64EndOfCentralDir--;
- kZip64EndOfCentralDirLocator--;
- }
- };
- static CMarkersInitializer g_MarkerInitializer;
-}
-
-}}
-
diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h
index ce8c1e4f..1391cdf4 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipHeader.h
+++ b/CPP/7zip/Archive/Zip/ZipHeader.h
@@ -1,57 +1,39 @@
-// Archive/Zip/Header.h
+// ZipHeader.h
#ifndef __ARCHIVE_ZIP_HEADER_H
#define __ARCHIVE_ZIP_HEADER_H
-#include "Common/Types.h"
+#include "../../../Common/MyTypes.h"
namespace NArchive {
namespace NZip {
+const unsigned kMarkerSize = 4;
+
namespace NSignature
{
- extern UInt32 kLocalFileHeader;
- extern UInt32 kDataDescriptor;
- extern UInt32 kCentralFileHeader;
- extern UInt32 kEndOfCentralDir;
- extern UInt32 kZip64EndOfCentralDir;
- extern UInt32 kZip64EndOfCentralDirLocator;
-
- static const UInt32 kMarkerSize = 4;
+ const UInt32 kLocalFileHeader = 0x04034B50;
+ const UInt32 kDataDescriptor = 0x08074B50;
+ const UInt32 kCentralFileHeader = 0x02014B50;
+ const UInt32 kEcd = 0x06054B50;
+ const UInt32 kEcd64 = 0x06064B50;
+ const UInt32 kEcd64Locator = 0x07064B50;
+
+ // const UInt32 kSpan = 0x08074B50;
+ const UInt32 kNoSpan = 0x30304b50; // PK00, replaces kSpan, if there is only 1 segment
}
-const UInt32 kEcdSize = 22;
-const UInt32 kZip64EcdSize = 44;
-const UInt32 kZip64EcdLocatorSize = 20;
-/*
-struct CEndOfCentralDirectoryRecord
-{
- UInt16 ThisDiskNumber;
- UInt16 StartCentralDirectoryDiskNumber;
- UInt16 NumEntriesInCentaralDirectoryOnThisDisk;
- UInt16 NumEntriesInCentaralDirectory;
- UInt32 CentralDirectorySize;
- UInt32 CentralDirectoryStartOffset;
- UInt16 CommentSize;
-};
+const unsigned kLocalHeaderSize = 4 + 26; // including signature
+const unsigned kDataDescriptorSize = 4 + 12; // including signature
+const unsigned kCentralHeaderSize = 4 + 42; // including signature
-struct CEndOfCentralDirectoryRecordFull
-{
- UInt32 Signature;
- CEndOfCentralDirectoryRecord Header;
-};
-*/
+const unsigned kEcdSize = 22; // including signature
+const unsigned kEcd64_MainSize = 44;
+const unsigned kEcd64_FullSize = 12 + kEcd64_MainSize;
+const unsigned kEcd64Locator_Size = 20;
namespace NFileHeader
{
- /*
- struct CVersion
- {
- Byte Version;
- Byte HostOS;
- };
- */
-
namespace NCompressionMethod
{
enum EType
@@ -77,7 +59,7 @@ namespace NFileHeader
kPPMd = 0x62,
kWzAES = 0x63
};
- const int kNumCompressionMethods = 11;
+
const Byte kMadeByProgramVersion = 63;
const Byte kExtractVersion_Default = 10;
@@ -90,8 +72,6 @@ namespace NFileHeader
const Byte kExtractVersion_Aes = 51;
const Byte kExtractVersion_LZMA = 63;
const Byte kExtractVersion_PPMd = 63;
-
- // const Byte kSupportedVersion = 20;
}
namespace NExtraID
@@ -127,155 +107,93 @@ namespace NFileHeader
};
}
- const UInt32 kLocalBlockSize = 26;
- /*
- struct CLocalBlock
- {
- CVersion ExtractVersion;
-
- UInt16 Flags;
- UInt16 CompressionMethod;
- UInt32 Time;
- UInt32 FileCRC;
- UInt32 PackSize;
- UInt32 UnPackSize;
- UInt16 NameSize;
- UInt16 ExtraSize;
- };
- */
-
- const UInt32 kDataDescriptorSize = 16;
- // const UInt32 kDataDescriptor64Size = 16 + 8;
- /*
- struct CDataDescriptor
- {
- UInt32 Signature;
- UInt32 FileCRC;
- UInt32 PackSize;
- UInt32 UnPackSize;
- };
-
- struct CLocalBlockFull
- {
- UInt32 Signature;
- CLocalBlock Header;
- };
- */
-
- const UInt32 kCentralBlockSize = 42;
- /*
- struct CBlock
- {
- CVersion MadeByVersion;
- CVersion ExtractVersion;
- UInt16 Flags;
- UInt16 CompressionMethod;
- UInt32 Time;
- UInt32 FileCRC;
- UInt32 PackSize;
- UInt32 UnPackSize;
- UInt16 NameSize;
- UInt16 ExtraSize;
- UInt16 CommentSize;
- UInt16 DiskNumberStart;
- UInt16 InternalAttributes;
- UInt32 ExternalAttributes;
- UInt32 LocalHeaderOffset;
- };
-
- struct CBlockFull
- {
- UInt32 Signature;
- CBlock Header;
- };
- */
-
namespace NFlags
{
- const int kEncrypted = 1 << 0;
- const int kLzmaEOS = 1 << 1;
- const int kDescriptorUsedMask = 1 << 3;
- const int kStrongEncrypted = 1 << 6;
- const int kUtf8 = 1 << 11;
-
- const int kImplodeDictionarySizeMask = 1 << 1;
- const int kImplodeLiteralsOnMask = 1 << 2;
+ const unsigned kEncrypted = 1 << 0;
+ const unsigned kLzmaEOS = 1 << 1;
+ const unsigned kDescriptorUsedMask = 1 << 3;
+ const unsigned kStrongEncrypted = 1 << 6;
+ const unsigned kUtf8 = 1 << 11;
+
+ const unsigned kImplodeDictionarySizeMask = 1 << 1;
+ const unsigned kImplodeLiteralsOnMask = 1 << 2;
- const int kDeflateTypeBitStart = 1;
- const int kNumDeflateTypeBits = 2;
- const int kNumDeflateTypes = (1 << kNumDeflateTypeBits);
- const int kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1;
+ const unsigned kDeflateTypeBitStart = 1;
+ const unsigned kNumDeflateTypeBits = 2;
+ const unsigned kNumDeflateTypes = (1 << kNumDeflateTypeBits);
+ const unsigned kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1;
}
namespace NHostOS
{
enum EEnum
{
- kFAT = 0,
- kAMIGA = 1,
- kVMS = 2, // VAX/VMS
- kUnix = 3,
- kVM_CMS = 4,
- kAtari = 5, // what if it's a minix filesystem? [cjh]
- kHPFS = 6, // filesystem used by OS/2 (and NT 3.x)
- kMac = 7,
- kZ_System = 8,
- kCPM = 9,
- kTOPS20 = 10, // pkzip 2.50 NTFS
- kNTFS = 11, // filesystem used by Windows NT
- kQDOS = 12, // SMS/QDOS
- kAcorn = 13, // Archimedes Acorn RISC OS
- kVFAT = 14, // filesystem used by Windows 95, NT
- kMVS = 15,
- kBeOS = 16, // hybrid POSIX/database filesystem
- kTandem = 17,
- kOS400 = 18,
- kOSX = 19
+ kFAT = 0,
+ kAMIGA = 1,
+ kVMS = 2, // VAX/VMS
+ kUnix = 3,
+ kVM_CMS = 4,
+ kAtari = 5, // what if it's a minix filesystem? [cjh]
+ kHPFS = 6, // filesystem used by OS/2 (and NT 3.x)
+ kMac = 7,
+ kZ_System = 8,
+ kCPM = 9,
+ kTOPS20 = 10, // pkzip 2.50 NTFS
+ kNTFS = 11, // filesystem used by Windows NT
+ kQDOS = 12, // SMS/QDOS
+ kAcorn = 13, // Archimedes Acorn RISC OS
+ kVFAT = 14, // filesystem used by Windows 95, NT
+ kMVS = 15,
+ kBeOS = 16, // hybrid POSIX/database filesystem
+ kTandem = 17,
+ kOS400 = 18,
+ kOSX = 19
};
}
- namespace NUnixAttribute
+
+ namespace NUnixAttrib
{
- const UInt32 kIFMT = 0170000; /* Unix file type mask */
+ const UInt32 kIFMT = 0170000; // file type mask
- const UInt32 kIFDIR = 0040000; /* Unix directory */
- const UInt32 kIFREG = 0100000; /* Unix regular file */
- const UInt32 kIFSOCK = 0140000; /* Unix socket (BSD, not SysV or Amiga) */
- const UInt32 kIFLNK = 0120000; /* Unix symbolic link (not SysV, Amiga) */
- const UInt32 kIFBLK = 0060000; /* Unix block special (not Amiga) */
- const UInt32 kIFCHR = 0020000; /* Unix character special (not Amiga) */
- const UInt32 kIFIFO = 0010000; /* Unix fifo (BCC, not MSC or Amiga) */
+ const UInt32 kIFDIR = 0040000; // directory
+ const UInt32 kIFREG = 0100000; // regular file
+ const UInt32 kIFSOCK = 0140000; // socket (BSD, not SysV or Amiga)
+ const UInt32 kIFLNK = 0120000; // symbolic link (not SysV, Amiga)
+ const UInt32 kIFBLK = 0060000; // block special (not Amiga)
+ const UInt32 kIFCHR = 0020000; // character special (not Amiga)
+ const UInt32 kIFIFO = 0010000; // fifo (BCC, not MSC or Amiga)
- const UInt32 kISUID = 04000; /* Unix set user id on execution */
- const UInt32 kISGID = 02000; /* Unix set group id on execution */
- const UInt32 kISVTX = 01000; /* Unix directory permissions control */
- const UInt32 kENFMT = kISGID; /* Unix record locking enforcement flag */
- const UInt32 kIRWXU = 00700; /* Unix read, write, execute: owner */
- const UInt32 kIRUSR = 00400; /* Unix read permission: owner */
- const UInt32 kIWUSR = 00200; /* Unix write permission: owner */
- const UInt32 kIXUSR = 00100; /* Unix execute permission: owner */
- const UInt32 kIRWXG = 00070; /* Unix read, write, execute: group */
- const UInt32 kIRGRP = 00040; /* Unix read permission: group */
- const UInt32 kIWGRP = 00020; /* Unix write permission: group */
- const UInt32 kIXGRP = 00010; /* Unix execute permission: group */
- const UInt32 kIRWXO = 00007; /* Unix read, write, execute: other */
- const UInt32 kIROTH = 00004; /* Unix read permission: other */
- const UInt32 kIWOTH = 00002; /* Unix write permission: other */
- const UInt32 kIXOTH = 00001; /* Unix execute permission: other */
+ const UInt32 kISUID = 04000; // set user id on execution
+ const UInt32 kISGID = 02000; // set group id on execution
+ const UInt32 kISVTX = 01000; // directory permissions control
+ const UInt32 kENFMT = kISGID; // record locking enforcement flag
+ const UInt32 kIRWXU = 00700; // read, write, execute: owner
+ const UInt32 kIRUSR = 00400; // read permission: owner
+ const UInt32 kIWUSR = 00200; // write permission: owner
+ const UInt32 kIXUSR = 00100; // execute permission: owner
+ const UInt32 kIRWXG = 00070; // read, write, execute: group
+ const UInt32 kIRGRP = 00040; // read permission: group
+ const UInt32 kIWGRP = 00020; // write permission: group
+ const UInt32 kIXGRP = 00010; // execute permission: group
+ const UInt32 kIRWXO = 00007; // read, write, execute: other
+ const UInt32 kIROTH = 00004; // read permission: other
+ const UInt32 kIWOTH = 00002; // write permission: other
+ const UInt32 kIXOTH = 00001; // execute permission: other
}
- namespace NAmigaAttribute
+ namespace NAmigaAttrib
{
- const UInt32 kIFMT = 06000; /* Amiga file type mask */
- const UInt32 kIFDIR = 04000; /* Amiga directory */
- const UInt32 kIFREG = 02000; /* Amiga regular file */
- const UInt32 kIHIDDEN = 00200; /* to be supported in AmigaDOS 3.x */
- const UInt32 kISCRIPT = 00100; /* executable script (text command file) */
- const UInt32 kIPURE = 00040; /* allow loading into resident memory */
- const UInt32 kIARCHIVE = 00020; /* not modified since bit was last set */
- const UInt32 kIREAD = 00010; /* can be opened for reading */
- const UInt32 kIWRITE = 00004; /* can be opened for writing */
- const UInt32 kIEXECUTE = 00002; /* executable image, a loadable runfile */
- const UInt32 kIDELETE = 00001; /* can be deleted */
+ const UInt32 kIFMT = 06000; // Amiga file type mask
+ const UInt32 kIFDIR = 04000; // Amiga directory
+ const UInt32 kIFREG = 02000; // Amiga regular file
+ const UInt32 kIHIDDEN = 00200; // to be supported in AmigaDOS 3.x
+ const UInt32 kISCRIPT = 00100; // executable script (text command file)
+ const UInt32 kIPURE = 00040; // allow loading into resident memory
+ const UInt32 kIARCHIVE = 00020; // not modified since bit was last set
+ const UInt32 kIREAD = 00010; // can be opened for reading
+ const UInt32 kIWRITE = 00004; // can be opened for writing
+ const UInt32 kIEXECUTE = 00002; // executable image, a loadable runfile
+ const UInt32 kIDELETE = 00001; // can be deleted
}
}
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
index e930488f..345fbf56 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipIn.cpp
+++ b/CPP/7zip/Archive/Zip/ZipIn.cpp
@@ -2,13 +2,15 @@
#include "StdAfx.h"
-#include "../../../../C/CpuArch.h"
+// #include <stdio.h>
-#include "Common/DynamicBuffer.h"
+#include "../../../Common/DynamicBuffer.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/StreamUtils.h"
+#include "../IArchive.h"
+
#include "ZipIn.h"
#define Get16(p) GetUi16(p)
@@ -17,100 +19,342 @@
namespace NArchive {
namespace NZip {
-
+
+struct CEcd
+{
+ UInt16 thisDiskNumber;
+ UInt16 startCDDiskNumber;
+ UInt16 numEntriesInCDOnThisDisk;
+ UInt16 numEntriesInCD;
+ UInt32 cdSize;
+ UInt32 cdStartOffset;
+ UInt16 commentSize;
+
+ void Parse(const Byte *p);
+
+ bool IsEmptyArc()
+ {
+ return thisDiskNumber == 0 && startCDDiskNumber == 0 &&
+ numEntriesInCDOnThisDisk == 0 && numEntriesInCD == 0 && cdSize == 0
+ && cdStartOffset == 0 // test it
+ ;
+ }
+};
+
+void CEcd::Parse(const Byte *p)
+{
+ thisDiskNumber = Get16(p);
+ startCDDiskNumber = Get16(p + 2);
+ numEntriesInCDOnThisDisk = Get16(p + 4);
+ numEntriesInCD = Get16(p + 6);
+ cdSize = Get32(p + 8);
+ cdStartOffset = Get32(p + 12);
+ commentSize = Get16(p + 16);
+}
+
+struct CEcd64
+{
+ UInt16 versionMade;
+ UInt16 versionNeedExtract;
+ UInt32 thisDiskNumber;
+ UInt32 startCDDiskNumber;
+ UInt64 numEntriesInCDOnThisDisk;
+ UInt64 numEntriesInCD;
+ UInt64 cdSize;
+ UInt64 cdStartOffset;
+
+ void Parse(const Byte *p);
+ CEcd64() { memset(this, 0, sizeof(*this)); }
+};
+
+void CEcd64::Parse(const Byte *p)
+{
+ versionMade = Get16(p);
+ versionNeedExtract = Get16(p + 2);
+ thisDiskNumber = Get32(p + 4);
+ startCDDiskNumber = Get32(p + 8);
+ numEntriesInCDOnThisDisk = Get64(p + 12);
+ numEntriesInCD = Get64(p + 20);
+ cdSize = Get64(p + 28);
+ cdStartOffset = Get64(p + 36);
+}
+
HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
{
_inBufMode = false;
Close();
- RINOK(stream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition));
- m_Position = m_StreamStartPosition;
+ RINOK(stream->Seek(0, STREAM_SEEK_CUR, &m_Position));
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &ArcInfo.FileEndPos));
+ RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL));
+
+ // printf("\nOpen offset = %d", (int)m_Position);
RINOK(FindAndReadMarker(stream, searchHeaderSizeLimit));
RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL));
- m_Stream = stream;
+ Stream = stream;
return S_OK;
}
void CInArchive::Close()
{
- _inBuffer.ReleaseStream();
- m_Stream.Release();
+ IsArc = false;
+ HeadersError = false;
+ HeadersWarning = false;
+ ExtraMinorError = false;
+ UnexpectedEnd = false;
+ NoCentralDir = false;
+ IsZip64 = false;
+ Stream.Release();
}
HRESULT CInArchive::Seek(UInt64 offset)
{
- return m_Stream->Seek(offset, STREAM_SEEK_SET, NULL);
+ return Stream->Seek(offset, STREAM_SEEK_SET, NULL);
}
-//////////////////////////////////////
-// Markers
+static bool CheckDosTime(UInt32 dosTime)
+{
+ if (dosTime == 0)
+ return true;
+ unsigned month = (dosTime >> 21) & 0xF;
+ unsigned day = (dosTime >> 16) & 0x1F;
+ unsigned hour = (dosTime >> 11) & 0x1F;
+ unsigned min = (dosTime >> 5) & 0x3F;
+ unsigned sec = (dosTime & 0x1F) * 2;
+ if (month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59)
+ return false;
+ return true;
+}
-static inline bool TestMarkerCandidate(const Byte *p, UInt32 &value)
+API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size)
{
+ if (size < 8)
+ return k_IsArc_Res_NEED_MORE;
+ if (p[0] != 'P')
+ return k_IsArc_Res_NO;
+
+ UInt32 value = Get32(p);
+
+ if (value == NSignature::kNoSpan)
+ {
+ p += 4;
+ size -= 4;
+ }
+
value = Get32(p);
- return
- (value == NSignature::kLocalFileHeader) ||
- (value == NSignature::kEndOfCentralDir);
+
+ if (value == NSignature::kEcd)
+ {
+ if (size < kEcdSize)
+ return k_IsArc_Res_NEED_MORE;
+ CEcd ecd;
+ ecd.Parse(p + 4);
+ // if (ecd.cdSize != 0)
+ if (!ecd.IsEmptyArc())
+ return k_IsArc_Res_NO;
+ return k_IsArc_Res_YES; // k_IsArc_Res_YES_2;
+ }
+
+ if (value != NSignature::kLocalFileHeader)
+ return k_IsArc_Res_NO;
+
+ if (size < kLocalHeaderSize)
+ return k_IsArc_Res_NEED_MORE;
+
+ p += 4;
+
+ {
+ const unsigned kPureHeaderSize = kLocalHeaderSize - 4;
+ unsigned i;
+ for (i = 0; i < kPureHeaderSize && p[i] == 0; i++);
+ if (i == kPureHeaderSize)
+ return k_IsArc_Res_NEED_MORE;
+ }
+
+ /*
+ if (p[0] >= 128) // ExtractVersion.Version;
+ return k_IsArc_Res_NO;
+ */
+
+ // ExtractVersion.Version = p[0];
+ // ExtractVersion.HostOS = p[1];
+ // Flags = Get16(p + 2);
+ // Method = Get16(p + 4);
+ /*
+ // 9.33: some zip archives contain incorrect value in timestamp. So we don't check it now
+ UInt32 dosTime = Get32(p + 6);
+ if (!CheckDosTime(dosTime))
+ return k_IsArc_Res_NO;
+ */
+ // Crc = Get32(p + 10);
+ // PackSize = Get32(p + 14);
+ // Size = Get32(p + 18);
+ unsigned nameSize = Get16(p + 22);
+ unsigned extraSize = Get16(p + 24);
+ UInt32 extraOffset = kLocalHeaderSize + (UInt32)nameSize;
+ if (extraOffset + extraSize > (1 << 16))
+ return k_IsArc_Res_NO;
+
+ p -= 4;
+
+ {
+ size_t rem = size - kLocalHeaderSize;
+ if (rem > nameSize)
+ rem = nameSize;
+ const Byte *p2 = p + kLocalHeaderSize;
+ for (size_t i = 0; i < rem; i++)
+ if (p2[i] == 0)
+ return k_IsArc_Res_NO;
+ }
+
+ if (size < extraOffset)
+ return k_IsArc_Res_NEED_MORE;
+
+ if (extraSize > 0)
+ {
+ p += extraOffset;
+ size -= extraOffset;
+ while (extraSize != 0)
+ {
+ if (extraSize < 4)
+ {
+ // 7-Zip before 9.31 created incorrect WsAES Extra in folder's local headers.
+ // so we return k_IsArc_Res_YES to support such archives.
+ // return k_IsArc_Res_NO; // do we need to support such extra ?
+ return k_IsArc_Res_YES;
+ }
+ if (size < 4)
+ return k_IsArc_Res_NEED_MORE;
+ unsigned dataSize = Get16(p + 2);
+ size -= 4;
+ extraSize -= 4;
+ p += 4;
+ if (dataSize > extraSize)
+ return k_IsArc_Res_NO;
+ if (dataSize > size)
+ return k_IsArc_Res_NEED_MORE;
+ size -= dataSize;
+ extraSize -= dataSize;
+ p += dataSize;
+ }
+ }
+
+ return k_IsArc_Res_YES;
}
-static const UInt32 kNumMarkerAddtionalBytes = 2;
-static inline bool TestMarkerCandidate2(const Byte *p, UInt32 &value)
+static UInt32 IsArc_Zip_2(const Byte *p, size_t size, bool isFinal)
{
- value = Get32(p);
- if (value == NSignature::kEndOfCentralDir)
- return (Get16(p + 4) == 0);
- return (value == NSignature::kLocalFileHeader && p[4] < 128);
+ UInt32 res = IsArc_Zip(p, size);
+ if (res == k_IsArc_Res_NEED_MORE && isFinal)
+ return k_IsArc_Res_NO;
+ return res;
}
-HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLimit)
{
ArcInfo.Clear();
- m_Position = m_StreamStartPosition;
+ ArcInfo.MarkerPos = m_Position;
+ ArcInfo.MarkerPos2 = m_Position;
- Byte marker[NSignature::kMarkerSize];
- RINOK(ReadStream_FALSE(stream, marker, NSignature::kMarkerSize));
- m_Position += NSignature::kMarkerSize;
- if (TestMarkerCandidate(marker, m_Signature))
- return S_OK;
+ if (searchLimit && *searchLimit == 0)
+ {
+ const unsigned kStartBufSize = kMarkerSize;
+ Byte startBuf[kStartBufSize];
+ size_t processed = kStartBufSize;
+ RINOK(ReadStream(stream, startBuf, &processed));
+ m_Position += processed;
+ if (processed < kMarkerSize)
+ return S_FALSE;
+ m_Signature = Get32(startBuf);
+ if (m_Signature != NSignature::kEcd &&
+ m_Signature != NSignature::kLocalFileHeader)
+ {
+ if (m_Signature != NSignature::kNoSpan)
+ return S_FALSE;
+ size_t processed = kStartBufSize;
+ RINOK(ReadStream(stream, startBuf, &processed));
+ m_Position += processed;
+ if (processed < kMarkerSize)
+ return S_FALSE;
+ m_Signature = Get32(startBuf);
+ if (m_Signature != NSignature::kEcd &&
+ m_Signature != NSignature::kLocalFileHeader)
+ return S_FALSE;
+ ArcInfo.MarkerPos2 += 4;
+ }
+
+ // we use weak test in case of *searchLimit == 0)
+ // since error will be detected later in Open function
+ // m_Position = ArcInfo.MarkerPos2 + 4;
+ return S_OK; // maybe we need to search backward.
+ }
+
+ const size_t kBufSize = (size_t)1 << 18; // must be larger than kCheckSize
+ const size_t kCheckSize = (size_t)1 << 16; // must be smaller than kBufSize
+ CByteArr buffer(kBufSize);
+
+ size_t numBytesInBuffer = 0;
+ UInt64 curScanPos = 0;
- CByteDynamicBuffer dynamicBuffer;
- const UInt32 kSearchMarkerBufferSize = 0x10000;
- dynamicBuffer.EnsureCapacity(kSearchMarkerBufferSize);
- Byte *buffer = dynamicBuffer;
- UInt32 numBytesPrev = NSignature::kMarkerSize - 1;
- memcpy(buffer, marker + 1, numBytesPrev);
- UInt64 curTestPos = m_StreamStartPosition + 1;
for (;;)
{
- if (searchHeaderSizeLimit != NULL)
- if (curTestPos - m_StreamStartPosition > *searchHeaderSizeLimit)
- break;
- size_t numReadBytes = kSearchMarkerBufferSize - numBytesPrev;
- RINOK(ReadStream(stream, buffer + numBytesPrev, &numReadBytes));
+ size_t numReadBytes = kBufSize - numBytesInBuffer;
+ RINOK(ReadStream(stream, buffer + numBytesInBuffer, &numReadBytes));
m_Position += numReadBytes;
- UInt32 numBytesInBuffer = numBytesPrev + (UInt32)numReadBytes;
- const UInt32 kMarker2Size = NSignature::kMarkerSize + kNumMarkerAddtionalBytes;
- if (numBytesInBuffer < kMarker2Size)
+ numBytesInBuffer += numReadBytes;
+ bool isFinished = (numBytesInBuffer != kBufSize);
+
+ size_t limit = (isFinished ? numBytesInBuffer : numBytesInBuffer - kCheckSize);
+
+ if (searchLimit && curScanPos + limit > *searchLimit)
+ limit = (size_t)(*searchLimit - curScanPos + 1);
+
+ if (limit < 1)
break;
- UInt32 numTests = numBytesInBuffer - kMarker2Size + 1;
- for (UInt32 pos = 0; pos < numTests; pos++)
+
+ const Byte *buf = buffer;
+ for (size_t pos = 0; pos < limit; pos++)
{
- if (buffer[pos] != 0x50)
+ if (buf[pos] != 0x50)
+ continue;
+ if (buf[pos + 1] != 0x4B)
continue;
- if (TestMarkerCandidate2(buffer + pos, m_Signature))
+ size_t rem = numBytesInBuffer - pos;
+ UInt32 res = IsArc_Zip_2(buf + pos, rem, isFinished);
+ if (res != k_IsArc_Res_NO)
{
- curTestPos += pos;
- ArcInfo.StartPosition = curTestPos;
- m_Position = curTestPos + NSignature::kMarkerSize;
+ if (rem < kMarkerSize)
+ return S_FALSE;
+ m_Signature = Get32(buf + pos);
+ ArcInfo.MarkerPos += curScanPos + pos;
+ ArcInfo.MarkerPos2 = ArcInfo.MarkerPos;
+ if (m_Signature == NSignature::kNoSpan)
+ {
+ m_Signature = Get32(buf + pos + 4);
+ ArcInfo.MarkerPos2 += 4;
+ }
+ m_Position = ArcInfo.MarkerPos2 + kMarkerSize;
return S_OK;
}
}
- curTestPos += numTests;
- numBytesPrev = numBytesInBuffer - numTests;
- memmove(buffer, buffer + numTests, numBytesPrev);
+
+ if (isFinished)
+ break;
+
+ curScanPos += limit;
+ numBytesInBuffer -= limit;
+ memmove(buffer, buffer + limit, numBytesInBuffer);
}
+
return S_FALSE;
}
+HRESULT CInArchive::IncreaseRealPosition(UInt64 addValue)
+{
+ return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position);
+}
+
+class CUnexpectEnd {};
+
HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
{
size_t realProcessedSize = size;
@@ -121,42 +365,35 @@ HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
catch (const CInBufferException &e) { return e.ErrorCode; }
}
else
- result = ReadStream(m_Stream, data, &realProcessedSize);
- if (processedSize != NULL)
+ result = ReadStream(Stream, data, &realProcessedSize);
+ if (processedSize)
*processedSize = (UInt32)realProcessedSize;
m_Position += realProcessedSize;
return result;
}
-void CInArchive::Skip(UInt64 num)
-{
- for (UInt64 i = 0; i < num; i++)
- ReadByte();
-}
-
-void CInArchive::IncreaseRealPosition(UInt64 addValue)
-{
- if (m_Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position) != S_OK)
- throw CInArchiveException(CInArchiveException::kSeekStreamError);
-}
-
-bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
-{
- UInt32 realProcessedSize;
- if (ReadBytes(data, size, &realProcessedSize) != S_OK)
- throw CInArchiveException(CInArchiveException::kReadStreamError);
- return (realProcessedSize == size);
-}
-
-void CInArchive::SafeReadBytes(void *data, UInt32 size)
+void CInArchive::SafeReadBytes(void *data, unsigned size)
{
- if (!ReadBytesAndTestSize(data, size))
- throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
+ size_t processed = size;
+ if (_inBufMode)
+ {
+ processed = _inBuffer.ReadBytes((Byte *)data, size);
+ m_Position += processed;
+ }
+ else
+ {
+ HRESULT result = ReadStream(Stream, data, &processed);
+ m_Position += processed;
+ if (result != S_OK)
+ throw CSystemException(result);
+ }
+ if (processed != size)
+ throw CUnexpectEnd();
}
-void CInArchive::ReadBuffer(CByteBuffer &buffer, UInt32 size)
+void CInArchive::ReadBuffer(CByteBuffer &buffer, unsigned size)
{
- buffer.SetCapacity(size);
+ buffer.Alloc(size);
if (size > 0)
SafeReadBytes(buffer, size);
}
@@ -168,65 +405,73 @@ Byte CInArchive::ReadByte()
return b;
}
-UInt16 CInArchive::ReadUInt16()
-{
- Byte buf[2];
- SafeReadBytes(buf, 2);
- return Get16(buf);
-}
+UInt16 CInArchive::ReadUInt16() { Byte buf[2]; SafeReadBytes(buf, 2); return Get16(buf); }
+UInt32 CInArchive::ReadUInt32() { Byte buf[4]; SafeReadBytes(buf, 4); return Get32(buf); }
+UInt64 CInArchive::ReadUInt64() { Byte buf[8]; SafeReadBytes(buf, 8); return Get64(buf); }
-UInt32 CInArchive::ReadUInt32()
+void CInArchive::Skip(unsigned num)
{
- Byte buf[4];
- SafeReadBytes(buf, 4);
- return Get32(buf);
+ if (_inBufMode)
+ {
+ size_t skip = _inBuffer.Skip(num);
+ m_Position += skip;
+ if (skip != num)
+ throw CUnexpectEnd();
+ }
+ else
+ {
+ for (unsigned i = 0; i < num; i++)
+ ReadByte();
+ }
}
-UInt64 CInArchive::ReadUInt64()
+void CInArchive::Skip64(UInt64 num)
{
- Byte buf[8];
- SafeReadBytes(buf, 8);
- return Get64(buf);
+ for (UInt64 i = 0; i < num; i++)
+ ReadByte();
}
-bool CInArchive::ReadUInt32(UInt32 &value)
-{
- Byte buf[4];
- if (!ReadBytesAndTestSize(buf, 4))
- return false;
- value = Get32(buf);
- return true;
-}
-void CInArchive::ReadFileName(UInt32 nameSize, AString &dest)
+void CInArchive::ReadFileName(unsigned size, AString &s)
{
- if (nameSize == 0)
- dest.Empty();
- char *p = dest.GetBuffer((int)nameSize);
- SafeReadBytes(p, nameSize);
- p[nameSize] = 0;
- dest.ReleaseBuffer();
+ if (size == 0)
+ {
+ s.Empty();
+ return;
+ }
+ char *p = s.GetBuffer(size);
+ SafeReadBytes(p, size);
+ p[size] = 0;
+ s.ReleaseBuffer();
}
-void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,
+bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock,
UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber)
{
extraBlock.Clear();
UInt32 remain = extraSize;
- while(remain >= 4)
+ while (remain >= 4)
{
CExtraSubBlock subBlock;
subBlock.ID = ReadUInt16();
- UInt32 dataSize = ReadUInt16();
+ unsigned dataSize = ReadUInt16();
remain -= 4;
if (dataSize > remain) // it's bug
- dataSize = remain;
+ {
+ HeadersWarning = true;
+ Skip(remain);
+ return false;
+ }
if (subBlock.ID == NFileHeader::NExtraID::kZip64)
{
if (unpackSize == 0xFFFFFFFF)
{
if (dataSize < 8)
- break;
+ {
+ HeadersWarning = true;
+ Skip(remain);
+ return false;
+ }
unpackSize = ReadUInt64();
remain -= 8;
dataSize -= 8;
@@ -255,8 +500,7 @@ void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,
remain -= 4;
dataSize -= 4;
}
- for (UInt32 i = 0; i < dataSize; i++)
- ReadByte();
+ Skip(dataSize);
}
else
{
@@ -265,88 +509,125 @@ void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,
}
remain -= dataSize;
}
+ if (remain != 0)
+ {
+ ExtraMinorError = true;
+ // 7-Zip before 9.31 created incorrect WsAES Extra in folder's local headers.
+ // so we don't return false, but just set warning flag
+ // return false;
+ }
Skip(remain);
+ return true;
}
-HRESULT CInArchive::ReadLocalItem(CItemEx &item)
+bool CInArchive::ReadLocalItem(CItemEx &item)
{
- const int kBufSize = 26;
- Byte p[kBufSize];
- SafeReadBytes(p, kBufSize);
+ const unsigned kPureHeaderSize = kLocalHeaderSize - 4;
+ Byte p[kPureHeaderSize];
+ SafeReadBytes(p, kPureHeaderSize);
+ {
+ unsigned i;
+ for (i = 0; i < kPureHeaderSize && p[i] == 0; i++);
+ if (i == kPureHeaderSize)
+ return false;
+ }
item.ExtractVersion.Version = p[0];
item.ExtractVersion.HostOS = p[1];
item.Flags = Get16(p + 2);
- item.CompressionMethod = Get16(p + 4);
+ item.Method = Get16(p + 4);
item.Time = Get32(p + 6);
- item.FileCRC = Get32(p + 10);
+ item.Crc = Get32(p + 10);
item.PackSize = Get32(p + 14);
- item.UnPackSize = Get32(p + 18);
- UInt32 fileNameSize = Get16(p + 22);
- item.LocalExtraSize = Get16(p + 24);
- ReadFileName(fileNameSize, item.Name);
- item.FileHeaderWithNameSize = 4 + NFileHeader::kLocalBlockSize + fileNameSize;
- if (item.LocalExtraSize > 0)
+ item.Size = Get32(p + 18);
+ unsigned nameSize = Get16(p + 22);
+ unsigned extraSize = Get16(p + 24);
+ ReadFileName(nameSize, item.Name);
+ item.LocalFullHeaderSize = kLocalHeaderSize + (UInt32)nameSize + extraSize;
+
+ /*
+ if (item.IsDir())
+ item.Size = 0; // check It
+ */
+
+ if (extraSize > 0)
{
UInt64 localHeaderOffset = 0;
UInt32 diskStartNumber = 0;
- ReadExtra(item.LocalExtraSize, item.LocalExtra, item.UnPackSize, item.PackSize,
- localHeaderOffset, diskStartNumber);
+ if (!ReadExtra(extraSize, item.LocalExtra, item.Size, item.PackSize,
+ localHeaderOffset, diskStartNumber))
+ return false;
}
- /*
- if (item.IsDir())
- item.UnPackSize = 0; // check It
- */
- return S_OK;
+ if (!CheckDosTime(item.Time))
+ {
+ HeadersWarning = true;
+ // return false;
+ }
+ if (item.Name.Len() != nameSize)
+ return false;
+ return item.LocalFullHeaderSize <= ((UInt32)1 << 16);
}
-static bool FlagsAreSame(CItem &i1, CItem &i2)
+static bool FlagsAreSame(const CItem &i1, const CItem &i2)
{
- if (i1.CompressionMethod != i2.CompressionMethod)
+ if (i1.Method != i2.Method)
return false;
- // i1.Time
-
if (i1.Flags == i2.Flags)
return true;
UInt32 mask = 0xFFFF;
- switch(i1.CompressionMethod)
+ switch(i1.Method)
{
case NFileHeader::NCompressionMethod::kDeflated:
mask = 0x7FF9;
break;
default:
- if (i1.CompressionMethod <= NFileHeader::NCompressionMethod::kImploded)
+ if (i1.Method <= NFileHeader::NCompressionMethod::kImploded)
mask = 0x7FFF;
}
return ((i1.Flags & mask) == (i2.Flags & mask));
}
+static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
+{
+ if (!FlagsAreSame(cdItem, localItem))
+ return false;
+ if (!localItem.HasDescriptor())
+ {
+ if (cdItem.Crc != localItem.Crc ||
+ cdItem.PackSize != localItem.PackSize ||
+ cdItem.Size != localItem.Size)
+ return false;
+ }
+ /* pkzip 2.50 creates incorrect archives. It uses
+ - WIN encoding for name in local header
+ - OEM encoding for name in central header
+ We don't support these strange items. */
+
+ /* if (cdItem.Name.Len() != localItem.Name.Len())
+ return false;
+ */
+ if (cdItem.Name != localItem.Name)
+ return false;
+ return true;
+}
+
HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item)
{
if (item.FromLocal)
return S_OK;
try
{
- RINOK(Seek(ArcInfo.Base + item.LocalHeaderPosition));
+ UInt64 offset = ArcInfo.Base + item.LocalHeaderPos;
+ if (ArcInfo.Base < 0 && (Int64)offset < 0)
+ return S_FALSE;
+ RINOK(Seek(offset));
CItemEx localItem;
if (ReadUInt32() != NSignature::kLocalFileHeader)
return S_FALSE;
- RINOK(ReadLocalItem(localItem));
- if (!FlagsAreSame(item, localItem))
+ ReadLocalItem(localItem);
+ if (!AreItemsEqual(localItem, item))
return S_FALSE;
-
- if ((!localItem.HasDescriptor() &&
- (
- item.FileCRC != localItem.FileCRC ||
- item.PackSize != localItem.PackSize ||
- item.UnPackSize != localItem.UnPackSize
- )
- ) ||
- item.Name.Length() != localItem.Name.Length()
- )
- return S_FALSE;
- item.FileHeaderWithNameSize = localItem.FileHeaderWithNameSize;
- item.LocalExtraSize = localItem.LocalExtraSize;
+ item.LocalFullHeaderSize = localItem.LocalFullHeaderSize;
item.LocalExtra = localItem.LocalExtra;
item.FromLocal = true;
}
@@ -356,53 +637,45 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item)
HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item)
{
- if (item.HasDescriptor())
+ const unsigned kBufSize = (1 << 12);
+ Byte buf[kBufSize];
+
+ UInt32 numBytesInBuffer = 0;
+ UInt32 packedSize = 0;
+
+ for (;;)
{
- const int kBufferSize = (1 << 12);
- Byte buffer[kBufferSize];
-
- UInt32 numBytesInBuffer = 0;
- UInt32 packedSize = 0;
-
- bool descriptorWasFound = false;
- for (;;)
+ UInt32 processedSize;
+ RINOK(ReadBytes(buf + numBytesInBuffer, kBufSize - numBytesInBuffer, &processedSize));
+ numBytesInBuffer += processedSize;
+ if (numBytesInBuffer < kDataDescriptorSize)
+ return S_FALSE;
+ UInt32 i;
+ for (i = 0; i <= numBytesInBuffer - kDataDescriptorSize; i++)
{
- UInt32 processedSize;
- RINOK(ReadBytes(buffer + numBytesInBuffer, kBufferSize - numBytesInBuffer, &processedSize));
- numBytesInBuffer += processedSize;
- if (numBytesInBuffer < NFileHeader::kDataDescriptorSize)
- return S_FALSE;
- UInt32 i;
- for (i = 0; i <= numBytesInBuffer - NFileHeader::kDataDescriptorSize; i++)
+ // descriptor signature field is Info-ZIP's extension to pkware Zip specification.
+ // New ZIP specification also allows descriptorSignature.
+ if (buf[i] != 0x50)
+ continue;
+ // !!!! It must be fixed for Zip64 archives
+ if (Get32(buf + i) == NSignature::kDataDescriptor)
{
- // descriptorSignature field is Info-ZIP's extension
- // to Zip specification.
- UInt32 descriptorSignature = Get32(buffer + i);
-
- // !!!! It must be fixed for Zip64 archives
- UInt32 descriptorPackSize = Get32(buffer + i + 8);
- if (descriptorSignature== NSignature::kDataDescriptor && descriptorPackSize == packedSize + i)
+ UInt32 descriptorPackSize = Get32(buf + i + 8);
+ if (descriptorPackSize == packedSize + i)
{
- descriptorWasFound = true;
- item.FileCRC = Get32(buffer + i + 4);
+ item.Crc = Get32(buf + i + 4);
item.PackSize = descriptorPackSize;
- item.UnPackSize = Get32(buffer + i + 12);
- IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - NFileHeader::kDataDescriptorSize))));
- break;
+ item.Size = Get32(buf + i + 12);
+ return IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - kDataDescriptorSize))));
}
}
- if (descriptorWasFound)
- break;
- packedSize += i;
- int j;
- for (j = 0; i < numBytesInBuffer; i++, j++)
- buffer[j] = buffer[i];
- numBytesInBuffer = j;
}
+ packedSize += i;
+ unsigned j;
+ for (j = 0; i < numBytesInBuffer; i++, j++)
+ buf[j] = buf[i];
+ numBytesInBuffer = j;
}
- else
- IncreaseRealPosition(item.PackSize);
- return S_OK;
}
HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item)
@@ -433,7 +706,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item)
unpackSize = ReadUInt32();
}
- if (crc != item.FileCRC || item.PackSize != packSize || item.UnPackSize != unpackSize)
+ if (crc != item.Crc || item.PackSize != packSize || item.Size != unpackSize)
return S_FALSE;
}
}
@@ -444,106 +717,161 @@ HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item)
HRESULT CInArchive::ReadCdItem(CItemEx &item)
{
item.FromCentral = true;
- const int kBufSize = 42;
- Byte p[kBufSize];
- SafeReadBytes(p, kBufSize);
+ Byte p[kCentralHeaderSize - 4];
+ SafeReadBytes(p, kCentralHeaderSize - 4);
+
item.MadeByVersion.Version = p[0];
item.MadeByVersion.HostOS = p[1];
item.ExtractVersion.Version = p[2];
item.ExtractVersion.HostOS = p[3];
item.Flags = Get16(p + 4);
- item.CompressionMethod = Get16(p + 6);
+ item.Method = Get16(p + 6);
item.Time = Get32(p + 8);
- item.FileCRC = Get32(p + 12);
+ item.Crc = Get32(p + 12);
item.PackSize = Get32(p + 16);
- item.UnPackSize = Get32(p + 20);
- UInt16 headerNameSize = Get16(p + 24);
- UInt16 headerExtraSize = Get16(p + 26);
- UInt16 headerCommentSize = Get16(p + 28);
- UInt32 headerDiskNumberStart = Get16(p + 30);
- item.InternalAttributes = Get16(p + 32);
- item.ExternalAttributes = Get32(p + 34);
- item.LocalHeaderPosition = Get32(p + 38);
- ReadFileName(headerNameSize, item.Name);
+ item.Size = Get32(p + 20);
+ unsigned nameSize = Get16(p + 24);
+ UInt16 extraSize = Get16(p + 26);
+ UInt16 commentSize = Get16(p + 28);
+ UInt32 diskNumberStart = Get16(p + 30);
+ item.InternalAttrib = Get16(p + 32);
+ item.ExternalAttrib = Get32(p + 34);
+ item.LocalHeaderPos = Get32(p + 38);
+ ReadFileName(nameSize, item.Name);
- if (headerExtraSize > 0)
+ if (extraSize > 0)
{
- ReadExtra(headerExtraSize, item.CentralExtra, item.UnPackSize, item.PackSize,
- item.LocalHeaderPosition, headerDiskNumberStart);
+ ReadExtra(extraSize, item.CentralExtra, item.Size, item.PackSize,
+ item.LocalHeaderPos, diskNumberStart);
}
- if (headerDiskNumberStart != 0)
- throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
+ if (diskNumberStart != 0)
+ return E_NOTIMPL;
// May be these strings must be deleted
/*
if (item.IsDir())
- item.UnPackSize = 0;
+ item.Size = 0;
*/
- ReadBuffer(item.Comment, headerCommentSize);
+ ReadBuffer(item.Comment, commentSize);
return S_OK;
}
+void CCdInfo::ParseEcd(const Byte *p)
+{
+ NumEntries = Get16(p + 10);
+ Size = Get32(p + 12);
+ Offset = Get32(p + 16);
+}
+
+void CCdInfo::ParseEcd64(const Byte *p)
+{
+ NumEntries = Get64(p + 24);
+ Size = Get64(p + 40);
+ Offset = Get64(p + 48);
+}
+
HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo)
{
+ if (offset >= ((UInt64)1 << 63))
+ return S_FALSE;
RINOK(Seek(offset));
- const UInt32 kEcd64Size = 56;
- Byte buf[kEcd64Size];
- if (!ReadBytesAndTestSize(buf, kEcd64Size))
+ Byte buf[kEcd64_FullSize];
+
+ RINOK(ReadStream_FALSE(Stream, buf, kEcd64_FullSize));
+
+ if (Get32(buf) != NSignature::kEcd64)
return S_FALSE;
- if (Get32(buf) != NSignature::kZip64EndOfCentralDir)
+ UInt64 mainSize = Get64(buf + 4);
+ if (mainSize < kEcd64_MainSize || mainSize > ((UInt64)1 << 32))
return S_FALSE;
- // cdInfo.NumEntries = Get64(buf + 24);
- cdInfo.Size = Get64(buf + 40);
- cdInfo.Offset = Get64(buf + 48);
+ cdInfo.ParseEcd64(buf);
return S_OK;
}
HRESULT CInArchive::FindCd(CCdInfo &cdInfo)
{
UInt64 endPosition;
- RINOK(m_Stream->Seek(0, STREAM_SEEK_END, &endPosition));
- const UInt32 kBufSizeMax = (1 << 16) + kEcdSize + kZip64EcdLocatorSize;
- CByteBuffer byteBuffer;
- byteBuffer.SetCapacity(kBufSizeMax);
- Byte *buf = byteBuffer;
+ RINOK(Stream->Seek(0, STREAM_SEEK_END, &endPosition));
+
+ const UInt32 kBufSizeMax = ((UInt32)1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize;
UInt32 bufSize = (endPosition < kBufSizeMax) ? (UInt32)endPosition : kBufSizeMax;
if (bufSize < kEcdSize)
return S_FALSE;
+ CByteArr byteBuffer(bufSize);
+
UInt64 startPosition = endPosition - bufSize;
- RINOK(m_Stream->Seek(startPosition, STREAM_SEEK_SET, &m_Position));
+ RINOK(Stream->Seek(startPosition, STREAM_SEEK_SET, &m_Position));
if (m_Position != startPosition)
return S_FALSE;
- if (!ReadBytesAndTestSize(buf, bufSize))
- return S_FALSE;
- for (int i = (int)(bufSize - kEcdSize); i >= 0; i--)
+
+ RINOK(ReadStream_FALSE(Stream, byteBuffer, bufSize));
+
+ const Byte *buf = byteBuffer;
+ for (UInt32 i = bufSize - kEcdSize;; i--)
{
- if (Get32(buf + i) == NSignature::kEndOfCentralDir)
+ if (buf[i] != 0x50)
{
- if (i >= kZip64EcdLocatorSize)
+ if (i == 0) return S_FALSE;
+ i--;
+ if (buf[i] != 0x50)
{
- const Byte *locator = buf + i - kZip64EcdLocatorSize;
- if (Get32(locator) == NSignature::kZip64EndOfCentralDirLocator)
+ if (i == 0) return S_FALSE;
+ continue;
+ }
+ }
+ if (Get32(buf + i) == NSignature::kEcd)
+ {
+ if (i >= kEcd64_FullSize + kEcd64Locator_Size)
+ {
+ const Byte *locator = buf + i - kEcd64Locator_Size;
+ if (Get32(locator) == NSignature::kEcd64Locator &&
+ Get32(locator + 4) == 0) // number of the disk with the start of the zip64 ECD
{
+ // Most of the zip64 use fixed size Zip64 ECD
+
UInt64 ecd64Offset = Get64(locator + 8);
- if (TryEcd64(ecd64Offset, cdInfo) == S_OK)
- return S_OK;
- if (TryEcd64(ArcInfo.StartPosition + ecd64Offset, cdInfo) == S_OK)
+ UInt64 absEcd64 = endPosition - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize);
+ {
+ const Byte *ecd64 = locator - kEcd64_FullSize;
+ if (Get32(ecd64) == NSignature::kEcd64 &&
+ Get64(ecd64 + 4) == kEcd64_MainSize)
+ {
+ cdInfo.ParseEcd64(ecd64);
+ ArcInfo.Base = absEcd64 - ecd64Offset;
+ return S_OK;
+ }
+ }
+
+ // some zip64 use variable size Zip64 ECD.
+ // we try to find it
+ if (absEcd64 != ecd64Offset)
+ {
+ if (TryEcd64(ecd64Offset, cdInfo) == S_OK)
+ {
+ ArcInfo.Base = 0;
+ return S_OK;
+ }
+ }
+ if (ArcInfo.MarkerPos != 0 &&
+ ArcInfo.MarkerPos + ecd64Offset != absEcd64)
{
- ArcInfo.Base = ArcInfo.StartPosition;
- return S_OK;
+ if (TryEcd64(ArcInfo.MarkerPos + ecd64Offset, cdInfo) == S_OK)
+ {
+ ArcInfo.Base = ArcInfo.MarkerPos;
+ return S_OK;
+ }
}
}
}
- if (Get32(buf + i + 4) == 0)
+ if (Get32(buf + i + 4) == 0) // ThisDiskNumber, StartCentralDirectoryDiskNumber;
{
- // cdInfo.NumEntries = GetUInt16(buf + i + 10);
- cdInfo.Size = Get32(buf + i + 12);
- cdInfo.Offset = Get32(buf + i + 16);
- UInt64 curPos = endPosition - bufSize + i;
+ cdInfo.ParseEcd(buf + i);
+ UInt64 absEcdPos = endPosition - bufSize + i;
UInt64 cdEnd = cdInfo.Size + cdInfo.Offset;
- if (curPos != cdEnd)
+ ArcInfo.Base = 0;
+ if (absEcdPos != cdEnd)
{
/*
if (cdInfo.Offset <= 16 && cdInfo.Size != 0)
@@ -553,290 +881,301 @@ HRESULT CInArchive::FindCd(CCdInfo &cdInfo)
}
else
*/
- ArcInfo.Base = curPos - cdEnd;
+ ArcInfo.Base = absEcdPos - cdEnd;
}
return S_OK;
}
}
+ if (i == 0)
+ return S_FALSE;
}
- return S_FALSE;
}
+
HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress)
{
items.Clear();
- RINOK(m_Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position));
+ RINOK(Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position));
if (m_Position != cdOffset)
return S_FALSE;
- if (!_inBuffer.Create(1 << 15))
- return E_OUTOFMEMORY;
- _inBuffer.SetStream(m_Stream);
_inBuffer.Init();
_inBufMode = true;
- while(m_Position - cdOffset < cdSize)
+ while (m_Position - cdOffset < cdSize)
{
if (ReadUInt32() != NSignature::kCentralFileHeader)
return S_FALSE;
CItemEx cdItem;
RINOK(ReadCdItem(cdItem));
items.Add(cdItem);
- if (progress && items.Size() % 1000 == 0)
- RINOK(progress->SetCompleted(items.Size()));
+ if (progress && items.Size() % 1 == 0)
+ RINOK(progress->SetCompletedCD(items.Size()));
}
return (m_Position - cdOffset == cdSize) ? S_OK : S_FALSE;
}
HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress)
{
- ArcInfo.Base = 0;
CCdInfo cdInfo;
RINOK(FindCd(cdInfo));
HRESULT res = S_FALSE;
cdSize = cdInfo.Size;
cdOffset = cdInfo.Offset;
+ if (progress)
+ progress->SetTotalCD(cdInfo.NumEntries);
res = TryReadCd(items, ArcInfo.Base + cdOffset, cdSize, progress);
if (res == S_FALSE && ArcInfo.Base == 0)
{
- res = TryReadCd(items, cdInfo.Offset + ArcInfo.StartPosition, cdSize, progress);
+ res = TryReadCd(items, ArcInfo.MarkerPos + cdOffset, cdSize, progress);
if (res == S_OK)
- ArcInfo.Base = ArcInfo.StartPosition;
+ ArcInfo.Base = ArcInfo.MarkerPos;
}
- if (!ReadUInt32(m_Signature))
- return S_FALSE;
return res;
}
-HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems)
+static HRESULT FindItem(const CObjectVector<CItemEx> &items, UInt64 offset)
{
- items.Clear();
- numCdItems = 0;
- while (m_Signature == NSignature::kLocalFileHeader)
+ unsigned left = 0, right = items.Size();
+ for (;;)
{
- // FSeek points to next byte after signature
- // NFileHeader::CLocalBlock localHeader;
- CItemEx item;
- item.LocalHeaderPosition = m_Position - m_StreamStartPosition - 4; // points to signature;
- RINOK(ReadLocalItem(item));
- item.FromLocal = true;
- ReadLocalItemDescriptor(item);
- items.Add(item);
- if (progress && items.Size() % 100 == 0)
- RINOK(progress->SetCompleted(items.Size()));
- if (!ReadUInt32(m_Signature))
- break;
+ if (left >= right)
+ return -1;
+ unsigned index = (left + right) / 2;
+ UInt64 position = items[index].LocalHeaderPos;
+ if (offset == position)
+ return index;
+ if (offset < position)
+ right = index;
+ else
+ left = index + 1;
}
- cdOffset = m_Position - 4;
- 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;
+}
- CItemEx cdItem;
- RINOK(ReadCdItem(cdItem));
+bool IsStrangeItem(const CItem &item)
+{
+ return item.Name.Len() > (1 << 14) || item.Method > (1 << 8);
+}
- if (i == 0)
+HRESULT CInArchive::ReadLocals(
+ CObjectVector<CItemEx> &items, CProgressVirt *progress)
+{
+ items.Clear();
+ while (m_Signature == NSignature::kLocalFileHeader)
+ {
+ CItemEx item;
+ item.LocalHeaderPos = m_Position - 4 - ArcInfo.MarkerPos;
+ // we write ralative LocalHeaderPos here. Later we can correct it to real Base.
+ try
{
- int j;
- for (j = 0; j < items.Size(); j++)
+ ReadLocalItem(item);
+ item.FromLocal = true;
+ if (item.HasDescriptor())
+ ReadLocalItemDescriptor(item);
+ else
{
- CItemEx &item = items[j];
- if (item.Name == cdItem.Name)
- {
- ArcInfo.Base = item.LocalHeaderPosition - cdItem.LocalHeaderPosition;
- break;
- }
+ RINOK(IncreaseRealPosition(item.PackSize));
}
- if (j == items.Size())
- return S_FALSE;
+ items.Add(item);
+ m_Signature = ReadUInt32();
}
-
- int index;
- int left = 0, right = items.Size();
- for (;;)
+ catch (CUnexpectEnd &)
{
- if (left >= right)
+ if (items.IsEmpty() || items.Size() == 1 && IsStrangeItem(items[0]))
return S_FALSE;
- index = (left + right) / 2;
- UInt64 position = items[index].LocalHeaderPosition - ArcInfo.Base;
- if (cdItem.LocalHeaderPosition == position)
- break;
- if (cdItem.LocalHeaderPosition < position)
- right = index;
- else
- left = index + 1;
+ throw;
}
- CItemEx &item = items[index];
- // item.LocalHeaderPosition = cdItem.LocalHeaderPosition;
- item.MadeByVersion = cdItem.MadeByVersion;
- item.CentralExtra = cdItem.CentralExtra;
-
- if (
- // item.ExtractVersion != cdItem.ExtractVersion ||
- !FlagsAreSame(item, cdItem) ||
- item.FileCRC != cdItem.FileCRC)
- return S_FALSE;
+ if (progress && items.Size() % 1 == 0)
+ RINOK(progress->SetCompletedLocal(items.Size(), item.LocalHeaderPos));
+ }
- if (item.Name.Length() != cdItem.Name.Length() ||
- item.PackSize != cdItem.PackSize ||
- item.UnPackSize != cdItem.UnPackSize
- )
- return S_FALSE;
- item.Name = cdItem.Name;
- item.InternalAttributes = cdItem.InternalAttributes;
- item.ExternalAttributes = cdItem.ExternalAttributes;
- item.Comment = cdItem.Comment;
- item.FromCentral = cdItem.FromCentral;
- if (!ReadUInt32(m_Signature))
+ if (items.Size() == 1 && m_Signature != NSignature::kCentralFileHeader)
+ if (IsStrangeItem(items[0]))
return S_FALSE;
- }
- for (i = 0; i < items.Size(); i++)
- items[i].LocalHeaderPosition -= ArcInfo.Base;
return S_OK;
}
-struct CEcd
-{
- UInt16 thisDiskNumber;
- UInt16 startCDDiskNumber;
- UInt16 numEntriesInCDOnThisDisk;
- UInt16 numEntriesInCD;
- UInt32 cdSize;
- UInt32 cdStartOffset;
- UInt16 commentSize;
- void Parse(const Byte *p);
-};
-
-void CEcd::Parse(const Byte *p)
-{
- thisDiskNumber = Get16(p);
- startCDDiskNumber = Get16(p + 2);
- numEntriesInCDOnThisDisk = Get16(p + 4);
- numEntriesInCD = Get16(p + 6);
- cdSize = Get32(p + 8);
- cdStartOffset = Get32(p + 12);
- commentSize = Get16(p + 16);
-}
-
-struct CEcd64
-{
- UInt16 versionMade;
- UInt16 versionNeedExtract;
- UInt32 thisDiskNumber;
- UInt32 startCDDiskNumber;
- UInt64 numEntriesInCDOnThisDisk;
- UInt64 numEntriesInCD;
- UInt64 cdSize;
- UInt64 cdStartOffset;
- void Parse(const Byte *p);
- CEcd64() { memset(this, 0, sizeof(*this)); }
-};
-
-void CEcd64::Parse(const Byte *p)
-{
- versionMade = Get16(p);
- versionNeedExtract = Get16(p + 2);
- thisDiskNumber = Get32(p + 4);
- startCDDiskNumber = Get32(p + 8);
- numEntriesInCDOnThisDisk = Get64(p + 12);
- numEntriesInCD = Get64(p + 20);
- cdSize = Get64(p + 28);
- cdStartOffset = Get64(p + 36);
-}
#define COPY_ECD_ITEM_16(n) if (!isZip64 || ecd. n != 0xFFFF) ecd64. n = ecd. n;
#define COPY_ECD_ITEM_32(n) if (!isZip64 || ecd. n != 0xFFFFFFFF) ecd64. n = ecd. n;
-HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress)
+HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *progress)
{
- IsOkHeaders = true;
- // m_Signature must be kLocalFileHeaderSignature or
- // kEndOfCentralDirSignature
+ items.Clear();
+
+ // m_Signature must be kLocalFileHeader or kEcd
// m_Position points to next byte after signature
+ RINOK(Stream->Seek(m_Position, STREAM_SEEK_SET, NULL));
- IsZip64 = false;
- items.Clear();
+ if (!_inBuffer.Create(1 << 15))
+ return E_OUTOFMEMORY;
+ _inBuffer.SetStream(Stream);
- UInt64 cdSize, cdStartOffset;
- HRESULT res;
- try
+ bool needReadCd = true;
+ bool localsWereRead = false;
+ if (m_Signature == NSignature::kEcd)
{
- res = ReadCd(items, cdStartOffset, cdSize, progress);
+ // It must be empty archive or backware archive
+ // we don't support backware archive still
+
+ const unsigned kBufSize = kEcdSize - 4;
+ Byte buf[kBufSize];
+ SafeReadBytes(buf, kBufSize);
+ CEcd ecd;
+ ecd.Parse(buf);
+ // if (ecd.cdSize != 0)
+ // Do we need also to support the case where empty zip archive with PK00 uses cdOffset = 4 ??
+ if (!ecd.IsEmptyArc())
+ return S_FALSE;
+
+ ArcInfo.Base = ArcInfo.MarkerPos;
+ needReadCd = false;
+ IsArc = true; // check it: we need more tests?
+ RINOK(Stream->Seek(ArcInfo.MarkerPos2 + 4, STREAM_SEEK_SET, &m_Position));
}
- catch(CInArchiveException &)
+
+ UInt64 cdSize = 0, cdRelatOffset = 0, cdAbsOffset = 0;
+ HRESULT res = S_OK;
+
+ if (needReadCd)
{
- res = S_FALSE;
+ CItemEx firstItem;
+ // try
+ {
+ try
+ {
+ if (!ReadLocalItem(firstItem))
+ return S_FALSE;
+ }
+ catch(CUnexpectEnd &)
+ {
+ return S_FALSE;
+ }
+
+ IsArc = true;
+ res = ReadCd(items, cdRelatOffset, cdSize, progress);
+ if (res == S_OK)
+ m_Signature = ReadUInt32();
+ }
+ // catch() { res = S_FALSE; }
+ if (res != S_FALSE && res != S_OK)
+ return res;
+
+ if (res == S_OK && items.Size() == 0)
+ res = S_FALSE;
+
+ if (res == S_OK)
+ {
+ // we can't read local items here to keep _inBufMode state
+ firstItem.LocalHeaderPos = ArcInfo.MarkerPos2 - ArcInfo.Base;
+ int index = FindItem(items, firstItem.LocalHeaderPos);
+ if (index == -1)
+ res = S_FALSE;
+ else if (!AreItemsEqual(firstItem, items[index]))
+ res = S_FALSE;
+ ArcInfo.CdWasRead = true;
+ ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos;
+ }
}
- if (res != S_FALSE && res != S_OK)
- return res;
- /*
- if (res != S_OK)
- return res;
- res = S_FALSE;
- */
+ CObjectVector<CItemEx> cdItems;
- int numCdItems = items.Size();
+ bool needSetBase = false;
+ unsigned numCdItems = items.Size();
+
if (res == S_FALSE)
{
+ // CD doesn't match firstItem so we clear items and read Locals.
+ items.Clear();
+ localsWereRead = true;
_inBufMode = false;
- ArcInfo.Base = 0;
- RINOK(m_Stream->Seek(ArcInfo.StartPosition, STREAM_SEEK_SET, &m_Position));
- if (m_Position != ArcInfo.StartPosition)
- return S_FALSE;
- if (!ReadUInt32(m_Signature))
- return S_FALSE;
- RINOK(ReadLocalsAndCd(items, progress, cdStartOffset, numCdItems));
- cdSize = (m_Position - 4) - cdStartOffset;
- cdStartOffset -= ArcInfo.Base;
+ ArcInfo.Base = ArcInfo.MarkerPos;
+ RINOK(Stream->Seek(ArcInfo.MarkerPos2, STREAM_SEEK_SET, &m_Position));
+ m_Signature = ReadUInt32();
+
+ RINOK(ReadLocals(items, progress));
+
+ if (m_Signature != NSignature::kCentralFileHeader)
+ {
+ m_Position -= 4;
+ NoCentralDir = true;
+ HeadersError = true;
+ return S_OK;
+ }
+ _inBufMode = true;
+ _inBuffer.Init();
+ cdAbsOffset = m_Position - 4;
+ for (;;)
+ {
+ CItemEx cdItem;
+ RINOK(ReadCdItem(cdItem));
+ cdItems.Add(cdItem);
+ if (progress && cdItems.Size() % 1 == 0)
+ RINOK(progress->SetCompletedCD(items.Size()));
+ m_Signature = ReadUInt32();
+ if (m_Signature != NSignature::kCentralFileHeader)
+ break;
+ }
+
+ cdSize = (m_Position - 4) - cdAbsOffset;
+ needSetBase = true;
+ numCdItems = cdItems.Size();
+
+ if (!cdItems.IsEmpty())
+ {
+ ArcInfo.CdWasRead = true;
+ ArcInfo.FirstItemRelatOffset = cdItems[0].LocalHeaderPos;
+ }
}
CEcd64 ecd64;
bool isZip64 = false;
- UInt64 zip64EcdStartOffset = m_Position - 4 - ArcInfo.Base;
- if (m_Signature == NSignature::kZip64EndOfCentralDir)
+ UInt64 ecd64AbsOffset = m_Position - 4;
+ if (m_Signature == NSignature::kEcd64)
{
IsZip64 = isZip64 = true;
UInt64 recordSize = ReadUInt64();
- const int kBufSize = kZip64EcdSize;
+ const unsigned kBufSize = kEcd64_MainSize;
Byte buf[kBufSize];
SafeReadBytes(buf, kBufSize);
ecd64.Parse(buf);
- Skip(recordSize - kZip64EcdSize);
- if (!ReadUInt32(m_Signature))
- return S_FALSE;
+ Skip64(recordSize - kEcd64_MainSize);
+ m_Signature = ReadUInt32();
+
if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
- throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
+ return E_NOTIMPL;
+
+ if (needSetBase)
+ {
+ ArcInfo.Base = cdAbsOffset - ecd64.cdStartOffset;
+ cdRelatOffset = ecd64.cdStartOffset;
+ needSetBase = false;
+ }
+
if (ecd64.numEntriesInCDOnThisDisk != numCdItems ||
ecd64.numEntriesInCD != numCdItems ||
ecd64.cdSize != cdSize ||
- (ecd64.cdStartOffset != cdStartOffset &&
+ (ecd64.cdStartOffset != cdRelatOffset &&
(!items.IsEmpty())))
return S_FALSE;
}
- if (m_Signature == NSignature::kZip64EndOfCentralDirLocator)
+ if (m_Signature == NSignature::kEcd64Locator)
{
+ if (!isZip64)
+ return S_FALSE;
/* UInt32 startEndCDDiskNumber = */ ReadUInt32();
- UInt64 endCDStartOffset = ReadUInt64();
+ UInt64 ecd64RelatOffset = ReadUInt64();
/* UInt32 numberOfDisks = */ ReadUInt32();
- if (zip64EcdStartOffset != endCDStartOffset)
- return S_FALSE;
- if (!ReadUInt32(m_Signature))
+ if (ecd64AbsOffset != ArcInfo.Base + ecd64RelatOffset)
return S_FALSE;
+ m_Signature = ReadUInt32();
}
- if (m_Signature != NSignature::kEndOfCentralDir)
+ if (m_Signature != NSignature::kEcd)
return S_FALSE;
- const int kBufSize = kEcdSize - 4;
+ const unsigned kBufSize = kEcdSize - 4;
Byte buf[kBufSize];
SafeReadBytes(buf, kBufSize);
CEcd ecd;
@@ -849,47 +1188,119 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *pr
COPY_ECD_ITEM_32(cdSize);
COPY_ECD_ITEM_32(cdStartOffset);
- ReadBuffer(ArcInfo.Comment, ecd.commentSize);
+ if (needSetBase)
+ {
+ ArcInfo.Base = cdAbsOffset - ecd64.cdStartOffset;
+ cdRelatOffset = ecd64.cdStartOffset;
+ needSetBase = false;
+ }
+
+ if (localsWereRead && (UInt64)ArcInfo.Base != ArcInfo.MarkerPos)
+ {
+ UInt64 delta = ArcInfo.MarkerPos - ArcInfo.Base;
+ for (unsigned i = 0; i < items.Size(); i++)
+ items[i].LocalHeaderPos += delta;
+ }
+
+
+ // ---------- merge Central Directory Items ----------
+
+ if (!cdItems.IsEmpty())
+ {
+ for (unsigned i = 0; i < cdItems.Size(); i++)
+ {
+ const CItemEx &cdItem = cdItems[i];
+ int index = FindItem(items, cdItem.LocalHeaderPos);
+ if (index == -1)
+ {
+ items.Add(cdItem);
+ continue;
+ }
+ CItemEx &item = items[index];
+ if (item.Name != cdItem.Name
+ // || item.Name.Len() != cdItem.Name.Len()
+ || item.PackSize != cdItem.PackSize
+ || item.Size != cdItem.Size
+ // item.ExtractVersion != cdItem.ExtractVersion
+ || !FlagsAreSame(item, cdItem)
+ || item.Crc != cdItem.Crc)
+ continue;
+
+ // item.LocalHeaderPos = cdItem.LocalHeaderPos;
+ // item.Name = cdItem.Name;
+ item.MadeByVersion = cdItem.MadeByVersion;
+ item.CentralExtra = cdItem.CentralExtra;
+ item.InternalAttrib = cdItem.InternalAttrib;
+ item.ExternalAttrib = cdItem.ExternalAttrib;
+ item.Comment = cdItem.Comment;
+ item.FromCentral = cdItem.FromCentral;
+ }
+ }
if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
- throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
- if (numCdItems != items.Size())
- IsOkHeaders = false;
- if ((UInt16)ecd64.numEntriesInCDOnThisDisk != ((UInt16)numCdItems) ||
+ return E_NOTIMPL;
+
+ if (isZip64)
+ {
+ if (ecd64.numEntriesInCDOnThisDisk != items.Size())
+ HeadersError = true;
+ }
+ else
+ {
+ // old 7-zip could store 32-bit number of CD items to 16-bit field.
+ if ((UInt16)ecd64.numEntriesInCDOnThisDisk != (UInt16)numCdItems ||
+ (UInt16)ecd64.numEntriesInCDOnThisDisk != (UInt16)items.Size())
+ HeadersError = true;
+ }
+
+ ReadBuffer(ArcInfo.Comment, ecd.commentSize);
+ _inBufMode = false;
+ _inBuffer.Free();
+
+ if (
(UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) ||
(UInt32)ecd64.cdSize != (UInt32)cdSize ||
- ((UInt32)(ecd64.cdStartOffset) != (UInt32)cdStartOffset &&
+ ((UInt32)(ecd64.cdStartOffset) != (UInt32)cdRelatOffset &&
(!items.IsEmpty())))
return S_FALSE;
- _inBufMode = false;
- _inBuffer.Free();
- ArcInfo.FinishPosition = m_Position;
+ // printf("\nOpen OK");
return S_OK;
}
+HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress)
+{
+ HRESULT res;
+ try
+ {
+ res = ReadHeaders2(items, progress);
+ }
+ catch (const CInBufferException &e) { res = e.ErrorCode; }
+ catch (const CUnexpectEnd &)
+ {
+ if (items.IsEmpty())
+ return S_FALSE;
+ UnexpectedEnd = true;
+ res = S_OK;
+ }
+ catch (...)
+ {
+ _inBufMode = false;
+ throw;
+ }
+ ArcInfo.FinishPos = m_Position;
+ _inBufMode = false;
+ return res;
+}
+
ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size)
{
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> stream(streamSpec);
- SeekInArchive(ArcInfo.Base + position);
- streamSpec->SetStream(m_Stream);
+ Stream->Seek(ArcInfo.Base + position, STREAM_SEEK_SET, NULL);
+ streamSpec->SetStream(Stream);
streamSpec->Init(size);
return stream.Detach();
}
-IInStream* CInArchive::CreateStream()
-{
- CMyComPtr<IInStream> stream = m_Stream;
- return stream.Detach();
-}
-
-bool CInArchive::SeekInArchive(UInt64 position)
-{
- UInt64 newPosition;
- if (m_Stream->Seek(position, STREAM_SEEK_SET, &newPosition) != S_OK)
- return false;
- return (newPosition == position);
-}
-
}}
diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h
index 0565339a..f6b349b1 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipIn.h
+++ b/CPP/7zip/Archive/Zip/ZipIn.h
@@ -3,121 +3,187 @@
#ifndef __ZIP_IN_H
#define __ZIP_IN_H
-#include "Common/MyCom.h"
+#include "../../../Common/MyCom.h"
#include "../../IStream.h"
#include "../../Common/InBuffer.h"
#include "ZipHeader.h"
-#include "ZipItemEx.h"
+#include "ZipItem.h"
+
+API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size);
namespace NArchive {
namespace NZip {
-class CInArchiveException
+class CItemEx: public CItem
{
public:
- enum ECauseType
- {
- kUnexpectedEndOfArchive = 0,
- kArchiceHeaderCRCError,
- kFileHeaderCRCError,
- kIncorrectArchive,
- kDataDescroptorsAreNotSupported,
- kMultiVolumeArchiveAreNotSupported,
- kReadStreamError,
- kSeekStreamError
- }
- Cause;
- CInArchiveException(ECauseType cause): Cause(cause) {}
+ UInt32 LocalFullHeaderSize; // including Name and Extra
+
+ UInt64 GetLocalFullSize() const
+ { return LocalFullHeaderSize + PackSize + (HasDescriptor() ? kDataDescriptorSize : 0); }
+ UInt64 GetDataPosition() const
+ { return LocalHeaderPos + LocalFullHeaderSize; };
};
-class CInArchiveInfo
+struct CInArchiveInfo
{
-public:
- UInt64 Base;
- UInt64 StartPosition;
- UInt64 FinishPosition;
+ Int64 Base; /* Base offset of start of archive in stream.
+ Offsets in headers must be calculated from that Base.
+ Base is equal to MarkerPos for normal ZIPs.
+ Base can point to PE stub for some ZIP SFXs.
+ if CentralDir was read,
+ Base can be negative, if start of data is not available,
+ if CentralDirs was not read,
+ Base = ArcInfo.MarkerPos; */
+
+ /* The following *Pos variables contain absolute offsets in Stream */
+ UInt64 MarkerPos; /* Pos of first signature, it can point to PK00 signature
+ = MarkerPos2 in most archives
+ = MarkerPos2 - 4 if there is PK00 signature */
+ UInt64 MarkerPos2; // Pos of first local item signature in stream
+ UInt64 FinishPos; // Finish pos of archive data
+ UInt64 FileEndPos; // Finish pos of stream
+
+ UInt64 FirstItemRelatOffset; /* Relative offset of first local (read from cd) (relative to Base).
+ = 0 in most archives
+ = size of stub for some SFXs */
+ bool CdWasRead;
+
CByteBuffer Comment;
- CInArchiveInfo(): Base(0), StartPosition(0) {}
- UInt64 GetPhySize() const { return FinishPosition - StartPosition; }
+ CInArchiveInfo(): Base(0), MarkerPos(0), MarkerPos2(0), FinishPos(0), FileEndPos(0),
+ FirstItemRelatOffset(0), CdWasRead(false) {}
+
+ UInt64 GetPhySize() const { return FinishPos - Base; }
+ UInt64 GetEmbeddedStubSize() const
+ {
+ if (CdWasRead)
+ return FirstItemRelatOffset;
+ return MarkerPos2 - Base;
+ }
+ bool ThereIsTail() const { return FileEndPos > FinishPos; }
+
void Clear()
{
Base = 0;
- StartPosition = 0;
- Comment.SetCapacity(0);
+ MarkerPos = 0;
+ MarkerPos2 = 0;
+ FinishPos = 0;
+ FileEndPos = 0;
+
+ FirstItemRelatOffset = 0;
+ CdWasRead = false;
+
+ Comment.Free();
}
};
-class CProgressVirt
+struct CProgressVirt
{
-public:
- STDMETHOD(SetTotal)(UInt64 numFiles) PURE;
- STDMETHOD(SetCompleted)(UInt64 numFiles) PURE;
+ virtual HRESULT SetCompletedLocal(UInt64 numFiles, UInt64 numBytes) = 0;
+ virtual HRESULT SetTotalCD(UInt64 numFiles) = 0;
+ virtual HRESULT SetCompletedCD(UInt64 numFiles) = 0;
};
struct CCdInfo
{
- // UInt64 NumEntries;
+ UInt64 NumEntries;
UInt64 Size;
UInt64 Offset;
+
+ void ParseEcd(const Byte *p);
+ void ParseEcd64(const Byte *p);
};
class CInArchive
{
- CMyComPtr<IInStream> m_Stream;
+ CInBuffer _inBuffer;
+ bool _inBufMode;
UInt32 m_Signature;
- UInt64 m_StreamStartPosition;
UInt64 m_Position;
-
- bool _inBufMode;
- CInBuffer _inBuffer;
HRESULT Seek(UInt64 offset);
-
HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
- void ReadFileName(UInt32 nameSize, AString &dest);
-
+ HRESULT IncreaseRealPosition(UInt64 addValue);
+
HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize);
- bool ReadBytesAndTestSize(void *data, UInt32 size);
- void SafeReadBytes(void *data, UInt32 size);
- void ReadBuffer(CByteBuffer &buffer, UInt32 size);
+ void SafeReadBytes(void *data, unsigned size);
+ void ReadBuffer(CByteBuffer &buffer, unsigned size);
Byte ReadByte();
UInt16 ReadUInt16();
UInt32 ReadUInt32();
UInt64 ReadUInt64();
- bool ReadUInt32(UInt32 &signature);
-
- void Skip(UInt64 num);
- void IncreaseRealPosition(UInt64 addValue);
-
- void ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,
+ void Skip(unsigned num);
+ void Skip64(UInt64 num);
+ void ReadFileName(unsigned nameSize, AString &dest);
+
+ bool ReadExtra(unsigned extraSize, CExtraBlock &extraBlock,
UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber);
- HRESULT ReadLocalItem(CItemEx &item);
+ bool ReadLocalItem(CItemEx &item);
HRESULT ReadLocalItemDescriptor(CItemEx &item);
HRESULT ReadCdItem(CItemEx &item);
HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo);
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, int &numCdItems);
+ HRESULT ReadLocals(CObjectVector<CItemEx> &localItems, CProgressVirt *progress);
+
+ HRESULT ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *progress);
public:
CInArchiveInfo ArcInfo;
+
+ bool IsArc;
bool IsZip64;
- bool IsOkHeaders;
-
+ bool HeadersError;
+ bool HeadersWarning;
+ bool ExtraMinorError;
+ bool UnexpectedEnd;
+ bool NoCentralDir;
+
+ CMyComPtr<IInStream> Stream;
+
+ void Close();
+ HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
HRESULT ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress);
+
+ bool IsOpen() const { return Stream != NULL; }
+ bool AreThereErrors() const { return HeadersError || UnexpectedEnd; }
+
+ bool IsLocalOffsetOK(const CItemEx &item) const
+ {
+ if (item.FromLocal)
+ return true;
+ return /* ArcInfo.Base >= 0 || */ ArcInfo.Base + (Int64)item.LocalHeaderPos >= 0;
+ }
+
HRESULT ReadLocalItemAfterCdItem(CItemEx &item);
HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item);
- HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
- void Close();
- bool SeekInArchive(UInt64 position);
+
ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size);
- IInStream* CreateStream();
- bool IsOpen() const { return m_Stream != NULL; }
+ UInt64 GetOffsetInStream(UInt64 offsetFromArc) const { return ArcInfo.Base + offsetFromArc; }
+
+ bool CanUpdate() const
+ {
+ if (AreThereErrors())
+ return false;
+ if (ArcInfo.Base < 0)
+ return false;
+ if ((Int64)ArcInfo.MarkerPos2 < ArcInfo.Base)
+ return false;
+
+ // 7-zip probably can update archives with embedded stubs.
+ // we just disable that feature for more safety.
+ if (ArcInfo.GetEmbeddedStubSize() != 0)
+ return false;
+
+ if (ArcInfo.ThereIsTail())
+ return false;
+ return true;
+ }
};
}}
diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp
index ad89f558..ae88944d 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipItem.cpp
+++ b/CPP/7zip/Archive/Zip/ZipItem.cpp
@@ -10,21 +10,13 @@
namespace NArchive {
namespace NZip {
-bool operator==(const CVersion &v1, const CVersion &v2)
-{
- return (v1.Version == v2.Version) && (v1.HostOS == v2.HostOS);
-}
+using namespace NFileHeader;
-bool operator!=(const CVersion &v1, const CVersion &v2)
-{
- return !(v1 == v2);
-}
-
-bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const
+bool CExtraSubBlock::ExtractNtfsTime(unsigned index, FILETIME &ft) const
{
ft.dwHighDateTime = ft.dwLowDateTime = 0;
- UInt32 size = (UInt32)Data.GetCapacity();
- if (ID != NFileHeader::NExtraID::kNTFS || size < 32)
+ UInt32 size = (UInt32)Data.Size();
+ if (ID != NExtraID::kNTFS || size < 32)
return false;
const Byte *p = (const Byte *)Data;
p += 4; // for reserved
@@ -32,13 +24,13 @@ bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const
while (size > 4)
{
UInt16 tag = GetUi16(p);
- UInt32 attrSize = GetUi16(p + 2);
+ unsigned attrSize = GetUi16(p + 2);
p += 4;
size -= 4;
if (attrSize > size)
attrSize = size;
- if (tag == NFileHeader::NNtfsExtra::kTagTime && attrSize >= 24)
+ if (tag == NNtfsExtra::kTagTime && attrSize >= 24)
{
p += 8 * index;
ft.dwLowDateTime = GetUi32(p);
@@ -51,25 +43,25 @@ bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const
return false;
}
-bool CExtraSubBlock::ExtractUnixTime(bool isCentral, int index, UInt32 &res) const
+bool CExtraSubBlock::ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const
{
res = 0;
- UInt32 size = (UInt32)Data.GetCapacity();
- if (ID != NFileHeader::NExtraID::kUnixTime || size < 5)
+ UInt32 size = (UInt32)Data.Size();
+ if (ID != NExtraID::kUnixTime || size < 5)
return false;
const Byte *p = (const Byte *)Data;
Byte flags = *p++;
size--;
if (isCentral)
{
- if (index != NFileHeader::NUnixTime::kMTime ||
- (flags & (1 << NFileHeader::NUnixTime::kMTime)) == 0 ||
+ if (index != NUnixTime::kMTime ||
+ (flags & (1 << NUnixTime::kMTime)) == 0 ||
size < 4)
return false;
res = GetUi32(p);
return true;
}
- for (int i = 0; i < 3; i++)
+ for (unsigned i = 0; i < 3; i++)
if ((flags & (1 << i)) != 0)
{
if (size < 4)
@@ -96,30 +88,33 @@ bool CItem::IsDir() const
return true;
if (!FromCentral)
return false;
- WORD highAttributes = WORD((ExternalAttributes >> 16 ) & 0xFFFF);
- switch (MadeByVersion.HostOS)
+
+ UInt16 highAttrib = (UInt16)((ExternalAttrib >> 16 ) & 0xFFFF);
+
+ Byte hostOS = GetHostOS();
+ switch (hostOS)
{
- case NFileHeader::NHostOS::kAMIGA:
- switch (highAttributes & NFileHeader::NAmigaAttribute::kIFMT)
+ case NHostOS::kAMIGA:
+ switch (highAttrib & NAmigaAttrib::kIFMT)
{
- case NFileHeader::NAmigaAttribute::kIFDIR: return true;
- case NFileHeader::NAmigaAttribute::kIFREG: return false;
+ case NAmigaAttrib::kIFDIR: return true;
+ case NAmigaAttrib::kIFREG: return false;
default: return false; // change it throw kUnknownAttributes;
}
- case NFileHeader::NHostOS::kFAT:
- case NFileHeader::NHostOS::kNTFS:
- case NFileHeader::NHostOS::kHPFS:
- case NFileHeader::NHostOS::kVFAT:
- return ((ExternalAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
- case NFileHeader::NHostOS::kAtari:
- case NFileHeader::NHostOS::kMac:
- case NFileHeader::NHostOS::kVMS:
- case NFileHeader::NHostOS::kVM_CMS:
- case NFileHeader::NHostOS::kAcorn:
- case NFileHeader::NHostOS::kMVS:
+ case NHostOS::kFAT:
+ case NHostOS::kNTFS:
+ case NHostOS::kHPFS:
+ case NHostOS::kVFAT:
+ return ((ExternalAttrib & FILE_ATTRIBUTE_DIRECTORY) != 0);
+ case NHostOS::kAtari:
+ case NHostOS::kMac:
+ case NHostOS::kVMS:
+ case NHostOS::kVM_CMS:
+ case NHostOS::kAcorn:
+ case NHostOS::kMVS:
return false; // change it throw kUnknownAttributes;
- case NFileHeader::NHostOS::kUnix:
- return (highAttributes & NFileHeader::NUnixAttribute::kIFDIR) != 0;
+ case NHostOS::kUnix:
+ return (highAttrib & NUnixAttrib::kIFDIR) != 0;
default:
return false;
}
@@ -127,13 +122,13 @@ bool CItem::IsDir() const
UInt32 CItem::GetWinAttrib() const
{
- DWORD winAttrib = 0;
- switch (MadeByVersion.HostOS)
+ UInt32 winAttrib = 0;
+ switch (GetHostOS())
{
- case NFileHeader::NHostOS::kFAT:
- case NFileHeader::NHostOS::kNTFS:
+ case NHostOS::kFAT:
+ case NHostOS::kNTFS:
if (FromCentral)
- winAttrib = ExternalAttributes;
+ winAttrib = ExternalAttrib;
break;
}
if (IsDir()) // test it;
@@ -144,35 +139,15 @@ UInt32 CItem::GetWinAttrib() const
bool CItem::GetPosixAttrib(UInt32 &attrib) const
{
// some archivers can store PosixAttrib in high 16 bits even with HostOS=FAT.
- if (FromCentral && MadeByVersion.HostOS == NFileHeader::NHostOS::kUnix)
+ if (FromCentral && GetHostOS() == NHostOS::kUnix)
{
- attrib = ExternalAttributes >> 16;
+ attrib = ExternalAttrib >> 16;
return (attrib != 0);
}
attrib = 0;
if (IsDir())
- attrib = NFileHeader::NUnixAttribute::kIFDIR;
+ attrib = NUnixAttrib::kIFDIR;
return false;
}
-void CLocalItem::SetFlagBits(int startBitNumber, int numBits, int value)
-{
- UInt16 mask = (UInt16)(((1 << numBits) - 1) << startBitNumber);
- Flags &= ~mask;
- Flags |= value << startBitNumber;
-}
-
-void CLocalItem::SetBitMask(int bitMask, bool enable)
-{
- if(enable)
- Flags |= bitMask;
- else
- Flags &= ~bitMask;
-}
-
-void CLocalItem::SetEncrypted(bool encrypted)
- { SetBitMask(NFileHeader::NFlags::kEncrypted, encrypted); }
-void CLocalItem::SetUtf8(bool isUtf8)
- { SetBitMask(NFileHeader::NFlags::kUtf8, isUtf8); }
-
}}
diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h
index 5efd433a..d50c3ae9 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipItem.h
+++ b/CPP/7zip/Archive/Zip/ZipItem.h
@@ -3,10 +3,12 @@
#ifndef __ARCHIVE_ZIP_ITEM_H
#define __ARCHIVE_ZIP_ITEM_H
-#include "Common/MyString.h"
-#include "Common/Buffer.h"
-#include "Common/UTFConvert.h"
-#include "Common/StringConvert.h"
+#include "../../../../C/CpuArch.h"
+
+#include "../../../Common/MyBuffer.h"
+#include "../../../Common/MyString.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/UTFConvert.h"
#include "ZipHeader.h"
@@ -19,25 +21,25 @@ struct CVersion
Byte HostOS;
};
-bool operator==(const CVersion &v1, const CVersion &v2);
-bool operator!=(const CVersion &v1, const CVersion &v2);
-
struct CExtraSubBlock
{
UInt16 ID;
CByteBuffer Data;
- bool ExtractNtfsTime(int index, FILETIME &ft) const;
- bool ExtractUnixTime(bool isCentral, int index, UInt32 &res) const;
+
+ bool ExtractNtfsTime(unsigned index, FILETIME &ft) const;
+ bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const;
};
-struct CWzAesExtraField
+const unsigned k_WzAesExtra_Size = 7;
+
+struct CWzAesExtra
{
- UInt16 VendorVersion; // 0x0001 - AE-1, 0x0002 - AE-2,
- // UInt16 VendorId; // "AE"
- Byte Strength; // 1 - 128-bit , 2 - 192-bit , 3 - 256-bit
+ UInt16 VendorVersion; // 1: AE-1, 2: AE-2,
+ // UInt16 VendorId; // 'A' 'E'
+ Byte Strength; // 1: 128-bit, 2: 192-bit, 3: 256-bit
UInt16 Method;
- CWzAesExtraField(): VendorVersion(2), Strength(3), Method(0) {}
+ CWzAesExtra(): VendorVersion(2), Strength(3), Method(0) {}
bool NeedCrc() const { return (VendorVersion == 1); }
@@ -45,19 +47,21 @@ struct CWzAesExtraField
{
if (sb.ID != NFileHeader::NExtraID::kWzAES)
return false;
- if (sb.Data.GetCapacity() < 7)
+ if (sb.Data.Size() < k_WzAesExtra_Size)
return false;
const Byte *p = (const Byte *)sb.Data;
- VendorVersion = (((UInt16)p[1]) << 8) | p[0];
+ VendorVersion = GetUi16(p);
if (p[2] != 'A' || p[3] != 'E')
return false;
Strength = p[4];
- Method = (((UInt16)p[6]) << 16) | p[5];
+ // 9.31: The BUG was fixed:
+ Method = GetUi16(p + 5);
return true;
}
+
void SetSubBlock(CExtraSubBlock &sb) const
{
- sb.Data.SetCapacity(7);
+ sb.Data.Alloc(k_WzAesExtra_Size);
sb.ID = NFileHeader::NExtraID::kWzAES;
Byte *p = (Byte *)sb.Data;
p[0] = (Byte)VendorVersion;
@@ -70,7 +74,7 @@ struct CWzAesExtraField
}
};
-namespace NStrongCryptoFlags
+namespace NStrongCrypto_AlgId
{
const UInt16 kDES = 0x6601;
const UInt16 kRC2old = 0x6602;
@@ -85,7 +89,7 @@ namespace NStrongCryptoFlags
const UInt16 kRC4 = 0x6801;
}
-struct CStrongCryptoField
+struct CStrongCryptoExtra
{
UInt16 Format;
UInt16 AlgId;
@@ -97,12 +101,12 @@ struct CStrongCryptoField
if (sb.ID != NFileHeader::NExtraID::kStrongEncrypt)
return false;
const Byte *p = (const Byte *)sb.Data;
- if (sb.Data.GetCapacity() < 8)
+ if (sb.Data.Size() < 8)
return false;
- Format = (((UInt16)p[1]) << 8) | p[0];
- AlgId = (((UInt16)p[3]) << 8) | p[2];
- BitLen = (((UInt16)p[5]) << 8) | p[4];
- Flags = (((UInt16)p[7]) << 8) | p[6];
+ Format = GetUi16(p + 0);
+ AlgId = GetUi16(p + 2);
+ BitLen = GetUi16(p + 4);
+ Flags = GetUi16(p + 6);
return (Format == 2);
}
};
@@ -110,39 +114,50 @@ struct CStrongCryptoField
struct CExtraBlock
{
CObjectVector<CExtraSubBlock> SubBlocks;
+
void Clear() { SubBlocks.Clear(); }
+
size_t GetSize() const
{
size_t res = 0;
- for (int i = 0; i < SubBlocks.Size(); i++)
- res += SubBlocks[i].Data.GetCapacity() + 2 + 2;
+ FOR_VECTOR (i, SubBlocks)
+ res += SubBlocks[i].Data.Size() + 2 + 2;
return res;
}
- bool GetWzAesField(CWzAesExtraField &aesField) const
+
+ bool GetWzAes(CWzAesExtra &e) const
{
- for (int i = 0; i < SubBlocks.Size(); i++)
- if (aesField.ParseFromSubBlock(SubBlocks[i]))
+ FOR_VECTOR (i, SubBlocks)
+ if (e.ParseFromSubBlock(SubBlocks[i]))
return true;
return false;
}
- bool GetStrongCryptoField(CStrongCryptoField &f) const
+ bool HasWzAes() const
+ {
+ CWzAesExtra e;
+ return GetWzAes(e);
+ }
+
+ bool GetStrongCrypto(CStrongCryptoExtra &e) const
{
- for (int i = 0; i < SubBlocks.Size(); i++)
- if (f.ParseFromSubBlock(SubBlocks[i]))
+ FOR_VECTOR (i, SubBlocks)
+ if (e.ParseFromSubBlock(SubBlocks[i]))
return true;
return false;
}
- bool HasWzAesField() const
+ /*
+ bool HasStrongCrypto() const
{
- CWzAesExtraField aesField;
- return GetWzAesField(aesField);
+ CStrongCryptoExtra e;
+ return GetStrongCrypto(e);
}
+ */
- bool GetNtfsTime(int index, FILETIME &ft) const
+ bool GetNtfsTime(unsigned index, FILETIME &ft) const
{
- for (int i = 0; i < SubBlocks.Size(); i++)
+ FOR_VECTOR (i, SubBlocks)
{
const CExtraSubBlock &sb = SubBlocks[i];
if (sb.ID == NFileHeader::NExtraID::kNTFS)
@@ -151,9 +166,9 @@ struct CExtraBlock
return false;
}
- bool GetUnixTime(bool isCentral, int index, UInt32 &res) const
+ bool GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const
{
- for (int i = 0; i < SubBlocks.Size(); i++)
+ FOR_VECTOR (i, SubBlocks)
{
const CExtraSubBlock &sb = SubBlocks[i];
if (sb.ID == NFileHeader::NExtraID::kUnixTime)
@@ -162,14 +177,6 @@ struct CExtraBlock
return false;
}
- /*
- bool HasStrongCryptoField() const
- {
- CStrongCryptoField f;
- return GetStrongCryptoField(f);
- }
- */
-
void RemoveUnknownSubBlocks()
{
for (int i = SubBlocks.Size() - 1; i >= 0; i--)
@@ -182,95 +189,134 @@ struct CExtraBlock
class CLocalItem
{
public:
- CVersion ExtractVersion;
UInt16 Flags;
- UInt16 CompressionMethod;
- UInt32 Time;
- UInt32 FileCRC;
+ UInt16 Method;
+ CVersion ExtractVersion;
+
+ UInt64 Size;
UInt64 PackSize;
- UInt64 UnPackSize;
+ UInt32 Time;
+ UInt32 Crc;
AString Name;
CExtraBlock LocalExtra;
bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; }
-
bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; }
bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; };
- bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || CompressionMethod == NFileHeader::NCompressionMethod::kWzAES); };
-
+ bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); };
bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
+ bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
bool IsDir() const;
- bool IgnoreItem() const { return false; }
-
- bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
- UString GetUnicodeString(const AString &s) const
+ /*
+ void GetUnicodeString(const AString &s, UString &res) const
{
- UString res;
- if (IsUtf8())
- if (!ConvertUTF8ToUnicode(s, res))
- res.Empty();
- if (res.IsEmpty())
- res = MultiByteToUnicodeString(s, GetCodePage());
- return res;
+ bool isUtf8 = IsUtf8();
+ if (isUtf8)
+ if (ConvertUTF8ToUnicode(s, res))
+ return;
+ MultiByteToUnicodeString2(res, s, GetCodePage());
}
-
+ */
+
private:
- void SetFlagBits(int startBitNumber, int numBits, int value);
- void SetBitMask(int bitMask, bool enable);
+
+ void SetFlag(unsigned bitMask, bool enable)
+ {
+ if (enable)
+ Flags |= bitMask;
+ else
+ Flags &= ~bitMask;
+ }
+
public:
+
void ClearFlags() { Flags = 0; }
- void SetEncrypted(bool encrypted);
- void SetUtf8(bool isUtf8);
+ void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); }
+ void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); }
- WORD GetCodePage() const { return CP_OEMCP; }
+ UINT GetCodePage() const { return CP_OEMCP; }
};
+
class CItem: public CLocalItem
{
public:
CVersion MadeByVersion;
- UInt16 InternalAttributes;
- UInt32 ExternalAttributes;
+ UInt16 InternalAttrib;
+ UInt32 ExternalAttrib;
- UInt64 LocalHeaderPosition;
+ UInt64 LocalHeaderPos;
- FILETIME NtfsMTime;
- FILETIME NtfsATime;
- FILETIME NtfsCTime;
-
CExtraBlock CentralExtra;
CByteBuffer Comment;
bool FromLocal;
bool FromCentral;
- bool NtfsTimeIsDefined;
+ // CItem can be used as CLocalItem. So we must clear unused fields
+ CItem():
+ InternalAttrib(0),
+ ExternalAttrib(0),
+ FromLocal(false),
+ FromCentral(false)
+ {
+ MadeByVersion.Version = 0;
+ MadeByVersion.HostOS = 0;
+ }
+
bool IsDir() const;
UInt32 GetWinAttrib() const;
bool GetPosixAttrib(UInt32 &attrib) const;
+ Byte GetHostOS() const { return FromCentral ? MadeByVersion.HostOS : ExtractVersion.HostOS; }
+
+ void GetUnicodeString(const AString &s, UString &res, bool useSpecifiedCodePage, UINT codePage) const
+ {
+ bool isUtf8 = IsUtf8();
+
+ #ifdef _WIN32
+ if (!isUtf8)
+ {
+ if (useSpecifiedCodePage)
+ isUtf8 = (codePage == CP_UTF8);
+ else if (GetHostOS() == NFileHeader::NHostOS::kUnix)
+ {
+ /* Some ZIP archives in Unix use UTF-8 encoding without Utf8 flag in header.
+ We try to get name as UTF-8.
+ Do we need to do it in POSIX version also? */
+ isUtf8 = true;
+ }
+ }
+ #endif
+
+ if (isUtf8)
+ if (ConvertUTF8ToUnicode(s, res))
+ return;
+ MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage());
+ }
+
bool IsThereCrc() const
{
- if (CompressionMethod == NFileHeader::NCompressionMethod::kWzAES)
+ if (Method == NFileHeader::NCompressionMethod::kWzAES)
{
- CWzAesExtraField aesField;
- if (CentralExtra.GetWzAesField(aesField))
+ CWzAesExtra aesField;
+ if (CentralExtra.GetWzAes(aesField))
return aesField.NeedCrc();
}
- return (FileCRC != 0 || !IsDir());
+ return (Crc != 0 || !IsDir());
}
- WORD GetCodePage() const
+ UINT GetCodePage() const
{
- return (WORD)((MadeByVersion.HostOS == NFileHeader::NHostOS::kFAT
- || MadeByVersion.HostOS == NFileHeader::NHostOS::kNTFS
- ) ? CP_OEMCP : CP_ACP);
+ Byte hostOS = GetHostOS();
+ return (UINT)((
+ hostOS == NFileHeader::NHostOS::kFAT ||
+ hostOS == NFileHeader::NHostOS::kNTFS) ? CP_OEMCP : CP_ACP);
}
- CItem() : FromLocal(false), FromCentral(false), NtfsTimeIsDefined(false) {}
};
}}
diff --git a/CPP/7zip/Archive/Zip/ZipItemEx.h b/CPP/7zip/Archive/Zip/ZipItemEx.h
deleted file mode 100755
index ab62cdbb..00000000
--- a/CPP/7zip/Archive/Zip/ZipItemEx.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Archive/ZipItemEx.h
-
-#ifndef __ARCHIVE_ZIP_ITEMEX_H
-#define __ARCHIVE_ZIP_ITEMEX_H
-
-#include "ZipHeader.h"
-#include "ZipItem.h"
-
-namespace NArchive {
-namespace NZip {
-
-class CItemEx: public CItem
-{
-public:
- UInt32 FileHeaderWithNameSize;
- UInt16 LocalExtraSize;
-
- UInt64 GetLocalFullSize() const
- { return FileHeaderWithNameSize + LocalExtraSize + PackSize +
- (HasDescriptor() ? NFileHeader::kDataDescriptorSize : 0); };
- /*
- UInt64 GetLocalFullSize(bool isZip64) const
- { return FileHeaderWithNameSize + LocalExtraSize + PackSize +
- (HasDescriptor() ? (isZip64 ? NFileHeader::kDataDescriptor64Size : NFileHeader::kDataDescriptorSize) : 0); };
- */
- UInt64 GetLocalExtraPosition() const
- { return LocalHeaderPosition + FileHeaderWithNameSize; };
- UInt64 GetDataPosition() const
- { return GetLocalExtraPosition() + LocalExtraSize; };
-};
-
-}}
-
-#endif
diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp
index aa82143e..2a1ba2c4 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipOut.cpp
@@ -9,80 +9,93 @@
namespace NArchive {
namespace NZip {
-void COutArchive::Create(IOutStream *outStream)
+HRESULT COutArchive::Create(IOutStream *outStream)
{
+ m_CurPos = 0;
if (!m_OutBuffer.Create(1 << 16))
- throw CSystemException(E_OUTOFMEMORY);
+ return E_OUTOFMEMORY;
m_Stream = outStream;
m_OutBuffer.SetStream(outStream);
m_OutBuffer.Init();
- m_BasePosition = 0;
+
+ return m_Stream->Seek(0, STREAM_SEEK_CUR, &m_Base);
+}
+
+void COutArchive::MoveCurPos(UInt64 distanceToMove)
+{
+ m_CurPos += distanceToMove; // test overflow
}
-void COutArchive::MoveBasePosition(UInt64 distanceToMove)
+void COutArchive::SeekToRelatPos(UInt64 offset)
{
- m_BasePosition += distanceToMove; // test overflow
+ HRESULT res = m_Stream->Seek(m_Base + offset, STREAM_SEEK_SET, NULL);
+ if (res != S_OK)
+ throw CSystemException(res);
}
-void COutArchive::PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption)
+void COutArchive::PrepareWriteCompressedDataZip64(unsigned fileNameLen, bool isZip64, bool aesEncryption)
{
m_IsZip64 = isZip64;
m_ExtraSize = isZip64 ? (4 + 8 + 8) : 0;
if (aesEncryption)
- m_ExtraSize += 4 + 7;
- m_LocalFileHeaderSize = 4 + NFileHeader::kLocalBlockSize + fileNameLength + m_ExtraSize;
+ m_ExtraSize += 4 + k_WzAesExtra_Size;
+ m_LocalFileHeaderSize = kLocalHeaderSize + fileNameLen + m_ExtraSize;
}
-void COutArchive::PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption)
+void COutArchive::PrepareWriteCompressedData(unsigned fileNameLen, UInt64 unPackSize, bool aesEncryption)
{
- // We test it to 0xF8000000 to support case when compressed size
- // can be larger than uncompressed size.
- PrepareWriteCompressedDataZip64(fileNameLength, unPackSize >= 0xF8000000, aesEncryption);
+ // We use Zip64, if unPackSize size is larger than 0xF8000000 to support
+ // cases when compressed size can be about 3% larger than uncompressed size
+
+ PrepareWriteCompressedDataZip64(fileNameLen, unPackSize >= (UInt32)0xF8000000, aesEncryption);
}
-void COutArchive::PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption)
+#define DOES_NEED_ZIP64(v) (v >= (UInt32)0xFFFFFFFF)
+
+void COutArchive::PrepareWriteCompressedData2(unsigned fileNameLen, UInt64 unPackSize, UInt64 packSize, bool aesEncryption)
{
- bool isUnPack64 = unPackSize >= 0xFFFFFFFF;
- bool isPack64 = packSize >= 0xFFFFFFFF;
- bool isZip64 = isPack64 || isUnPack64;
- PrepareWriteCompressedDataZip64(fileNameLength, isZip64, aesEncryption);
+ bool isZip64 =
+ DOES_NEED_ZIP64(unPackSize) ||
+ DOES_NEED_ZIP64(packSize);
+ PrepareWriteCompressedDataZip64(fileNameLen, isZip64, aesEncryption);
}
void COutArchive::WriteBytes(const void *buffer, UInt32 size)
{
m_OutBuffer.WriteBytes(buffer, size);
- m_BasePosition += size;
+ m_CurPos += size;
}
-void COutArchive::WriteByte(Byte b)
+void COutArchive::Write8(Byte b)
{
- WriteBytes(&b, 1);
+ m_OutBuffer.WriteByte(b);
+ m_CurPos++;
}
-void COutArchive::WriteUInt16(UInt16 value)
+void COutArchive::Write16(UInt16 val)
{
for (int i = 0; i < 2; i++)
{
- WriteByte((Byte)value);
- value >>= 8;
+ Write8((Byte)val);
+ val >>= 8;
}
}
-void COutArchive::WriteUInt32(UInt32 value)
+void COutArchive::Write32(UInt32 val)
{
for (int i = 0; i < 4; i++)
{
- WriteByte((Byte)value);
- value >>= 8;
+ Write8((Byte)val);
+ val >>= 8;
}
}
-void COutArchive::WriteUInt64(UInt64 value)
+void COutArchive::Write64(UInt64 val)
{
for (int i = 0; i < 8; i++)
{
- WriteByte((Byte)value);
- value >>= 8;
+ Write8((Byte)val);
+ val >>= 8;
}
}
@@ -90,178 +103,181 @@ void COutArchive::WriteExtra(const CExtraBlock &extra)
{
if (extra.SubBlocks.Size() != 0)
{
- for (int i = 0; i < extra.SubBlocks.Size(); i++)
+ FOR_VECTOR (i, extra.SubBlocks)
{
const CExtraSubBlock &subBlock = extra.SubBlocks[i];
- WriteUInt16(subBlock.ID);
- WriteUInt16((UInt16)subBlock.Data.GetCapacity());
- WriteBytes(subBlock.Data, (UInt32)subBlock.Data.GetCapacity());
+ Write16(subBlock.ID);
+ Write16((UInt16)subBlock.Data.Size());
+ WriteBytes(subBlock.Data, (UInt32)subBlock.Data.Size());
}
}
}
-void COutArchive::SeekTo(UInt64 offset)
+void COutArchive::WriteCommonItemInfo(const CLocalItem &item, bool isZip64)
{
- HRESULT res = m_Stream->Seek(offset, STREAM_SEEK_SET, NULL);
- if (res != S_OK)
- throw CSystemException(res);
+ {
+ Byte ver = item.ExtractVersion.Version;
+ if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64)
+ ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64;
+ Write8(ver);
+ }
+ Write8(item.ExtractVersion.HostOS);
+ Write16(item.Flags);
+ Write16(item.Method);
+ Write32(item.Time);
+ Write32(item.Crc);
}
+#define WRITE_32_VAL_SPEC(__v, __isZip64) Write32((__isZip64) ? 0xFFFFFFFF : (UInt32)(__v));
+
void COutArchive::WriteLocalHeader(const CLocalItem &item)
{
- SeekTo(m_BasePosition);
+ SeekToCurPos();
- bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF;
+ bool isZip64 = m_IsZip64 ||
+ DOES_NEED_ZIP64(item.PackSize) ||
+ DOES_NEED_ZIP64(item.Size);
- WriteUInt32(NSignature::kLocalFileHeader);
- {
- Byte ver = item.ExtractVersion.Version;
- if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64)
- ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64;
- WriteByte(ver);
- }
- WriteByte(item.ExtractVersion.HostOS);
- WriteUInt16(item.Flags);
- WriteUInt16(item.CompressionMethod);
- WriteUInt32(item.Time);
- WriteUInt32(item.FileCRC);
- WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.PackSize);
- WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize);
- WriteUInt16((UInt16)item.Name.Length());
+ Write32(NSignature::kLocalFileHeader);
+ WriteCommonItemInfo(item, isZip64);
+
+ WRITE_32_VAL_SPEC(item.PackSize, isZip64);
+ WRITE_32_VAL_SPEC(item.Size, isZip64);
+
+ Write16((UInt16)item.Name.Len());
{
- UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 16): 0) + item.LocalExtra.GetSize());
- if (localExtraSize > m_ExtraSize)
+ UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 8 + 8): 0) + item.LocalExtra.GetSize());
+ if (localExtraSize != m_ExtraSize)
throw CSystemException(E_FAIL);
}
- WriteUInt16((UInt16)m_ExtraSize); // test it;
- WriteBytes((const char *)item.Name, item.Name.Length());
+ Write16((UInt16)m_ExtraSize);
+ WriteBytes((const char *)item.Name, item.Name.Len());
- UInt32 extraPos = 0;
if (isZip64)
{
- extraPos += 4 + 16;
- WriteUInt16(NFileHeader::NExtraID::kZip64);
- WriteUInt16(16);
- WriteUInt64(item.UnPackSize);
- WriteUInt64(item.PackSize);
+ Write16(NFileHeader::NExtraID::kZip64);
+ Write16(8 + 8);
+ Write64(item.Size);
+ Write64(item.PackSize);
}
WriteExtra(item.LocalExtra);
- extraPos += (UInt32)item.LocalExtra.GetSize();
- for (; extraPos < m_ExtraSize; extraPos++)
- WriteByte(0);
+
+ // Why don't we write NTFS timestamps to local header?
+ // Probably we want to reduce size of archive?
m_OutBuffer.FlushWithCheck();
- MoveBasePosition(item.PackSize);
- SeekTo(m_BasePosition);
+ MoveCurPos(item.PackSize);
}
-void COutArchive::WriteCentralHeader(const CItem &item)
+void COutArchive::WriteCentralHeader(const CItemOut &item)
{
- bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF;
- bool isPack64 = item.PackSize >= 0xFFFFFFFF;
- bool isPosition64 = item.LocalHeaderPosition >= 0xFFFFFFFF;
- bool isZip64 = isPack64 || isUnPack64 || isPosition64;
+ bool isUnPack64 = DOES_NEED_ZIP64(item.Size);
+ bool isPack64 = DOES_NEED_ZIP64(item.PackSize);
+ bool isPosition64 = DOES_NEED_ZIP64(item.LocalHeaderPos);
+ bool isZip64 = isPack64 || isUnPack64 || isPosition64;
- WriteUInt32(NSignature::kCentralFileHeader);
- WriteByte(item.MadeByVersion.Version);
- WriteByte(item.MadeByVersion.HostOS);
- {
- Byte ver = item.ExtractVersion.Version;
- if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64)
- ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64;
- WriteByte(ver);
- }
- WriteByte(item.ExtractVersion.HostOS);
- WriteUInt16(item.Flags);
- WriteUInt16(item.CompressionMethod);
- WriteUInt32(item.Time);
- WriteUInt32(item.FileCRC);
- WriteUInt32(isPack64 ? 0xFFFFFFFF: (UInt32)item.PackSize);
- WriteUInt32(isUnPack64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize);
- WriteUInt16((UInt16)item.Name.Length());
- UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0));
+ Write32(NSignature::kCentralFileHeader);
+ Write8(item.MadeByVersion.Version);
+ Write8(item.MadeByVersion.HostOS);
+
+ WriteCommonItemInfo(item, isZip64);
+
+ WRITE_32_VAL_SPEC(item.PackSize, isPack64);
+ WRITE_32_VAL_SPEC(item.Size, isUnPack64);
+
+ Write16((UInt16)item.Name.Len());
+
+ UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0));
const UInt16 kNtfsExtraSize = 4 + 2 + 2 + (3 * 8);
- UInt16 centralExtraSize = (UInt16)(isZip64 ? (4 + zip64ExtraSize) : 0) + (item.NtfsTimeIsDefined ? (4 + kNtfsExtraSize) : 0);
- centralExtraSize = (UInt16)(centralExtraSize + item.CentralExtra.GetSize());
- WriteUInt16(centralExtraSize); // test it;
- WriteUInt16((UInt16)item.Comment.GetCapacity());
- WriteUInt16(0); // DiskNumberStart;
- WriteUInt16(item.InternalAttributes);
- WriteUInt32(item.ExternalAttributes);
- WriteUInt32(isPosition64 ? 0xFFFFFFFF: (UInt32)item.LocalHeaderPosition);
- WriteBytes((const char *)item.Name, item.Name.Length());
+ const UInt16 centralExtraSize = (UInt16)(
+ (isZip64 ? 4 + zip64ExtraSize : 0) +
+ (item.NtfsTimeIsDefined ? 4 + kNtfsExtraSize : 0) +
+ item.CentralExtra.GetSize());
+
+ Write16(centralExtraSize); // test it;
+ Write16((UInt16)item.Comment.Size());
+ Write16(0); // DiskNumberStart;
+ Write16(item.InternalAttrib);
+ Write32(item.ExternalAttrib);
+ WRITE_32_VAL_SPEC(item.LocalHeaderPos, isPosition64);
+ WriteBytes((const char *)item.Name, item.Name.Len());
+
if (isZip64)
{
- WriteUInt16(NFileHeader::NExtraID::kZip64);
- WriteUInt16(zip64ExtraSize);
- if(isUnPack64)
- WriteUInt64(item.UnPackSize);
- if(isPack64)
- WriteUInt64(item.PackSize);
- if(isPosition64)
- WriteUInt64(item.LocalHeaderPosition);
+ Write16(NFileHeader::NExtraID::kZip64);
+ Write16(zip64ExtraSize);
+ if (isUnPack64)
+ Write64(item.Size);
+ if (isPack64)
+ Write64(item.PackSize);
+ if (isPosition64)
+ Write64(item.LocalHeaderPos);
}
+
if (item.NtfsTimeIsDefined)
{
- WriteUInt16(NFileHeader::NExtraID::kNTFS);
- WriteUInt16(kNtfsExtraSize);
- WriteUInt32(0); // reserved
- WriteUInt16(NFileHeader::NNtfsExtra::kTagTime);
- WriteUInt16(8 * 3);
- WriteUInt32(item.NtfsMTime.dwLowDateTime);
- WriteUInt32(item.NtfsMTime.dwHighDateTime);
- WriteUInt32(item.NtfsATime.dwLowDateTime);
- WriteUInt32(item.NtfsATime.dwHighDateTime);
- WriteUInt32(item.NtfsCTime.dwLowDateTime);
- WriteUInt32(item.NtfsCTime.dwHighDateTime);
+ Write16(NFileHeader::NExtraID::kNTFS);
+ Write16(kNtfsExtraSize);
+ Write32(0); // reserved
+ Write16(NFileHeader::NNtfsExtra::kTagTime);
+ Write16(8 * 3);
+ WriteNtfsTime(item.Ntfs_MTime);
+ WriteNtfsTime(item.Ntfs_ATime);
+ WriteNtfsTime(item.Ntfs_CTime);
}
+
WriteExtra(item.CentralExtra);
- if (item.Comment.GetCapacity() > 0)
- WriteBytes(item.Comment, (UInt32)item.Comment.GetCapacity());
+ if (item.Comment.Size() > 0)
+ WriteBytes(item.Comment, (UInt32)item.Comment.Size());
}
-void COutArchive::WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer *comment)
+void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment)
{
- SeekTo(m_BasePosition);
+ SeekToCurPos();
- UInt64 cdOffset = GetCurrentPosition();
- for(int i = 0; i < items.Size(); i++)
+ UInt64 cdOffset = GetCurPos();
+ FOR_VECTOR (i, items)
WriteCentralHeader(items[i]);
- UInt64 cd64EndOffset = GetCurrentPosition();
+ UInt64 cd64EndOffset = GetCurPos();
UInt64 cdSize = cd64EndOffset - cdOffset;
- bool cdOffset64 = cdOffset >= 0xFFFFFFFF;
- bool cdSize64 = cdSize >= 0xFFFFFFFF;
+ bool cdOffset64 = DOES_NEED_ZIP64(cdOffset);
+ bool cdSize64 = DOES_NEED_ZIP64(cdSize);
bool items64 = items.Size() >= 0xFFFF;
bool isZip64 = (cdOffset64 || cdSize64 || items64);
+
+ // isZip64 = true; // to test Zip64
if (isZip64)
{
- WriteUInt32(NSignature::kZip64EndOfCentralDir);
- WriteUInt64(kZip64EcdSize); // ThisDiskNumber = 0;
- WriteUInt16(45); // version
- WriteUInt16(45); // version
- WriteUInt32(0); // ThisDiskNumber = 0;
- WriteUInt32(0); // StartCentralDirectoryDiskNumber;;
- WriteUInt64((UInt64)items.Size());
- WriteUInt64((UInt64)items.Size());
- WriteUInt64((UInt64)cdSize);
- WriteUInt64((UInt64)cdOffset);
-
- WriteUInt32(NSignature::kZip64EndOfCentralDirLocator);
- WriteUInt32(0); // number of the disk with the start of the zip64 end of central directory
- WriteUInt64(cd64EndOffset);
- WriteUInt32(1); // total number of disks
+ Write32(NSignature::kEcd64);
+ Write64(kEcd64_MainSize);
+ Write16(45); // made by version
+ Write16(45); // extract version
+ Write32(0); // ThisDiskNumber = 0;
+ Write32(0); // StartCentralDirectoryDiskNumber;;
+ Write64((UInt64)items.Size());
+ Write64((UInt64)items.Size());
+ Write64((UInt64)cdSize);
+ Write64((UInt64)cdOffset);
+
+ Write32(NSignature::kEcd64Locator);
+ Write32(0); // number of the disk with the start of the zip64 end of central directory
+ Write64(cd64EndOffset);
+ Write32(1); // total number of disks
}
- WriteUInt32(NSignature::kEndOfCentralDir);
- WriteUInt16(0); // ThisDiskNumber = 0;
- WriteUInt16(0); // StartCentralDirectoryDiskNumber;
- WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size()));
- WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size()));
- WriteUInt32(cdSize64 ? 0xFFFFFFFF: (UInt32)cdSize);
- WriteUInt32(cdOffset64 ? 0xFFFFFFFF: (UInt32)cdOffset);
- UInt32 commentSize = (UInt32)(comment ? comment->GetCapacity() : 0);
- WriteUInt16((UInt16)commentSize);
+
+ Write32(NSignature::kEcd);
+ Write16(0); // ThisDiskNumber = 0;
+ Write16(0); // StartCentralDirectoryDiskNumber;
+ Write16((UInt16)(items64 ? 0xFFFF: items.Size()));
+ Write16((UInt16)(items64 ? 0xFFFF: items.Size()));
+
+ WRITE_32_VAL_SPEC(cdSize, cdSize64);
+ WRITE_32_VAL_SPEC(cdOffset, cdOffset64);
+
+ UInt32 commentSize = (UInt32)(comment ? comment->Size() : 0);
+ Write16((UInt16)commentSize);
if (commentSize > 0)
WriteBytes((const Byte *)*comment, commentSize);
m_OutBuffer.FlushWithCheck();
@@ -271,14 +287,21 @@ void COutArchive::CreateStreamForCompressing(IOutStream **outStream)
{
COffsetOutStream *streamSpec = new COffsetOutStream;
CMyComPtr<IOutStream> tempStream(streamSpec);
- streamSpec->Init(m_Stream, m_BasePosition + m_LocalFileHeaderSize);
+ streamSpec->Init(m_Stream, m_Base + m_CurPos + m_LocalFileHeaderSize);
*outStream = tempStream.Detach();
}
+/*
void COutArchive::SeekToPackedDataPosition()
{
SeekTo(m_BasePosition + m_LocalFileHeaderSize);
}
+*/
+
+void COutArchive::SeekToCurPos()
+{
+ SeekToRelatPos(m_CurPos);
+}
void COutArchive::CreateStreamForCopying(ISequentialOutStream **outStream)
{
diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h
index 2f6349e5..eaaa0320 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipOut.h
+++ b/CPP/7zip/Archive/Zip/ZipOut.h
@@ -3,7 +3,7 @@
#ifndef __ZIP_OUT_H
#define __ZIP_OUT_H
-#include "Common/MyCom.h"
+#include "../../../Common/MyCom.h"
#include "../../IStream.h"
#include "../../Common/OutBuffer.h"
@@ -14,41 +14,73 @@ namespace NArchive {
namespace NZip {
// can throw CSystemException and COutBufferException
-
+
+class CItemOut: public CItem
+{
+public:
+ FILETIME Ntfs_MTime;
+ FILETIME Ntfs_ATime;
+ FILETIME Ntfs_CTime;
+ bool NtfsTimeIsDefined;
+
+ // It's possible that NtfsTime is not defined, but there is NtfsTime in Extra.
+
+ CItemOut(): NtfsTimeIsDefined(false) {}
+};
+
class COutArchive
{
CMyComPtr<IOutStream> m_Stream;
COutBuffer m_OutBuffer;
- UInt64 m_BasePosition;
+ UInt64 m_Base; // Base of arc (offset in output Stream)
+ UInt64 m_CurPos; // Curent position in archive (relative from m_Base)
+
UInt32 m_LocalFileHeaderSize;
UInt32 m_ExtraSize;
bool m_IsZip64;
+ void SeekToRelatPos(UInt64 offset);
+
void WriteBytes(const void *buffer, UInt32 size);
- void WriteByte(Byte b);
- void WriteUInt16(UInt16 value);
- void WriteUInt32(UInt32 value);
- void WriteUInt64(UInt64 value);
+ void Write8(Byte b);
+ void Write16(UInt16 val);
+ void Write32(UInt32 val);
+ void Write64(UInt64 val);
+ void WriteNtfsTime(const FILETIME &ft)
+ {
+ Write32(ft.dwLowDateTime);
+ Write32(ft.dwHighDateTime);
+ }
- void WriteExtraHeader(const CItem &item);
- void WriteCentralHeader(const CItem &item);
void WriteExtra(const CExtraBlock &extra);
- void SeekTo(UInt64 offset);
+ void WriteCommonItemInfo(const CLocalItem &item, bool isZip64);
+ void WriteCentralHeader(const CItemOut &item);
+
+ void PrepareWriteCompressedDataZip64(unsigned fileNameLen, bool isZip64, bool aesEncryption);
+
public:
- void Create(IOutStream *outStream);
- void MoveBasePosition(UInt64 distanceToMove);
- UInt64 GetCurrentPosition() const { return m_BasePosition; };
- void PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption);
- void PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption);
- void PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption);
+ HRESULT Create(IOutStream *outStream);
+
+ void MoveCurPos(UInt64 distanceToMove);
+ UInt64 GetCurPos() const { return m_CurPos; };
+
+ void SeekToCurPos();
+
+ void PrepareWriteCompressedData(unsigned fileNameLen, UInt64 unPackSize, bool aesEncryption);
+ void PrepareWriteCompressedData2(unsigned fileNameLen, UInt64 unPackSize, UInt64 packSize, bool aesEncryption);
void WriteLocalHeader(const CLocalItem &item);
- void WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer *comment);
+ void WriteLocalHeader_And_SeekToNextFile(const CLocalItem &item)
+ {
+ WriteLocalHeader(item);
+ SeekToCurPos();
+ }
+
+ void WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment);
void CreateStreamForCompressing(IOutStream **outStream);
void CreateStreamForCopying(ISequentialOutStream **outStream);
- void SeekToPackedDataPosition();
};
}}
diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp
index 3e7aade8..545e76c6 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipRegister.cpp
+++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp
@@ -5,14 +5,27 @@
#include "../../Common/RegisterArc.h"
#include "ZipHandler.h"
-static IInArchive *CreateArc() { return new NArchive::NZip::CHandler; }
-#ifndef EXTRACT_ONLY
-static IOutArchive *CreateArcOut() { return new NArchive::NZip::CHandler; }
-#else
-#define CreateArcOut 0
-#endif
+
+namespace NArchive {
+namespace NZip {
+
+IMP_CreateArcIn
+IMP_CreateArcOut
static CArcInfo g_ArcInfo =
- { L"zip", L"zip jar xpi odt ods docx xlsx", 0, 1, { 0x50, 0x4B, 0x03, 0x04 }, 4, false, CreateArc, CreateArcOut };
+ { "zip", "zip zipx jar xpi odt ods docx xlsx epub", 0, 1,
+ 3 + 4 + 4 + 6,
+ {
+ 4, 0x50, 0x4B, 0x03, 0x04,
+ 4, 0x50, 0x4B, 0x05, 0x06,
+ 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B,
+ },
+ 0,
+ NArcInfoFlags::kFindSignature |
+ NArcInfoFlags::kMultiSignature |
+ NArcInfoFlags::kUseGlobalOffset,
+ REF_CreateArc_Pair, IsArc_Zip };
REGISTER_ARC(Zip)
+
+}}
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index a91364be..2978e387 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -4,12 +4,12 @@
#include "../../../../C/Alloc.h"
-#include "Common/AutoPtr.h"
-#include "Common/Defs.h"
-#include "Common/StringConvert.h"
+#include "../../../Common/AutoPtr.h"
+#include "../../../Common/Defs.h"
+#include "../../../Common/StringConvert.h"
-#include "Windows/Defs.h"
-#include "Windows/Thread.h"
+#include "../../../Windows/Defs.h"
+#include "../../../Windows/Thread.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/LimitedStreams.h"
@@ -44,12 +44,12 @@ static const Byte kExtractHostOS = kHostOS;
static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStored;
-static HRESULT CopyBlockToArchive(ISequentialInStream *inStream,
+static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, UInt64 size,
COutArchive &outArchive, ICompressProgressInfo *progress)
{
CMyComPtr<ISequentialOutStream> outStream;
outArchive.CreateStreamForCopying(&outStream);
- return NCompress::CopyStream(inStream, outStream, progress);
+ return NCompress::CopyStream_ExactSize(inStream, outStream, size, progress);
}
static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive,
@@ -57,13 +57,7 @@ static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive,
{
UInt64 position;
RINOK(inStream->Seek(range.Position, STREAM_SEEK_SET, &position));
-
- CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
- CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
- streamSpec->SetStream(inStream);
- streamSpec->Init(range.Size);
-
- RINOK(CopyBlockToArchive(inStreamLimited, outArchive, progress));
+ RINOK(CopyBlockToArchive(inStream, range.Size, outArchive, progress));
return progress->SetRatioInfo(&range.Size, &range.Size);
}
@@ -71,42 +65,42 @@ static void SetFileHeader(
COutArchive &archive,
const CCompressionMethodMode &options,
const CUpdateItem &ui,
- CItem &item)
+ CItemOut &item)
{
- item.UnPackSize = ui.Size;
+ item.Size = ui.Size;
bool isDir;
item.ClearFlags();
- if (ui.NewProperties)
+ if (ui.NewProps)
{
isDir = ui.IsDir;
item.Name = ui.Name;
item.SetUtf8(ui.IsUtf8);
- item.ExternalAttributes = ui.Attributes;
+ item.ExternalAttrib = ui.Attrib;
item.Time = ui.Time;
- item.NtfsMTime = ui.NtfsMTime;
- item.NtfsATime = ui.NtfsATime;
- item.NtfsCTime = ui.NtfsCTime;
+ item.Ntfs_MTime = ui.Ntfs_MTime;
+ item.Ntfs_ATime = ui.Ntfs_ATime;
+ item.Ntfs_CTime = ui.Ntfs_CTime;
item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined;
}
else
isDir = item.IsDir();
- item.LocalHeaderPosition = archive.GetCurrentPosition();
+ item.LocalHeaderPos = archive.GetCurPos();
item.MadeByVersion.HostOS = kMadeByHostOS;
item.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion;
item.ExtractVersion.HostOS = kExtractHostOS;
- item.InternalAttributes = 0; // test it
+ item.InternalAttrib = 0; // test it
item.SetEncrypted(!isDir && options.PasswordIsDefined);
if (isDir)
{
item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;
- item.CompressionMethod = kMethodForDirectory;
+ item.Method = kMethodForDirectory;
item.PackSize = 0;
- item.FileCRC = 0; // test it
+ item.Crc = 0; // test it
}
}
@@ -114,9 +108,9 @@ static void SetItemInfoFromCompressingResult(const CCompressingResult &compressi
bool isAesMode, Byte aesKeyMode, CItem &item)
{
item.ExtractVersion.Version = compressingResult.ExtractVersion;
- item.CompressionMethod = compressingResult.Method;
- item.FileCRC = compressingResult.CRC;
- item.UnPackSize = compressingResult.UnpackSize;
+ item.Method = compressingResult.Method;
+ item.Crc = compressingResult.CRC;
+ item.Size = compressingResult.UnpackSize;
item.PackSize = compressingResult.PackSize;
item.LocalExtra.Clear();
@@ -124,11 +118,11 @@ static void SetItemInfoFromCompressingResult(const CCompressingResult &compressi
if (isAesMode)
{
- CWzAesExtraField wzAesField;
+ CWzAesExtra wzAesField;
wzAesField.Strength = aesKeyMode;
wzAesField.Method = compressingResult.Method;
- item.CompressionMethod = NFileHeader::NCompressionMethod::kWzAES;
- item.FileCRC = 0;
+ item.Method = NFileHeader::NCompressionMethod::kWzAES;
+ item.Crc = 0;
CExtraSubBlock sb;
wzAesField.SetSubBlock(sb);
item.LocalExtra.SubBlocks.Add(sb);
@@ -142,10 +136,7 @@ static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo);
struct CThreadInfo
{
- #ifdef EXTERNAL_CODECS
- CMyComPtr<ICompressCodecsInfo> _codecsInfo;
- const CObjectVector<CCodecInfoEx> *_externalCodecs;
- #endif
+ DECL_EXTERNAL_CODECS_LOC_VARS2;
NWindows::CThread Thread;
NWindows::NSynchronization::CAutoResetEvent CompressEvent;
@@ -202,9 +193,7 @@ void CThreadInfo::WaitAndCode()
if (ExitThread)
return;
Result = Coder.Compress(
- #ifdef EXTERNAL_CODECS
- _codecsInfo, _externalCodecs,
- #endif
+ EXTERNAL_CODECS_LOC_VARS
InStream, OutStream, Progress, CompressingResult);
if (Result == S_OK && Progress)
Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize);
@@ -224,7 +213,7 @@ public:
CObjectVector<CThreadInfo> Threads;
~CThreads()
{
- for (int i = 0; i < Threads.Size(); i++)
+ FOR_VECTOR (i, Threads)
Threads[i].StopWaitClose();
}
};
@@ -245,7 +234,7 @@ public:
CMemRefs(CMemBlockManagerMt *manager): Manager(manager) {} ;
~CMemRefs()
{
- for (int i = 0; i < Refs.Size(); i++)
+ FOR_VECTOR (i, Refs)
Refs[i].FreeOpt(Manager);
}
};
@@ -335,69 +324,74 @@ STDMETHODIMP CMtProgressMixer::SetRatioInfo(const UInt64 *inSize, const UInt64 *
#endif
-static HRESULT UpdateItemOldData(COutArchive &archive,
- IInStream *inStream,
- const CUpdateItem &ui, CItemEx &item,
+static HRESULT UpdateItemOldData(
+ COutArchive &archive,
+ CInArchive *inArchive,
+ const CItemEx &itemEx,
+ const CUpdateItem &ui,
+ CItemOut &item,
/* bool izZip64, */
ICompressProgressInfo *progress,
UInt64 &complexity)
{
- if (ui.NewProperties)
+ if (ui.NewProps)
{
if (item.HasDescriptor())
return E_NOTIMPL;
// use old name size.
// CUpdateRange range(item.GetLocalExtraPosition(), item.LocalExtraSize + item.PackSize);
- CUpdateRange range(item.GetDataPosition(), item.PackSize);
+ CUpdateRange range(inArchive->GetOffsetInStream(itemEx.GetDataPosition()), itemEx.PackSize);
- // item.ExternalAttributes = ui.Attributes;
- // Test it
+ // we keep ExternalAttrib and some another properties from old archive
+ // item.ExternalAttrib = ui.Attrib;
+
item.Name = ui.Name;
item.SetUtf8(ui.IsUtf8);
item.Time = ui.Time;
- item.NtfsMTime = ui.NtfsMTime;
- item.NtfsATime = ui.NtfsATime;
- item.NtfsCTime = ui.NtfsCTime;
+ item.Ntfs_MTime = ui.Ntfs_MTime;
+ item.Ntfs_ATime = ui.Ntfs_ATime;
+ item.Ntfs_CTime = ui.Ntfs_CTime;
item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined;
item.CentralExtra.RemoveUnknownSubBlocks();
item.LocalExtra.RemoveUnknownSubBlocks();
-
- archive.PrepareWriteCompressedData2((UInt16)item.Name.Length(), item.UnPackSize, item.PackSize, item.LocalExtra.HasWzAesField());
- item.LocalHeaderPosition = archive.GetCurrentPosition();
- archive.SeekToPackedDataPosition();
- RINOK(WriteRange(inStream, archive, range, progress));
- complexity += range.Size;
+ item.LocalHeaderPos = archive.GetCurPos();
+
+ archive.PrepareWriteCompressedData2(item.Name.Len(), item.Size, item.PackSize, item.LocalExtra.HasWzAes());
archive.WriteLocalHeader(item);
+ RINOK(WriteRange(inArchive->Stream, archive, range, progress));
+ complexity += range.Size;
}
else
{
- CUpdateRange range(item.LocalHeaderPosition, item.GetLocalFullSize());
+ CUpdateRange range(inArchive->GetOffsetInStream(itemEx.LocalHeaderPos), itemEx.GetLocalFullSize());
// set new header position
- item.LocalHeaderPosition = archive.GetCurrentPosition();
+ item.LocalHeaderPos = archive.GetCurPos();
- RINOK(WriteRange(inStream, archive, range, progress));
+ RINOK(WriteRange(inArchive->Stream, archive, range, progress));
complexity += range.Size;
- archive.MoveBasePosition(range.Size);
+ archive.MoveCurPos(range.Size);
}
return S_OK;
}
static void WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *options,
- const CUpdateItem &ui, CItemEx &item)
+ const CUpdateItem &ui, CItemOut &item)
{
SetFileHeader(archive, *options, ui, item);
- archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsRealAesMode());
- archive.WriteLocalHeader(item);
+ archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size,
+ // options->IsRealAesMode()
+ false // fixed 9.31
+ );
+ archive.WriteLocalHeader_And_SeekToNextFile(item);
}
static HRESULT Update2St(
DECL_EXTERNAL_CODECS_LOC_VARS
COutArchive &archive,
CInArchive *inArchive,
- IInStream *inStream,
const CObjectVector<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
const CCompressionMethodMode *options,
@@ -410,26 +404,29 @@ static HRESULT Update2St(
CAddCommon compressor(*options);
- CObjectVector<CItem> items;
+ CObjectVector<CItemOut> items;
UInt64 unpackSizeTotal = 0, packSizeTotal = 0;
- for (int itemIndex = 0; itemIndex < updateItems.Size(); itemIndex++)
+ FOR_VECTOR (itemIndex, updateItems)
{
lps->InSize = unpackSizeTotal;
lps->OutSize = packSizeTotal;
RINOK(lps->SetCur());
const CUpdateItem &ui = updateItems[itemIndex];
- CItemEx item;
- if (!ui.NewProperties || !ui.NewData)
+ CItemEx itemEx;
+ CItemOut item;
+
+ if (!ui.NewProps || !ui.NewData)
{
- item = inputItems[ui.IndexInArchive];
- if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK)
+ itemEx = inputItems[ui.IndexInArc];
+ if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK)
return E_NOTIMPL;
+ (CItem &)item = itemEx;
}
if (ui.NewData)
{
- bool isDir = ((ui.NewProperties) ? ui.IsDir : item.IsDir());
+ bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir());
if (isDir)
{
WriteDirHeader(archive, options, ui, item);
@@ -445,10 +442,12 @@ static HRESULT Update2St(
continue;
}
RINOK(res);
+ if (!fileInStream)
+ return E_INVALIDARG;
// file Size can be 64-bit !!!
SetFileHeader(archive, *options, ui, item);
- archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsRealAesMode());
+ archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options->IsRealAesMode());
CCompressingResult compressingResult;
CMyComPtr<IOutStream> outStream;
archive.CreateStreamForCompressing(&outStream);
@@ -456,9 +455,9 @@ static HRESULT Update2St(
EXTERNAL_CODECS_LOC_VARS
fileInStream, outStream, progress, compressingResult));
SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item);
- archive.WriteLocalHeader(item);
+ archive.WriteLocalHeader_And_SeekToNextFile(item);
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
- unpackSizeTotal += item.UnPackSize;
+ unpackSizeTotal += item.Size;
packSizeTotal += item.PackSize;
}
}
@@ -466,12 +465,12 @@ static HRESULT Update2St(
{
UInt64 complexity = 0;
lps->SendRatio = false;
- RINOK(UpdateItemOldData(archive, inStream, ui, item, progress, complexity));
+ RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, complexity));
lps->SendRatio = true;
lps->ProgressOffset += complexity;
}
items.Add(item);
- lps->ProgressOffset += NFileHeader::kLocalBlockSize;
+ lps->ProgressOffset += kLocalHeaderSize;
}
lps->InSize = unpackSizeTotal;
lps->OutSize = packSizeTotal;
@@ -484,7 +483,6 @@ static HRESULT Update2(
DECL_EXTERNAL_CODECS_LOC_VARS
COutArchive &archive,
CInArchive *inArchive,
- IInStream *inStream,
const CObjectVector<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
const CCompressionMethodMode *options,
@@ -495,7 +493,7 @@ static HRESULT Update2(
UInt64 numFilesToCompress = 0;
UInt64 numBytesToCompress = 0;
- int i;
+ unsigned i;
for (i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &ui = updateItems[i];
@@ -511,18 +509,18 @@ static HRESULT Update2(
}
else
{
- CItemEx inputItem = inputItems[ui.IndexInArchive];
+ CItemEx inputItem = inputItems[ui.IndexInArc];
if (inArchive->ReadLocalItemAfterCdItemFull(inputItem) != S_OK)
return E_NOTIMPL;
complexity += inputItem.GetLocalFullSize();
// complexity += inputItem.GetCentralExtraPlusCommentSize();
}
- complexity += NFileHeader::kLocalBlockSize;
- complexity += NFileHeader::kCentralBlockSize;
+ complexity += kLocalHeaderSize;
+ complexity += kCentralHeaderSize;
}
if (comment)
- complexity += comment->GetCapacity();
+ complexity += comment->Size();
complexity++; // end of central
updateCallback->SetTotal(complexity);
@@ -540,6 +538,9 @@ static HRESULT Update2(
UInt32 numThreads = options->NumThreads;
if (numThreads > kNumMaxThreads)
numThreads = kNumMaxThreads;
+ if (numThreads < 1)
+ numThreads = 1;
+
const size_t kMemPerThread = (1 << 25);
const size_t kBlockSize = 1 << 16;
@@ -549,16 +550,18 @@ static HRESULT Update2(
if (numFilesToCompress <= 1)
mtMode = false;
+ Byte method = options->MethodSequence.Front();
if (!mtMode)
{
- if (numThreads < 2)
- if (options2.MethodInfo.FindProp(NCoderPropID::kNumThreads) < 0 &&
- options2.NumThreadsWasChanged)
- options2.MethodInfo.AddNumThreadsProp(1);
+ if (options2.MethodInfo.FindProp(NCoderPropID::kNumThreads) < 0)
+ {
+ // fixed for 9.31. bzip2 default is just one thread.
+ if (options2.NumThreadsWasChanged || method == NFileHeader::NCompressionMethod::kBZip2)
+ options2.MethodInfo.AddNumThreadsProp(numThreads);
+ }
}
else
{
- Byte method = options->MethodSequence.Front();
if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined)
numThreads = 1;
if (method == NFileHeader::NCompressionMethod::kBZip2)
@@ -594,13 +597,13 @@ static HRESULT Update2(
#endif
return Update2St(
EXTERNAL_CODECS_LOC_VARS
- archive, inArchive, inStream,
+ archive, inArchive,
inputItems, updateItems, &options2, comment, updateCallback);
#ifndef _7ZIP_ST
- CObjectVector<CItem> items;
+ CObjectVector<CItemOut> items;
CMtProgressMixer *mtProgressMixerSpec = new CMtProgressMixer;
CMyComPtr<ICompressProgressInfo> progress = mtProgressMixerSpec;
@@ -629,8 +632,7 @@ static HRESULT Update2(
{
CThreadInfo &threadInfo = threads.Threads[i];
#ifdef EXTERNAL_CODECS
- threadInfo._codecsInfo = codecsInfo;
- threadInfo._externalCodecs = externalCodecs;
+ threadInfo.__externalCodecs = __externalCodecs;
#endif
RINOK(threadInfo.CreateEvents());
threadInfo.OutStreamSpec = new COutMemStream(&memManager);
@@ -643,9 +645,9 @@ static HRESULT Update2(
RINOK(threadInfo.CreateThread());
}
}
- int mtItemIndex = 0;
+ unsigned mtItemIndex = 0;
- int itemIndex = 0;
+ unsigned itemIndex = 0;
int lastRealStreamItemIndex = -1;
while (itemIndex < updateItems.Size())
@@ -655,17 +657,19 @@ static HRESULT Update2(
const CUpdateItem &ui = updateItems[mtItemIndex++];
if (!ui.NewData)
continue;
- CItemEx item;
- if (ui.NewProperties)
+ CItemEx itemEx;
+ CItemOut item;
+ if (ui.NewProps)
{
if (ui.IsDir)
continue;
}
else
{
- item = inputItems[ui.IndexInArchive];
- if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK)
+ itemEx = inputItems[ui.IndexInArc];
+ if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK)
return E_NOTIMPL;
+ (CItem &)item = itemEx;
if (item.IsDir())
continue;
}
@@ -676,13 +680,15 @@ static HRESULT Update2(
if (res == S_FALSE)
{
complexity += ui.Size;
- complexity += NFileHeader::kLocalBlockSize;
+ complexity += kLocalHeaderSize;
mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
refs.Refs[mtItemIndex - 1].Skip = true;
continue;
}
RINOK(res);
+ if (!fileInStream)
+ return E_INVALIDARG;
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
@@ -719,29 +725,31 @@ static HRESULT Update2(
const CUpdateItem &ui = updateItems[itemIndex];
- CItemEx item;
- if (!ui.NewProperties || !ui.NewData)
+ CItemEx itemEx;
+ CItemOut item;
+ if (!ui.NewProps || !ui.NewData)
{
- item = inputItems[ui.IndexInArchive];
- if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK)
+ itemEx = inputItems[ui.IndexInArc];
+ if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK)
return E_NOTIMPL;
+ (CItem &)item = itemEx;
}
if (ui.NewData)
{
- bool isDir = ((ui.NewProperties) ? ui.IsDir : item.IsDir());
+ bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir());
if (isDir)
{
WriteDirHeader(archive, options, ui, item);
}
else
{
- if (lastRealStreamItemIndex < itemIndex)
+ if (lastRealStreamItemIndex < (int)itemIndex)
{
lastRealStreamItemIndex = itemIndex;
SetFileHeader(archive, *options, ui, item);
// file Size can be 64-bit !!!
- archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsRealAesMode());
+ archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options->IsRealAesMode());
}
CMemBlocks2 &memRef = refs.Refs[itemIndex];
@@ -750,10 +758,13 @@ static HRESULT Update2(
CMyComPtr<IOutStream> outStream;
archive.CreateStreamForCompressing(&outStream);
memRef.WriteToStream(memManager.GetBlockSize(), outStream);
+ SetFileHeader(archive, *options, ui, item);
+ // the BUG was fixed in 9.26:
+ // SetItemInfoFromCompressingResult must be after SetFileHeader
+ // to write correct Size.
SetItemInfoFromCompressingResult(memRef.CompressingResult,
options->IsRealAesMode(), options->AesKeyMode, item);
- SetFileHeader(archive, *options, ui, item);
- archive.WriteLocalHeader(item);
+ archive.WriteLocalHeader_And_SeekToNextFile(item);
// RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
memRef.FreeOpt(&memManager);
}
@@ -783,10 +794,10 @@ static HRESULT Update2(
{
RINOK(threadInfo.OutStreamSpec->WriteToRealStream());
threadInfo.OutStreamSpec->ReleaseOutStream();
+ SetFileHeader(archive, *options, ui, item);
SetItemInfoFromCompressingResult(threadInfo.CompressingResult,
options->IsRealAesMode(), options->AesKeyMode, item);
- SetFileHeader(archive, *options, ui, item);
- archive.WriteLocalHeader(item);
+ archive.WriteLocalHeader_And_SeekToNextFile(item);
}
else
{
@@ -801,10 +812,10 @@ static HRESULT Update2(
}
else
{
- RINOK(UpdateItemOldData(archive, inStream, ui, item, progress, complexity));
+ RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, complexity));
}
items.Add(item);
- complexity += NFileHeader::kLocalBlockSize;
+ complexity += kLocalHeaderSize;
mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
itemIndex++;
}
@@ -993,15 +1004,18 @@ STDMETHODIMP CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *proce
STDMETHODIMP CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
- switch(seekOrigin)
+ switch (seekOrigin)
{
- case STREAM_SEEK_SET: _virtPos = offset; break;
- case STREAM_SEEK_CUR: _virtPos += offset; break;
- case STREAM_SEEK_END: _virtPos = _virtSize + offset; break;
+ case STREAM_SEEK_SET: break;
+ case STREAM_SEEK_CUR: offset += _virtPos; break;
+ case STREAM_SEEK_END: offset += _virtSize; break;
default: return STG_E_INVALIDFUNCTION;
}
+ if (offset < 0)
+ return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
+ _virtPos = offset;
if (newPosition)
- *newPosition = _virtPos;
+ *newPosition = offset;
return S_OK;
}
@@ -1029,16 +1043,33 @@ HRESULT Update(
const CObjectVector<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
ISequentialOutStream *seqOutStream,
- CInArchive *inArchive,
+ CInArchive *inArchive, bool removeSfx,
CCompressionMethodMode *compressionMethodMode,
IArchiveUpdateCallback *updateCallback)
{
+ if (inArchive)
+ {
+ if (!inArchive->CanUpdate())
+ return E_NOTIMPL;
+ }
+
+
CMyComPtr<IOutStream> outStream;
{
CMyComPtr<IOutStream> outStreamReal;
seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStreamReal);
if (!outStreamReal)
return E_NOTIMPL;
+
+ if (inArchive)
+ {
+ if (inArchive->ArcInfo.Base > 0 && !removeSfx)
+ {
+ RINOK(inArchive->Stream->Seek(0, STREAM_SEEK_SET, NULL));
+ RINOK(NCompress::CopyStream_ExactSize(inArchive->Stream, outStreamReal, inArchive->ArcInfo.Base, NULL));
+ }
+ }
+
CCacheOutStream *cacheStream = new CCacheOutStream();
outStream = cacheStream;
if (!cacheStream->Allocate())
@@ -1046,32 +1077,23 @@ HRESULT Update(
RINOK(cacheStream->Init(outStreamReal));
}
- if (inArchive)
- {
- if (inArchive->ArcInfo.Base != 0 ||
- inArchive->ArcInfo.StartPosition != 0 ||
- !inArchive->IsOkHeaders)
- return E_NOTIMPL;
- }
-
COutArchive outArchive;
- outArchive.Create(outStream);
- /*
- if (inArchive && inArchive->ArcInfo.StartPosition > 0)
+ RINOK(outArchive.Create(outStream));
+
+ if (inArchive)
{
- CMyComPtr<ISequentialInStream> inStream;
- inStream.Attach(inArchive->CreateLimitedStream(0, inArchive->ArcInfo.StartPosition));
- RINOK(CopyBlockToArchive(inStream, outArchive, NULL));
- outArchive.MoveBasePosition(inArchive->ArcInfo.StartPosition);
+ if ((Int64)inArchive->ArcInfo.MarkerPos2 > inArchive->ArcInfo.Base)
+ {
+ RINOK(inArchive->Stream->Seek(inArchive->ArcInfo.Base, STREAM_SEEK_SET, NULL));
+ UInt64 embStubSize = inArchive->ArcInfo.MarkerPos2 - inArchive->ArcInfo.Base;
+ RINOK(NCompress::CopyStream_ExactSize(inArchive->Stream, outStream, embStubSize, NULL));
+ outArchive.MoveCurPos(embStubSize);
+ }
}
- */
- CMyComPtr<IInStream> inStream;
- if (inArchive)
- inStream.Attach(inArchive->CreateStream());
return Update2(
EXTERNAL_CODECS_LOC_VARS
- outArchive, inArchive, inStream,
+ outArchive, inArchive,
inputItems, updateItems,
compressionMethodMode,
inArchive ? &inArchive->ArcInfo.Comment : NULL,
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h
index eee16738..747c07bc 100755..100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.h
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.h
@@ -1,4 +1,4 @@
-// Zip/Update.h
+// ZipUpdate.h
#ifndef __ZIP_UPDATE_H
#define __ZIP_UPDATE_H
@@ -18,28 +18,29 @@ struct CUpdateRange
{
UInt64 Position;
UInt64 Size;
- CUpdateRange() {};
+
+ // CUpdateRange() {};
CUpdateRange(UInt64 position, UInt64 size): Position(position), Size(size) {};
};
struct CUpdateItem
{
bool NewData;
- bool NewProperties;
+ bool NewProps;
bool IsDir;
bool NtfsTimeIsDefined;
bool IsUtf8;
- int IndexInArchive;
+ int IndexInArc;
int IndexInClient;
- UInt32 Attributes;
+ UInt32 Attrib;
UInt32 Time;
UInt64 Size;
AString Name;
// bool Commented;
// CUpdateRange CommentRange;
- FILETIME NtfsMTime;
- FILETIME NtfsATime;
- FILETIME NtfsCTime;
+ FILETIME Ntfs_MTime;
+ FILETIME Ntfs_ATime;
+ FILETIME Ntfs_CTime;
CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {}
};
@@ -49,7 +50,7 @@ HRESULT Update(
const CObjectVector<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
ISequentialOutStream *seqOutStream,
- CInArchive *inArchive,
+ CInArchive *inArchive, bool removeSfx,
CCompressionMethodMode *compressionMethodMode,
IArchiveUpdateCallback *updateCallback);