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
path: root/CPP
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2016-05-10 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:59 +0300
commit66ac98bb02ac0fadd2a0e3266ea39279984580a3 (patch)
treec14c790212474e8b51df443d686b202cfe6b2315 /CPP
parentc20d013055085bf49b4c93b2c617030b10c1fb4d (diff)
16.0016.00
Diffstat (limited to 'CPP')
-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
81 files changed, 2349 insertions, 824 deletions
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(;)
};