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:
-rw-r--r--C/7zArcIn.c10
-rw-r--r--C/7zVersion.h12
-rw-r--r--C/CpuArch.c13
-rw-r--r--C/Sha1.c23
-rw-r--r--CPP/7zip/Archive/7z/7zIn.cpp6
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.cpp79
-rw-r--r--CPP/7zip/Archive/Cab/CabHandler.cpp24
-rw-r--r--CPP/7zip/Archive/ComHandler.cpp8
-rw-r--r--CPP/7zip/Archive/DmgHandler.cpp93
-rw-r--r--CPP/7zip/Archive/GptHandler.cpp16
-rw-r--r--CPP/7zip/Archive/HfsHandler.cpp5
-rw-r--r--CPP/7zip/Archive/Iso/IsoItem.h2
-rw-r--r--CPP/7zip/Archive/LzmaHandler.cpp2
-rw-r--r--CPP/7zip/Archive/Nsis/NsisDecode.cpp2
-rw-r--r--CPP/7zip/Archive/Nsis/NsisIn.cpp19
-rw-r--r--CPP/7zip/Archive/Nsis/NsisIn.h4
-rw-r--r--CPP/7zip/Archive/NtfsHandler.cpp12
-rw-r--r--CPP/7zip/Archive/PeHandler.cpp25
-rw-r--r--CPP/7zip/Archive/Rar/Rar5Handler.cpp58
-rw-r--r--CPP/7zip/Archive/Rar/RarHandler.cpp66
-rw-r--r--CPP/7zip/Archive/Rar/RarItem.h2
-rw-r--r--CPP/7zip/Archive/SplitHandler.cpp8
-rw-r--r--CPP/7zip/Archive/Udf/UdfIn.cpp5
-rw-r--r--CPP/7zip/Archive/Wim/WimHandler.cpp25
-rw-r--r--CPP/7zip/Archive/XzHandler.cpp14
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandler.cpp134
-rw-r--r--CPP/7zip/Archive/Zip/ZipHeader.h5
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.cpp1536
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.h261
-rw-r--r--CPP/7zip/Archive/Zip/ZipItem.h2
-rw-r--r--CPP/7zip/Archive/Zip/ZipRegister.cpp3
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.cpp51
-rw-r--r--CPP/7zip/Common/LimitedStreams.cpp19
-rw-r--r--CPP/7zip/Common/LimitedStreams.h1
-rw-r--r--CPP/7zip/Compress/BZip2Decoder.cpp4
-rw-r--r--CPP/7zip/Compress/BZip2Encoder.h8
-rw-r--r--CPP/7zip/Compress/BZip2Register.cpp13
-rw-r--r--CPP/7zip/Compress/Bcj2Register.cpp9
-rw-r--r--CPP/7zip/Compress/BcjCoder.cpp9
-rw-r--r--CPP/7zip/Compress/BcjCoder.h11
-rw-r--r--CPP/7zip/Compress/BcjRegister.cpp9
-rw-r--r--CPP/7zip/Compress/BranchMisc.cpp9
-rw-r--r--CPP/7zip/Compress/BranchMisc.h11
-rw-r--r--CPP/7zip/Compress/BranchRegister.cpp9
-rw-r--r--CPP/7zip/Compress/ByteSwap.cpp9
-rw-r--r--CPP/7zip/Compress/CopyRegister.cpp6
-rw-r--r--CPP/7zip/Compress/Deflate64Register.cpp14
-rw-r--r--CPP/7zip/Compress/DeflateDecoder.h6
-rw-r--r--CPP/7zip/Compress/DeflateEncoder.h4
-rw-r--r--CPP/7zip/Compress/DeflateRegister.cpp13
-rw-r--r--CPP/7zip/Compress/DeltaFilter.cpp31
-rw-r--r--CPP/7zip/Compress/Lzma2Encoder.h2
-rw-r--r--CPP/7zip/Compress/Lzma2Register.cpp9
-rw-r--r--CPP/7zip/Compress/LzmaEncoder.h2
-rw-r--r--CPP/7zip/Compress/LzmaRegister.cpp9
-rw-r--r--CPP/7zip/Compress/PpmdEncoder.h3
-rw-r--r--CPP/7zip/Compress/PpmdRegister.cpp9
-rw-r--r--CPP/7zip/Compress/Rar3Decoder.cpp24
-rw-r--r--CPP/7zip/Compress/RarCodecsRegister.cpp6
-rw-r--r--CPP/7zip/Compress/ShrinkDecoder.cpp157
-rw-r--r--CPP/7zip/Compress/ShrinkDecoder.h6
-rw-r--r--CPP/7zip/Crypto/7zAes.h6
-rw-r--r--CPP/7zip/Crypto/7zAesRegister.cpp9
-rw-r--r--CPP/7zip/Crypto/MyAes.h2
-rw-r--r--CPP/7zip/Crypto/MyAesReg.cpp8
-rw-r--r--CPP/7zip/UI/Agent/AgentProxy.cpp15
-rw-r--r--CPP/7zip/UI/Common/ArchiveCommandLine.cpp2
-rw-r--r--CPP/7zip/UI/Common/ArchiveOpenCallback.cpp1
-rw-r--r--CPP/7zip/UI/Common/OpenArchive.cpp37
-rw-r--r--CPP/7zip/UI/Common/ZipRegistry.cpp2
-rw-r--r--CPP/7zip/UI/Explorer/ContextMenu.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/App.cpp70
-rw-r--r--CPP/7zip/UI/FileManager/App.h37
-rw-r--r--CPP/7zip/UI/FileManager/FM.cpp21
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.cpp2
-rw-r--r--CPP/7zip/UI/FileManager/Panel.cpp30
-rw-r--r--CPP/7zip/UI/FileManager/Panel.h14
-rw-r--r--CPP/7zip/UI/FileManager/PanelDrag.cpp8
-rw-r--r--CPP/7zip/UI/FileManager/PanelFolderChange.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/PanelSplitFile.cpp4
-rw-r--r--CPP/Common/CrcReg.cpp2
-rw-r--r--CPP/Common/DynLimBuf.cpp2
-rw-r--r--CPP/Common/Sha1Reg.cpp2
-rw-r--r--CPP/Common/Sha256Reg.cpp2
-rw-r--r--CPP/Common/XzCrc64Reg.cpp2
-rw-r--r--DOC/7zip.inf4
-rw-r--r--DOC/7zip.nsi4
-rw-r--r--DOC/7zip.wxs4
-rw-r--r--DOC/License.txt2
-rw-r--r--DOC/copying.txt20
-rw-r--r--DOC/readme.txt4
-rw-r--r--DOC/src-history.txt6
92 files changed, 2406 insertions, 869 deletions
diff --git a/C/7zArcIn.c b/C/7zArcIn.c
index 06e35de0..ca2d5f6e 100644
--- a/C/7zArcIn.c
+++ b/C/7zArcIn.c
@@ -1,5 +1,5 @@
/* 7zArcIn.c -- 7z Input functions
-2015-11-18 : Igor Pavlov : Public domain */
+2016-03-31 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -788,13 +788,9 @@ static SRes ReadUnpackInfo(CSzAr *p,
numCodersOutStreams += numCoders;
if (numCodersOutStreams < numCoders)
return SZ_ERROR_UNSUPPORTED;
-
- packStreamIndex += numPackStreams;
- if (packStreamIndex < numPackStreams)
- return SZ_ERROR_UNSUPPORTED;
-
- if (packStreamIndex > p->NumPackStreams)
+ if (numPackStreams > p->NumPackStreams - packStreamIndex)
return SZ_ERROR_ARCHIVE;
+ packStreamIndex += numPackStreams;
}
}
diff --git a/C/7zVersion.h b/C/7zVersion.h
index c4f5c8e9..d4c60367 100644
--- a/C/7zVersion.h
+++ b/C/7zVersion.h
@@ -1,14 +1,14 @@
-#define MY_VER_MAJOR 15
-#define MY_VER_MINOR 14
+#define MY_VER_MAJOR 16
+#define MY_VER_MINOR 00
#define MY_VER_BUILD 0
-#define MY_VERSION_NUMBERS "15.14"
-#define MY_VERSION "15.14"
-#define MY_DATE "2015-12-31"
+#define MY_VERSION_NUMBERS "16.00"
+#define MY_VERSION "16.00"
+#define MY_DATE "2016-05-10"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
-#define MY_COPYRIGHT_CR "Copyright (c) 1999-2015 Igor Pavlov"
+#define MY_COPYRIGHT_CR "Copyright (c) 1999-2016 Igor Pavlov"
#ifdef USE_COPYRIGHT_CR
#define MY_COPYRIGHT MY_COPYRIGHT_CR
diff --git a/C/CpuArch.c b/C/CpuArch.c
index 36fc5bb4..554ffa4f 100644
--- a/C/CpuArch.c
+++ b/C/CpuArch.c
@@ -1,5 +1,5 @@
/* CpuArch.c -- CPU specific code
-2015-03-25: Igor Pavlov : Public domain */
+2016-02-25: Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -45,7 +45,8 @@ static UInt32 CheckFlag(UInt32 flag)
"push %%EDX\n\t"
"popf\n\t"
"andl %%EAX, %0\n\t":
- "=c" (flag) : "c" (flag));
+ "=c" (flag) : "c" (flag) :
+ "%eax", "%edx");
#endif
return flag;
}
@@ -79,7 +80,13 @@ void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
#else
__asm__ __volatile__ (
- #if defined(MY_CPU_X86) && defined(__PIC__)
+ #if defined(MY_CPU_AMD64) && defined(__PIC__)
+ "mov %%rbx, %%rdi;"
+ "cpuid;"
+ "xchg %%rbx, %%rdi;"
+ : "=a" (*a) ,
+ "=D" (*b) ,
+ #elif defined(MY_CPU_X86) && defined(__PIC__)
"mov %%ebx, %%edi;"
"cpuid;"
"xchgl %%ebx, %%edi;"
diff --git a/C/Sha1.c b/C/Sha1.c
index 785c7064..040cfe50 100644
--- a/C/Sha1.c
+++ b/C/Sha1.c
@@ -1,5 +1,5 @@
/* Sha1.c -- SHA-1 Hash
-2015-05-10 : Igor Pavlov : Public domain
+2016-02-09 : Igor Pavlov : Public domain
This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */
#include "Precomp.h"
@@ -151,18 +151,23 @@ void Sha1_Update(CSha1 *p, const Byte *data, size_t size)
if (pos2 != 0)
{
- UInt32 w = ((UInt32)data[0]) << 24;
- if (--size && pos2 < 3)
+ UInt32 w;
+ pos2 = (3 - pos2) * 8;
+ w = ((UInt32)*data++) << pos2;
+ if (--size && pos2)
{
- w |= ((UInt32)data[1]) << 16;
- if (--size && pos2 < 2)
+ pos2 -= 8;
+ w |= ((UInt32)*data++) << pos2;
+ if (--size && pos2)
{
- w |= ((UInt32)data[2]) << 8;
- --size;
+ pos2 -= 8;
+ w |= ((UInt32)*data++) << pos2;
+ size--;
}
}
- data += 4 - pos2;
- p->buffer[pos++] |= (w >> (8 * pos2));
+ p->buffer[pos] |= w;
+ if (pos2 == 0)
+ pos++;
}
for (;;)
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
index fc527be6..0634768b 100644
--- a/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/CPP/7zip/Archive/7z/7zIn.cpp
@@ -93,6 +93,8 @@ void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *d
Byte external = archive->ReadByte();
if (external != 0)
{
+ if (!dataVector)
+ ThrowIncorrect();
CNum dataIndex = archive->ReadNum();
if (dataIndex >= dataVector->Size())
ThrowIncorrect();
@@ -761,6 +763,8 @@ void CInArchive::ReadUnpackInfo(
folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;
numCodersOutStreams += numCoders;
folders.FoStartPackStreamIndex[fo] = packStreamIndex;
+ if (numPackStreams > folders.NumPackStreams - packStreamIndex)
+ ThrowIncorrect();
packStreamIndex += numPackStreams;
folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;
}
@@ -770,6 +774,8 @@ void CInArchive::ReadUnpackInfo(
folders.FoStartPackStreamIndex[fo] = packStreamIndex;
folders.FoCodersDataOffset[fo] = _inByteBack->GetPtr() - startBufPtr;
folders.CodersData.CopyFrom(startBufPtr, dataSize);
+
+ // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported();
}
WaitId(NID::kCodersUnpackSize);
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index 7e9478fc..e1c7aad8 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -380,29 +380,33 @@ static inline bool IsExeFilter(CMethodId m)
return false;
}
-static unsigned Get_FilterGroup_for_Folder(CRecordVector<CFilterMode2> &filters, const CFolderEx &f)
+static unsigned Get_FilterGroup_for_Folder(
+ CRecordVector<CFilterMode2> &filters, const CFolderEx &f, bool extractFilter)
{
CFilterMode2 m;
m.Id = 0;
m.Delta = 0;
m.Encrypted = f.IsEncrypted();
- const CCoderInfo &coder = f.Coders[f.UnpackCoder];
-
- if (coder.MethodID == k_Delta)
+ if (extractFilter)
{
- if (coder.Props.Size() == 1)
+ const CCoderInfo &coder = f.Coders[f.UnpackCoder];
+
+ if (coder.MethodID == k_Delta)
{
- m.Delta = (unsigned)coder.Props[0] + 1;
- m.Id = k_Delta;
+ if (coder.Props.Size() == 1)
+ {
+ m.Delta = (unsigned)coder.Props[0] + 1;
+ m.Id = k_Delta;
+ }
+ }
+ else if (IsExeFilter(coder.MethodID))
+ {
+ m.Id = (UInt32)coder.MethodID;
+ if (m.Id == k_BCJ2)
+ m.Id = k_BCJ;
+ m.SetDelta();
}
- }
- else if (IsExeFilter(coder.MethodID))
- {
- m.Id = (UInt32)coder.MethodID;
- if (m.Id == k_BCJ2)
- m.Id = k_BCJ;
- m.SetDelta();
}
return GetGroup(filters, m);
@@ -1577,7 +1581,7 @@ HRESULT Update(
return E_NOTIMPL;
*/
- UInt64 startBlockSize = db != 0 ? db->ArcInfo.StartPosition: 0;
+ UInt64 startBlockSize = db ? db->ArcInfo.StartPosition: 0;
if (startBlockSize > 0 && !options.RemoveSfxBlock)
{
RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL));
@@ -1591,8 +1595,21 @@ HRESULT Update(
CRecordVector<CFilterMode2> filters;
CObjectVector<CSolidGroup> groups;
bool thereAreRepacks = false;
+
+ bool useFilters = options.UseFilters;
+ if (useFilters)
+ {
+ const CCompressionMethodMode &method = *options.Method;
+
+ FOR_VECTOR (i, method.Methods)
+ if (IsFilterMethod(method.Methods[i].Id))
+ {
+ useFilters = false;
+ break;
+ }
+ }
- if (db != 0)
+ if (db)
{
fileIndexToUpdateIndexMap.Alloc(db->Files.Size());
unsigned i;
@@ -1638,16 +1655,18 @@ HRESULT Update(
CFolderEx f;
db->ParseFolderEx(i, f);
- bool isEncrypted = f.IsEncrypted();
-
- unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f);
+ const bool isEncrypted = f.IsEncrypted();
+ const bool needCopy = (numCopyItems == numUnpackStreams);
+ const bool extractFilter = (useFilters || needCopy);
+
+ unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f, extractFilter);
while (groupIndex >= groups.Size())
groups.AddNew();
groups[groupIndex].folderRefs.Add(rep);
- if (numCopyItems == numUnpackStreams)
+ if (needCopy)
complexity += db->GetFolderFullPackSize(i);
else
{
@@ -1732,22 +1751,8 @@ HRESULT Update(
// ---------- Split files to groups ----------
- bool useFilters = options.UseFilters;
const CCompressionMethodMode &method = *options.Method;
- if (useFilters)
- for (i = 0; i < method.Methods.Size(); i++)
- if (IsFilterMethod(method.Methods[i].Id))
- {
- useFilters = false;
- break;
- }
-
- /*
- if (!method.Bonds.IsEmpty())
- useFilters = false;
- */
-
for (i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &ui = updateItems[i];
@@ -2156,7 +2161,13 @@ HRESULT Update(
#ifndef _7ZIP_ST
if (options.MultiThreadMixer)
{
+ // 16.00: hang was fixed : for case if decoding was not finished.
+ // We close CBinderInStream and it calls CStreamBinder::CloseRead()
+ inStreamSizeCount.Release();
+ sbInStream.Release();
+
threadDecoder.WaitExecuteFinish();
+
HRESULT decodeRes = threadDecoder.Result;
// if (res == k_My_HRESULT_CRC_ERROR)
if (decodeRes == S_FALSE)
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp
index 9c841545..31aa5e1d 100644
--- a/CPP/7zip/Archive/Cab/CabHandler.cpp
+++ b/CPP/7zip/Archive/Cab/CabHandler.cpp
@@ -348,15 +348,19 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
CMyComPtr<IInStream> nextStream = inStream;
bool prevChecked = false;
+ UString startVolName;
+ bool startVolName_was_Requested = false;
UInt64 numItems = 0;
unsigned numTempVolumes = 0;
// try
{
- while (nextStream != NULL)
+ while (nextStream)
{
CDatabaseEx db;
db.Stream = nextStream;
+
HRESULT res = archive.Open(db, maxCheckStartPosition);
+
_errorInHeaders |= archive.HeaderError;
_errorInHeaders |= archive.ErrorInNames;
_unexpectedEnd |= archive.UnexpectedEnd;
@@ -426,6 +430,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
for (;;)
{
const COtherArc *otherArc = NULL;
+
if (!prevChecked)
{
if (numTempVolumes == 0)
@@ -449,18 +454,35 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
}
}
}
+
if (!otherArc)
{
const CInArcInfo &ai = m_Database.Volumes.Back().ArcInfo;
if (ai.IsThereNext())
otherArc = &ai.NextArc;
}
+
if (!otherArc)
break;
if (!openVolumeCallback)
break;
// printf("\n%s", otherArc->FileName);
const UString fullName = MultiByteToUnicodeString(otherArc->FileName, CP_ACP);
+
+ if (!startVolName_was_Requested)
+ {
+ // some "bad" cab example can contain the link to itself.
+ startVolName_was_Requested = true;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
+ if (prop.vt == VT_BSTR)
+ startVolName = prop.bstrVal;
+ }
+ if (fullName == startVolName)
+ break;
+ }
+
HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);
if (result == S_OK)
break;
diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp
index e39dbab5..2798bd71 100644
--- a/CPP/7zip/Archive/ComHandler.cpp
+++ b/CPP/7zip/Archive/ComHandler.cpp
@@ -578,14 +578,16 @@ HRESULT CDatabase::Open(IInStream *inStream)
if (item.IsDir() || numCabs > 1)
continue;
bool isMsiName;
- UString msiName = ConvertName(item.Name, isMsiName);
+ const UString msiName = ConvertName(item.Name, isMsiName);
if (isMsiName && !msiName.IsEmpty())
{
- bool isThereExt = (msiName.Find(L'.') >= 0);
+ // bool isThereExt = (msiName.Find(L'.') >= 0);
bool isMsiSpec = (msiName[0] == k_Msi_SpecChar);
if (msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab")
|| !isMsiSpec && msiName.Len() >= 3 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe")
- || !isMsiSpec && !isThereExt)
+ // || !isMsiSpec && !isThereExt
+ )
+
{
numCabs++;
MainSubfile = i;
diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp
index 2a80e255..09952ac8 100644
--- a/CPP/7zip/Archive/DmgHandler.cpp
+++ b/CPP/7zip/Archive/DmgHandler.cpp
@@ -34,48 +34,35 @@
static const Byte k_Base64Table[256] =
{
- 64,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
- 77,77,77,77,77,77,77,77,77,77,77,62,77,64,77,63,52,53,54,55,56,57,58,59,60,61,77,77,77,77,77,77,
- 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77,
- 77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77,
- 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
- 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
- 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
- 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77
+ 66,77,77,77,77,77,77,77,77,65,65,77,77,65,77,77,
+ 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
+ 65,77,77,77,77,77,77,77,77,77,77,62,77,77,77,63,
+ 52,53,54,55,56,57,58,59,60,61,77,77,77,64,77,77,
+ 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
+ 15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77,
+ 77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
+ 41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77,
+ 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
+ 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
+ 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
+ 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
+ 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
+ 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
+ 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
+ 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77
};
static Byte *Base64ToBin(Byte *dest, const char *src)
{
UInt32 val = 1;
- UInt32 c = k_Base64Table[(Byte)(*src++)];
for (;;)
{
- /*
- UInt32 c = (Byte)(*src++);
- if (c >= 'A')
- {
- if (c <= 'Z') c -= 'A';
- else if (c >= 'a' && c <= 'z') c -= 'a' - 26;
- else continue;
- }
- else if (c >= '0')
- {
- if (c <= '9') c += 52 - '0';
- else if (c == '=') break;
- else continue;
- }
- else if (c == '+') c = 62;
- else if (c == '/') c = 63;
- else if (c == 0) break;
- else continue;
- */
+ UInt32 c = k_Base64Table[(Byte)(*src++)];
- // UInt32 c = k_Base64Table[(Byte)(*src++)];
if (c < 64)
{
val = (val << 6) | c;
- c = k_Base64Table[(Byte)(*src++)];
if ((val & ((UInt32)1 << 24)) == 0)
continue;
dest[0] = (Byte)(val >> 16);
@@ -85,19 +72,41 @@ static Byte *Base64ToBin(Byte *dest, const char *src)
val = 1;
continue;
}
- if (c == 64)
+
+ if (c == 65) // space
+ continue;
+
+ if (c == 64) // '='
break;
- c = k_Base64Table[(Byte)(*src++)];
+
+ if (c == 66 && val == 1) // end of string
+ return dest;
+
+ return NULL;
}
- if (val >= ((UInt32)1 << 12))
+ if (val < (1 << 12))
+ return NULL;
+
+ if (val & (1 << 18))
{
- if (val >= ((UInt32)1 << 18))
- *dest++ = (Byte)(val >> 16);
- *dest++ = (Byte)(val);
+ *dest++ = (Byte)(val >> 10);
+ *dest++ = (Byte)(val >> 2);
+ }
+ else if (k_Base64Table[(Byte)(*src++)] != 64) // '='
+ return NULL;
+ else
+ *dest++ = (Byte)(val >> 4);
+
+ for (;;)
+ {
+ Byte c = k_Base64Table[(Byte)(*src++)];
+ if (c == 65) // space
+ continue;
+ if (c == 66) // end of string
+ return dest;
+ return NULL;
}
-
- return dest;
}
@@ -720,7 +729,13 @@ HRESULT CHandler::Open2(IInStream *stream)
return S_FALSE;
destLen = dataString->Len() / 4 * 3 + 4;
rawBuf.Alloc(destLen);
- destLen = (unsigned)(Base64ToBin(rawBuf, *dataString) - rawBuf);
+ {
+ const Byte *endPtr = Base64ToBin(rawBuf, *dataString);
+ if (!endPtr)
+ return S_FALSE;
+ destLen = (unsigned)(endPtr - rawBuf);
+ }
+
#ifdef DMG_SHOW_RAW
CExtraFile &extra = _extras.AddNew();
{
diff --git a/CPP/7zip/Archive/GptHandler.cpp b/CPP/7zip/Archive/GptHandler.cpp
index e54b1477..53e941c7 100644
--- a/CPP/7zip/Archive/GptHandler.cpp
+++ b/CPP/7zip/Archive/GptHandler.cpp
@@ -87,6 +87,9 @@ struct CPartType
static const CPartType kPartTypes[] =
{
// { 0x0, 0, "Unused" },
+
+ { 0x21686148, 0, "BIOS Boot" },
+
{ 0xC12A7328, 0, "EFI System" },
{ 0x024DEE41, 0, "MBR" },
@@ -98,10 +101,13 @@ static const CPartType kPartTypes[] =
// { 0x37AFFC90, 0, "IBM GPFS" },
// { 0xE75CAF8F, 0, "Windows Storage Spaces" },
- { 0x83BD6B9D, 0, "FreeBSD Boot" },
+ { 0x0FC63DAF, 0, "Linux Data" },
+ { 0x0657FD6D, 0, "Linux Swap" },
+
+ { 0x83BD6B9D, 0, "FreeBSD Boot" },
{ 0x516E7CB4, 0, "FreeBSD Data" },
{ 0x516E7CB5, 0, "FreeBSD Swap" },
- { 0x516E7CB6, "ufs", "FreeBSD UFS" },
+ { 0x516E7CB6, "ufs", "FreeBSD UFS" },
{ 0x516E7CB8, 0, "FreeBSD Vinum" },
{ 0x516E7CB8, "zfs", "FreeBSD ZFS" },
@@ -335,6 +341,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break;
s += c;
}
+ if (s.IsEmpty())
+ {
+ char temp[16];
+ ConvertUInt32ToString(index, temp);
+ s.AddAscii(temp);
+ }
{
int typeIndex = FindPartType(item.Type);
s += L'.';
diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp
index 8459280d..057a2d79 100644
--- a/CPP/7zip/Archive/HfsHandler.cpp
+++ b/CPP/7zip/Archive/HfsHandler.cpp
@@ -987,7 +987,9 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
item.GroupID = Get32(r + 0x24);
item.AdminFlags = r[0x28];
item.OwnerFlags = r[0x29];
+ */
item.FileMode = Get16(r + 0x2A);
+ /*
item.special.iNodeNum = Get16(r + 0x2C); // or .linkCount
item.FileType = Get32(r + 0x30);
item.FileCreator = Get32(r + 0x34);
@@ -1572,6 +1574,9 @@ HRESULT CHandler::ExtractZlibFile(
UInt32 size = GetUi32(tableBuf + i * 8 + 4);
+ if (size > buf.Size() || size > kCompressionBlockSize + 1)
+ return S_FALSE;
+
RINOK(ReadStream_FALSE(inStream, buf, size));
if ((buf[0] & 0xF) == 0xF)
diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h
index 2603afdb..ce154264 100644
--- a/CPP/7zip/Archive/Iso/IsoItem.h
+++ b/CPP/7zip/Archive/Iso/IsoItem.h
@@ -79,7 +79,7 @@ struct CDirRecord
while (rem >= 5)
{
unsigned len = p[2];
- if (len > rem)
+ if (len < 3 || len > rem)
return 0;
if (p[0] == 'N' && p[1] == 'M' && p[3] == 1)
{
diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp
index e4ac2a42..121cd67c 100644
--- a/CPP/7zip/Archive/LzmaHandler.cpp
+++ b/CPP/7zip/Archive/LzmaHandler.cpp
@@ -110,7 +110,7 @@ HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream)
{
_filterCoder = new CFilterCoder(false);
CMyComPtr<ICompressCoder> coder = _filterCoder;
- _filterCoder->Filter = new CBcjCoder(false);
+ _filterCoder->Filter = new NCompress::NBcj::CCoder(false);
_bcjStream = _filterCoder;
}
}
diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp
index 68243129..0bbf6094 100644
--- a/CPP/7zip/Archive/Nsis/NsisDecode.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp
@@ -59,7 +59,7 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
{
_filter = new CFilterCoder(false);
_filterInStream = _filter;
- _filter->Filter = new CBcjCoder(false);
+ _filter->Filter = new NCompress::NBcj::CCoder(false);
}
RINOK(_filter->SetInStream(_codecInStream));
_decoderInStream = _filterInStream;
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp
index 6ca87df4..e04a97a8 100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp
@@ -88,7 +88,7 @@ enum
EW_SENDMESSAGE, // SendMessage
EW_ISWINDOW, // IsWindow
EW_GETDLGITEM, // GetDlgItem
- EW_SETCTLCOLORS, // SerCtlColors
+ EW_SETCTLCOLORS, // SetCtlColors
EW_SETBRANDINGIMAGE, // SetBrandingImage
EW_CREATEFONT, // CreateFont
EW_SHOWWINDOW, // ShowWindow, EnableWindow, HideWindow
@@ -1155,9 +1155,13 @@ bool CInArchive::IsGoodString(UInt32 param) const
if (param == 0)
return true;
const Byte *p = _data + _stringsPos;
+ unsigned c;
if (IsUnicode)
- return (Get16(p + param * 2 - 2)) == 0;
- return p[param - 1] == 0;
+ c = Get16(p + param * 2 - 2);
+ else
+ c = p[param - 1];
+ // some files have '\\' character before string?
+ return (c == 0 || c == '\\');
}
bool CInArchive::AreTwoParamStringsEqual(UInt32 param1, UInt32 param2) const
@@ -1509,7 +1513,7 @@ static const UInt32 CMD_REF_Pre = (1 << 2);
static const UInt32 CMD_REF_Show = (1 << 3);
static const UInt32 CMD_REF_Leave = (1 << 4);
static const UInt32 CMD_REF_OnFunc = (1 << 5);
-static const UInt32 CMD_REF_Section = (1 << 6);
+static const UInt32 CMD_REF_Section = (1 << 6);
static const UInt32 CMD_REF_InitPluginDir = (1 << 7);
// static const UInt32 CMD_REF_Creator = (1 << 5); // _Pre is used instead
static const unsigned CMD_REF_OnFunc_NumShifts = 28; // it uses for onFunc too
@@ -3357,7 +3361,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
#ifdef NSIS_SCRIPT
s += isSetOutPath ? "SetOutPath" : "CreateDirectory";
- AddParam(params[0]);
+ AddParam(params[0]);
#endif
break;
@@ -3571,15 +3575,16 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
AddParam(params[0]);
- SmallSpaceComment();
-
/*
for (int i = 1; i < 3; i++)
AddParam_UInt(params[i]);
*/
if (params[3] != 0)
+ {
+ SmallSpaceComment();
AddParam(params[3]);
+ }
#endif
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h
index 498784b8..d8e6808b 100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.h
+++ b/CPP/7zip/Archive/Nsis/NsisIn.h
@@ -421,7 +421,11 @@ public:
const char *kRemoveStr = "$INSTDIR\\";
if (s.IsPrefixedBy_Ascii_NoCase(kRemoveStr))
+ {
s.Delete(0, MyStringLen(kRemoveStr));
+ if (s[0] == L'\\')
+ s.DeleteFrontal(1);
+ }
if (item.IsUninstaller && ExeStub.Size() == 0)
s += L".nsis";
return s;
diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp
index fa4bbc9c..25f4c8a6 100644
--- a/CPP/7zip/Archive/NtfsHandler.cpp
+++ b/CPP/7zip/Archive/NtfsHandler.cpp
@@ -1148,8 +1148,16 @@ bool CMftRec::Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 r
return false;
if (usaOffset >= 0x30) // NTFS 3.1+
- if (Get32(p + 0x2C) != recNumber)
- return false;
+ {
+ UInt32 iii = Get32(p + 0x2C);
+ if (iii != recNumber)
+ {
+ // ntfs-3g probably writes 0 (that probably is incorrect value) to this field for unused records.
+ // so we support that "bad" case.
+ if (iii != 0)
+ return false;
+ }
+ }
UInt16 usn = Get16(p + usaOffset);
// PRF(printf("\nusn = %d", usn));
diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp
index 28562007..160648f6 100644
--- a/CPP/7zip/Archive/PeHandler.cpp
+++ b/CPP/7zip/Archive/PeHandler.cpp
@@ -347,8 +347,8 @@ struct CSection
CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {}
- // const UInt32 GetSize() const { return PSize; }
- const UInt32 GetSize() const { return MyMin(PSize, VSize); }
+ const UInt32 GetSizeExtract() const { return PSize; }
+ const UInt32 GetSizeMin() const { return MyMin(PSize, VSize); }
void UpdateTotalSize(UInt32 &totalSize) const
{
@@ -362,8 +362,8 @@ struct CSection
int Compare(const CSection &s) const
{
RINOZ(MyCompare(Pa, s.Pa));
- UInt32 size1 = GetSize();
- UInt32 size2 = s.GetSize();
+ UInt32 size1 = GetSizeExtract();
+ UInt32 size2 = s.GetSizeExtract();
return MyCompare(size1, size2);
}
};
@@ -1045,7 +1045,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
switch (propID)
{
case kpidPath: prop = MultiByteToUnicodeString(item.Name); break;
- case kpidSize: prop = (UInt64)item.GetSize(); break;
+ case kpidSize: prop = (UInt64)item.PSize; break;
case kpidPackSize: prop = (UInt64)item.PSize; break;
case kpidVirtualSize: prop = (UInt64)item.VSize; break;
case kpidOffset: prop = item.Pa; break;
@@ -1898,7 +1898,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchiveOpenCallback *callback)
{
const CSection &sect = _sections[sectionIndex];
- const size_t fileSize = sect.GetSize();
+ const size_t fileSize = sect.GetSizeMin();
if (fileSize > kFileSizeMax)
return S_FALSE;
@@ -1926,6 +1926,7 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi
_oneLang = true;
bool stringsOk = true;
size_t maxOffset = 0;
+
FOR_VECTOR (i, specItems)
{
const CTableItem &item1 = specItems[i];
@@ -2007,6 +2008,7 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi
}
// PrintError("ver.Parse error");
}
+
item.Enabled = true;
_items.Add(item);
}
@@ -2041,7 +2043,10 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi
UInt32 mask = (1 << numBits) - 1;
size_t end = ((maxOffset + mask) & ~mask);
- if (/* end < sect.VSize && */ end <= sect.GetSize())
+ // PSize can be much larger than VSize in some exe installers.
+ // it contains archive data after PE resources.
+ // So we need to use PSize here!
+ if (/* end < sect.VSize && */ end <= sect.PSize)
{
CSection sect2;
sect2.Flags = 0;
@@ -2059,7 +2064,7 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi
// 9.29: we use sect.PSize instead of sect.VSize to support some CAB-SFX
// the code for .rsrc_2 is commented.
- sect2.PSize = sect.GetSize() - (UInt32)maxOffset;
+ sect2.PSize = sect.PSize - (UInt32)maxOffset;
if (sect2.PSize != 0)
{
@@ -2473,7 +2478,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else if (mixItem.ResourceIndex >= 0)
size = _items[mixItem.ResourceIndex].GetSize();
else
- size = _sections[mixItem.SectionIndex].GetSize();
+ size = _sections[mixItem.SectionIndex].GetSizeExtract();
totalSize += size;
}
extractCallback->SetTotal(totalSize);
@@ -2549,7 +2554,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
else
{
- currentItemSize = sect.GetSize();
+ currentItemSize = sect.GetSizeExtract();
if (!testMode && !outStream)
continue;
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp
index 131f2c9b..959c2e36 100644
--- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp
+++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp
@@ -2333,6 +2333,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
UInt64 total = 0;
+ bool isThereUndefinedSize = false;
bool thereAreLinks = false;
{
@@ -2342,9 +2343,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
unsigned index = allFilesMode ? t : indices[t];
const CRefItem &ref = _refs[index];
const CItem &item = _items[ref.Item];
+ const CItem &lastItem = _items[ref.Last];
extractStatuses[index] |= kStatus_Extract;
- total += item.Size;
+
+ if (!lastItem.Is_UnknownSize())
+ total += lastItem.Size;
+ else
+ isThereUndefinedSize = true;
if (ref.Link >= 0)
{
@@ -2352,11 +2358,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
if ((unsigned)ref.Link < index)
{
- const CItem &linkItem = _items[_refs[(unsigned)ref.Link].Item];
+ const CRefItem &linkRef = _refs[(unsigned)ref.Link];
+ const CItem &linkItem = _items[linkRef.Item];
if (linkItem.IsSolid() && linkItem.Size <= k_CopyLinkFile_MaxSize)
{
if (extractStatuses[(unsigned)ref.Link] == 0)
- total += linkItem.Size;
+ {
+ const CItem &lastLinkItem = _items[linkRef.Last];
+ if (!lastLinkItem.Is_UnknownSize())
+ total += lastLinkItem.Size;
+ else
+ isThereUndefinedSize = true;
+ }
extractStatuses[(unsigned)ref.Link] |= kStatus_Link;
thereAreLinks = true;
}
@@ -2375,11 +2388,18 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
while (j > solidLimit)
{
j--;
- const CItem &item2 = _items[_refs[j].Item];
+ const CRefItem &ref2 = _refs[j];
+ const CItem &item2 = _items[ref2.Item];
if (!item2.IsService())
{
if (extractStatuses[j] == 0)
- total += item2.Size;
+ {
+ const CItem &lastItem2 = _items[ref2.Last];
+ if (!lastItem2.Is_UnknownSize())
+ total += lastItem2.Size;
+ else
+ isThereUndefinedSize = true;
+ }
extractStatuses[j] |= kStatus_Skip;
if (!item2.IsSolid())
break;
@@ -2415,13 +2435,20 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
while (j > solidLimit)
{
j--;
- const CItem &item2 = _items[_refs[j].Item];
+ const CRefItem &ref2 = _refs[j];
+ const CItem &item2 = _items[ref2.Item];
if (!item2.IsService())
{
if (extractStatuses[j] != 0)
break;
extractStatuses[j] = kStatus_Skip;
- total += item2.Size;
+ {
+ const CItem &lastItem2 = _items[ref2.Last];
+ if (!lastItem2.Is_UnknownSize())
+ total += lastItem2.Size;
+ else
+ isThereUndefinedSize = true;
+ }
if (!item2.IsSolid())
break;
}
@@ -2449,7 +2476,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
}
- RINOK(extractCallback->SetTotal(total));
+ if (total != 0 || !isThereUndefinedSize)
+ {
+ RINOK(extractCallback->SetTotal(total));
+ }
}
@@ -2502,8 +2532,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const CRefItem *ref = &_refs[index];
const CItem *item = &_items[ref->Item];
+ const CItem &lastItem = _items[ref->Last];
+
+ curUnpackSize = 0;
+ if (!lastItem.Is_UnknownSize())
+ curUnpackSize = lastItem.Size;
- curUnpackSize = item->Size;
curPackSize = GetPackSize(index);
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
@@ -2532,11 +2566,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
const CRefItem &ref2 = _refs[index2];
const CItem &item2 = _items[ref2.Item];
+ const CItem &lastItem2 = _items[ref2.Last];
if (!item2.IsSolid())
{
item = &item2;
ref = &ref2;
- curUnpackSize = item->Size;
+ if (!lastItem2.Is_UnknownSize())
+ curUnpackSize = lastItem2.Size;
+ else
+ curUnpackSize = 0;
curPackSize = GetPackSize(index2);
}
else if ((unsigned)index2 < index)
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp
index 3b5924b4..6f3e0a0c 100644
--- a/CPP/7zip/Archive/Rar/RarHandler.cpp
+++ b/CPP/7zip/Archive/Rar/RarHandler.cpp
@@ -953,6 +953,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
NCOM::CPropVariant prop;
const CRefItem &refItem = _refItems[index];
const CItem &item = _items[refItem.ItemIndex];
+ const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
+
/*
const CItem *mainItem = &item;
if (item.BaseFileIndex >= 0)
@@ -972,7 +974,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break;
}
case kpidIsDir: prop = item.IsDir(); break;
- case kpidSize: prop = item.Size; break;
+ case kpidSize: if (lastItem.Is_Size_Defined()) prop = lastItem.Size; break;
case kpidPackSize: prop = GetPackSize(index); break;
case kpidMTime: RarTimeToProp(item.MTime, prop); break;
case kpidCTime: if (item.CTimeDefined) RarTimeToProp(item.CTime, prop); break;
@@ -985,7 +987,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter(); break;
case kpidCRC:
{
- const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
prop = ((lastItem.IsSplitAfter()) ? item.FileCRC : lastItem.FileCRC);
break;
}
@@ -1378,34 +1379,52 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CRecordVector<unsigned> importantIndexes;
CRecordVector<bool> extractStatuses;
+ bool isThereUndefinedSize = false;
+
for (UInt32 t = 0; t < numItems; t++)
{
unsigned index = allFilesMode ? t : indices[t];
- const CRefItem &refItem = _refItems[index];
- const CItem &item = _items[refItem.ItemIndex];
- censoredTotalUnPacked += item.Size;
- // censoredTotalPacked += item.PackSize;
+
+ {
+ const CRefItem &refItem = _refItems[index];
+ const CItem &item = _items[refItem.ItemIndex + refItem.NumItems - 1];
+
+ if (item.Is_Size_Defined())
+ censoredTotalUnPacked += item.Size;
+ else
+ isThereUndefinedSize = true;
+
+ // censoredTotalPacked += item.PackSize;
+ }
+
unsigned j;
for (j = lastIndex; j <= index; j++)
// if (!_items[_refItems[j].ItemIndex].IsSolid())
if (!IsSolid(j))
lastIndex = j;
+
for (j = lastIndex; j <= index; j++)
{
const CRefItem &refItem = _refItems[j];
- const CItem &item = _items[refItem.ItemIndex];
+ const CItem &item = _items[refItem.ItemIndex + refItem.NumItems - 1];
- // const CItem &item = _items[j];
-
- importantTotalUnPacked += item.Size;
+ if (item.Is_Size_Defined())
+ importantTotalUnPacked += item.Size;
+ else
+ isThereUndefinedSize = true;
// importantTotalPacked += item.PackSize;
importantIndexes.Add(j);
extractStatuses.Add(j == index);
}
+
lastIndex = index + 1;
}
- RINOK(extractCallback->SetTotal(importantTotalUnPacked));
+ if (importantTotalUnPacked != 0 || !isThereUndefinedSize)
+ {
+ RINOK(extractCallback->SetTotal(importantTotalUnPacked));
+ }
+
UInt64 currentImportantTotalUnPacked = 0;
UInt64 currentImportantTotalPacked = 0;
UInt64 currentUnPackSize, currentPackSize;
@@ -1431,13 +1450,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lps->Init(extractCallback, false);
bool solidStart = true;
- for (unsigned i = 0; i < importantIndexes.Size(); i++,
+
+ for (unsigned i = 0;;
+ i++,
currentImportantTotalUnPacked += currentUnPackSize,
currentImportantTotalPacked += currentPackSize)
{
lps->InSize = currentImportantTotalPacked;
lps->OutSize = currentImportantTotalUnPacked;
RINOK(lps->SetCur());
+
+ if (i >= importantIndexes.Size())
+ break;
+
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode;
@@ -1452,8 +1477,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const CRefItem &refItem = _refItems[index];
const CItem &item = _items[refItem.ItemIndex];
-
- currentUnPackSize = item.Size;
+ const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
+
+ UInt64 outSize = (UInt64)(Int64)-1;
+ currentUnPackSize = 0;
+ if (lastItem.Is_Size_Defined())
+ {
+ outSize = lastItem.Size;
+ currentUnPackSize = outSize;
+ }
currentPackSize = GetPackSize(index);
@@ -1678,12 +1710,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
continue;
}
- HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress);
+ HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &outSize, progress);
if (item.IsEncrypted())
filterStreamSpec->ReleaseInStream();
- const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
+ if (outSize == (UInt64)(Int64)-1)
+ currentUnPackSize = outStreamSpec->GetSize();
+
int opRes = (volsInStreamSpec->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ?
NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kCRCError;
diff --git a/CPP/7zip/Archive/Rar/RarItem.h b/CPP/7zip/Archive/Rar/RarItem.h
index 13daa1cb..10e21c57 100644
--- a/CPP/7zip/Archive/Rar/RarItem.h
+++ b/CPP/7zip/Archive/Rar/RarItem.h
@@ -42,6 +42,8 @@ struct CItem
Byte Salt[8];
+ bool Is_Size_Defined() const { return Size != (UInt64)(Int64)-1; }
+
bool IsEncrypted() const { return (Flags & NHeader::NFile::kEncrypted) != 0; }
bool IsSolid() const { return (Flags & NHeader::NFile::kSolid) != 0; }
bool IsCommented() const { return (Flags & NHeader::NFile::kComment) != 0; }
diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp
index 23187064..4ca417e0 100644
--- a/CPP/7zip/Archive/SplitHandler.cpp
+++ b/CPP/7zip/Archive/SplitHandler.cpp
@@ -187,11 +187,15 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
UInt64 size;
{
+ /*
NCOM::CPropVariant prop;
RINOK(volumeCallback->GetProperty(kpidSize, &prop));
if (prop.vt != VT_UI8)
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
+ */
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &size));
+ RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
}
_totalSize += size;
@@ -217,11 +221,15 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
if (!stream)
break;
{
+ /*
NCOM::CPropVariant prop;
RINOK(volumeCallback->GetProperty(kpidSize, &prop));
if (prop.vt != VT_UI8)
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
+ */
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &size));
+ RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
}
_totalSize += size;
_sizes.Add(size);
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp
index a051a271..908f2356 100644
--- a/CPP/7zip/Archive/Udf/UdfIn.cpp
+++ b/CPP/7zip/Archive/Udf/UdfIn.cpp
@@ -389,7 +389,10 @@ HRESULT CInArchive::ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc
return S_FALSE;
CFile &file = Files.Back();
const CLogVol &vol = LogVols[volIndex];
- CPartition &partition = Partitions[vol.PartitionMaps[lad.Location.PartitionRef].PartitionIndex];
+ unsigned partitionRef = lad.Location.PartitionRef;
+ if (partitionRef >= vol.PartitionMaps.Size())
+ return S_FALSE;
+ CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex];
UInt32 key = lad.Location.Pos;
UInt32 value;
diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp
index 910de06d..e6bc21f6 100644
--- a/CPP/7zip/Archive/Wim/WimHandler.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandler.cpp
@@ -475,14 +475,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidPackSize:
{
- UInt64 size = 0;
if (si)
{
if (!si->Resource.IsSolidSmall())
- {
- size = si->Resource.PackSize;
- prop = size;
- }
+ prop = si->Resource.PackSize;
else
{
if (si->Resource.SolidIndex >= 0)
@@ -493,12 +489,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
}
}
}
+ else if (!item.IsDir)
+ prop = (UInt64)0;
+
break;
}
case kpidSize:
{
- UInt64 size = 0;
if (si)
{
if (si->Resource.IsSolid())
@@ -507,22 +505,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
if (si->Resource.SolidIndex >= 0)
{
- CSolid &ss = _db.Solids[(unsigned)si->Resource.SolidIndex];
+ const CSolid &ss = _db.Solids[(unsigned)si->Resource.SolidIndex];
prop = ss.UnpackSize;
}
}
else
- {
- size = si->Resource.PackSize;
- prop = size;
- }
+ prop = si->Resource.PackSize;
}
else
- {
- size = si->Resource.UnpackSize;
- prop = size;
- }
+ prop = si->Resource.UnpackSize;
}
+ else if (!item.IsDir)
+ prop = (UInt64)0;
+
break;
}
diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
index 11f4b444..318be190 100644
--- a/CPP/7zip/Archive/XzHandler.cpp
+++ b/CPP/7zip/Archive/XzHandler.cpp
@@ -10,6 +10,8 @@
#include "../../Common/Defs.h"
#include "../../Common/IntToString.h"
+#include "../../Windows/PropVariant.h"
+
#include "../ICoder.h"
#include "../Common/CWrappers.h"
@@ -21,7 +23,9 @@
#include "IArchive.h"
+#ifndef EXTRACT_ONLY
#include "Common/HandlerOut.h"
+#endif
#include "XzHandler.h"
@@ -83,14 +87,19 @@ class CHandler:
CMyComPtr<IInStream> _stream;
CMyComPtr<ISequentialInStream> _seqStream;
- UInt32 _filterId;
AString _methodsString;
+ #ifndef EXTRACT_ONLY
+
+ UInt32 _filterId;
+
void Init()
{
_filterId = 0;
CMultiMethodProps::Init();
}
+
+ #endif
HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback);
@@ -126,9 +135,12 @@ public:
CHandler::CHandler()
{
+ #ifndef EXTRACT_ONLY
Init();
+ #endif
}
+
static const Byte kProps[] =
{
kpidSize,
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp
index 092dcbc9..75034de0 100644
--- a/CPP/7zip/Archive/Zip/ZipHandler.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp
@@ -12,6 +12,7 @@
#include "../../IPassword.h"
#include "../../Common/FilterCoder.h"
+#include "../../Common/LimitedStreams.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
#include "../../Common/StreamUtils.h"
@@ -142,14 +143,19 @@ static const Byte kProps[] =
kpidCRC,
kpidMethod,
kpidHostOS,
- kpidUnpackVer
+ kpidUnpackVer,
+ kpidVolumeIndex
};
static const Byte kArcProps[] =
{
kpidEmbeddedStubSize,
kpidBit64,
- kpidComment
+ kpidComment,
+ kpidTotalPhySize,
+ kpidIsVolume,
+ kpidVolumeIndex,
+ kpidNumVolumes
};
CHandler::CHandler()
@@ -175,18 +181,23 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
case kpidBit64: if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break;
case kpidComment: if (m_Archive.ArcInfo.Comment.Size() != 0) prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break;
- case kpidPhySize: prop = m_Archive.ArcInfo.GetPhySize(); break;
- case kpidOffset: /* if (m_Archive.ArcInfo.Base != 0) */
- prop = m_Archive.ArcInfo.Base; break;
+
+ case kpidPhySize: prop = m_Archive.GetPhySize(); break;
+ case kpidOffset: prop = m_Archive.GetOffset(); break;
case kpidEmbeddedStubSize:
{
- UInt64 stubSize = m_Archive.ArcInfo.GetEmbeddedStubSize();
+ UInt64 stubSize = m_Archive.GetEmbeddedStubSize();
if (stubSize != 0)
prop = stubSize;
break;
}
+ case kpidTotalPhySize: if (m_Archive.IsMultiVol) prop = m_Archive.Vols.GetTotalSize(); break;
+ case kpidVolumeIndex: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.StartVolIndex; break;
+ case kpidIsVolume: if (m_Archive.IsMultiVol) prop = true; break;
+ case kpidNumVolumes: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.Streams.Size(); break;
+
case kpidWarningFlags:
{
UInt32 v = 0;
@@ -197,6 +208,18 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
break;
}
+ case kpidError:
+ {
+ if (!m_Archive.Vols.MissingName.IsEmpty())
+ {
+ UString s;
+ s.SetFromAscii("Missing volume : ");
+ s += m_Archive.Vols.MissingName;
+ prop = s;
+ }
+ break;
+ }
+
case kpidErrorFlags:
{
UInt32 v = 0;
@@ -209,7 +232,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
but the stream has access only to zip part.
In that case we ignore UnavailableStart error.
maybe we must show warning in that case. */
- UInt64 stubSize = m_Archive.ArcInfo.GetEmbeddedStubSize();
+ UInt64 stubSize = m_Archive.GetEmbeddedStubSize();
if (stubSize < (UInt64)-m_Archive.ArcInfo.Base)
v |= kpv_ErrorFlags_UnavailableStart;
}
@@ -429,6 +452,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidUnpackVer:
prop = (UInt32)item.ExtractVersion.Version;
break;
+
+ case kpidVolumeIndex:
+ prop = item.Disk;
+ break;
}
prop.Detach(value);
@@ -436,30 +463,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END
}
-class CProgressImp: public CProgressVirt
-{
- CMyComPtr<IArchiveOpenCallback> _callback;
-public:
- virtual HRESULT SetCompletedLocal(UInt64 numFiles, UInt64 numBytes);
- virtual HRESULT SetTotalCD(UInt64 numFiles);
- virtual HRESULT SetCompletedCD(UInt64 numFiles);
- CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {}
-};
-
-HRESULT CProgressImp::SetCompletedLocal(UInt64 numFiles, UInt64 numBytes)
-{
- return _callback->SetCompleted(&numFiles, &numBytes);
-}
-
-HRESULT CProgressImp::SetTotalCD(UInt64 numFiles)
-{
- return _callback->SetTotal(&numFiles, NULL);
-}
-
-HRESULT CProgressImp::SetCompletedCD(UInt64 numFiles)
-{
- return _callback->SetCompleted(&numFiles, NULL);
-}
STDMETHODIMP CHandler::Open(IInStream *inStream,
const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)
@@ -468,9 +471,13 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
try
{
Close();
- RINOK(m_Archive.Open(inStream, maxCheckStartPosition));
- CProgressImp progressImp(callback);
- return m_Archive.ReadHeaders(m_Items, callback ? &progressImp : NULL);
+ HRESULT res = m_Archive.Open(inStream, maxCheckStartPosition, callback, m_Items);
+ if (res != S_OK)
+ {
+ m_Items.Clear();
+ m_Archive.ClearRefs();
+ }
+ return res;
}
catch(...) { Close(); throw; }
COM_TRY_END
@@ -483,8 +490,6 @@ STDMETHODIMP CHandler::Close()
return S_OK;
}
-//////////////////////////////////////
-// CHandler::DecompressItems
class CLzmaDecoder:
public ICompressCoder,
@@ -550,6 +555,8 @@ struct CMethodItem
CMyComPtr<ICompressCoder> Coder;
};
+
+
class CZipDecoder
{
NCrypto::NZip::CDecoder *_zipCryptoDecoderSpec;
@@ -584,6 +591,24 @@ public:
Int32 &res);
};
+
+static HRESULT SkipStreamData(ISequentialInStream *stream, UInt64 size)
+{
+ const size_t kBufSize = 1 << 12;
+ Byte buf[kBufSize];
+ for (;;)
+ {
+ if (size == 0)
+ return S_OK;
+ size_t curSize = kBufSize;
+ if (curSize > size)
+ curSize = (size_t)size;
+ RINOK(ReadStream_FALSE(stream, buf, curSize));
+ size -= curSize;
+ }
+}
+
+
HRESULT CZipDecoder::Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
CInArchive &archive, const CItemEx &item,
@@ -634,9 +659,11 @@ HRESULT CZipDecoder::Decode(
outStreamSpec->SetStream(realOutStream);
outStreamSpec->Init(needCRC);
- UInt64 authenticationPos;
-
- CMyComPtr<ISequentialInStream> inStream;
+ CMyComPtr<ISequentialInStream> packStream;
+
+ CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(limitedStreamSpec);
+
{
UInt64 packSize = item.PackSize;
if (wzAesMode)
@@ -645,9 +672,14 @@ HRESULT CZipDecoder::Decode(
return S_OK;
packSize -= NCrypto::NWzAes::kMacSize;
}
- UInt64 dataPos = item.GetDataPosition();
- inStream.Attach(archive.CreateLimitedStream(dataPos, packSize));
- authenticationPos = dataPos + packSize;
+ RINOK(archive.GetItemStream(item, true, packStream));
+ if (!packStream)
+ {
+ res = NExtract::NOperationResult::kUnavailable;
+ return S_OK;
+ }
+ limitedStreamSpec->SetStream(packStream);
+ limitedStreamSpec->Init(packSize);
}
CMyComPtr<ICompressFilter> cryptoFilter;
@@ -912,9 +944,15 @@ HRESULT CZipDecoder::Decode(
bool authOk = true;
if (needCRC)
crcOK = (outStreamSpec->GetCRC() == item.Crc);
+
if (wzAesMode)
{
- inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAes::kMacSize));
+ const UInt64 rem = limitedStreamSpec->GetRem();
+ if (rem != 0)
+ if (SkipStreamData(inStream, rem) != S_OK)
+ authOk = false;
+
+ limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize);
if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK)
authOk = false;
}
@@ -988,16 +1026,21 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnavailable));
continue;
}
+
if (!item.FromLocal)
{
- HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item);
+ bool isAvail = true;
+ HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item, isAvail);
if (res == S_FALSE)
{
if (item.IsDir() || realOutStream || testMode)
{
RINOK(extractCallback->PrepareOperation(askMode));
realOutStream.Release();
- RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kHeadersError));
+ RINOK(extractCallback->SetOperationResult(
+ isAvail ?
+ NExtract::NOperationResult::kHeadersError :
+ NExtract::NOperationResult::kUnavailable));
}
continue;
}
@@ -1034,6 +1077,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(res))
}
+
lps->InSize = currentTotalPacked;
lps->OutSize = currentTotalUnPacked;
return lps->SetCur();
diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h
index 82e46eb6..fead0192 100644
--- a/CPP/7zip/Archive/Zip/ZipHeader.h
+++ b/CPP/7zip/Archive/Zip/ZipHeader.h
@@ -18,9 +18,8 @@ namespace NSignature
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 kSpan = 0x08074B50;
+ const UInt32 kNoSpan = 0x30304B50; // PK00, replaces kSpan, if there is only 1 segment
}
const unsigned kLocalHeaderSize = 4 + 26; // including signature
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
index 2ba7e3fa..fe5200f7 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.cpp
+++ b/CPP/7zip/Archive/Zip/ZipIn.cpp
@@ -5,8 +5,11 @@
// #include <stdio.h>
#include "../../../Common/DynamicBuffer.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringToInt.h"
+
+#include "../../../Windows/PropVariant.h"
-#include "../../Common/LimitedStreams.h"
#include "../../Common/StreamUtils.h"
#include "../IArchive.h"
@@ -17,100 +20,133 @@
#define Get32(p) GetUi32(p)
#define Get64(p) GetUi64(p)
+#define G16(offs, v) v = Get16(p + (offs))
+#define G32(offs, v) v = Get32(p + (offs))
+#define G64(offs, v) v = Get64(p + (offs))
+
namespace NArchive {
namespace NZip {
struct CEcd
{
- UInt16 thisDiskNumber;
- UInt16 startCDDiskNumber;
- UInt16 numEntriesInCDOnThisDisk;
- UInt16 numEntriesInCD;
- UInt32 cdSize;
- UInt32 cdStartOffset;
- UInt16 commentSize;
+ UInt16 ThisDisk;
+ UInt16 CdDisk;
+ UInt16 NumEntries_in_ThisDisk;
+ UInt16 NumEntries;
+ UInt32 Size;
+ UInt32 Offset;
+ UInt16 CommentSize;
- void Parse(const Byte *p);
-
- bool IsEmptyArc()
+ bool IsEmptyArc() const
{
- return thisDiskNumber == 0 && startCDDiskNumber == 0 &&
- numEntriesInCDOnThisDisk == 0 && numEntriesInCD == 0 && cdSize == 0
- && cdStartOffset == 0 // test it
+ return ThisDisk == 0
+ && CdDisk == 0
+ && NumEntries_in_ThisDisk == 0
+ && NumEntries == 0
+ && Size == 0
+ && Offset == 0 // test it
;
}
+
+ void Parse(const Byte *p); // (p) doesn't include signature
};
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);
+ // (p) doesn't include signature
+ G16(0, ThisDisk);
+ G16(2, CdDisk);
+ G16(4, NumEntries_in_ThisDisk);
+ G16(6, NumEntries);
+ G32(8, Size);
+ G32(12, Offset);
+ G16(16, CommentSize);
}
-struct CEcd64
+
+void CCdInfo::ParseEcd32(const Byte *p)
{
- 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)); }
-};
+ // (p) includes signature
+ p += 4;
+ G16(0, ThisDisk);
+ G16(2, CdDisk);
+ G16(4, NumEntries_in_ThisDisk);
+ G16(6, NumEntries);
+ G32(8, Size);
+ G32(12, Offset);
+ G16(16, CommentSize);
+}
-void CEcd64::Parse(const Byte *p)
+void CCdInfo::ParseEcd64e(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);
+ // (p) exclude signature
+ G16(0, VersionMade);
+ G16(2, VersionNeedExtract);
+ G32(4, ThisDisk);
+ G32(8, CdDisk);
+
+ G64(12, NumEntries_in_ThisDisk);
+ G64(20, NumEntries);
+ G64(28, Size);
+ G64(36, Offset);
}
-HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+
+struct CLocator
{
- _inBufMode = false;
- Close();
- 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));
+ UInt32 Ecd64Disk;
+ UInt32 NumDisks;
+ UInt64 Ecd64Offset;
+
+ CLocator(): Ecd64Disk(0), NumDisks(0), Ecd64Offset(0) {}
- // printf("\nOpen offset = %d", (int)m_Position);
- RINOK(FindAndReadMarker(stream, searchHeaderSizeLimit));
- RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL));
- Stream = stream;
- return S_OK;
+ void Parse(const Byte *p)
+ {
+ G32(0, Ecd64Disk);
+ G64(4, Ecd64Offset);
+ G32(12, NumDisks);
+ }
+};
+
+
+
+
+void CInArchive::ClearRefs()
+{
+ StreamRef.Release();
+ Stream = NULL;
+ StartStream = NULL;
+ Callback = NULL;
+
+ Vols.Clear();
}
void CInArchive::Close()
{
+ _processedCnt = 0;
IsArc = false;
+ IsArcOpen = false;
+ IsMultiVol = false;
+ UseDisk_in_SingleVol = false;
+ EcdVolIndex = 0;
HeadersError = false;
HeadersWarning = false;
ExtraMinorError = false;
UnexpectedEnd = false;
NoCentralDir = false;
IsZip64 = false;
- Stream.Release();
+ MarkerIsFound = false;
+
+ ClearRefs();
}
+
HRESULT CInArchive::Seek(UInt64 offset)
{
return Stream->Seek(offset, STREAM_SEEK_SET, NULL);
}
+
static bool CheckDosTime(UInt32 dosTime)
{
if (dosTime == 0)
@@ -134,7 +170,8 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size)
UInt32 value = Get32(p);
- if (value == NSignature::kNoSpan)
+ if (value == NSignature::kNoSpan
+ || value == NSignature::kSpan)
{
p += 4;
size -= 4;
@@ -250,28 +287,35 @@ static UInt32 IsArc_Zip_2(const Byte *p, size_t size, bool isFinal)
return res;
}
-HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLimit)
+
+
+HRESULT CInArchive::FindMarker(IInStream *stream, const UInt64 *searchLimit)
{
- ArcInfo.Clear();
ArcInfo.MarkerPos = m_Position;
ArcInfo.MarkerPos2 = m_Position;
if (searchLimit && *searchLimit == 0)
{
- const unsigned kStartBufSize = kMarkerSize;
- Byte startBuf[kStartBufSize];
- size_t processed = kStartBufSize;
+ Byte startBuf[kMarkerSize];
+ size_t processed = kMarkerSize;
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;
+ {
+ if (m_Signature != NSignature::kSpan)
+ return S_FALSE;
+ if (m_Position != 4) // we don't support multivol archives with sfx stub
+ return S_FALSE;
+ ArcInfo.IsSpanMode = true;
+ }
+ size_t processed = kMarkerSize;
RINOK(ReadStream(stream, startBuf, &processed));
m_Position += processed;
if (processed < kMarkerSize)
@@ -283,9 +327,8 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLim
ArcInfo.MarkerPos2 += 4;
}
- // we use weak test in case of *searchLimit == 0)
+ // 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.
}
@@ -302,9 +345,17 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLim
RINOK(ReadStream(stream, buffer + numBytesInBuffer, &numReadBytes));
m_Position += numReadBytes;
numBytesInBuffer += numReadBytes;
- bool isFinished = (numBytesInBuffer != kBufSize);
+ const bool isFinished = (numBytesInBuffer != kBufSize);
- size_t limit = (isFinished ? numBytesInBuffer : numBytesInBuffer - kCheckSize);
+ size_t limit = numBytesInBuffer;;
+ if (isFinished)
+ {
+ if (limit == 0)
+ break;
+ limit--;
+ }
+ else
+ limit -= kCheckSize;
if (searchLimit && curScanPos + limit > *searchLimit)
limit = (size_t)(*searchLimit - curScanPos + 1);
@@ -328,7 +379,8 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLim
m_Signature = Get32(buf + pos);
ArcInfo.MarkerPos += curScanPos + pos;
ArcInfo.MarkerPos2 = ArcInfo.MarkerPos;
- if (m_Signature == NSignature::kNoSpan)
+ if (m_Signature == NSignature::kNoSpan
+ || m_Signature == NSignature::kSpan)
{
m_Signature = Get32(buf + pos + 4);
ArcInfo.MarkerPos2 += 4;
@@ -349,13 +401,86 @@ HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchLim
return S_FALSE;
}
-HRESULT CInArchive::IncreaseRealPosition(Int64 addValue)
+
+HRESULT CInArchive::IncreaseRealPosition(Int64 addValue, bool &isFinished)
{
- return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position);
+ isFinished = false;
+ if (!IsMultiVol)
+ return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position);
+
+ for (;;)
+ {
+ if (addValue == 0)
+ return S_OK;
+ if (addValue > 0)
+ {
+ if (Vols.StreamIndex < 0)
+ return S_FALSE;
+ if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size())
+ {
+ isFinished = true;
+ return S_OK;
+ }
+ {
+ const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex];
+ if (!s.Stream)
+ {
+ isFinished = true;
+ return S_OK;
+ }
+ if (m_Position > s.Size)
+ return S_FALSE;
+ UInt64 rem = s.Size - m_Position;
+ if ((UInt64)addValue <= rem)
+ return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position);
+ RINOK(Stream->Seek(s.Size, STREAM_SEEK_SET, &m_Position));
+ addValue -= rem;
+ Stream = NULL;
+ Vols.StreamIndex++;
+ if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size())
+ {
+ isFinished = true;
+ return S_OK;
+ }
+ }
+ const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex];
+ if (!s2.Stream)
+ {
+ isFinished = true;
+ return S_OK;
+ }
+ Stream = s2.Stream;
+ m_Position = 0;
+ RINOK(Stream->Seek(0, STREAM_SEEK_SET, &m_Position));
+ }
+ else
+ {
+ if (!Stream)
+ return S_FALSE;
+ {
+ if (m_Position >= (UInt64)(-addValue))
+ return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position);
+ addValue += m_Position;
+ RINOK(Stream->Seek(0, STREAM_SEEK_SET, &m_Position));
+ m_Position = 0;
+ Stream = NULL;
+ if (--Vols.StreamIndex < 0)
+ return S_FALSE;
+ }
+ const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex];
+ if (!s2.Stream)
+ return S_FALSE;
+ Stream = s2.Stream;
+ m_Position = s2.Size;
+ RINOK(Stream->Seek(s2.Size, STREAM_SEEK_SET, &m_Position));
+ }
+ }
}
+
class CUnexpectEnd {};
+
HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
{
size_t realProcessedSize = size;
@@ -376,18 +501,46 @@ HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
void CInArchive::SafeReadBytes(void *data, unsigned size)
{
size_t processed = size;
- if (_inBufMode)
- {
- processed = _inBuffer.ReadBytes((Byte *)data, size);
- m_Position += processed;
- }
+
+ HRESULT result = S_OK;
+
+ if (!_inBufMode)
+ result = ReadStream(Stream, data, &processed);
else
{
- HRESULT result = ReadStream(Stream, data, &processed);
- m_Position += processed;
- if (result != S_OK)
- throw CSystemException(result);
+ for (;;)
+ {
+ processed = _inBuffer.ReadBytes((Byte *)data, size);
+ if (processed != 0
+ || IsMultiVol
+ || !CanStartNewVol
+ || Vols.StreamIndex < 0
+ || (unsigned)Vols.StreamIndex >= Vols.Streams.Size())
+ break;
+ Vols.StreamIndex++;
+ const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex];
+ if (!s.Stream)
+ break;
+ // if (Vols.NeedSeek)
+ {
+ result = s.Stream->Seek(0, STREAM_SEEK_SET, NULL);
+ m_Position = 0;
+ if (result != S_OK)
+ break;
+ Vols.NeedSeek = false;
+ }
+ _inBuffer.SetStream(s.Stream);
+ _inBuffer.Init();
+ }
+ CanStartNewVol = false;
}
+
+ m_Position += processed;
+ _processedCnt += processed;
+
+ if (result != S_OK)
+ throw CSystemException(result);
+
if (processed != size)
throw CUnexpectEnd();
}
@@ -410,12 +563,15 @@ UInt16 CInArchive::ReadUInt16() { Byte buf[2]; SafeReadBytes(buf, 2); return Get
UInt32 CInArchive::ReadUInt32() { Byte buf[4]; SafeReadBytes(buf, 4); return Get32(buf); }
UInt64 CInArchive::ReadUInt64() { Byte buf[8]; SafeReadBytes(buf, 8); return Get64(buf); }
+// we use Skip() inside headers only, so no need for stream change in multivol.
+
void CInArchive::Skip(unsigned num)
{
if (_inBufMode)
{
size_t skip = _inBuffer.Skip(num);
m_Position += skip;
+ _processedCnt += skip;
if (skip != num)
throw CUnexpectEnd();
}
@@ -440,16 +596,18 @@ void CInArchive::ReadFileName(unsigned size, AString &s)
s.Empty();
return;
}
- char *p = s.GetBuf(size);
- SafeReadBytes(p, size);
+ SafeReadBytes(s.GetBuf(size), size);
s.ReleaseBuf_CalcLen(size);
}
+
bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock,
UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber)
{
extraBlock.Clear();
+
UInt32 remain = extraSize;
+
while (remain >= 4)
{
CExtraSubBlock subBlock;
@@ -509,6 +667,7 @@ bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock,
}
remain -= dataSize;
}
+
if (remain != 0)
{
ExtraMinorError = true;
@@ -516,12 +675,17 @@ bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock,
// so we don't return false, but just set warning flag
// return false;
}
+
Skip(remain);
return true;
}
+
bool CInArchive::ReadLocalItem(CItemEx &item)
{
+ item.Disk = 0;
+ if (IsMultiVol && Vols.StreamIndex >= 0)
+ item.Disk = Vols.StreamIndex;
const unsigned kPureHeaderSize = kLocalHeaderSize - 4;
Byte p[kPureHeaderSize];
SafeReadBytes(p, kPureHeaderSize);
@@ -534,14 +698,14 @@ bool CInArchive::ReadLocalItem(CItemEx &item)
item.ExtractVersion.Version = p[0];
item.ExtractVersion.HostOS = p[1];
- item.Flags = Get16(p + 2);
- item.Method = Get16(p + 4);
- item.Time = Get32(p + 6);
- item.Crc = Get32(p + 10);
- item.PackSize = Get32(p + 14);
- item.Size = Get32(p + 18);
- unsigned nameSize = Get16(p + 22);
- unsigned extraSize = Get16(p + 24);
+ G16(2, item.Flags);
+ G16(4, item.Method);
+ G32(6, item.Time);
+ G32(10, item.Crc);
+ G32(14, item.PackSize);
+ G32(18, item.Size);
+ const unsigned nameSize = Get16(p + 22);
+ const unsigned extraSize = Get16(p + 24);
ReadFileName(nameSize, item.Name);
item.LocalFullHeaderSize = kLocalHeaderSize + (UInt32)nameSize + extraSize;
@@ -581,6 +745,7 @@ bool CInArchive::ReadLocalItem(CItemEx &item)
return item.LocalFullHeaderSize <= ((UInt32)1 << 16);
}
+
static bool FlagsAreSame(const CItem &i1, const CItem &i2)
{
if (i1.Method != i2.Method)
@@ -597,9 +762,16 @@ static bool FlagsAreSame(const CItem &i1, const CItem &i2)
if (i1.Method <= NFileHeader::NCompressionMethod::kImploded)
mask = 0x7FFF;
}
+
+ // we can ignore utf8 flag, if name is ascii
+ if ((i1.Flags ^ i2.Flags) & NFileHeader::NFlags::kUtf8)
+ if (i1.Name.IsAscii() && i2.Name.IsAscii())
+ mask &= ~NFileHeader::NFlags::kUtf8;
+
return ((i1.Flags & mask) == (i2.Flags & mask));
}
+
// #ifdef _WIN32
static bool AreEqualPaths_IgnoreSlashes(const char *s1, const char *s2)
{
@@ -623,6 +795,7 @@ static bool AreEqualPaths_IgnoreSlashes(const char *s1, const char *s2)
}
// #endif
+
static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
{
if (!FlagsAreSame(cdItem, localItem))
@@ -670,16 +843,52 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
return true;
}
-HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item)
+
+HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail)
{
+ isAvail = true;
if (item.FromLocal)
return S_OK;
try
{
- UInt64 offset = ArcInfo.Base + item.LocalHeaderPos;
- if (ArcInfo.Base < 0 && (Int64)offset < 0)
- return S_FALSE;
- RINOK(Seek(offset));
+ UInt64 offset = item.LocalHeaderPos;
+
+ if (IsMultiVol)
+ {
+ if (item.Disk >= Vols.Streams.Size())
+ {
+ isAvail = false;
+ return S_FALSE;
+ }
+ IInStream *str2 = Vols.Streams[item.Disk].Stream;
+ if (!str2)
+ {
+ isAvail = false;
+ return S_FALSE;
+ }
+ RINOK(str2->Seek(offset, STREAM_SEEK_SET, NULL));
+ Stream = str2;
+ Vols.StreamIndex = item.Disk;
+ }
+ else
+ {
+ if (UseDisk_in_SingleVol && item.Disk != EcdVolIndex)
+ {
+ isAvail = false;
+ return S_FALSE;
+ }
+ Stream = StreamRef;
+
+ offset += ArcInfo.Base;
+ if (ArcInfo.Base < 0 && (Int64)offset < 0)
+ {
+ isAvail = false;
+ return S_FALSE;
+ }
+ RINOK(Seek(offset));
+ }
+
+
CItemEx localItem;
if (ReadUInt32() != NSignature::kLocalFileHeader)
return S_FALSE;
@@ -694,6 +903,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item)
return S_OK;
}
+
HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item)
{
const unsigned kBufSize = (1 << 12);
@@ -726,7 +936,8 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item)
item.Crc = Get32(buf + i + 4);
item.PackSize = descriptorPackSize;
item.Size = Get32(buf + i + 12);
- return IncreaseRealPosition((Int64)(Int32)(0 - (numBytesInBuffer - i - kDataDescriptorSize)));
+ bool isFinished;
+ return IncreaseRealPosition((Int64)(Int32)(0 - (numBytesInBuffer - i - kDataDescriptorSize)), isFinished);
}
}
}
@@ -739,15 +950,18 @@ HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item)
}
}
+
HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item)
{
if (item.FromLocal)
return S_OK;
try
{
- RINOK(ReadLocalItemAfterCdItem(item));
+ bool isAvail = true;
+ RINOK(ReadLocalItemAfterCdItem(item, isAvail));
if (item.HasDescriptor())
{
+ // pkzip's version without descriptor is not supported
RINOK(Seek(ArcInfo.Base + item.GetDataPosition() + item.PackSize));
if (ReadUInt32() != NSignature::kDataDescriptor)
return S_FALSE;
@@ -775,6 +989,7 @@ HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item)
return S_OK;
}
+
HRESULT CInArchive::ReadCdItem(CItemEx &item)
{
item.FromCentral = true;
@@ -785,30 +1000,24 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item)
item.MadeByVersion.HostOS = p[1];
item.ExtractVersion.Version = p[2];
item.ExtractVersion.HostOS = p[3];
- item.Flags = Get16(p + 4);
- item.Method = Get16(p + 6);
- item.Time = Get32(p + 8);
- item.Crc = Get32(p + 12);
- item.PackSize = Get32(p + 16);
- item.Size = Get32(p + 20);
+ G16(4, item.Flags);
+ G16(6, item.Method);
+ G32(8, item.Time);
+ G32(12, item.Crc);
+ G32(16, item.PackSize);
+ G32(20, item.Size);
const unsigned nameSize = Get16(p + 24);
const unsigned extraSize = Get16(p + 26);
const unsigned commentSize = Get16(p + 28);
- UInt32 diskNumberStart = Get16(p + 30);
- item.InternalAttrib = Get16(p + 32);
- item.ExternalAttrib = Get32(p + 34);
- item.LocalHeaderPos = Get32(p + 38);
+ G16(30, item.Disk);
+ G16(32, item.InternalAttrib);
+ G32(34, item.ExternalAttrib);
+ G32(38, item.LocalHeaderPos);
ReadFileName(nameSize, item.Name);
if (extraSize > 0)
- {
- ReadExtra(extraSize, item.CentralExtra, item.Size, item.PackSize,
- item.LocalHeaderPos, diskNumberStart);
- }
+ ReadExtra(extraSize, item.CentralExtra, item.Size, item.PackSize, item.LocalHeaderPos, item.Disk);
- if (diskNumberStart != 0)
- return E_NOTIMPL;
-
// May be these strings must be deleted
/*
if (item.IsDir())
@@ -819,19 +1028,6 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item)
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)
{
@@ -847,155 +1043,256 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo)
UInt64 mainSize = Get64(buf + 4);
if (mainSize < kEcd64_MainSize || mainSize > ((UInt64)1 << 32))
return S_FALSE;
- cdInfo.ParseEcd64(buf);
+ cdInfo.ParseEcd64e(buf + 12);
return S_OK;
}
-HRESULT CInArchive::FindCd(CCdInfo &cdInfo)
+
+HRESULT CInArchive::FindCd(bool checkOffsetMode)
{
- UInt64 endPosition;
- RINOK(Stream->Seek(0, STREAM_SEEK_END, &endPosition));
+ CCdInfo &cdInfo = Vols.ecd;
+
+ UInt64 endPos;
+
+ RINOK(Stream->Seek(0, STREAM_SEEK_END, &endPos));
const UInt32 kBufSizeMax = ((UInt32)1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize;
- UInt32 bufSize = (endPosition < kBufSizeMax) ? (UInt32)endPosition : kBufSizeMax;
+ const UInt32 bufSize = (endPos < kBufSizeMax) ? (UInt32)endPos : kBufSizeMax;
if (bufSize < kEcdSize)
return S_FALSE;
CByteArr byteBuffer(bufSize);
- UInt64 startPosition = endPosition - bufSize;
- RINOK(Stream->Seek(startPosition, STREAM_SEEK_SET, &m_Position));
- if (m_Position != startPosition)
+ const UInt64 startPos = endPos - bufSize;
+ RINOK(Stream->Seek(startPos, STREAM_SEEK_SET, &m_Position));
+ if (m_Position != startPos)
return S_FALSE;
RINOK(ReadStream_FALSE(Stream, byteBuffer, bufSize));
- const Byte *buf = byteBuffer;
- for (UInt32 i = bufSize - kEcdSize;; i--)
+ for (UInt32 i = bufSize - kEcdSize + 1;;)
{
- if (buf[i] != 0x50)
+ if (i == 0)
+ return S_FALSE;
+
+ const Byte *buf = byteBuffer;
+
+ for (;;)
{
- if (i == 0) return S_FALSE;
i--;
- if (buf[i] != 0x50)
- {
- if (i == 0) return S_FALSE;
- continue;
- }
+ if (buf[i] == 0x50)
+ break;
+ if (i == 0)
+ return S_FALSE;
}
- if (Get32(buf + i) == NSignature::kEcd)
+
+ if (Get32(buf + i) != NSignature::kEcd)
+ continue;
+
+ cdInfo.ParseEcd32(buf + i);
+
+ if (i >= kEcd64Locator_Size)
{
- if (i >= kEcd64_FullSize + kEcd64Locator_Size)
+ const Byte *locatorPtr = buf + i - kEcd64Locator_Size;
+ if (Get32(locatorPtr) == NSignature::kEcd64Locator)
{
- 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
+ CLocator locator;
+ locator.Parse(locatorPtr + 4);
+ if ((cdInfo.ThisDisk == locator.NumDisks - 1 || cdInfo.ThisDisk == 0xFFFF)
+ && locator.Ecd64Disk < locator.NumDisks)
{
- // Most of the zip64 use fixed size Zip64 ECD
+ if (locator.Ecd64Disk != cdInfo.ThisDisk && cdInfo.ThisDisk != 0xFFFF)
+ return E_NOTIMPL;
- UInt64 ecd64Offset = Get64(locator + 8);
- UInt64 absEcd64 = endPosition - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize);
+ // Most of the zip64 use fixed size Zip64 ECD
+ // we try relative backward reading.
+
+ UInt64 absEcd64 = endPos - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize);
+ if (checkOffsetMode || absEcd64 == locator.Ecd64Offset)
{
- const Byte *ecd64 = locator - kEcd64_FullSize;
- if (Get32(ecd64) == NSignature::kEcd64 &&
- Get64(ecd64 + 4) == kEcd64_MainSize)
+ const Byte *ecd64 = locatorPtr - kEcd64_FullSize;
+ if (Get32(ecd64) == NSignature::kEcd64)
{
- cdInfo.ParseEcd64(ecd64);
- ArcInfo.Base = absEcd64 - ecd64Offset;
- return S_OK;
+ UInt64 mainEcd64Size = Get64(ecd64 + 4);
+ if (mainEcd64Size == kEcd64_MainSize)
+ {
+ cdInfo.ParseEcd64e(ecd64 + 12);
+ ArcInfo.Base = absEcd64 - locator.Ecd64Offset;
+ // ArcInfo.BaseVolIndex = cdInfo.ThisDisk;
+ return S_OK;
+ }
}
}
-
+
// some zip64 use variable size Zip64 ECD.
- // we try to find it
- if (absEcd64 != ecd64Offset)
+ // we try to use absolute offset from locator.
+
+ if (absEcd64 != locator.Ecd64Offset)
{
- if (TryEcd64(ecd64Offset, cdInfo) == S_OK)
+ if (TryEcd64(locator.Ecd64Offset, cdInfo) == S_OK)
{
ArcInfo.Base = 0;
+ // ArcInfo.BaseVolIndex = cdInfo.ThisDisk;
return S_OK;
}
}
- if (ArcInfo.MarkerPos != 0 &&
- ArcInfo.MarkerPos + ecd64Offset != absEcd64)
+
+ // for variable Zip64 ECD with for archives with offset != 0.
+
+ if (checkOffsetMode
+ && ArcInfo.MarkerPos != 0
+ && ArcInfo.MarkerPos + locator.Ecd64Offset != absEcd64)
{
- if (TryEcd64(ArcInfo.MarkerPos + ecd64Offset, cdInfo) == S_OK)
+ if (TryEcd64(ArcInfo.MarkerPos + locator.Ecd64Offset, cdInfo) == S_OK)
{
ArcInfo.Base = ArcInfo.MarkerPos;
+ // ArcInfo.BaseVolIndex = cdInfo.ThisDisk;
return S_OK;
}
}
}
}
- if (Get32(buf + i + 4) == 0) // ThisDiskNumber, StartCentralDirectoryDiskNumber;
+ }
+
+ // bool isVolMode = (Vols.EndVolIndex != -1);
+ // UInt32 searchDisk = (isVolMode ? Vols.EndVolIndex : 0);
+
+ if (/* searchDisk == thisDisk && */ cdInfo.CdDisk <= cdInfo.ThisDisk)
+ {
+ // if (isVolMode)
+ {
+ if (cdInfo.CdDisk != cdInfo.ThisDisk)
+ return S_OK;
+ }
+
+ UInt64 absEcdPos = endPos - bufSize + i;
+ UInt64 cdEnd = cdInfo.Size + cdInfo.Offset;
+ ArcInfo.Base = 0;
+ // ArcInfo.BaseVolIndex = cdInfo.ThisDisk;
+ if (absEcdPos != cdEnd)
{
- cdInfo.ParseEcd(buf + i);
- UInt64 absEcdPos = endPosition - bufSize + i;
- UInt64 cdEnd = cdInfo.Size + cdInfo.Offset;
- ArcInfo.Base = 0;
- if (absEcdPos != cdEnd)
+ /*
+ if (cdInfo.Offset <= 16 && cdInfo.Size != 0)
{
- /*
- if (cdInfo.Offset <= 16 && cdInfo.Size != 0)
- {
- // here we support some rare ZIP files with Central directory at the start
- ArcInfo.Base = 0;
- }
- else
- */
- ArcInfo.Base = absEcdPos - cdEnd;
+ // here we support some rare ZIP files with Central directory at the start
+ ArcInfo.Base = 0;
}
- return S_OK;
+ else
+ */
+ ArcInfo.Base = absEcdPos - cdEnd;
}
+ return S_OK;
}
- if (i == 0)
- return S_FALSE;
}
}
-HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress)
+HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize)
{
items.Clear();
- RINOK(Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position));
- if (m_Position != cdOffset)
- return S_FALSE;
+
+ ISequentialInStream *stream;
+
+ if (!IsMultiVol)
+ {
+ stream = this->StartStream;
+ Vols.StreamIndex = -1;
+ RINOK(this->StartStream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position));
+ if (m_Position != cdOffset)
+ return S_FALSE;
+ }
+ else
+ {
+ if (cdInfo.CdDisk >= Vols.Streams.Size())
+ return S_FALSE;
+ IInStream *str2 = Vols.Streams[cdInfo.CdDisk].Stream;
+ if (!str2)
+ return S_FALSE;
+ RINOK(str2->Seek(cdOffset, STREAM_SEEK_SET, NULL));
+ stream = str2;
+ Vols.NeedSeek = false;
+ Vols.StreamIndex = cdInfo.CdDisk;
+ m_Position = cdOffset;
+ }
+
+ _inBuffer.SetStream(stream);
_inBuffer.Init();
_inBufMode = true;
- while (m_Position - cdOffset < cdSize)
+ _processedCnt = 0;
+
+ while (_processedCnt < cdSize)
{
+ CanStartNewVol = true;
if (ReadUInt32() != NSignature::kCentralFileHeader)
return S_FALSE;
- CItemEx cdItem;
- RINOK(ReadCdItem(cdItem));
- items.Add(cdItem);
- if (progress && (items.Size() & 0xFFF) == 0)
- RINOK(progress->SetCompletedCD(items.Size()));
+ {
+ CItemEx cdItem;
+ RINOK(ReadCdItem(cdItem));
+ items.Add(cdItem);
+ }
+ if (Callback && (items.Size() & 0xFFF) == 0)
+ {
+ const UInt64 numFiles = items.Size();
+ RINOK(Callback->SetCompleted(&numFiles, NULL));
+ }
}
- return (m_Position - cdOffset == cdSize) ? S_OK : S_FALSE;
+
+ CanStartNewVol = true;
+
+ return (_processedCnt == cdSize) ? S_OK : S_FALSE;
}
-HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress)
+
+HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize)
{
- CCdInfo cdInfo;
- RINOK(FindCd(cdInfo));
+ bool checkOffsetMode = true;
+
+ if (IsMultiVol)
+ {
+ if (Vols.EndVolIndex == -1)
+ return S_FALSE;
+ Stream = Vols.Streams[Vols.EndVolIndex].Stream;
+ if (!Vols.StartIsZip)
+ checkOffsetMode = false;
+ }
+ else
+ Stream = StartStream;
+
+ if (!Vols.ecd_wasRead)
+ {
+ RINOK(FindCd(checkOffsetMode));
+ }
+
+ CCdInfo &cdInfo = Vols.ecd;
+
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)
+ cdDisk = cdInfo.CdDisk;
+
+ if (Callback)
{
- res = TryReadCd(items, ArcInfo.MarkerPos + cdOffset, cdSize, progress);
+ RINOK(Callback->SetTotal(&cdInfo.NumEntries, NULL));
+ }
+
+ const UInt64 base = (IsMultiVol ? 0 : ArcInfo.Base);
+ res = TryReadCd(items, cdInfo, base + cdOffset, cdSize);
+
+ if (res == S_FALSE && !IsMultiVol && base != ArcInfo.MarkerPos)
+ {
+ // do we need that additional attempt to read cd?
+ res = TryReadCd(items, cdInfo, ArcInfo.MarkerPos + cdOffset, cdSize);
if (res == S_OK)
ArcInfo.Base = ArcInfo.MarkerPos;
}
+
return res;
}
-static HRESULT FindItem(const CObjectVector<CItemEx> &items, UInt64 offset)
+
+static int FindItem(const CObjectVector<CItemEx> &items, const CItemEx &item)
{
unsigned left = 0, right = items.Size();
for (;;)
@@ -1003,42 +1300,66 @@ static HRESULT FindItem(const CObjectVector<CItemEx> &items, UInt64 offset)
if (left >= right)
return -1;
unsigned index = (left + right) / 2;
- UInt64 position = items[index].LocalHeaderPos;
- if (offset == position)
+ const CItemEx &item2 = items[index];
+ if (item.Disk < item2.Disk)
+ right = index;
+ else if (item.Disk > item2.Disk)
+ left = index + 1;
+ else if (item.LocalHeaderPos == item2.LocalHeaderPos)
return index;
- if (offset < position)
+ else if (item.LocalHeaderPos < item2.LocalHeaderPos)
right = index;
else
left = index + 1;
}
}
-bool IsStrangeItem(const CItem &item)
+static bool IsStrangeItem(const CItem &item)
{
return item.Name.Len() > (1 << 14) || item.Method > (1 << 8);
}
-HRESULT CInArchive::ReadLocals(
- CObjectVector<CItemEx> &items, CProgressVirt *progress)
+HRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items)
{
items.Clear();
+
while (m_Signature == NSignature::kLocalFileHeader)
{
CItemEx item;
- item.LocalHeaderPos = m_Position - 4 - ArcInfo.MarkerPos;
+ item.LocalHeaderPos = m_Position - 4;
+ if (!IsMultiVol)
+ item.LocalHeaderPos -= ArcInfo.MarkerPos;
+
// we write ralative LocalHeaderPos here. Later we can correct it to real Base.
+
try
{
ReadLocalItem(item);
item.FromLocal = true;
+ bool isFinished = false;
+
if (item.HasDescriptor())
ReadLocalItemDescriptor(item);
else
{
- RINOK(IncreaseRealPosition(item.PackSize));
+ /*
+ if (IsMultiVol)
+ {
+ const int kStep = 10000;
+ RINOK(IncreaseRealPosition(-kStep, isFinished));
+ RINOK(IncreaseRealPosition(item.PackSize + kStep, isFinished));
+ }
+ else
+ */
+ RINOK(IncreaseRealPosition(item.PackSize, isFinished));
}
+
items.Add(item);
+
+ if (isFinished)
+ throw CUnexpectEnd();
+
m_Signature = ReadUInt32();
}
catch (CUnexpectEnd &)
@@ -1048,34 +1369,364 @@ HRESULT CInArchive::ReadLocals(
throw;
}
- if (progress && (items.Size() & 0xFF) == 0)
- RINOK(progress->SetCompletedLocal(items.Size(), item.LocalHeaderPos));
+ if (Callback && (items.Size() & 0xFF) == 0)
+ {
+ const UInt64 numFiles = items.Size();
+ UInt64 numBytes = 0;
+ // if (!sMultiVol)
+ numBytes = item.LocalHeaderPos;
+ RINOK(Callback->SetCompleted(&numFiles, &numBytes));
+ }
}
if (items.Size() == 1 && m_Signature != NSignature::kCentralFileHeader)
if (IsStrangeItem(items[0]))
return S_FALSE;
+
+ return S_OK;
+}
+
+
+
+HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
+{
+ UString name;
+ {
+ NWindows::NCOM::CPropVariant prop;
+ RINOK(volCallback->GetProperty(kpidName, &prop));
+ if (prop.vt != VT_BSTR)
+ return S_OK;
+ name = prop.bstrVal;
+ }
+
+ UString base = name;
+ int dotPos = name.ReverseFind_Dot();
+
+ if (dotPos < 0)
+ return S_OK;
+
+ base.DeleteFrom(dotPos + 1);
+
+ const UString ext = name.Ptr(dotPos + 1);
+ StartVolIndex = (Int32)(-1);
+
+ if (ext.IsEmpty())
+ return S_OK;
+ else
+ {
+ wchar_t c = ext[0];
+ IsUpperCase = (c >= 'A' && c <= 'Z');
+ if (ext.IsEqualTo_Ascii_NoCase("zip"))
+ {
+ BaseName = base;
+ StartIsZ = true;
+ StartIsZip = true;
+ return S_OK;
+ }
+ else if (ext.IsEqualTo_Ascii_NoCase("exe"))
+ {
+ StartIsExe = true;
+ BaseName = base;
+ StartVolIndex = 0;
+ }
+ else if (ext[0] == 'z' || ext[0] == 'Z')
+ {
+ if (ext.Len() < 3)
+ return S_OK;
+ const wchar_t *end = NULL;
+ UInt32 volNum = ConvertStringToUInt32(ext.Ptr(1), &end);
+ if (*end != 0 || volNum < 1 || volNum > ((UInt32)1 << 30))
+ return S_OK;
+ StartVolIndex = volNum - 1;
+ BaseName = base;
+ StartIsZ = true;
+ }
+ else
+ return S_OK;
+ }
+
+ UString volName = BaseName;
+ volName.AddAscii(IsUpperCase ? "ZIP" : "zip");
+ HRESULT result = volCallback->GetStream(volName, &ZipStream);
+ if (result == S_FALSE || !ZipStream)
+ {
+ if (MissingName.IsEmpty())
+ MissingName = volName;
+ return S_OK;
+ }
+
+ return result;
+}
+
+
+HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback,
+ unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols)
+{
+ numMissingVols = 0;
+
+ for (unsigned i = start;; i++)
+ {
+ if (lastDisk >= 0 && i >= (unsigned)lastDisk)
+ break;
+
+ if (i < Vols.Streams.Size())
+ if (Vols.Streams[i].Stream)
+ continue;
+
+ CMyComPtr<IInStream> stream;
+
+ if ((int)i == zipDisk)
+ {
+ stream = Vols.ZipStream;
+ }
+ else if ((int)i == Vols.StartVolIndex)
+ {
+ stream = StartStream;
+ }
+ else
+ {
+ UString volName = Vols.BaseName;
+ {
+ volName += (wchar_t)(Vols.IsUpperCase ? 'Z' : 'z');
+ {
+ char s[32];
+ ConvertUInt32ToString(i + 1, s);
+ unsigned len = (unsigned)strlen(s);
+ while (len < 2)
+ {
+ volName += (wchar_t)'0';
+ len++;
+ }
+ volName.AddAscii(s);
+ }
+ }
+
+ HRESULT result = volCallback->GetStream(volName, &stream);
+ if (result != S_OK && result != S_FALSE)
+ return result;
+ if (result == S_FALSE || !stream)
+ {
+ if (Vols.MissingName.IsEmpty())
+ Vols.MissingName = volName;
+ numMissingVols++;
+ if (numMissingVols > numMissingVolsMax)
+ return S_OK;
+ if (lastDisk == -1 && numMissingVols != 0)
+ return S_OK;
+ continue;
+ }
+ }
+
+ UInt64 size;
+
+ UInt64 pos;
+ RINOK(stream->Seek(0, STREAM_SEEK_CUR, &pos));
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &size));
+ RINOK(stream->Seek(pos, STREAM_SEEK_SET, NULL));
+
+ while (i >= Vols.Streams.Size())
+ Vols.Streams.AddNew();
+
+ CVols::CSubStreamInfo &ss = Vols.Streams[i];
+ Vols.NumVols++;
+ ss.Stream = stream;
+ ss.Size = size;
+
+ if ((int)i == zipDisk)
+ {
+ Vols.EndVolIndex = Vols.Streams.Size() - 1;
+ break;
+ }
+ }
+
return S_OK;
}
+HRESULT CInArchive::ReadVols()
+{
+ CMyComPtr<IArchiveOpenVolumeCallback> volCallback;
+
+ Callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volCallback);
+ if (!volCallback)
+ return S_OK;
+
+ RINOK(Vols.ParseArcName(volCallback));
+
+ int startZIndex = Vols.StartVolIndex;
+
+ if (!Vols.StartIsZ)
+ {
+ // if (!Vols.StartIsExe)
+ return S_OK;
+ }
+
+ int zipDisk = -1;
+ int cdDisk = -1;
+
+ if (Vols.StartIsZip)
+ Vols.ZipStream = StartStream;
+
+ bool cdOK = false;
+
+ if (Vols.ZipStream)
+ {
+ Stream = Vols.ZipStream;
+ HRESULT res = FindCd(true);
+ CCdInfo &ecd = Vols.ecd;
+ if (res == S_OK)
+ {
+ zipDisk = ecd.ThisDisk;
+ Vols.ecd_wasRead = true;
+ if (ecd.ThisDisk == 0
+ || ecd.ThisDisk >= ((UInt32)1 << 30)
+ || ecd.ThisDisk < ecd.CdDisk)
+ return S_OK;
+ cdDisk = ecd.CdDisk;
+ if (Vols.StartVolIndex < 0)
+ Vols.StartVolIndex = ecd.ThisDisk;
+ // Vols.StartVolIndex = ecd.ThisDisk;
+ // Vols.EndVolIndex = ecd.ThisDisk;
+ unsigned numMissingVols;
+ if (cdDisk == zipDisk)
+ cdOK = true;
+ else
+ {
+ RINOK(ReadVols2(volCallback, cdDisk, zipDisk, zipDisk, 0, numMissingVols));
+ if (numMissingVols == 0)
+ cdOK = false;
+ }
+ }
+ else if (res != S_FALSE)
+ return res;
+ }
+
+ if (Vols.Streams.Size() > 0)
+ IsMultiVol = true;
+
+ if (Vols.StartVolIndex < 0)
+ return S_OK;
+
+ unsigned numMissingVols;
+
+ if (cdDisk != 0)
+ {
+ RINOK(ReadVols2(volCallback, 0, cdDisk < 0 ? -1 : cdDisk, zipDisk, 1 << 10, numMissingVols));
+ }
+
+ if (Vols.ZipStream)
+ {
+ if (Vols.Streams.IsEmpty())
+ if (zipDisk > (1 << 10))
+ return S_OK;
+ RINOK(ReadVols2(volCallback, zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols));
+ }
+
+ if (!Vols.Streams.IsEmpty())
+ {
+ IsMultiVol = true;
+ /*
+ if (cdDisk)
+ IsMultiVol = true;
+ */
+ if (startZIndex >= 0)
+ {
+ if (Vols.Streams.Size() >= (unsigned)startZIndex)
+ {
+ for (unsigned i = 0; i < (unsigned)startZIndex; i++)
+ if (!Vols.Streams[i].Stream)
+ {
+ Vols.StartParsingVol = startZIndex;
+ break;
+ }
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+
+
+
+
+HRESULT CVols::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+
+ for (;;)
+ {
+ if (StreamIndex < 0)
+ return S_OK;
+ if ((unsigned)StreamIndex >= Streams.Size())
+ return S_OK;
+ const CVols::CSubStreamInfo &s = Streams[StreamIndex];
+ if (!s.Stream)
+ return S_FALSE;
+ if (NeedSeek)
+ {
+ RINOK(s.Stream->Seek(0, STREAM_SEEK_SET, NULL));
+ NeedSeek = false;
+ }
+ UInt32 realProcessedSize = 0;
+ HRESULT res = s.Stream->Read(data, size, &realProcessedSize);
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ if (res != S_OK)
+ return res;
+ if (realProcessedSize != 0)
+ return res;
+ StreamIndex++;
+ NeedSeek = true;
+ }
+}
+
+STDMETHODIMP CVolStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ return Vols->Read(data, size, processedSize);
+}
+
+
+
+
#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::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *progress)
+
+HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
{
- items.Clear();
+ HRESULT res = S_OK;
+
+ bool localsWereRead = false;
+ UInt64 cdSize = 0, cdRelatOffset = 0, cdAbsOffset = 0;
+ UInt32 cdDisk = 0;
+ if (!_inBuffer.Create(1 << 15))
+ return E_OUTOFMEMORY;
+
+ if (!MarkerIsFound)
+ {
+ IsArc = true;
+ res = ReadCd(items, cdDisk, cdRelatOffset, cdSize);
+ if (res == S_OK)
+ m_Signature = ReadUInt32();
+ }
+ else
+ {
+
// m_Signature must be kLocalFileHeader or kEcd
// m_Position points to next byte after signature
RINOK(Stream->Seek(m_Position, STREAM_SEEK_SET, NULL));
- if (!_inBuffer.Create(1 << 15))
- return E_OUTOFMEMORY;
_inBuffer.SetStream(Stream);
bool needReadCd = true;
- bool localsWereRead = false;
+
if (m_Signature == NSignature::kEcd)
{
// It must be empty archive or backware archive
@@ -1097,9 +1748,6 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p
RINOK(Stream->Seek(ArcInfo.MarkerPos2 + 4, STREAM_SEEK_SET, &m_Position));
}
- UInt64 cdSize = 0, cdRelatOffset = 0, cdAbsOffset = 0;
- HRESULT res = S_OK;
-
if (needReadCd)
{
CItemEx firstItem;
@@ -1116,7 +1764,7 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p
}
IsArc = true;
- res = ReadCd(items, cdRelatOffset, cdSize, progress);
+ res = ReadCd(items, cdDisk, cdRelatOffset, cdSize);
if (res == S_OK)
m_Signature = ReadUInt32();
}
@@ -1130,16 +1778,27 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p
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]))
+ if ((Int64)ArcInfo.MarkerPos2 < ArcInfo.Base)
res = S_FALSE;
- ArcInfo.CdWasRead = true;
- ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos;
+ else
+ {
+ firstItem.LocalHeaderPos = ArcInfo.MarkerPos2 - ArcInfo.Base;
+ int index = FindItem(items, firstItem);
+ if (index == -1)
+ res = S_FALSE;
+ else if (!AreItemsEqual(firstItem, items[index]))
+ res = S_FALSE;
+ else
+ {
+ ArcInfo.CdWasRead = true;
+ ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos;
+ }
+ }
}
}
+ }
+
+
CObjectVector<CItemEx> cdItems;
@@ -1148,19 +1807,32 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p
if (res == S_FALSE)
{
- // CD doesn't match firstItem so we clear items and read Locals.
+ // CD doesn't match firstItem,
+ // so we clear items and read Locals.
items.Clear();
localsWereRead = true;
_inBufMode = false;
ArcInfo.Base = ArcInfo.MarkerPos;
+
+ if (IsMultiVol)
+ {
+ Vols.StreamIndex = Vols.StartParsingVol;
+ if (Vols.StartParsingVol >= (int)Vols.Streams.Size())
+ return S_FALSE;
+ Stream = Vols.Streams[Vols.StartParsingVol].Stream;
+ if (!Stream)
+ return S_FALSE;
+ }
+
RINOK(Stream->Seek(ArcInfo.MarkerPos2, STREAM_SEEK_SET, &m_Position));
m_Signature = ReadUInt32();
-
- RINOK(ReadLocals(items, progress));
+ RINOK(ReadLocals(items));
+
if (m_Signature != NSignature::kCentralFileHeader)
{
- m_Position -= 4;
+ // if (!UnexpectedEnd)
+ m_Position -= 4;
NoCentralDir = true;
HeadersError = true;
return S_OK;
@@ -1168,15 +1840,24 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p
_inBufMode = true;
_inBuffer.Init();
+
cdAbsOffset = m_Position - 4;
+ cdDisk = Vols.StreamIndex;
for (;;)
{
CItemEx cdItem;
+ CanStartNewVol = true;
+
RINOK(ReadCdItem(cdItem));
+
cdItems.Add(cdItem);
- if (progress && (cdItems.Size() & 0xFFF) == 0)
- RINOK(progress->SetCompletedCD(items.Size()));
+ if (Callback && (cdItems.Size() & 0xFFF) == 0)
+ {
+ const UInt64 numFiles = items.Size();
+ RINOK(Callback->SetCompleted(&numFiles, NULL));
+ }
+ CanStartNewVol = true;
m_Signature = ReadUInt32();
if (m_Signature != NSignature::kCentralFileHeader)
break;
@@ -1193,95 +1874,159 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p
}
}
- CEcd64 ecd64;
+
+
+ CCdInfo ecd64;
+ CLocator locator;
bool isZip64 = false;
- UInt64 ecd64AbsOffset = m_Position - 4;
+ const UInt64 ecd64AbsOffset = m_Position - 4;
+ int ecd64Disk = -1;
if (m_Signature == NSignature::kEcd64)
{
+ ecd64Disk = Vols.StreamIndex;
+
IsZip64 = isZip64 = true;
- UInt64 recordSize = ReadUInt64();
- const unsigned kBufSize = kEcd64_MainSize;
- Byte buf[kBufSize];
- SafeReadBytes(buf, kBufSize);
- ecd64.Parse(buf);
+ {
+ const UInt64 recordSize = ReadUInt64();
+ if (recordSize < kEcd64_MainSize)
+ {
+ HeadersError = true;
+ return S_OK;
+ }
+
+ {
+ const unsigned kBufSize = kEcd64_MainSize;
+ Byte buf[kBufSize];
+ SafeReadBytes(buf, kBufSize);
+ ecd64.ParseEcd64e(buf);
+ }
+
+ Skip64(recordSize - kEcd64_MainSize);
+ }
- Skip64(recordSize - kEcd64_MainSize);
- m_Signature = ReadUInt32();
- if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
- return E_NOTIMPL;
+ m_Signature = ReadUInt32();
- if (needSetBase)
+ if (m_Signature != NSignature::kEcd64Locator)
+ {
+ HeadersError = true;
+ return S_OK;
+ }
+
{
- ArcInfo.Base = cdAbsOffset - ecd64.cdStartOffset;
- cdRelatOffset = ecd64.cdStartOffset;
- needSetBase = false;
+ const unsigned kBufSize = 16;
+ Byte buf[kBufSize];
+ SafeReadBytes(buf, kBufSize);
+ locator.Parse(buf);
}
- if (ecd64.numEntriesInCDOnThisDisk != numCdItems ||
- ecd64.numEntriesInCD != numCdItems ||
- ecd64.cdSize != cdSize ||
- (ecd64.cdStartOffset != cdRelatOffset &&
- (!items.IsEmpty())))
- return S_FALSE;
+ m_Signature = ReadUInt32();
}
- if (m_Signature == NSignature::kEcd64Locator)
+
+ if (m_Signature != NSignature::kEcd)
{
- if (!isZip64)
- return S_FALSE;
- /* UInt32 startEndCDDiskNumber = */ ReadUInt32();
- UInt64 ecd64RelatOffset = ReadUInt64();
- /* UInt32 numberOfDisks = */ ReadUInt32();
- if (ecd64AbsOffset != ArcInfo.Base + ecd64RelatOffset)
- return S_FALSE;
- m_Signature = ReadUInt32();
+ HeadersError = true;
+ return S_OK;
}
+
- if (m_Signature != NSignature::kEcd)
- return S_FALSE;
+ // ---------- ECD ----------
- const unsigned kBufSize = kEcdSize - 4;
- Byte buf[kBufSize];
- SafeReadBytes(buf, kBufSize);
CEcd ecd;
- ecd.Parse(buf);
+ {
+ const unsigned kBufSize = kEcdSize - 4;
+ Byte buf[kBufSize];
+ SafeReadBytes(buf, kBufSize);
+ ecd.Parse(buf);
+ }
- COPY_ECD_ITEM_16(thisDiskNumber);
- COPY_ECD_ITEM_16(startCDDiskNumber);
- COPY_ECD_ITEM_16(numEntriesInCDOnThisDisk);
- COPY_ECD_ITEM_16(numEntriesInCD);
- COPY_ECD_ITEM_32(cdSize);
- COPY_ECD_ITEM_32(cdStartOffset);
+ COPY_ECD_ITEM_16(ThisDisk);
+ COPY_ECD_ITEM_16(CdDisk);
+ COPY_ECD_ITEM_16(NumEntries_in_ThisDisk);
+ COPY_ECD_ITEM_16(NumEntries);
+ COPY_ECD_ITEM_32(Size);
+ COPY_ECD_ITEM_32(Offset);
- if (needSetBase)
+ if (IsMultiVol)
{
- ArcInfo.Base = cdAbsOffset - ecd64.cdStartOffset;
- cdRelatOffset = ecd64.cdStartOffset;
- needSetBase = false;
+ if (cdDisk != (int)ecd64.CdDisk)
+ HeadersError = true;
}
+ else if (needSetBase)
+ {
+ if (isZip64)
+ {
+ if (ecd64Disk == Vols.StartVolIndex)
+ {
+ ArcInfo.Base = ecd64AbsOffset - locator.Ecd64Offset;
+ // cdRelatOffset = ecd64.Offset;
+ needSetBase = false;
+ }
+ }
+ else
+ {
+ if ((int)cdDisk == Vols.StartVolIndex)
+ {
+ ArcInfo.Base = cdAbsOffset - ecd64.Offset;
+ cdRelatOffset = ecd64.Offset;
+ needSetBase = false;
+ }
+ }
+ }
+
+ EcdVolIndex = ecd64.ThisDisk;
- if (localsWereRead && (UInt64)ArcInfo.Base != ArcInfo.MarkerPos)
+ if (!IsMultiVol)
{
- UInt64 delta = ArcInfo.MarkerPos - ArcInfo.Base;
- for (unsigned i = 0; i < items.Size(); i++)
- items[i].LocalHeaderPos += delta;
+ UseDisk_in_SingleVol = true;
+
+ if (localsWereRead)
+ {
+ if ((UInt64)ArcInfo.Base != ArcInfo.MarkerPos)
+ {
+ const UInt64 delta = ArcInfo.MarkerPos - ArcInfo.Base;
+ FOR_VECTOR (i, items)
+ items[i].LocalHeaderPos += delta;
+ }
+
+ if (EcdVolIndex != 0)
+ {
+ FOR_VECTOR (i, items)
+ items[i].Disk = EcdVolIndex;
+ }
+ }
}
+ if (isZip64)
+ {
+ if (ecd64.ThisDisk == 0 && ecd64AbsOffset != ArcInfo.Base + locator.Ecd64Offset
+ // || ecd64.NumEntries_in_ThisDisk != numCdItems
+ || ecd64.NumEntries != numCdItems
+ || ecd64.Size != cdSize
+ || (ecd64.Offset != cdRelatOffset && !items.IsEmpty()))
+ {
+ HeadersError = true;
+ return S_OK;
+ }
+ }
// ---------- merge Central Directory Items ----------
if (!cdItems.IsEmpty())
{
- for (unsigned i = 0; i < cdItems.Size(); i++)
+ CObjectVector<CItemEx> items2;
+
+ FOR_VECTOR (i, cdItems)
{
const CItemEx &cdItem = cdItems[i];
- int index = FindItem(items, cdItem.LocalHeaderPos);
+ int index = FindItem(items, cdItem);
if (index == -1)
{
- items.Add(cdItem);
+ items2.Add(cdItem);
+ HeadersError = true;
continue;
}
CItemEx &item = items[index];
@@ -1292,9 +2037,11 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p
// item.ExtractVersion != cdItem.ExtractVersion
|| !FlagsAreSame(item, cdItem)
|| item.Crc != cdItem.Crc)
+ {
+ HeadersError = true;
continue;
+ }
- // item.LocalHeaderPos = cdItem.LocalHeaderPos;
// item.Name = cdItem.Name;
item.MadeByVersion = cdItem.MadeByVersion;
item.CentralExtra = cdItem.CentralExtra;
@@ -1303,33 +2050,47 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p
item.Comment = cdItem.Comment;
item.FromCentral = cdItem.FromCentral;
}
+
+ items += items2;
}
- if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
- return E_NOTIMPL;
-
+
+ if (ecd.NumEntries < ecd.NumEntries_in_ThisDisk)
+ HeadersError = true;
+
+ if (ecd.ThisDisk == 0)
+ {
+ // if (isZip64)
+ {
+ if (ecd.NumEntries != ecd.NumEntries_in_ThisDisk)
+ HeadersError = true;
+ }
+ }
+
+ if (ecd.NumEntries > items.Size())
+ HeadersError = true;
+
if (isZip64)
{
- if (ecd64.numEntriesInCDOnThisDisk != items.Size())
+ if (ecd64.NumEntries != 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())
+ /*
+ if ((UInt16)ecd64.NumEntries == (UInt16)items.Size())
HeadersError = true;
+ */
}
- ReadBuffer(ArcInfo.Comment, ecd.commentSize);
+ ReadBuffer(ArcInfo.Comment, ecd.CommentSize);
_inBufMode = false;
_inBuffer.Free();
- if (
- (UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) ||
- (UInt32)ecd64.cdSize != (UInt32)cdSize ||
- ((UInt32)(ecd64.cdStartOffset) != (UInt32)cdRelatOffset &&
- (!items.IsEmpty())))
+ if ((UInt16)ecd64.NumEntries != (UInt16)numCdItems
+ || (UInt32)ecd64.Size != (UInt32)cdSize
+ || ((UInt32)ecd64.Offset != (UInt32)cdRelatOffset && !items.IsEmpty()))
{
// return S_FALSE;
HeadersError = true;
@@ -1340,39 +2101,170 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *p
}
-HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress)
+
+HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit,
+ IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items)
{
- HRESULT res;
- try
+ _inBufMode = false;
+ items.Clear();
+
+ Close();
+ ArcInfo.Clear();
+
+ UInt64 startPos;
+ RINOK(stream->Seek(0, STREAM_SEEK_CUR, &startPos));
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &ArcInfo.FileEndPos));
+ m_Position = ArcInfo.FileEndPos;
+
+ StartStream = stream;
+ Callback = callback;
+
+ bool volWasRequested = false;
+
+ if (callback
+ && (startPos == 0 || !searchLimit || *searchLimit != 0))
{
- res = ReadHeaders2(items, progress);
+ volWasRequested = true;
+ RINOK(ReadVols());
}
- catch (const CInBufferException &e) { res = e.ErrorCode; }
- catch (const CUnexpectEnd &)
+
+ if (IsMultiVol && Vols.StartVolIndex != 0)
{
- if (items.IsEmpty())
- return S_FALSE;
- UnexpectedEnd = true;
- res = S_OK;
+ Stream = Vols.Streams[0].Stream;
+ if (Stream)
+ {
+ m_Position = 0;
+ RINOK(Stream->Seek(0, STREAM_SEEK_SET, NULL));
+ UInt64 limit = 0;
+ HRESULT res = FindMarker(Stream, &limit);
+ if (res == S_OK)
+ MarkerIsFound = true;
+ else if (res != S_FALSE)
+ return res;
+ }
+ }
+ else
+ {
+ // printf("\nOpen offset = %u\n", (unsigned)startPos);
+ RINOK(stream->Seek(startPos, STREAM_SEEK_SET, NULL));
+ m_Position = startPos;
+ HRESULT res = FindMarker(stream, searchLimit);
+ UInt64 curPos = m_Position;
+ if (res == S_OK)
+ MarkerIsFound = true;
+ else
+ {
+ // if (res != S_FALSE)
+ return res;
+ }
+
+ MarkerIsFound = true;
+
+ if (ArcInfo.IsSpanMode && !volWasRequested)
+ {
+ RINOK(ReadVols());
+ }
+
+ if (IsMultiVol && (unsigned)Vols.StartVolIndex < Vols.Streams.Size())
+ {
+ Stream = Vols.Streams[Vols.StartVolIndex].Stream;
+ if (!Stream)
+ IsMultiVol = false;
+ else
+ {
+ RINOK(Stream->Seek(curPos, STREAM_SEEK_SET, NULL));
+ m_Position = curPos;
+ }
+ }
+ else
+ IsMultiVol = false;
+
+ if (!IsMultiVol)
+ {
+ RINOK(stream->Seek(curPos, STREAM_SEEK_SET, NULL));
+ m_Position = curPos;
+ StreamRef = stream;
+ Stream = stream;
+ }
}
- catch (...)
+
+
{
+ HRESULT res;
+ try
+ {
+ res = ReadHeaders2(items);
+ }
+ 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;
+ }
+
+ if (IsMultiVol)
+ {
+ ArcInfo.FinishPos = ArcInfo.FileEndPos;
+ if ((unsigned)Vols.StreamIndex < Vols.Streams.Size())
+ if (m_Position < Vols.Streams[Vols.StreamIndex].Size)
+ ArcInfo.ThereIsTail = true;
+ }
+ else
+ {
+ ArcInfo.FinishPos = m_Position;
+ ArcInfo.ThereIsTail = (ArcInfo.FileEndPos > m_Position);
+ }
+
_inBufMode = false;
- throw;
+ IsArcOpen = true;
+ if (!IsMultiVol)
+ Vols.Streams.Clear();
+ return res;
}
- ArcInfo.FinishPos = m_Position;
- _inBufMode = false;
- return res;
}
-ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size)
+
+HRESULT CInArchive::GetItemStream(const CItemEx &item, bool seekPackData, CMyComPtr<ISequentialInStream> &stream)
{
- CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
- CMyComPtr<ISequentialInStream> stream(streamSpec);
- Stream->Seek(ArcInfo.Base + position, STREAM_SEEK_SET, NULL);
- streamSpec->SetStream(Stream);
- streamSpec->Init(size);
- return stream.Detach();
+ stream.Release();
+
+ UInt64 pos = item.LocalHeaderPos;
+ if (seekPackData)
+ pos += item.LocalFullHeaderSize;
+
+ if (!IsMultiVol)
+ {
+ if (UseDisk_in_SingleVol && item.Disk != EcdVolIndex)
+ return S_OK;
+ pos += ArcInfo.Base;
+ RINOK(StreamRef->Seek(pos, STREAM_SEEK_SET, NULL));
+ stream = StreamRef;
+ return S_OK;
+ }
+
+ if (item.Disk >= Vols.Streams.Size())
+ return S_OK;
+
+ IInStream *str2 = Vols.Streams[item.Disk].Stream;
+ if (!str2)
+ return S_OK;
+ RINOK(str2->Seek(pos, STREAM_SEEK_SET, NULL));
+
+ Vols.NeedSeek = false;
+ Vols.StreamIndex = item.Disk;
+
+ CVolStream *volsStreamSpec = new CVolStream;
+ volsStreamSpec->Vols = &Vols;
+ stream = volsStreamSpec;
+
+ return S_OK;
}
}}
diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h
index 734d3bcb..9b10905e 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.h
+++ b/CPP/7zip/Archive/Zip/ZipIn.h
@@ -28,6 +28,7 @@ public:
{ return LocalHeaderPos + LocalFullHeaderSize; }
};
+
struct CInArchiveInfo
{
Int64 Base; /* Base offset of start of archive in stream.
@@ -40,74 +41,195 @@ struct CInArchiveInfo
Base = ArcInfo.MarkerPos; */
/* The following *Pos variables contain absolute offsets in Stream */
- UInt64 MarkerPos; /* Pos of first signature, it can point to PK00 signature
+
+ UInt64 MarkerPos; /* Pos of first signature, it can point to kSpan/kNoSpan signature
= MarkerPos2 in most archives
- = MarkerPos2 - 4 if there is PK00 signature */
+ = MarkerPos2 - 4 if there is kSpan/kNoSpan signature */
UInt64 MarkerPos2; // Pos of first local item signature in stream
- UInt64 FinishPos; // Finish pos of archive data
+ UInt64 FinishPos; // Finish pos of archive data in starting volume
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;
+ bool IsSpanMode;
+ bool ThereIsTail;
+
+ // UInt32 BaseVolIndex;
CByteBuffer Comment;
- 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; }
+ CInArchiveInfo():
+ Base(0),
+ MarkerPos(0),
+ MarkerPos2(0),
+ FinishPos(0),
+ FileEndPos(0),
+ FirstItemRelatOffset(0),
+ CdWasRead(false),
+ IsSpanMode(false),
+ ThereIsTail(false)
+ // BaseVolIndex(0)
+ {}
+
void Clear()
{
+ // BaseVolIndex = 0;
Base = 0;
MarkerPos = 0;
MarkerPos2 = 0;
FinishPos = 0;
FileEndPos = 0;
+ ThereIsTail = false;
FirstItemRelatOffset = 0;
+
CdWasRead = false;
+ IsSpanMode = false;
Comment.Free();
}
};
-struct CProgressVirt
-{
- virtual HRESULT SetCompletedLocal(UInt64 numFiles, UInt64 numBytes) = 0;
- virtual HRESULT SetTotalCD(UInt64 numFiles) = 0;
- virtual HRESULT SetCompletedCD(UInt64 numFiles) = 0;
-};
struct CCdInfo
{
+ // 64
+ UInt16 VersionMade;
+ UInt16 VersionNeedExtract;
+
+ // old zip
+ UInt32 ThisDisk;
+ UInt32 CdDisk;
+ UInt64 NumEntries_in_ThisDisk;
UInt64 NumEntries;
UInt64 Size;
UInt64 Offset;
- void ParseEcd(const Byte *p);
- void ParseEcd64(const Byte *p);
+ UInt16 CommentSize;
+
+ CCdInfo() { memset(this, 0, sizeof(*this)); }
+
+ void ParseEcd32(const Byte *p); // (p) includes signature
+ void ParseEcd64e(const Byte *p); // (p) exclude signature
};
+
+class CVols
+{
+public:
+
+ struct CSubStreamInfo
+ {
+ CMyComPtr<IInStream> Stream;
+ UInt64 Size;
+
+ CSubStreamInfo(): Size(0) {}
+ };
+
+ CObjectVector<CSubStreamInfo> Streams;
+ int StreamIndex;
+ bool NeedSeek;
+
+ CMyComPtr<IInStream> ZipStream;
+
+ bool StartIsExe; // is .exe
+ bool StartIsZ; // is .zip or .zNN
+ bool StartIsZip; // is .zip
+ bool IsUpperCase;
+ Int32 StartVolIndex; // = (NN - 1), if StartStream is .zNN
+
+ Int32 StartParsingVol; // if we need local parsing, we must use that stream
+ unsigned NumVols;
+
+ int EndVolIndex; // index of last volume (ecd volume),
+ // -1, if is not multivol
+
+ UString BaseName; // including '.'
+
+ UString MissingName;
+
+ CCdInfo ecd;
+ bool ecd_wasRead;
+
+ void Clear()
+ {
+ StreamIndex = -1;
+ NeedSeek = false;
+
+
+ StartIsExe = false;
+ StartIsZ = false;
+ StartIsZip = false;
+ IsUpperCase = false;
+
+ StartVolIndex = -1;
+ StartParsingVol = 0;
+ NumVols = 0;
+ EndVolIndex = -1;
+
+ BaseName.Empty();
+ MissingName.Empty();
+
+ ecd_wasRead = false;
+
+ Streams.Clear();
+ ZipStream.Release();
+ }
+
+ HRESULT ParseArcName(IArchiveOpenVolumeCallback *volCallback);
+
+ HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
+
+ UInt64 GetTotalSize() const
+ {
+ UInt64 total = 0;
+ FOR_VECTOR (i, Streams)
+ total += Streams[i].Size;
+ return total;
+ }
+};
+
+
+class CVolStream:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+public:
+ CVols *Vols;
+
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+
class CInArchive
{
CInBuffer _inBuffer;
bool _inBufMode;
UInt32 m_Signature;
UInt64 m_Position;
+
+ UInt64 _processedCnt;
+ bool CanStartNewVol;
+
+ CMyComPtr<IInStream> StreamRef;
+ IInStream *Stream;
+ IInStream *StartStream;
+
+ bool IsArcOpen;
+
+ HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback,
+ unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols);
+ HRESULT ReadVols();
+
HRESULT Seek(UInt64 offset);
- HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
- HRESULT IncreaseRealPosition(Int64 addValue);
+ HRESULT FindMarker(IInStream *stream, const UInt64 *searchLimit);
+ HRESULT IncreaseRealPosition(Int64 addValue, bool &isFinished);
HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize);
void SafeReadBytes(void *data, unsigned size);
@@ -126,12 +248,14 @@ class CInArchive
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 ReadLocals(CObjectVector<CItemEx> &localItems, CProgressVirt *progress);
+ HRESULT FindCd(bool checkOffsetMode);
+ HRESULT TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize);
+ HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize);
+ HRESULT ReadLocals(CObjectVector<CItemEx> &localItems);
- HRESULT ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *progress);
+ HRESULT ReadHeaders2(CObjectVector<CItemEx> &items);
+
+ HRESULT GetVolStream(unsigned vol, UInt64 pos, CMyComPtr<ISequentialInStream> &stream);
public:
CInArchiveInfo ArcInfo;
@@ -142,46 +266,87 @@ public:
bool ExtraMinorError;
bool UnexpectedEnd;
bool NoCentralDir;
+
+ bool MarkerIsFound;
+
+ bool IsMultiVol;
+ bool UseDisk_in_SingleVol;
+ UInt32 EcdVolIndex;
+
+ CVols Vols;
+
+ IArchiveOpenCallback *Callback;
+
+ CInArchive(): Stream(NULL), Callback(NULL), IsArcOpen(false) {}
+
+ UInt64 GetPhySize() const
+ {
+ if (IsMultiVol)
+ return ArcInfo.FinishPos;
+ else
+ return ArcInfo.FinishPos - ArcInfo.Base;
+ }
+
+ UInt64 GetOffset() const
+ {
+ if (IsMultiVol)
+ return 0;
+ else
+ return ArcInfo.Base;
+ }
+
- CMyComPtr<IInStream> Stream;
-
+ void ClearRefs();
void Close();
- HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
- HRESULT ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress);
+ HRESULT Open(IInStream *stream, const UInt64 *searchLimit, IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items);
+ HRESULT ReadHeaders(CObjectVector<CItemEx> &items);
- bool IsOpen() const { return Stream != NULL; }
- bool AreThereErrors() const { return HeadersError || UnexpectedEnd; }
+ bool IsOpen() const { return IsArcOpen; }
+
+ bool AreThereErrors() const
+ {
+ return HeadersError
+ || UnexpectedEnd
+ || !Vols.MissingName.IsEmpty();
+ }
bool IsLocalOffsetOK(const CItemEx &item) const
{
if (item.FromLocal)
return true;
- return /* ArcInfo.Base >= 0 || */ ArcInfo.Base + (Int64)item.LocalHeaderPos >= 0;
+ return (Int64)GetOffset() + (Int64)item.LocalHeaderPos >= 0;
+ }
+
+ UInt64 GetEmbeddedStubSize() const
+ {
+ if (ArcInfo.CdWasRead)
+ return ArcInfo.FirstItemRelatOffset;
+ if (IsMultiVol)
+ return 0;
+ return ArcInfo.MarkerPos2 - ArcInfo.Base;
}
- HRESULT ReadLocalItemAfterCdItem(CItemEx &item);
+
+ HRESULT ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail);
HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item);
- ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size);
+ HRESULT GetItemStream(const CItemEx &item, bool seekPackData, CMyComPtr<ISequentialInStream> &stream);
- UInt64 GetOffsetInStream(UInt64 offsetFromArc) const { return ArcInfo.Base + offsetFromArc; }
+ IInStream *GetBaseStream() { return StreamRef; }
bool CanUpdate() const
{
- if (AreThereErrors())
- return false;
- if (ArcInfo.Base < 0)
- return false;
- if ((Int64)ArcInfo.MarkerPos2 < ArcInfo.Base)
+ if (AreThereErrors()
+ || IsMultiVol
+ || ArcInfo.Base < 0
+ || (Int64)ArcInfo.MarkerPos2 < ArcInfo.Base
+ || ArcInfo.ThereIsTail
+ || GetEmbeddedStubSize() != 0)
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.h b/CPP/7zip/Archive/Zip/ZipItem.h
index 5f078b60..c134ec79 100644
--- a/CPP/7zip/Archive/Zip/ZipItem.h
+++ b/CPP/7zip/Archive/Zip/ZipItem.h
@@ -199,6 +199,8 @@ public:
UInt64 PackSize;
UInt32 Time;
UInt32 Crc;
+
+ UInt32 Disk;
AString Name;
diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp
index 2be783e6..6674189f 100644
--- a/CPP/7zip/Archive/Zip/ZipRegister.cpp
+++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp
@@ -12,10 +12,11 @@ namespace NZip {
static const Byte k_Signature[] = {
4, 0x50, 0x4B, 0x03, 0x04,
4, 0x50, 0x4B, 0x05, 0x06,
+ 6, 0x50, 0x4B, 0x07, 0x08, 0x50, 0x4B,
6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B };
REGISTER_ARC_IO(
- "zip", "zip zipx jar xpi odt ods docx xlsx epub", 0, 1,
+ "zip", "zip z01 zipx jar xpi odt ods docx xlsx epub", 0, 1,
k_Signature,
0,
NArcInfoFlags::kFindSignature |
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index 3128939e..1546a2af 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -52,16 +52,6 @@ static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, UInt64 size,
return NCompress::CopyStream_ExactSize(inStream, outStream, size, progress);
}
-static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive,
- const CUpdateRange &range, ICompressProgressInfo *progress)
-{
- UInt64 position;
- RINOK(inStream->Seek(range.Position, STREAM_SEEK_SET, &position));
- RINOK(CopyBlockToArchive(inStream, range.Size, outArchive, progress));
- return progress->SetRatioInfo(&range.Size, &range.Size);
-}
-
-
static void SetFileHeader(
COutArchive &archive,
const CCompressionMethodMode &options,
@@ -358,9 +348,12 @@ static HRESULT UpdateItemOldData(
return E_NOTIMPL;
// use old name size.
- // CUpdateRange range(item.GetLocalExtraPosition(), item.LocalExtraSize + item.PackSize);
- CUpdateRange range(inArchive->GetOffsetInStream(itemEx.GetDataPosition()), itemEx.PackSize);
+ CMyComPtr<ISequentialInStream> packStream;
+ RINOK(inArchive->GetItemStream(itemEx, true, packStream));
+ if (!packStream)
+ return E_NOTIMPL;
+
// we keep ExternalAttrib and some another properties from old archive
// item.ExternalAttrib = ui.Attrib;
@@ -378,19 +371,27 @@ static HRESULT UpdateItemOldData(
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;
+
+ RINOK(CopyBlockToArchive(packStream, itemEx.PackSize, archive, progress));
+
+ complexity += itemEx.PackSize;
}
else
{
- CUpdateRange range(inArchive->GetOffsetInStream(itemEx.LocalHeaderPos), itemEx.GetLocalFullSize());
+ CMyComPtr<ISequentialInStream> packStream;
+ RINOK(inArchive->GetItemStream(itemEx, false, packStream));
+ if (!packStream)
+ return E_NOTIMPL;
// set new header position
item.LocalHeaderPos = archive.GetCurPos();
- RINOK(WriteRange(inArchive->Stream, archive, range, progress));
- complexity += range.Size;
- archive.MoveCurPos(range.Size);
+ const UInt64 rangeSize = itemEx.GetLocalFullSize();
+
+ RINOK(CopyBlockToArchive(packStream, rangeSize, archive, progress));
+
+ complexity += rangeSize;
+ archive.MoveCurPos(rangeSize);
}
return S_OK;
@@ -1191,10 +1192,11 @@ HRESULT Update(
if (inArchive)
{
- if (inArchive->ArcInfo.Base > 0 && !removeSfx)
+ if (!inArchive->IsMultiVol && 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));
+ IInStream *baseStream = inArchive->GetBaseStream();
+ RINOK(baseStream->Seek(0, STREAM_SEEK_SET, NULL));
+ RINOK(NCompress::CopyStream_ExactSize(baseStream, outStreamReal, inArchive->ArcInfo.Base, NULL));
}
}
@@ -1210,11 +1212,12 @@ HRESULT Update(
if (inArchive)
{
- if ((Int64)inArchive->ArcInfo.MarkerPos2 > inArchive->ArcInfo.Base)
+ if (!inArchive->IsMultiVol && (Int64)inArchive->ArcInfo.MarkerPos2 > inArchive->ArcInfo.Base)
{
- RINOK(inArchive->Stream->Seek(inArchive->ArcInfo.Base, STREAM_SEEK_SET, NULL));
+ IInStream *baseStream = inArchive->GetBaseStream();
+ RINOK(baseStream->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));
+ RINOK(NCompress::CopyStream_ExactSize(baseStream, outStream, embStubSize, NULL));
outArchive.MoveCurPos(embStubSize);
}
}
diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp
index c7962167..8e032561 100644
--- a/CPP/7zip/Common/LimitedStreams.cpp
+++ b/CPP/7zip/Common/LimitedStreams.cpp
@@ -5,16 +5,19 @@
#include <string.h>
#include "LimitedStreams.h"
-#include "../../Common/Defs.h"
STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize = 0;
- UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size);
+ {
+ const UInt64 rem = _size - _pos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
HRESULT result = S_OK;
- if (sizeToRead > 0)
+ if (size != 0)
{
- result = _stream->Read(data, sizeToRead, &realProcessedSize);
+ result = _stream->Read(data, size, &realProcessedSize);
_pos += realProcessedSize;
if (realProcessedSize == 0)
_wasFinished = true;
@@ -34,9 +37,11 @@ STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSi
return S_OK;
// return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF
}
- UInt64 rem = _size - _virtPos;
- if (rem < size)
- size = (UInt32)rem;
+ {
+ const UInt64 rem = _size - _virtPos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
UInt64 newPos = _startOffset + _virtPos;
if (newPos != _physPos)
{
diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h
index b521eeb9..fb1ac3cd 100644
--- a/CPP/7zip/Common/LimitedStreams.h
+++ b/CPP/7zip/Common/LimitedStreams.h
@@ -30,6 +30,7 @@ public:
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
UInt64 GetSize() const { return _pos; }
+ UInt64 GetRem() const { return _size - _pos; }
bool WasFinished() const { return _wasFinished; }
};
diff --git a/CPP/7zip/Compress/BZip2Decoder.cpp b/CPP/7zip/Compress/BZip2Decoder.cpp
index 04222e49..56f1b02f 100644
--- a/CPP/7zip/Compress/BZip2Decoder.cpp
+++ b/CPP/7zip/Compress/BZip2Decoder.cpp
@@ -783,7 +783,7 @@ void CState::ThreadFunc()
}
packSize = Decoder->Base.BitDecoder.GetProcessedSize();
}
- catch(const CInBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; }
+ catch(const CInBufferException &e) { res = e.ErrorCode; if (res == S_OK) res = E_FAIL; }
catch(...) { res = E_FAIL; }
if (res != S_OK)
{
@@ -809,7 +809,7 @@ void CState::ThreadFunc()
res = S_FALSE;
}
}
- catch(const COutBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; }
+ catch(const COutBufferException &e) { res = e.ErrorCode; if (res == S_OK) res = E_FAIL; }
catch(...) { res = E_FAIL; }
if (res != S_OK)
{
diff --git a/CPP/7zip/Compress/BZip2Encoder.h b/CPP/7zip/Compress/BZip2Encoder.h
index bf05f59f..05d6fa16 100644
--- a/CPP/7zip/Compress/BZip2Encoder.h
+++ b/CPP/7zip/Compress/BZip2Encoder.h
@@ -214,11 +214,13 @@ public:
HRESULT Flush() { return m_OutStream.Flush(); }
+ MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
#ifndef _7ZIP_ST
- MY_UNKNOWN_IMP2(ICompressSetCoderMt, ICompressSetCoderProperties)
- #else
- MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
+ MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt)
#endif
+ MY_QUERYINTERFACE_ENTRY(ICompressSetCoderProperties)
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
diff --git a/CPP/7zip/Compress/BZip2Register.cpp b/CPP/7zip/Compress/BZip2Register.cpp
index 0dd6ec9a..6e960366 100644
--- a/CPP/7zip/Compress/BZip2Register.cpp
+++ b/CPP/7zip/Compress/BZip2Register.cpp
@@ -5,14 +5,21 @@
#include "../Common/RegisterCodec.h"
#include "BZip2Decoder.h"
+#if !defined(EXTRACT_ONLY) && !defined(BZIP2_EXTRACT_ONLY)
+#include "BZip2Encoder.h"
+#endif
-REGISTER_CODEC_CREATE(CreateDec, NCompress::NBZip2::CDecoder)
+namespace NCompress {
+namespace NBZip2 {
+
+REGISTER_CODEC_CREATE(CreateDec, CDecoder)
#if !defined(EXTRACT_ONLY) && !defined(BZIP2_EXTRACT_ONLY)
-#include "BZip2Encoder.h"
-REGISTER_CODEC_CREATE(CreateEnc, NCompress::NBZip2::CEncoder)
+REGISTER_CODEC_CREATE(CreateEnc, CEncoder)
#else
#define CreateEnc NULL
#endif
REGISTER_CODEC_2(BZip2, CreateDec, CreateEnc, 0x40202, "BZip2")
+
+}}
diff --git a/CPP/7zip/Compress/Bcj2Register.cpp b/CPP/7zip/Compress/Bcj2Register.cpp
index ef37ae0c..7a48f91c 100644
--- a/CPP/7zip/Compress/Bcj2Register.cpp
+++ b/CPP/7zip/Compress/Bcj2Register.cpp
@@ -6,9 +6,12 @@
#include "Bcj2Coder.h"
-REGISTER_CODEC_CREATE_2(CreateCodec, NCompress::NBcj2::CDecoder(), ICompressCoder2)
+namespace NCompress {
+namespace NBcj2 {
+
+REGISTER_CODEC_CREATE_2(CreateCodec, CDecoder(), ICompressCoder2)
#ifndef EXTRACT_ONLY
-REGISTER_CODEC_CREATE_2(CreateCodecOut, NCompress::NBcj2::CEncoder(), ICompressCoder2)
+REGISTER_CODEC_CREATE_2(CreateCodecOut, CEncoder(), ICompressCoder2)
#else
#define CreateCodecOut NULL
#endif
@@ -17,3 +20,5 @@ REGISTER_CODEC_VAR
{ CreateCodec, CreateCodecOut, 0x303011B, "BCJ2", 4, false };
REGISTER_CODEC(BCJ2)
+
+}}
diff --git a/CPP/7zip/Compress/BcjCoder.cpp b/CPP/7zip/Compress/BcjCoder.cpp
index 37815dce..32aa1762 100644
--- a/CPP/7zip/Compress/BcjCoder.cpp
+++ b/CPP/7zip/Compress/BcjCoder.cpp
@@ -4,16 +4,21 @@
#include "BcjCoder.h"
-STDMETHODIMP CBcjCoder::Init()
+namespace NCompress {
+namespace NBcj {
+
+STDMETHODIMP CCoder::Init()
{
_bufferPos = 0;
x86_Convert_Init(_prevMask);
return S_OK;
}
-STDMETHODIMP_(UInt32) CBcjCoder::Filter(Byte *data, UInt32 size)
+STDMETHODIMP_(UInt32) CCoder::Filter(Byte *data, UInt32 size)
{
UInt32 processed = (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, _encode);
_bufferPos += processed;
return processed;
}
+
+}}
diff --git a/CPP/7zip/Compress/BcjCoder.h b/CPP/7zip/Compress/BcjCoder.h
index 275fd4f2..7883906e 100644
--- a/CPP/7zip/Compress/BcjCoder.h
+++ b/CPP/7zip/Compress/BcjCoder.h
@@ -9,7 +9,10 @@
#include "../ICoder.h"
-class CBcjCoder:
+namespace NCompress {
+namespace NBcj {
+
+class CCoder:
public ICompressFilter,
public CMyUnknownImp
{
@@ -17,10 +20,12 @@ class CBcjCoder:
UInt32 _prevMask;
int _encode;
public:
- MY_UNKNOWN_IMP;
+ MY_UNKNOWN_IMP1(ICompressFilter);
INTERFACE_ICompressFilter(;)
- CBcjCoder(int encode): _bufferPos(0), _encode(encode) { x86_Convert_Init(_prevMask); }
+ CCoder(int encode): _bufferPos(0), _encode(encode) { x86_Convert_Init(_prevMask); }
};
+}}
+
#endif
diff --git a/CPP/7zip/Compress/BcjRegister.cpp b/CPP/7zip/Compress/BcjRegister.cpp
index 83c6830f..f06dcfe9 100644
--- a/CPP/7zip/Compress/BcjRegister.cpp
+++ b/CPP/7zip/Compress/BcjRegister.cpp
@@ -6,7 +6,12 @@
#include "BcjCoder.h"
+namespace NCompress {
+namespace NBcj {
+
REGISTER_FILTER_E(BCJ,
- CBcjCoder(false),
- CBcjCoder(true),
+ CCoder(false),
+ CCoder(true),
0x3030103, "BCJ")
+
+}}
diff --git a/CPP/7zip/Compress/BranchMisc.cpp b/CPP/7zip/Compress/BranchMisc.cpp
index 0bf39b79..d0e75e83 100644
--- a/CPP/7zip/Compress/BranchMisc.cpp
+++ b/CPP/7zip/Compress/BranchMisc.cpp
@@ -4,15 +4,20 @@
#include "BranchMisc.h"
-STDMETHODIMP CBranchCoder::Init()
+namespace NCompress {
+namespace NBranch {
+
+STDMETHODIMP CCoder::Init()
{
_bufferPos = 0;
return S_OK;
}
-STDMETHODIMP_(UInt32) CBranchCoder::Filter(Byte *data, UInt32 size)
+STDMETHODIMP_(UInt32) CCoder::Filter(Byte *data, UInt32 size)
{
UInt32 processed = (UInt32)BraFunc(data, size, _bufferPos, _encode);
_bufferPos += processed;
return processed;
}
+
+}}
diff --git a/CPP/7zip/Compress/BranchMisc.h b/CPP/7zip/Compress/BranchMisc.h
index bbb5add9..66fc23d2 100644
--- a/CPP/7zip/Compress/BranchMisc.h
+++ b/CPP/7zip/Compress/BranchMisc.h
@@ -13,7 +13,10 @@ typedef SizeT (*Func_Bra)(Byte *data, SizeT size, UInt32 ip, int encoding);
EXTERN_C_END
-class CBranchCoder:
+namespace NCompress {
+namespace NBranch {
+
+class CCoder:
public ICompressFilter,
public CMyUnknownImp
{
@@ -21,10 +24,12 @@ class CBranchCoder:
int _encode;
Func_Bra BraFunc;
public:
- MY_UNKNOWN_IMP;
+ MY_UNKNOWN_IMP1(ICompressFilter);
INTERFACE_ICompressFilter(;)
- CBranchCoder(Func_Bra bra, int encode): _bufferPos(0), _encode(encode), BraFunc(bra) {}
+ CCoder(Func_Bra bra, int encode): _bufferPos(0), _encode(encode), BraFunc(bra) {}
};
+}}
+
#endif
diff --git a/CPP/7zip/Compress/BranchRegister.cpp b/CPP/7zip/Compress/BranchRegister.cpp
index e1fcff6d..6331c1b9 100644
--- a/CPP/7zip/Compress/BranchRegister.cpp
+++ b/CPP/7zip/Compress/BranchRegister.cpp
@@ -8,9 +8,12 @@
#include "BranchMisc.h"
+namespace NCompress {
+namespace NBranch {
+
#define CREATE_BRA(n) \
- REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CBranchCoder(n ## _Convert, false)) \
- REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CBranchCoder(n ## _Convert, true)) \
+ REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CCoder(n ## _Convert, false)) \
+ REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CCoder(n ## _Convert, true)) \
CREATE_BRA(PPC)
CREATE_BRA(IA64)
@@ -34,3 +37,5 @@ REGISTER_CODECS_VAR
};
REGISTER_CODECS(Branch)
+
+}}
diff --git a/CPP/7zip/Compress/ByteSwap.cpp b/CPP/7zip/Compress/ByteSwap.cpp
index f5620d6c..4c11806e 100644
--- a/CPP/7zip/Compress/ByteSwap.cpp
+++ b/CPP/7zip/Compress/ByteSwap.cpp
@@ -8,12 +8,15 @@
#include "../Common/RegisterCodec.h"
+namespace NCompress {
+namespace NByteSwap {
+
class CByteSwap2:
public ICompressFilter,
public CMyUnknownImp
{
public:
- MY_UNKNOWN_IMP
+ MY_UNKNOWN_IMP1(ICompressFilter);
INTERFACE_ICompressFilter(;)
};
@@ -22,7 +25,7 @@ class CByteSwap4:
public CMyUnknownImp
{
public:
- MY_UNKNOWN_IMP
+ MY_UNKNOWN_IMP1(ICompressFilter);
INTERFACE_ICompressFilter(;)
};
@@ -85,3 +88,5 @@ REGISTER_CODECS_VAR
};
REGISTER_CODECS(ByteSwap)
+
+}}
diff --git a/CPP/7zip/Compress/CopyRegister.cpp b/CPP/7zip/Compress/CopyRegister.cpp
index 703c52ca..7141ab58 100644
--- a/CPP/7zip/Compress/CopyRegister.cpp
+++ b/CPP/7zip/Compress/CopyRegister.cpp
@@ -6,6 +6,10 @@
#include "CopyCoder.h"
-REGISTER_CODEC_CREATE(CreateCodec, NCompress::CCopyCoder())
+namespace NCompress {
+
+REGISTER_CODEC_CREATE(CreateCodec, CCopyCoder())
REGISTER_CODEC_2(Copy, CreateCodec, CreateCodec, 0, "Copy")
+
+}
diff --git a/CPP/7zip/Compress/Deflate64Register.cpp b/CPP/7zip/Compress/Deflate64Register.cpp
index 4b2cf0f7..14d20bb3 100644
--- a/CPP/7zip/Compress/Deflate64Register.cpp
+++ b/CPP/7zip/Compress/Deflate64Register.cpp
@@ -6,13 +6,21 @@
#include "DeflateDecoder.h"
-REGISTER_CODEC_CREATE(CreateDec, NCompress::NDeflate::NDecoder::CCOMCoder64())
-
#if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY)
#include "DeflateEncoder.h"
-REGISTER_CODEC_CREATE(CreateEnc, NCompress::NDeflate::NEncoder::CCOMCoder64())
+#endif
+
+namespace NCompress {
+namespace NDeflate {
+
+REGISTER_CODEC_CREATE(CreateDec, NDecoder::CCOMCoder64())
+
+#if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY)
+REGISTER_CODEC_CREATE(CreateEnc, NEncoder::CCOMCoder64())
#else
#define CreateEnc NULL
#endif
REGISTER_CODEC_2(Deflate64, CreateDec, CreateEnc, 0x40109, "Deflate64")
+
+}}
diff --git a/CPP/7zip/Compress/DeflateDecoder.h b/CPP/7zip/Compress/DeflateDecoder.h
index 0b29737f..5b2dd32d 100644
--- a/CPP/7zip/Compress/DeflateDecoder.h
+++ b/CPP/7zip/Compress/DeflateDecoder.h
@@ -92,14 +92,16 @@ public:
const UInt64 *outSize, ICompressProgressInfo *progress);
#ifndef NO_READ_FROM_CODER
- MY_UNKNOWN_IMP4(
+ MY_UNKNOWN_IMP5(
+ ICompressCoder,
ICompressGetInStreamProcessedSize,
ICompressSetInStream,
ICompressSetOutStreamSize,
ISequentialInStream
)
#else
- MY_UNKNOWN_IMP1(
+ MY_UNKNOWN_IMP2(
+ ICompressCoder,
ICompressGetInStreamProcessedSize)
#endif
diff --git a/CPP/7zip/Compress/DeflateEncoder.h b/CPP/7zip/Compress/DeflateEncoder.h
index 62423a34..6c4ae4fc 100644
--- a/CPP/7zip/Compress/DeflateEncoder.h
+++ b/CPP/7zip/Compress/DeflateEncoder.h
@@ -190,7 +190,7 @@ class CCOMCoder :
public CCoder
{
public:
- MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
+ MY_UNKNOWN_IMP2(ICompressCoder, ICompressSetCoderProperties)
CCOMCoder(): CCoder(false) {};
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
@@ -204,7 +204,7 @@ class CCOMCoder64 :
public CCoder
{
public:
- MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
+ MY_UNKNOWN_IMP2(ICompressCoder, ICompressSetCoderProperties)
CCOMCoder64(): CCoder(true) {};
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
diff --git a/CPP/7zip/Compress/DeflateRegister.cpp b/CPP/7zip/Compress/DeflateRegister.cpp
index 32221fcc..387be6ed 100644
--- a/CPP/7zip/Compress/DeflateRegister.cpp
+++ b/CPP/7zip/Compress/DeflateRegister.cpp
@@ -5,14 +5,21 @@
#include "../Common/RegisterCodec.h"
#include "DeflateDecoder.h"
+#if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY)
+#include "DeflateEncoder.h"
+#endif
-REGISTER_CODEC_CREATE(CreateDec, NCompress::NDeflate::NDecoder::CCOMCoder)
+namespace NCompress {
+namespace NDeflate {
+
+REGISTER_CODEC_CREATE(CreateDec, NDecoder::CCOMCoder)
#if !defined(EXTRACT_ONLY) && !defined(DEFLATE_EXTRACT_ONLY)
-#include "DeflateEncoder.h"
-REGISTER_CODEC_CREATE(CreateEnc, NCompress::NDeflate::NEncoder::CCOMCoder)
+REGISTER_CODEC_CREATE(CreateEnc, NEncoder::CCOMCoder)
#else
#define CreateEnc NULL
#endif
REGISTER_CODEC_2(Deflate, CreateDec, CreateEnc, 0x40108, "Deflate")
+
+}}
diff --git a/CPP/7zip/Compress/DeltaFilter.cpp b/CPP/7zip/Compress/DeltaFilter.cpp
index d90f62f5..3986ae4f 100644
--- a/CPP/7zip/Compress/DeltaFilter.cpp
+++ b/CPP/7zip/Compress/DeltaFilter.cpp
@@ -10,6 +10,9 @@
#include "../Common/RegisterCodec.h"
+namespace NCompress {
+namespace NDelta {
+
struct CDelta
{
unsigned _delta;
@@ -22,7 +25,7 @@ struct CDelta
#ifndef EXTRACT_ONLY
-class CDeltaEncoder:
+class CEncoder:
public ICompressFilter,
public ICompressSetCoderProperties,
public ICompressWriteCoderProperties,
@@ -30,25 +33,25 @@ class CDeltaEncoder:
public CMyUnknownImp
{
public:
- MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)
+ MY_UNKNOWN_IMP3(ICompressFilter, ICompressSetCoderProperties, ICompressWriteCoderProperties)
INTERFACE_ICompressFilter(;)
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
};
-STDMETHODIMP CDeltaEncoder::Init()
+STDMETHODIMP CEncoder::Init()
{
DeltaInit();
return S_OK;
}
-STDMETHODIMP_(UInt32) CDeltaEncoder::Filter(Byte *data, UInt32 size)
+STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size)
{
Delta_Encode(_state, _delta, data, size);
return size;
}
-STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
{
UInt32 delta = _delta;
for (UInt32 i = 0; i < numProps; i++)
@@ -75,7 +78,7 @@ STDMETHODIMP CDeltaEncoder::SetCoderProperties(const PROPID *propIDs, const PROP
return S_OK;
}
-STDMETHODIMP CDeltaEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
{
Byte prop = (Byte)(_delta - 1);
return outStream->Write(&prop, 1, NULL);
@@ -84,31 +87,31 @@ STDMETHODIMP CDeltaEncoder::WriteCoderProperties(ISequentialOutStream *outStream
#endif
-class CDeltaDecoder:
+class CDecoder:
public ICompressFilter,
public ICompressSetDecoderProperties2,
CDelta,
public CMyUnknownImp
{
public:
- MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
+ MY_UNKNOWN_IMP2(ICompressFilter, ICompressSetDecoderProperties2)
INTERFACE_ICompressFilter(;)
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
};
-STDMETHODIMP CDeltaDecoder::Init()
+STDMETHODIMP CDecoder::Init()
{
DeltaInit();
return S_OK;
}
-STDMETHODIMP_(UInt32) CDeltaDecoder::Filter(Byte *data, UInt32 size)
+STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
{
Delta_Decode(_state, _delta, data, size);
return size;
}
-STDMETHODIMP CDeltaDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size)
{
if (size != 1)
return E_INVALIDARG;
@@ -118,6 +121,8 @@ STDMETHODIMP CDeltaDecoder::SetDecoderProperties2(const Byte *props, UInt32 size
REGISTER_FILTER_E(Delta,
- CDeltaDecoder(),
- CDeltaEncoder(),
+ CDecoder(),
+ CEncoder(),
3, "Delta")
+
+}}
diff --git a/CPP/7zip/Compress/Lzma2Encoder.h b/CPP/7zip/Compress/Lzma2Encoder.h
index f0fb74d3..8ff6e838 100644
--- a/CPP/7zip/Compress/Lzma2Encoder.h
+++ b/CPP/7zip/Compress/Lzma2Encoder.h
@@ -20,7 +20,7 @@ class CEncoder:
{
CLzma2EncHandle _encoder;
public:
- MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)
+ MY_UNKNOWN_IMP3(ICompressCoder, ICompressSetCoderProperties, ICompressWriteCoderProperties)
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
diff --git a/CPP/7zip/Compress/Lzma2Register.cpp b/CPP/7zip/Compress/Lzma2Register.cpp
index d684d9d0..8f279ebf 100644
--- a/CPP/7zip/Compress/Lzma2Register.cpp
+++ b/CPP/7zip/Compress/Lzma2Register.cpp
@@ -10,8 +10,13 @@
#include "Lzma2Encoder.h"
#endif
+namespace NCompress {
+namespace NLzma2 {
+
REGISTER_CODEC_E(LZMA2,
- NCompress::NLzma2::CDecoder(),
- NCompress::NLzma2::CEncoder(),
+ CDecoder(),
+ CEncoder(),
0x21,
"LZMA2")
+
+}}
diff --git a/CPP/7zip/Compress/LzmaEncoder.h b/CPP/7zip/Compress/LzmaEncoder.h
index 3ed067f1..f919ac2c 100644
--- a/CPP/7zip/Compress/LzmaEncoder.h
+++ b/CPP/7zip/Compress/LzmaEncoder.h
@@ -21,7 +21,7 @@ class CEncoder:
CLzmaEncHandle _encoder;
UInt64 _inputProcessed;
public:
- MY_UNKNOWN_IMP2(ICompressSetCoderProperties, ICompressWriteCoderProperties)
+ MY_UNKNOWN_IMP3(ICompressCoder, ICompressSetCoderProperties, ICompressWriteCoderProperties)
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
diff --git a/CPP/7zip/Compress/LzmaRegister.cpp b/CPP/7zip/Compress/LzmaRegister.cpp
index c12416f2..c802a99f 100644
--- a/CPP/7zip/Compress/LzmaRegister.cpp
+++ b/CPP/7zip/Compress/LzmaRegister.cpp
@@ -10,8 +10,13 @@
#include "LzmaEncoder.h"
#endif
+namespace NCompress {
+namespace NLzma {
+
REGISTER_CODEC_E(LZMA,
- NCompress::NLzma::CDecoder(),
- NCompress::NLzma::CEncoder(),
+ CDecoder(),
+ CEncoder(),
0x30101,
"LZMA")
+
+}}
diff --git a/CPP/7zip/Compress/PpmdEncoder.h b/CPP/7zip/Compress/PpmdEncoder.h
index fb74cf57..671a5353 100644
--- a/CPP/7zip/Compress/PpmdEncoder.h
+++ b/CPP/7zip/Compress/PpmdEncoder.h
@@ -41,7 +41,8 @@ class CEncoder :
CPpmd7 _ppmd;
CEncProps _props;
public:
- MY_UNKNOWN_IMP2(
+ MY_UNKNOWN_IMP3(
+ ICompressCoder,
ICompressSetCoderProperties,
ICompressWriteCoderProperties)
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
diff --git a/CPP/7zip/Compress/PpmdRegister.cpp b/CPP/7zip/Compress/PpmdRegister.cpp
index 17f84bd0..a3ebb5f3 100644
--- a/CPP/7zip/Compress/PpmdRegister.cpp
+++ b/CPP/7zip/Compress/PpmdRegister.cpp
@@ -10,8 +10,13 @@
#include "PpmdEncoder.h"
#endif
+namespace NCompress {
+namespace NPpmd {
+
REGISTER_CODEC_E(PPMD,
- NCompress::NPpmd::CDecoder(),
- NCompress::NPpmd::CEncoder(),
+ CDecoder(),
+ CEncoder(),
0x30401,
"PPMD")
+
+}}
diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp
index 496400a4..832eb112 100644
--- a/CPP/7zip/Compress/Rar3Decoder.cpp
+++ b/CPP/7zip/Compress/Rar3Decoder.cpp
@@ -154,7 +154,7 @@ HRESULT CDecoder::WriteBuf()
FOR_VECTOR (i, _tempFilters)
{
CTempFilter *filter = _tempFilters[i];
- if (filter == NULL)
+ if (!filter)
continue;
if (filter->NextWindow)
{
@@ -187,8 +187,10 @@ HRESULT CDecoder::WriteBuf()
while (i + 1 < _tempFilters.Size())
{
CTempFilter *nextFilter = _tempFilters[i + 1];
- if (nextFilter == NULL || nextFilter->BlockStart != blockStart ||
- nextFilter->BlockSize != outBlockRef.Size || nextFilter->NextWindow)
+ if (!nextFilter
+ || nextFilter->BlockStart != blockStart
+ || nextFilter->BlockSize != outBlockRef.Size
+ || nextFilter->NextWindow)
break;
_vm.SetMemory(0, _vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);
ExecuteFilter(++i, outBlockRef);
@@ -203,7 +205,7 @@ HRESULT CDecoder::WriteBuf()
for (unsigned j = i; j < _tempFilters.Size(); j++)
{
CTempFilter *filter = _tempFilters[j];
- if (filter != NULL && filter->NextWindow)
+ if (filter && filter->NextWindow)
filter->NextWindow = false;
}
_wrPtr = writtenBorder;
@@ -273,7 +275,7 @@ bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
for (i = 0; i < _tempFilters.Size(); i++)
{
_tempFilters[i - numEmptyItems] = _tempFilters[i];
- if (_tempFilters[i] == NULL)
+ if (!_tempFilters[i])
numEmptyItems++;
if (numEmptyItems > 0)
_tempFilters[i] = NULL;
@@ -865,21 +867,21 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
{
try
{
- if (inSize == NULL || outSize == NULL)
+ if (!inSize)
return E_INVALIDARG;
- if (_vmData == 0)
+ if (!_vmData)
{
_vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax);
- if (_vmData == 0)
+ if (!_vmData)
return E_OUTOFMEMORY;
_vmCode = _vmData + kVmDataSizeMax;
}
- if (_window == 0)
+ if (!_window)
{
_window = (Byte *)::MidAlloc(kWindowSize);
- if (_window == 0)
+ if (!_window)
return E_OUTOFMEMORY;
}
if (!m_InBitStream.BitDecoder.Create(1 << 20))
@@ -893,7 +895,7 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
_outStream = outStream;
// CCoderReleaser coderReleaser(this);
- _unpackSize = *outSize;
+ _unpackSize = outSize ? *outSize : (UInt64)(Int64)-1;
return CodeReal(progress);
}
catch(const CInBufferException &e) { return e.ErrorCode; }
diff --git a/CPP/7zip/Compress/RarCodecsRegister.cpp b/CPP/7zip/Compress/RarCodecsRegister.cpp
index 2f3a1138..e1bc3d9b 100644
--- a/CPP/7zip/Compress/RarCodecsRegister.cpp
+++ b/CPP/7zip/Compress/RarCodecsRegister.cpp
@@ -9,7 +9,9 @@
#include "Rar3Decoder.h"
#include "Rar5Decoder.h"
-#define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NCompress::NRar ## x::CDecoder())
+namespace NCompress {
+
+#define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NRar ## x::CDecoder())
CREATE_CODEC(1)
CREATE_CODEC(2)
@@ -27,3 +29,5 @@ REGISTER_CODECS_VAR
};
REGISTER_CODECS(Rar)
+
+}
diff --git a/CPP/7zip/Compress/ShrinkDecoder.cpp b/CPP/7zip/Compress/ShrinkDecoder.cpp
index a89d323c..80b7e67c 100644
--- a/CPP/7zip/Compress/ShrinkDecoder.cpp
+++ b/CPP/7zip/Compress/ShrinkDecoder.cpp
@@ -1,7 +1,10 @@
// ShrinkDecoder.cpp
+
#include "StdAfx.h"
+#include <stdio.h>
+
#include "../../../C/Alloc.h"
#include "../Common/InBuffer.h"
@@ -13,8 +16,8 @@
namespace NCompress {
namespace NShrink {
-static const UInt32 kBufferSize = (1 << 20);
-static const int kNumMinBits = 9;
+static const UInt32 kBufferSize = (1 << 18);
+static const unsigned kNumMinBits = 9;
HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
@@ -32,109 +35,121 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
outBuffer.SetStream(outStream);
outBuffer.Init();
+ {
+ unsigned i;
+ for (i = 0; i < 257; i++)
+ _parents[i] = (UInt16)i;
+ for (; i < kNumItems; i++)
+ _parents[i] = kNumItems;
+ for (i = 0; i < kNumItems; i++)
+ _suffixes[i] = 0;
+ }
+
UInt64 prevPos = 0;
- int numBits = kNumMinBits;
- UInt32 head = 257;
- bool needPrev = false;
- UInt32 lastSymbol = 0;
-
- int i;
- for (i = 0; i < kNumItems; i++)
- _parents[i] = 0;
- for (i = 0; i < kNumItems; i++)
- _suffixes[i] = 0;
- for (i = 0; i < 257; i++)
- _isFree[i] = false;
- for (; i < kNumItems; i++)
- _isFree[i] = true;
+ unsigned numBits = kNumMinBits;
+ unsigned head = 257;
+ int lastSym = -1;
+ Byte lastChar2 = 0;
for (;;)
{
- UInt32 symbol = inBuffer.ReadBits(numBits);
+ UInt32 sym = inBuffer.ReadBits(numBits);
+
if (inBuffer.ExtraBitsWereRead())
break;
- if (_isFree[symbol])
- return S_FALSE;
- if (symbol == 256)
+
+ if (sym == 256)
{
- UInt32 symbol = inBuffer.ReadBits(numBits);
- if (symbol == 1)
+ sym = inBuffer.ReadBits(numBits);
+ if (sym == 1)
{
- if (numBits < kNumMaxBits)
- numBits++;
+ if (numBits >= kNumMaxBits)
+ return S_FALSE;
+ numBits++;
+ continue;
}
- else if (symbol == 2)
+ if (sym != 2)
+ return S_FALSE;
{
- if (needPrev)
- _isFree[head - 1] = true;
+ unsigned i;
for (i = 257; i < kNumItems; i++)
- _isParent[i] = false;
+ _stack[i] = 0;
for (i = 257; i < kNumItems; i++)
- if (!_isFree[i])
- _isParent[_parents[i]] = true;
+ {
+ unsigned par = _parents[i];
+ if (par != kNumItems)
+ _stack[par] = 1;
+ }
for (i = 257; i < kNumItems; i++)
- if (!_isParent[i])
- _isFree[i] = true;
+ if (_stack[i] == 0)
+ _parents[i] = kNumItems;
+
head = 257;
- while (head < kNumItems && !_isFree[head])
- head++;
- if (head < kNumItems)
+
+ continue;
+ }
+ }
+
+ bool needPrev = false;
+ if (head < kNumItems && lastSym >= 0)
+ {
+ while (head < kNumItems && _parents[head] != kNumItems)
+ head++;
+ if (head < kNumItems)
+ {
+ if (head == (unsigned)lastSym)
{
- needPrev = true;
- _isFree[head] = false;
- _parents[head] = (UInt16)lastSymbol;
- head++;
+ // we need to fix the code for that case
+ // _parents[head] is not allowed to link to itself
+ return E_NOTIMPL;
}
+ needPrev = true;
+ _parents[head] = (UInt16)lastSym;
+ _suffixes[head] = (Byte)lastChar2;
+ head++;
}
- else
- return S_FALSE;
- continue;
}
- UInt32 cur = symbol;
- i = 0;
- int corectionIndex = -1;
+
+ if (_parents[sym] == kNumItems)
+ return S_FALSE;
+
+ lastSym = sym;
+ unsigned cur = sym;
+ unsigned i = 0;
+
while (cur >= 256)
{
- if (cur == head - 1)
- corectionIndex = i;
_stack[i++] = _suffixes[cur];
cur = _parents[cur];
}
+
_stack[i++] = (Byte)cur;
+ lastChar2 = (Byte)cur;
+
if (needPrev)
- {
_suffixes[head - 1] = (Byte)cur;
- if (corectionIndex >= 0)
- _stack[corectionIndex] = (Byte)cur;
- }
- while (i > 0)
- outBuffer.WriteByte((_stack[--i]));
- while (head < kNumItems && !_isFree[head])
- head++;
- if (head < kNumItems)
- {
- needPrev = true;
- _isFree[head] = false;
- _parents[head] = (UInt16)symbol;
- head++;
- }
- else
- needPrev = false;
- lastSymbol = symbol;
- UInt64 nowPos = outBuffer.GetProcessedSize();
- if (progress != NULL && nowPos - prevPos > (1 << 18))
+ do
+ outBuffer.WriteByte(_stack[--i]);
+ while (i);
+
+ if (progress)
{
- prevPos = nowPos;
- UInt64 packSize = inBuffer.GetProcessedSize();
- RINOK(progress->SetRatioInfo(&packSize, &nowPos));
+ const UInt64 nowPos = outBuffer.GetProcessedSize();
+ if (nowPos - prevPos >= (1 << 18))
+ {
+ prevPos = nowPos;
+ const UInt64 packSize = inBuffer.GetProcessedSize();
+ RINOK(progress->SetRatioInfo(&packSize, &nowPos));
+ }
}
}
+
return outBuffer.Flush();
}
STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
catch(const CInBufferException &e) { return e.ErrorCode; }
diff --git a/CPP/7zip/Compress/ShrinkDecoder.h b/CPP/7zip/Compress/ShrinkDecoder.h
index 9bbecd41..42e5eee7 100644
--- a/CPP/7zip/Compress/ShrinkDecoder.h
+++ b/CPP/7zip/Compress/ShrinkDecoder.h
@@ -10,8 +10,8 @@
namespace NCompress {
namespace NShrink {
-const int kNumMaxBits = 13;
-const UInt32 kNumItems = 1 << kNumMaxBits;
+const unsigned kNumMaxBits = 13;
+const unsigned kNumItems = 1 << kNumMaxBits;
class CDecoder :
public ICompressCoder,
@@ -20,8 +20,6 @@ class CDecoder :
UInt16 _parents[kNumItems];
Byte _suffixes[kNumItems];
Byte _stack[kNumItems];
- bool _isFree[kNumItems];
- bool _isParent[kNumItems];
public:
MY_UNKNOWN_IMP
diff --git a/CPP/7zip/Crypto/7zAes.h b/CPP/7zip/Crypto/7zAes.h
index 4bd7d291..84e07ac9 100644
--- a/CPP/7zip/Crypto/7zAes.h
+++ b/CPP/7zip/Crypto/7zAes.h
@@ -86,7 +86,8 @@ class CEncoder:
public ICryptoResetInitVector
{
public:
- MY_UNKNOWN_IMP3(
+ MY_UNKNOWN_IMP4(
+ ICompressFilter,
ICryptoSetPassword,
ICompressWriteCoderProperties,
// ICryptoResetSalt,
@@ -104,7 +105,8 @@ class CDecoder:
public ICompressSetDecoderProperties2
{
public:
- MY_UNKNOWN_IMP2(
+ MY_UNKNOWN_IMP3(
+ ICompressFilter,
ICryptoSetPassword,
ICompressSetDecoderProperties2)
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
diff --git a/CPP/7zip/Crypto/7zAesRegister.cpp b/CPP/7zip/Crypto/7zAesRegister.cpp
index f1916cb1..f9d59699 100644
--- a/CPP/7zip/Crypto/7zAesRegister.cpp
+++ b/CPP/7zip/Crypto/7zAesRegister.cpp
@@ -6,7 +6,12 @@
#include "7zAes.h"
+namespace NCrypto {
+namespace N7z {
+
REGISTER_FILTER_E(7zAES,
- NCrypto::N7z::CDecoder(),
- NCrypto::N7z::CEncoder(),
+ CDecoder(),
+ CEncoder(),
0x6F10701, "7zAES")
+
+}}
diff --git a/CPP/7zip/Crypto/MyAes.h b/CPP/7zip/Crypto/MyAes.h
index 289935eb..84c21de3 100644
--- a/CPP/7zip/Crypto/MyAes.h
+++ b/CPP/7zip/Crypto/MyAes.h
@@ -30,7 +30,7 @@ class CAesCbcCoder:
public:
CAesCbcCoder(bool encodeMode, unsigned keySize);
- MY_UNKNOWN_IMP2(ICryptoProperties, ICompressSetCoderProperties)
+ MY_UNKNOWN_IMP3(ICompressFilter, ICryptoProperties, ICompressSetCoderProperties)
INTERFACE_ICompressFilter(;)
diff --git a/CPP/7zip/Crypto/MyAesReg.cpp b/CPP/7zip/Crypto/MyAesReg.cpp
index 34035da6..28006835 100644
--- a/CPP/7zip/Crypto/MyAesReg.cpp
+++ b/CPP/7zip/Crypto/MyAesReg.cpp
@@ -6,7 +6,11 @@
#include "MyAes.h"
+namespace NCrypto {
+
REGISTER_FILTER_E(AES256CBC,
- NCrypto::CAesCbcDecoder(32),
- NCrypto::CAesCbcEncoder(32),
+ CAesCbcDecoder(32),
+ CAesCbcEncoder(32),
0x6F00181, "AES256CBC")
+
+}
diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp
index 803a327a..4c0dbc77 100644
--- a/CPP/7zip/UI/Agent/AgentProxy.cpp
+++ b/CPP/7zip/UI/Agent/AgentProxy.cpp
@@ -304,14 +304,25 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress)
*/
unsigned namePos = 0;
+
+ unsigned numLevels = 0;
+
for (unsigned j = 0; j < len; j++)
{
wchar_t c = s[j];
if (c == WCHAR_PATH_SEPARATOR || c == L'/')
{
- name.SetFrom(s + namePos, j - namePos);
- curItem = AddDir(curItem, -1, name);
+ const unsigned kLevelLimit = 1 << 10;
+ if (numLevels <= kLevelLimit)
+ {
+ if (numLevels == kLevelLimit)
+ name.SetFromAscii("[LONG_PATH]");
+ else
+ name.SetFrom(s + namePos, j - namePos);
+ curItem = AddDir(curItem, -1, name);
+ }
namePos = j + 1;
+ numLevels++;
}
}
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
index 1bd202ed..61a781af 100644
--- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
+++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
@@ -1053,7 +1053,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
unsigned numNonSwitchStrings = nonSwitchStrings.Size();
if (numNonSwitchStrings < kMinNonSwitchWords)
- throw CArcCmdLineException("The command must be spcified");
+ throw CArcCmdLineException("The command must be specified");
if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))
throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]);
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
index 359835d3..fd2807ac 100644
--- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
+++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
@@ -43,6 +43,7 @@ STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
switch (propID)
{
case kpidName: prop = _subArchiveName; break;
+ // case kpidSize: prop = _subArchiveSize; break; // we don't use it now
}
else
switch (propID)
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp
index e323abd2..4081b0a6 100644
--- a/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -1632,6 +1632,36 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
#endif
{
+ #ifndef _SFX
+
+ bool isZip = false;
+ bool isRar = false;
+
+ const wchar_t c = extension[0];
+ if (c == 'z' || c == 'Z' || c == 'r' || c == 'R')
+ {
+ bool isNumber = false;
+ for (unsigned k = 1;; k++)
+ {
+ const wchar_t d = extension[k];
+ if (d == 0)
+ break;
+ if (d < '0' || d > '9')
+ {
+ isNumber = false;
+ break;
+ }
+ isNumber = true;
+ }
+ if (isNumber)
+ if (c == 'z' || c == 'Z')
+ isZip = true;
+ else
+ isRar = true;
+ }
+
+ #endif
+
FOR_VECTOR (i, op.codecs->Formats)
{
const CArcInfoEx &ai = op.codecs->Formats[i];
@@ -1647,7 +1677,12 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
isPrearcExt = true;
#endif
- if (ai.FindExtension(extension) >= 0)
+ if (ai.FindExtension(extension) >= 0
+ #ifndef _SFX
+ || isZip && StringsAreEqualNoCase_Ascii(ai.Name, "zip")
+ || isRar && StringsAreEqualNoCase_Ascii(ai.Name, "rar")
+ #endif
+ )
{
// PrintNumber("orderIndices.Insert", i);
orderIndices.Insert(numFinded++, i);
diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp
index 74660186..a0e692d0 100644
--- a/CPP/7zip/UI/Common/ZipRegistry.cpp
+++ b/CPP/7zip/UI/Common/ZipRegistry.cpp
@@ -98,6 +98,8 @@ void CInfo::Load()
OverwriteMode = NOverwriteMode::kAsk;
OverwriteMode_Force = false;
+ SplitDest.Val = true;
+
Paths.Clear();
CS_LOCK
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp
index d94e28e6..4e4ac221 100644
--- a/CPP/7zip/UI/Explorer/ContextMenu.cpp
+++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp
@@ -295,7 +295,7 @@ static bool IsItArcExt(const UString &ext)
return false;
}
-static UString GetSubFolderNameForExtract(const UString &arcName)
+UString GetSubFolderNameForExtract(const UString &arcName)
{
int dotPos = arcName.ReverseFind_Dot();
if (dotPos < 0)
diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp
index a262029f..6d5662de 100644
--- a/CPP/7zip/UI/FileManager/App.cpp
+++ b/CPP/7zip/UI/FileManager/App.cpp
@@ -46,7 +46,7 @@ void CPanelCallbackImp::OnTab()
_app->RefreshTitle();
}
-void CPanelCallbackImp::SetFocusToPath(int index)
+void CPanelCallbackImp::SetFocusToPath(unsigned index)
{
int newPanelIndex = index;
if (g_App.NumPanels == 1)
@@ -60,10 +60,10 @@ void CPanelCallbackImp::SetFocusToPath(int index)
void CPanelCallbackImp::OnCopy(bool move, bool copyToSame) { _app->OnCopy(move, copyToSame, _index); }
void CPanelCallbackImp::OnSetSameFolder() { _app->OnSetSameFolder(_index); }
void CPanelCallbackImp::OnSetSubFolder() { _app->OnSetSubFolder(_index); }
-void CPanelCallbackImp::PanelWasFocused() { _app->SetFocusedPanel(_index); _app->RefreshTitle(_index); }
+void CPanelCallbackImp::PanelWasFocused() { _app->SetFocusedPanel(_index); _app->RefreshTitlePanel(_index); }
void CPanelCallbackImp::DragBegin() { _app->DragBegin(_index); }
void CPanelCallbackImp::DragEnd() { _app->DragEnd(); }
-void CPanelCallbackImp::RefreshTitle(bool always) { _app->RefreshTitle(_index, always); }
+void CPanelCallbackImp::RefreshTitle(bool always) { _app->RefreshTitlePanel(_index, always); }
void CApp::ReloadLang()
{
@@ -115,11 +115,14 @@ void CApp::SetListSettings()
#endif
HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat,
- bool &archiveIsOpened, bool &encrypted)
+ bool needOpenArc,
+ bool &archiveIsOpened, bool &encrypted)
{
- if (PanelsCreated[panelIndex])
+ if (Panels[panelIndex].PanelCreated)
return S_OK;
+
m_PanelCallbackImp[panelIndex].Init(this, panelIndex);
+
UString path;
if (mainPath.IsEmpty())
{
@@ -128,13 +131,16 @@ HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UStr
}
else
path = mainPath;
+
int id = 1000 + 100 * panelIndex;
- RINOK(Panels[panelIndex].Create(_window, _window,
- id, path, arcFormat, &m_PanelCallbackImp[panelIndex], &AppState, archiveIsOpened, encrypted));
- PanelsCreated[panelIndex] = true;
- return S_OK;
+
+ return Panels[panelIndex].Create(_window, _window,
+ id, path, arcFormat, &m_PanelCallbackImp[panelIndex], &AppState,
+ needOpenArc,
+ archiveIsOpened, encrypted);
}
+
static void CreateToolbar(HWND parent,
NControl::CImageList &imageList,
NControl::CToolBar &toolBar,
@@ -165,6 +171,7 @@ static void CreateToolbar(HWND parent,
toolBar.SetImageList(0, imageList);
}
+
struct CButtonInfo
{
int CommandID;
@@ -273,9 +280,11 @@ void CApp::SaveToolbarChanges()
MoveSubWindows();
}
+
void MyLoadMenu();
-HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool &archiveIsOpened, bool &encrypted)
+
+HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, bool &archiveIsOpened, bool &encrypted)
{
_window.Attach(hwnd);
@@ -292,9 +301,9 @@ HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcForma
ReadToolbar();
ReloadToolbars();
- int i;
+ unsigned i;
for (i = 0; i < kNumPanelsMax; i++)
- PanelsCreated[i] = false;
+ Panels[i].PanelCreated = false;
AppState.Read();
@@ -316,33 +325,52 @@ HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcForma
}
for (i = 0; i < kNumPanelsMax; i++)
- if (NumPanels > 1 || i == LastFocusedPanel)
+ {
+ unsigned panelIndex = i;
+ if (needOpenArc && LastFocusedPanel == 1)
+ panelIndex = 1 - i;
+
+ bool isMainPanel = (panelIndex == LastFocusedPanel);
+
+ if (NumPanels > 1 || isMainPanel)
{
if (NumPanels == 1)
- Panels[i]._xSize = xSizes[0] + xSizes[1];
+ Panels[panelIndex]._xSize = xSizes[0] + xSizes[1];
bool archiveIsOpened2 = false;
bool encrypted2 = false;
- bool mainPanel = (i == LastFocusedPanel);
- RINOK(CreateOnePanel(i, mainPanel ? mainPath : L"", arcFormat, archiveIsOpened2, encrypted2));
- if (mainPanel)
+ UString path;
+ if (isMainPanel)
+ path = mainPath;
+
+ RINOK(CreateOnePanel(panelIndex, path, arcFormat,
+ isMainPanel && needOpenArc,
+ archiveIsOpened2, encrypted2));
+
+ if (isMainPanel)
{
archiveIsOpened = archiveIsOpened2;
encrypted = encrypted2;
+ if (needOpenArc && !archiveIsOpened2)
+ return S_OK;
}
}
+ }
SetFocusedPanel(LastFocusedPanel);
Panels[LastFocusedPanel].SetFocusToList();
return S_OK;
}
+
HRESULT CApp::SwitchOnOffOnePanel()
{
if (NumPanels == 1)
{
NumPanels++;
bool archiveIsOpened, encrypted;
- RINOK(CreateOnePanel(1 - LastFocusedPanel, UString(), UString(), archiveIsOpened, encrypted));
+ RINOK(CreateOnePanel(1 - LastFocusedPanel, UString(), UString(),
+ false, // needOpenArc
+ archiveIsOpened, encrypted));
Panels[1 - LastFocusedPanel].Enable(true);
Panels[1 - LastFocusedPanel].Show(SW_SHOWNORMAL);
}
@@ -530,7 +558,7 @@ static bool IsFsPath(const FString &path)
void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
{
- int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
+ unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
CPanel &srcPanel = Panels[srcPanelIndex];
CPanel &destPanel = Panels[destPanelIndex];
@@ -854,7 +882,7 @@ int CApp::GetFocusedPanelIndex() const
{
if (hwnd == 0)
return 0;
- for (int i = 0; i < kNumPanelsMax; i++)
+ for (unsigned i = 0; i < kNumPanelsMax; i++)
{
if (PanelsCreated[i] &&
((HWND)Panels[i] == hwnd || Panels[i]._listView == hwnd))
@@ -906,7 +934,7 @@ void CApp::RefreshTitle(bool always)
NWindows::MySetWindowText(_window, path);
}
-void CApp::RefreshTitle(int panelIndex, bool always)
+void CApp::RefreshTitlePanel(unsigned panelIndex, bool always)
{
if (panelIndex != GetFocusedPanelIndex())
return;
diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h
index dedbd821..9cc1066b 100644
--- a/CPP/7zip/UI/FileManager/App.h
+++ b/CPP/7zip/UI/FileManager/App.h
@@ -14,7 +14,7 @@ class CApp;
extern CApp g_App;
extern HWND g_HWND;
-const int kNumPanelsMax = 2;
+const unsigned kNumPanelsMax = 2;
extern bool g_IsSmallScreen;
@@ -32,15 +32,15 @@ enum
class CPanelCallbackImp: public CPanelCallback
{
CApp *_app;
- int _index;
+ unsigned _index;
public:
- void Init(CApp *app, int index)
+ void Init(CApp *app, unsigned index)
{
_app = app;
_index = index;
}
virtual void OnTab();
- virtual void SetFocusToPath(int index);
+ virtual void SetFocusToPath(unsigned index);
virtual void OnCopy(bool move, bool copyToSame);
virtual void OnSetSameFolder();
virtual void OnSetSubFolder();
@@ -111,8 +111,8 @@ public:
NWindows::CWindow _window;
bool ShowSystemMenu;
// bool ShowDeletedFiles;
- int NumPanels;
- int LastFocusedPanel;
+ unsigned NumPanels;
+ unsigned LastFocusedPanel;
bool ShowStandardToolbar;
bool ShowArchiveToolbar;
@@ -122,7 +122,6 @@ public:
CAppState AppState;
CPanelCallbackImp m_PanelCallbackImp[kNumPanelsMax];
CPanel Panels[kNumPanelsMax];
- bool PanelsCreated[kNumPanelsMax];
NWindows::NControl::CImageList _buttonsImageList;
@@ -151,13 +150,13 @@ public:
_dropTargetSpec->App = (this);
}
- void SetFocusedPanel(int index)
+ void SetFocusedPanel(unsigned index)
{
LastFocusedPanel = index;
_dropTargetSpec->TargetPanelIndex = LastFocusedPanel;
}
- void DragBegin(int panelIndex)
+ void DragBegin(unsigned panelIndex)
{
_dropTargetSpec->TargetPanelIndex = (NumPanels > 1) ? 1 - panelIndex : panelIndex;
_dropTargetSpec->SrcPanelIndex = panelIndex;
@@ -174,16 +173,16 @@ public:
void OnSetSameFolder(int srcPanelIndex);
void OnSetSubFolder(int srcPanelIndex);
- HRESULT CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted);
- HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool &archiveIsOpened, bool &encrypted);
+ HRESULT CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, bool needOpenArc, bool &archiveIsOpened, bool &encrypted);
+ HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, bool &archiveIsOpened, bool &encrypted);
void Read();
void Save();
void Release();
// void SetFocus(int panelIndex) { Panels[panelIndex].SetFocusToList(); }
void SetFocusToLastItem() { Panels[LastFocusedPanel].SetFocusToLastRememberedItem(); }
- int GetFocusedPanelIndex() const { return LastFocusedPanel; }
- bool IsPanelVisible(int index) const { return (NumPanels > 1 || index == LastFocusedPanel); }
+ unsigned GetFocusedPanelIndex() const { return LastFocusedPanel; }
+ bool IsPanelVisible(unsigned index) const { return (NumPanels > 1 || index == LastFocusedPanel); }
CPanel &GetFocusedPanel() { return Panels[GetFocusedPanelIndex()]; }
// File Menu
@@ -235,9 +234,9 @@ public:
void RefreshView() { GetFocusedPanel().OnReload(); }
void RefreshAllPanels()
{
- for (int i = 0; i < NumPanels; i++)
+ for (unsigned i = 0; i < NumPanels; i++)
{
- int index = i;
+ unsigned index = i;
if (NumPanels == 1)
index = LastFocusedPanel;
Panels[index].OnReload();
@@ -247,9 +246,9 @@ public:
/*
void SysIconsWereChanged()
{
- for (int i = 0; i < NumPanels; i++)
+ for (unsigned i = 0; i < NumPanels; i++)
{
- int index = i;
+ unsigned index = i;
if (NumPanels == 1)
index = LastFocusedPanel;
Panels[index].SysIconsWereChanged();
@@ -280,7 +279,7 @@ public:
}
void SetPanels_AutoRefresh_Mode()
{
- for (int i = 0; i < kNumPanelsMax; i++)
+ for (unsigned i = 0; i < kNumPanelsMax; i++)
Panels[i].Set_AutoRefresh_Mode(AutoRefresh_Mode);
}
@@ -347,7 +346,7 @@ public:
UString PrevTitle;
void RefreshTitle(bool always = false);
void RefreshTitleAlways() { RefreshTitle(true); }
- void RefreshTitle(int panelIndex, bool always = false);
+ void RefreshTitlePanel(unsigned panelIndex, bool always = false);
void MoveSubWindows();
};
diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp
index f91dda09..35b757dd 100644
--- a/CPP/7zip/UI/FileManager/FM.cpp
+++ b/CPP/7zip/UI/FileManager/FM.cpp
@@ -157,6 +157,7 @@ static bool g_CanChangeSplitter = false;
static UInt32 g_SplitterPos = 0;
static CSplitterPos g_Splitter;
static bool g_PanelsInfoDefined = false;
+static bool g_WindowWasCreated = false;
static int g_StartCaptureMousePos;
static int g_StartCaptureSplitterPos;
@@ -238,8 +239,9 @@ static BOOL InitInstance(int nCmdShow)
if (windowPosIsRead)
{
- // x = rect.left;
- // y = rect.top;
+ x = info.rect.left;
+ y = info.rect.top;
+
xSize = RECT_SIZE_X(info.rect);
ySize = RECT_SIZE_Y(info.rect);
}
@@ -258,6 +260,7 @@ static BOOL InitInstance(int nCmdShow)
info.numPanels = kNumDefaultPanels;
info.currentPanel = 0;
}
+
g_App.NumPanels = info.numPanels;
g_App.LastFocusedPanel = info.currentPanel;
@@ -832,7 +835,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
needOpenFile = true;
}
- HRESULT res = g_App.Create(hWnd, fullPath, g_ArcFormat, xSizes, archiveIsOpened, encrypted);
+ HRESULT res = g_App.Create(hWnd, fullPath, g_ArcFormat, xSizes,
+ needOpenFile,
+ archiveIsOpened, encrypted);
if (res == E_ABORT)
return -1;
@@ -852,6 +857,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
ErrorMessage(message);
return -1;
}
+
+ g_WindowWasCreated = true;
// g_SplitterPos = 0;
@@ -867,9 +874,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
RevokeDragDrop(hWnd);
g_App._dropTarget.Release();
- g_App.Save();
+ if (g_WindowWasCreated)
+ g_App.Save();
+
g_App.Release();
- SaveWindowInfo(hWnd);
+
+ if (g_WindowWasCreated)
+ SaveWindowInfo(hWnd);
g_ExitEventLauncher.Exit(true);
PostQuitMessage(0);
diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp
index 07f046e1..ac12a0eb 100644
--- a/CPP/7zip/UI/FileManager/LinkDialog.cpp
+++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp
@@ -333,7 +333,7 @@ void CApp::Link()
const UString srcPath = fsPrefix + srcPanel.GetItemPrefix(index);
UString path = srcPath;
{
- int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
+ unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
CPanel &destPanel = Panels[destPanelIndex];
if (NumPanels > 1)
if (destPanel.IsFSFolder())
diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp
index 96a34af8..a80fd049 100644
--- a/CPP/7zip/UI/FileManager/Panel.cpp
+++ b/CPP/7zip/UI/FileManager/Panel.cpp
@@ -74,6 +74,7 @@ HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id,
const UString &currentFolderPrefix,
const UString &arcFormat,
CPanelCallback *panelCallback, CAppState *appState,
+ bool needOpenArc,
bool &archiveIsOpened, bool &encrypted)
{
_mainWindow = mainWindow;
@@ -100,10 +101,15 @@ HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id,
RINOK(BindToPath(cfp, arcFormat, archiveIsOpened, encrypted));
+ if (needOpenArc && !archiveIsOpened)
+ return S_OK;
+
if (!CreateEx(0, kClassName, 0, WS_CHILD | WS_VISIBLE,
0, 0, _xSize, 260,
parentWindow, (HMENU)(UINT_PTR)id, g_hInstance))
return E_FAIL;
+ PanelCreated = true;
+
return S_OK;
}
@@ -525,7 +531,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
_statusBar.Create(WS_CHILD | WS_VISIBLE, L"Status", (*this), _statusBarID);
// _statusBar2.Create(WS_CHILD | WS_VISIBLE, L"Status", (*this), _statusBarID + 1);
- int sizes[] = {160, 250, 350, -1};
+ const int sizes[] = {220, 320, 420, -1};
_statusBar.SetParts(4, sizes);
// _statusBar2.SetParts(5, sizes);
@@ -834,18 +840,20 @@ void CPanel::AddToArchive()
// KillSelection();
}
-static UString GetSubFolderNameForExtract(const UString &arcPath)
+// function from ContextMenu.cpp
+UString GetSubFolderNameForExtract(const UString &arcPath);
+
+static UString GetSubFolderNameForExtract2(const UString &arcPath)
{
- UString s = arcPath;
- int slashPos = s.ReverseFind_PathSepar();
- int dotPos = s.ReverseFind_Dot();
- if (dotPos <= slashPos + 1)
- s += L'~';
- else
+ int slashPos = arcPath.ReverseFind_PathSepar();
+ UString s;
+ UString name = arcPath;
+ if (slashPos >= 0)
{
- s.DeleteFrom(dotPos);
- s.TrimRight();
+ s = arcPath.Left(slashPos + 1);
+ name = arcPath.Ptr(slashPos + 1);
}
+ s += GetSubFolderNameForExtract(name);
return s;
}
@@ -885,7 +893,7 @@ void CPanel::ExtractArchives()
UString outFolder = GetFsPath();
if (indices.Size() == 1)
- outFolder += GetSubFolderNameForExtract(GetItemRelPath(indices[0]));
+ outFolder += GetSubFolderNameForExtract2(GetItemRelPath(indices[0]));
else
outFolder += L'*';
outFolder.Add_PathSepar();
diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h
index fc74d556..261388de 100644
--- a/CPP/7zip/UI/FileManager/Panel.h
+++ b/CPP/7zip/UI/FileManager/Panel.h
@@ -57,7 +57,7 @@ const int kParentIndex = -1;
struct CPanelCallback
{
virtual void OnTab() = 0;
- virtual void SetFocusToPath(int index) = 0;
+ virtual void SetFocusToPath(unsigned index) = 0;
virtual void OnCopy(bool move, bool copyToSame) = 0;
virtual void OnSetSameFolder() = 0;
virtual void OnSetSubFolder() = 0;
@@ -222,6 +222,7 @@ struct CSelectedState
UString FocusedName;
bool SelectFocused;
UStringVector SelectedNames;
+
CSelectedState(): FocusedItem(-1), SelectFocused(false) {}
};
@@ -377,6 +378,8 @@ public:
bool _thereAreDeletedItems;
bool _markDeletedItems;
+ bool PanelCreated;
+
HWND GetParent();
UInt32 GetRealIndex(const LVITEMW &item) const
@@ -460,8 +463,8 @@ public:
HRESULT BindToPathAndRefresh(const UString &path);
void OpenDrivesFolder();
- void SetBookmark(int index);
- void OpenBookmark(int index);
+ void SetBookmark(unsigned index);
+ void OpenBookmark(unsigned index);
void LoadFullPath();
void LoadFullPathAndShow();
@@ -477,7 +480,9 @@ public:
const UString &currentFolderPrefix,
const UString &arcFormat,
CPanelCallback *panelCallback,
- CAppState *appState, bool &archiveIsOpened, bool &encrypted);
+ CAppState *appState,
+ bool needOpenArc,
+ bool &archiveIsOpened, bool &encrypted);
void SetFocusToList();
void SetFocusToLastRememberedItem();
@@ -496,6 +501,7 @@ public:
_flatMode(false),
_flatModeForDisk(false),
_flatModeForArc(false),
+ PanelCreated(false),
// _showNtfsStrems_Mode(false),
// _showNtfsStrems_ModeForDisk(false),
diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp
index 0cd08d4c..befd19f5 100644
--- a/CPP/7zip/UI/FileManager/PanelDrag.cpp
+++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp
@@ -16,6 +16,7 @@
#include "../Common/ArchiveName.h"
#include "../Common/CompressCall.h"
+#include "../Common/ExtractingFilePath.h"
#include "MessagesDialog.h"
@@ -350,7 +351,10 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)
if (isFSFolder)
s = GetItemRelPath(index);
else
+ {
s = GetItemName(index);
+ s = Get_Correct_FsFile_Name(s);
+ }
names.Add(fs2us(dirPrefix) + s);
}
if (!CopyNamesToHGlobal(dataObjectSpec->hGlobal, names))
@@ -470,7 +474,7 @@ void CDropTarget::PositionCursor(POINTL ptl)
{
POINT pt2 = pt;
App->_window.ScreenToClient(&pt2);
- for (int i = 0; i < kNumPanelsMax; i++)
+ for (unsigned i = 0; i < kNumPanelsMax; i++)
if (App->IsPanelVisible(i))
if (App->Panels[i].IsEnabled())
if (ChildWindowFromPointEx(App->_window, pt2,
@@ -478,7 +482,7 @@ void CDropTarget::PositionCursor(POINTL ptl)
{
m_Panel = &App->Panels[i];
m_IsAppTarget = false;
- if (i == SrcPanelIndex)
+ if ((int)i == SrcPanelIndex)
{
m_PanelDropIsAllowed = false;
return;
diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
index e4fbb5b3..91b6feb1 100644
--- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
+++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
@@ -263,12 +263,12 @@ HRESULT CPanel::BindToPathAndRefresh(const UString &path)
return S_OK;
}
-void CPanel::SetBookmark(int index)
+void CPanel::SetBookmark(unsigned index)
{
_appState->FastFolders.SetString(index, _currentFolderPrefix);
}
-void CPanel::OpenBookmark(int index)
+void CPanel::OpenBookmark(unsigned index)
{
BindToPathAndRefresh(_appState->FastFolders.GetString(index));
}
diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp
index a8c0d352..7aaa97b1 100644
--- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp
+++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp
@@ -189,7 +189,7 @@ void CApp::Split()
UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
UString path = srcPath;
- int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
+ unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
CPanel &destPanel = Panels[destPanelIndex];
if (NumPanels > 1)
if (destPanel.IsFSFolder())
@@ -367,7 +367,7 @@ void CApp::Combine()
UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
UString path = srcPath;
- int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
+ unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
CPanel &destPanel = Panels[destPanelIndex];
if (NumPanels > 1)
if (destPanel.IsFSFolder())
diff --git a/CPP/Common/CrcReg.cpp b/CPP/Common/CrcReg.cpp
index 2c343b31..4b662f52 100644
--- a/CPP/Common/CrcReg.cpp
+++ b/CPP/Common/CrcReg.cpp
@@ -34,7 +34,7 @@ class CCrcHasher:
public:
CCrcHasher(): _crc(CRC_INIT_VAL) { SetFunctions(0); }
- MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
+ MY_UNKNOWN_IMP2(IHasher, ICompressSetCoderProperties)
INTERFACE_IHasher(;)
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
};
diff --git a/CPP/Common/DynLimBuf.cpp b/CPP/Common/DynLimBuf.cpp
index 388c5952..1d1d99dc 100644
--- a/CPP/Common/DynLimBuf.cpp
+++ b/CPP/Common/DynLimBuf.cpp
@@ -71,7 +71,7 @@ CDynLimBuf &CDynLimBuf::operator+=(const char *s) throw()
size_t n = _pos + len;
if (n - _size < _size)
{
- size_t n = _sizeLimit;
+ n = _sizeLimit;
if (n - _size > _size)
n = _size * 2;
}
diff --git a/CPP/Common/Sha1Reg.cpp b/CPP/Common/Sha1Reg.cpp
index eedb7e29..1400c989 100644
--- a/CPP/Common/Sha1Reg.cpp
+++ b/CPP/Common/Sha1Reg.cpp
@@ -18,7 +18,7 @@ class CSha1Hasher:
public:
CSha1Hasher() { Sha1_Init(&_sha); }
- MY_UNKNOWN_IMP
+ MY_UNKNOWN_IMP1(IHasher)
INTERFACE_IHasher(;)
};
diff --git a/CPP/Common/Sha256Reg.cpp b/CPP/Common/Sha256Reg.cpp
index 6c822cc7..66941699 100644
--- a/CPP/Common/Sha256Reg.cpp
+++ b/CPP/Common/Sha256Reg.cpp
@@ -18,7 +18,7 @@ class CSha256Hasher:
public:
CSha256Hasher() { Sha256_Init(&_sha); }
- MY_UNKNOWN_IMP
+ MY_UNKNOWN_IMP1(IHasher)
INTERFACE_IHasher(;)
};
diff --git a/CPP/Common/XzCrc64Reg.cpp b/CPP/Common/XzCrc64Reg.cpp
index d1a51338..33b52493 100644
--- a/CPP/Common/XzCrc64Reg.cpp
+++ b/CPP/Common/XzCrc64Reg.cpp
@@ -19,7 +19,7 @@ class CXzCrc64Hasher:
public:
CXzCrc64Hasher(): _crc(CRC64_INIT_VAL) {}
- MY_UNKNOWN_IMP
+ MY_UNKNOWN_IMP1(IHasher)
INTERFACE_IHasher(;)
};
diff --git a/DOC/7zip.inf b/DOC/7zip.inf
index 54e27431..80e6355d 100644
--- a/DOC/7zip.inf
+++ b/DOC/7zip.inf
@@ -10,8 +10,8 @@ AppName = "7-Zip"
InstallDir = %CE1%\%AppName%
[Strings]
-AppVer = "15.14"
-AppDate = "2015-12-31"
+AppVer = "16.00"
+AppDate = "2016-05-10"
[CEDevice]
; ProcessorType = 2577 ; ARM
diff --git a/DOC/7zip.nsi b/DOC/7zip.nsi
index 05b274cf..49ee7956 100644
--- a/DOC/7zip.nsi
+++ b/DOC/7zip.nsi
@@ -1,8 +1,8 @@
;--------------------------------
;Defines
-!define VERSION_MAJOR 15
-!define VERSION_MINOR 14
+!define VERSION_MAJOR 16
+!define VERSION_MINOR 00
!define VERSION_POSTFIX_FULL ""
!ifdef WIN64
!ifdef IA64
diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs
index b0787b61..30deffa7 100644
--- a/DOC/7zip.wxs
+++ b/DOC/7zip.wxs
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
-<?define VerMajor = "15" ?>
-<?define VerMinor = "14" ?>
+<?define VerMajor = "16" ?>
+<?define VerMinor = "00" ?>
<?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>
diff --git a/DOC/License.txt b/DOC/License.txt
index c36ececb..2c6b3074 100644
--- a/DOC/License.txt
+++ b/DOC/License.txt
@@ -3,7 +3,7 @@
License for use and distribution
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 7-Zip Copyright (C) 1999-2015 Igor Pavlov.
+ 7-Zip Copyright (C) 1999-2016 Igor Pavlov.
Licenses for files are:
diff --git a/DOC/copying.txt b/DOC/copying.txt
index 4c389012..4362b491 100644
--- a/DOC/copying.txt
+++ b/DOC/copying.txt
@@ -1,8 +1,8 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -10,7 +10,7 @@
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
- Preamble
+ Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@@ -112,7 +112,7 @@ modification follow. Pay close attention to the difference between a
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
- GNU LESSER GENERAL PUBLIC LICENSE
+ GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
@@ -146,7 +146,7 @@ such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
-
+
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
@@ -432,7 +432,7 @@ decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
- NO WARRANTY
+ NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
@@ -455,7 +455,7 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
- END OF TERMS AND CONDITIONS
+ END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
@@ -485,7 +485,7 @@ convey the exclusion of warranty; and each file should have at least the
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
@@ -500,5 +500,3 @@ necessary. Here is a sample; alter the names:
Ty Coon, President of Vice
That's all there is to it!
-
-
diff --git a/DOC/readme.txt b/DOC/readme.txt
index fec95d72..907cd5be 100644
--- a/DOC/readme.txt
+++ b/DOC/readme.txt
@@ -1,9 +1,9 @@
-7-Zip 15.14 Sources
+7-Zip 16.00 Sources
-------------------
7-Zip is a file archiver for Windows.
-7-Zip Copyright (C) 1999-2015 Igor Pavlov.
+7-Zip Copyright (C) 1999-2016 Igor Pavlov.
License Info
diff --git a/DOC/src-history.txt b/DOC/src-history.txt
index d33ec609..bf6e2d0c 100644
--- a/DOC/src-history.txt
+++ b/DOC/src-history.txt
@@ -1,6 +1,12 @@
HISTORY of the 7-Zip source code
--------------------------------
+16.00 2016-05-10
+-------------------------
+- 7-Zip now can extract multivolume ZIP archives (z01, z02, ... , zip).
+- Some bugs were fixed,
+
+
15.12 2015-11-19
-------------------------
- The BUG in C version of 7z decoder was fixed: