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

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2014-11-23 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:51 +0300
commitf08f4dcc3c02464c17753b3feafcfe5243b9e236 (patch)
treeb0e1b15bc5368d92dff422e8ec0818564a2b00b8 /CPP/7zip/Archive/Cab
parent83f8ddcc5b2161e1e3c49666265257fca8aeb12c (diff)
9.349.34
Diffstat (limited to 'CPP/7zip/Archive/Cab')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabBlockInStream.cpp191
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabBlockInStream.h31
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabHandler.cpp512
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabHandler.h11
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabHeader.cpp0
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabHeader.h23
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabIn.cpp446
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabIn.h129
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabItem.h29
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/CabRegister.cpp14
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Cab/StdAfx.h2
11 files changed, 846 insertions, 542 deletions
diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
index 12c73eb5..cebec610 100755..100644
--- a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
+++ b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
@@ -3,8 +3,7 @@
#include "StdAfx.h"
#include "../../../../C/Alloc.h"
-
-#include "Common/Defs.h"
+#include "../../../../C/CpuArch.h"
#include "../../Common/StreamUtils.h"
@@ -17,173 +16,73 @@ static const UInt32 kBlockSize = (1 << 16);
bool CCabBlockInStream::Create()
{
- if (!_buffer)
- _buffer = (Byte *)::MyAlloc(kBlockSize);
- return (_buffer != 0);
+ if (!_buf)
+ _buf = (Byte *)::MyAlloc(kBlockSize);
+ return _buf != 0;
}
CCabBlockInStream::~CCabBlockInStream()
{
- MyFree(_buffer);
+ ::MyFree(_buf);
}
-class CCheckSum2
-{
- UInt32 m_Value;
- int m_Pos;
- Byte m_Hist[4];
-public:
- CCheckSum2(): m_Value(0){};
- void Init() { m_Value = 0; m_Pos = 0; }
- void Update(const void *data, UInt32 size);
- void FinishDataUpdate()
- {
- for (int i = 0; i < m_Pos; i++)
- m_Value ^= ((UInt32)(m_Hist[i])) << (8 * (m_Pos - i - 1));
- }
- void UpdateUInt32(UInt32 v) { m_Value ^= v; }
- UInt32 GetResult() const { return m_Value; }
-};
-
-void CCheckSum2::Update(const void *data, UInt32 size)
+static UInt32 CheckSum(const Byte *p, UInt32 size)
{
- UInt32 checkSum = m_Value;
- const Byte *dataPointer = (const Byte *)data;
-
- while (size != 0 && m_Pos != 0)
- {
- m_Hist[m_Pos] = *dataPointer++;
- m_Pos = (m_Pos + 1) & 3;
- size--;
- if (m_Pos == 0)
- for (int i = 0; i < 4; i++)
- checkSum ^= ((UInt32)m_Hist[i]) << (8 * i);
- }
-
- int numWords = size / 4;
-
- while (numWords-- != 0)
+ UInt32 sum = 0;
+ for (UInt32 i = size >> 2; i != 0; i--)
{
- UInt32 temp = *dataPointer++;
- temp |= ((UInt32)(*dataPointer++)) << 8;
- temp |= ((UInt32)(*dataPointer++)) << 16;
- temp |= ((UInt32)(*dataPointer++)) << 24;
- checkSum ^= temp;
+ sum ^= GetUi32(p);
+ p += 4;
}
- m_Value = checkSum;
-
size &= 3;
-
- while (size != 0)
- {
- m_Hist[m_Pos] = *dataPointer++;
- m_Pos = (m_Pos + 1) & 3;
- size--;
- }
+ if (size > 2) sum ^= (UInt32)(*p++) << 16;
+ if (size > 1) sum ^= (UInt32)(*p++) << 8;
+ if (size > 0) sum ^= (UInt32)(*p++);
+ return sum;
}
-static const UInt32 kDataBlockHeaderSize = 8;
-
-class CTempCabInBuffer2
+HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize)
{
-public:
- Byte Buffer[kDataBlockHeaderSize];
- UInt32 Pos;
- Byte ReadByte()
- {
- return Buffer[Pos++];
- }
- UInt32 ReadUInt32()
- {
- UInt32 value = 0;
- for (int i = 0; i < 4; i++)
- value |= (((UInt32)ReadByte()) << (8 * i));
- return value;
- }
- UInt16 ReadUInt16()
- {
- UInt16 value = 0;
- for (int i = 0; i < 2; i++)
- value |= (((UInt16)ReadByte()) << (8 * i));
- return value;
- }
-};
-
-HRESULT CCabBlockInStream::PreRead(UInt32 &packSize, UInt32 &unpackSize)
-{
- CTempCabInBuffer2 inBuffer;
- inBuffer.Pos = 0;
- RINOK(ReadStream_FALSE(_stream, inBuffer.Buffer, kDataBlockHeaderSize))
-
- UInt32 checkSum = inBuffer.ReadUInt32();
- packSize = inBuffer.ReadUInt16();
- unpackSize = inBuffer.ReadUInt16();
- if (ReservedSize != 0)
- {
- RINOK(ReadStream_FALSE(_stream, _buffer, ReservedSize));
- }
- _pos = 0;
- CCheckSum2 checkSumCalc;
- checkSumCalc.Init();
- UInt32 packSize2 = packSize;
- if (MsZip && _size == 0)
+ const UInt32 kHeaderSize = 8;
+ const UInt32 kReservedMax = 256;
+ Byte header[kHeaderSize + kReservedMax];
+ RINOK(ReadStream_FALSE(stream, header, kHeaderSize + ReservedSize))
+ packSize = GetUi16(header + 4);
+ unpackSize = GetUi16(header + 6);
+ if (packSize > kBlockSize - _size)
+ return S_FALSE;
+ RINOK(ReadStream_FALSE(stream, _buf + _size, packSize));
+
+ if (MsZip)
{
- if (packSize < 2)
- return S_FALSE; // bad block;
- Byte sig[2];
- RINOK(ReadStream_FALSE(_stream, sig, 2));
- if (sig[0] != 0x43 || sig[1] != 0x4B)
+ if (_size == 0)
+ {
+ if (packSize < 2 || _buf[0] != 0x43 || _buf[1] != 0x4B)
+ return S_FALSE;
+ _pos = 2;
+ }
+ if (_size + packSize > ((UInt32)1 << 15) + 12) /* v9.31 fix. MSZIP specification */
return S_FALSE;
- packSize2 -= 2;
- checkSumCalc.Update(sig, 2);
}
- if (kBlockSize - _size < packSize2)
- return S_FALSE;
-
- UInt32 curSize = packSize2;
- if (curSize != 0)
- {
- size_t processedSizeLoc = curSize;
- RINOK(ReadStream(_stream, _buffer + _size, &processedSizeLoc));
- checkSumCalc.Update(_buffer + _size, (UInt32)processedSizeLoc);
- _size += (UInt32)processedSizeLoc;
- if (processedSizeLoc != curSize)
+ if (GetUi32(header) != 0) // checkSum
+ if (CheckSum(header, kHeaderSize + ReservedSize) != CheckSum(_buf + _size, packSize))
return S_FALSE;
- }
- TotalPackSize = _size;
- checkSumCalc.FinishDataUpdate();
-
- bool dataError;
- if (checkSum == 0)
- dataError = false;
- else
- {
- checkSumCalc.UpdateUInt32(packSize | (((UInt32)unpackSize) << 16));
- dataError = (checkSumCalc.GetResult() != checkSum);
- }
- DataError |= dataError;
- return dataError ? S_FALSE : S_OK;
+ _size += packSize;
+ return S_OK;
}
STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != 0)
- *processedSize = 0;
- if (size == 0)
- return S_OK;
- if (_size != 0)
- {
- size = MyMin(_size, size);
- memmove(data, _buffer + _pos, size);
- _pos += size;
- _size -= size;
- if (processedSize != 0)
- *processedSize = size;
- return S_OK;
- }
- return S_OK; // no blocks data
+ UInt32 rem = _size - _pos;
+ if (size > rem)
+ size = rem;
+ memcpy(data, _buf + _pos, size);
+ _pos += size;
+ if (processedSize)
+ *processedSize = size;
+ return S_OK;
}
}}
diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.h b/CPP/7zip/Archive/Cab/CabBlockInStream.h
index 1db3835b..b795ed97 100755..100644
--- a/CPP/7zip/Archive/Cab/CabBlockInStream.h
+++ b/CPP/7zip/Archive/Cab/CabBlockInStream.h
@@ -1,9 +1,9 @@
-// CabBlockInStream.cpp
+// CabBlockInStream.h
-#ifndef __CABBLOCKINSTREAM_H
-#define __CABBLOCKINSTREAM_H
+#ifndef __CAB_BLOCK_IN_STREAM_H
+#define __CAB_BLOCK_IN_STREAM_H
-#include "Common/MyCom.h"
+#include "../../../Common/MyCom.h"
#include "../../IStream.h"
namespace NArchive {
@@ -13,30 +13,23 @@ class CCabBlockInStream:
public ISequentialInStream,
public CMyUnknownImp
{
- CMyComPtr<ISequentialInStream> _stream;
- Byte *_buffer;
- UInt32 _pos;
+ Byte *_buf;
UInt32 _size;
+ UInt32 _pos;
public:
- UInt32 TotalPackSize;
- UInt32 ReservedSize;
- bool DataError;
+ UInt32 ReservedSize; // < 256
bool MsZip;
- CCabBlockInStream(): _buffer(0), ReservedSize(0), MsZip(false), DataError(false), TotalPackSize(0) {}
+ MY_UNKNOWN_IMP
+
+ CCabBlockInStream(): _buf(0), ReservedSize(0), MsZip(false) {}
~CCabBlockInStream();
bool Create();
- void SetStream(ISequentialInStream *stream) { _stream = stream; }
-
- void InitForNewFolder() { TotalPackSize = 0; }
- void InitForNewBlock() { _size = 0; }
-
- MY_UNKNOWN_IMP
+ void InitForNewBlock() { _size = 0; _pos = 0; }
+ HRESULT PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize);
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
-
- HRESULT PreRead(UInt32 &packSize, UInt32 &unpackSize);
};
}}
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp
index fd707fe5..22bc93a0 100755..100644
--- a/CPP/7zip/Archive/Cab/CabHandler.cpp
+++ b/CPP/7zip/Archive/Cab/CabHandler.cpp
@@ -2,15 +2,17 @@
#include "StdAfx.h"
+// #include <stdio.h>
+
#include "../../../../C/Alloc.h"
-#include "Common/ComTry.h"
-#include "Common/IntToString.h"
-#include "Common/StringConvert.h"
-#include "Common/UTFConvert.h"
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/UTFConvert.h"
-#include "Windows/PropVariant.h"
-#include "Windows/Time.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/TimeUtils.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamUtils.h"
@@ -39,102 +41,243 @@ enum
};
#endif
-static STATPROPSTG kProps[] =
+static const Byte kProps[] =
{
- { NULL, kpidPath, VT_BSTR},
- { NULL, kpidSize, VT_UI8},
- { NULL, kpidMTime, VT_FILETIME},
- { NULL, kpidAttrib, VT_UI4},
- { NULL, kpidMethod, VT_BSTR},
- { NULL, kpidBlock, VT_I4}
+ kpidPath,
+ kpidSize,
+ kpidMTime,
+ kpidAttrib,
+ kpidMethod,
+ kpidBlock
#ifdef _CAB_DETAILS
,
- { L"BlockReal", kpidBlockReal, VT_UI4},
- { NULL, kpidOffset, VT_UI4},
- { NULL, kpidVolume, VT_UI4}
+ // kpidBlockReal, // L"BlockReal",
+ kpidOffset,
+ kpidVolume
#endif
};
-static const char *kMethods[] =
+static const Byte kArcProps[] =
{
- "None",
- "MSZip",
- "Quantum",
- "LZX"
+ kpidTotalPhySize,
+ kpidMethod,
+ // kpidSolid,
+ kpidNumBlocks,
+ kpidNumVolumes,
+ kpidVolumeIndex,
+ kpidId
};
-static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
-static const char *kUnknownMethod = "Unknown";
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
-static STATPROPSTG kArcProps[] =
+static const char *kMethods[] =
{
- { NULL, kpidMethod, VT_BSTR},
- // { NULL, kpidSolid, VT_BOOL},
- { NULL, kpidNumBlocks, VT_UI4},
- { NULL, kpidNumVolumes, VT_UI4}
+ "None"
+ , "MSZip"
+ , "Quantum"
+ , "LZX"
};
-IMP_IInArchive_Props
-IMP_IInArchive_ArcProps
+static const unsigned kMethodNameBufSize = 32; // "Quantum:255"
+
+static void SetMethodName(char *s, unsigned method, unsigned param)
+{
+ if (method < ARRAY_SIZE(kMethods))
+ {
+ s = MyStpCpy(s, kMethods[method]);
+ if (method != NHeader::NMethod::kLZX &&
+ method != NHeader::NMethod::kQuantum)
+ return;
+ *s++ = ':';
+ method = param;
+ }
+ ConvertUInt32ToString(method, s);
+}
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
- NWindows::NCOM::CPropVariant prop;
- switch(propID)
+ NCOM::CPropVariant prop;
+ switch (propID)
{
case kpidMethod:
{
- AString resString;
- CRecordVector<Byte> ids;
- int i;
- for (int v = 0; v < m_Database.Volumes.Size(); v++)
+ UInt32 mask = 0;
+ UInt32 params[2] = { 0, 0 };
{
- const CDatabaseEx &de = m_Database.Volumes[v];
- for (i = 0; i < de.Folders.Size(); i++)
- ids.AddToUniqueSorted(de.Folders[i].GetCompressionMethod());
+ FOR_VECTOR (v, m_Database.Volumes)
+ {
+ const CRecordVector<CFolder> &folders = m_Database.Volumes[v].Folders;
+ FOR_VECTOR (i, folders)
+ {
+ const CFolder &folder = folders[i];
+ unsigned method = folder.GetMethod();
+ mask |= ((UInt32)1 << method);
+ if (method == NHeader::NMethod::kLZX ||
+ method == NHeader::NMethod::kQuantum)
+ {
+ unsigned di = (method == NHeader::NMethod::kQuantum) ? 0 : 1;
+ if (params[di] < folder.MethodMinor)
+ params[di] = folder.MethodMinor;
+ }
+ }
+ }
}
- for (i = 0; i < ids.Size(); i++)
+ AString s;
+ for (unsigned i = 0; i < kNumMethodsMax; i++)
{
- Byte id = ids[i];
- AString method = (id < kNumMethods) ? kMethods[id] : kUnknownMethod;
- if (!resString.IsEmpty())
- resString += ' ';
- resString += method;
+ if ((mask & (1 << i)) == 0)
+ continue;
+ if (!s.IsEmpty())
+ s += ' ';
+ char temp[kMethodNameBufSize];
+ SetMethodName(temp, i, params[i == NHeader::NMethod::kQuantum ? 0 : 1]);
+ s += temp;
}
- prop = resString;
+ prop = s;
break;
}
// case kpidSolid: prop = _database.IsSolid(); break;
case kpidNumBlocks:
{
UInt32 numFolders = 0;
- for (int v = 0; v < m_Database.Volumes.Size(); v++)
+ FOR_VECTOR (v, m_Database.Volumes)
numFolders += m_Database.Volumes[v].Folders.Size();
prop = numFolders;
break;
}
- case kpidNumVolumes:
+
+ case kpidTotalPhySize:
{
+ if (m_Database.Volumes.Size() > 1)
+ {
+ UInt64 sum = 0;
+ FOR_VECTOR (v, m_Database.Volumes)
+ sum += m_Database.Volumes[v].ArcInfo.Size;
+ prop = sum;
+ }
+ break;
+ }
+
+ case kpidNumVolumes:
prop = (UInt32)m_Database.Volumes.Size();
break;
+
+ case kpidVolumeIndex:
+ {
+ if (m_Database.Volumes.Size() == 1)
+ {
+ const CDatabaseEx &db = m_Database.Volumes[0];
+ const CInArcInfo &ai = db.ArcInfo;
+ prop = (UInt32)ai.CabinetNumber;
+ }
+ break;
+ }
+
+ case kpidId:
+ {
+ if (m_Database.Volumes.Size() != 0)
+ {
+ prop = (UInt32)m_Database.Volumes[0].ArcInfo.SetID;
+ }
+ break;
+ }
+
+ case kpidOffset:
+ /*
+ if (m_Database.Volumes.Size() == 1)
+ prop = m_Database.Volumes[0].StartPosition;
+ */
+ prop = _offset;
+ break;
+
+ case kpidPhySize:
+ /*
+ if (m_Database.Volumes.Size() == 1)
+ prop = (UInt64)m_Database.Volumes[0].ArcInfo.Size;
+ */
+ prop = (UInt64)_phySize;
+ break;
+
+ case kpidErrorFlags:
+ {
+ UInt32 v = 0;
+ if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
+ if (_errorInHeaders) v |= kpv_ErrorFlags_HeadersError;
+ if (_unexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;
+ prop = v;
+ break;
+ }
+
+ case kpidError:
+ if (!_errorMessage.IsEmpty())
+ prop = _errorMessage;
+ break;
+
+ case kpidName:
+ {
+ if (m_Database.Volumes.Size() == 1)
+ {
+ const CDatabaseEx &db = m_Database.Volumes[0];
+ const CInArcInfo &ai = db.ArcInfo;
+ if (ai.SetID != 0)
+ {
+ AString s;
+ char temp[32];
+ ConvertUInt32ToString(ai.SetID, temp);
+ s += temp;
+ ConvertUInt32ToString(ai.CabinetNumber + 1, temp);
+ s += '_';
+ s += temp;
+ s += ".cab";
+ prop = s;
+ }
+ /*
+ // that code is incomplete. It gcan give accurate name of volume
+ char s[32];
+ ConvertUInt32ToString(ai.CabinetNumber + 2, s);
+ unsigned len = MyStringLen(s);
+ if (ai.IsThereNext())
+ {
+ AString fn = ai.NextArc.FileName;
+ if (fn.Len() > 4 && StringsAreEqualNoCase_Ascii(fn.RightPtr(4), ".cab"))
+ fn.DeleteFrom(fn.Len() - 4);
+ if (len < fn.Len())
+ {
+ if (strcmp(s, fn.RightPtr(len)) == 0)
+ {
+ AString s2 = fn;
+ s2.DeleteFrom(fn.Len() - len);
+ ConvertUInt32ToString(ai.CabinetNumber + 1, s);
+ s2 += s;
+ s2 += ".cab";
+ prop = GetUnicodeString(s2);
+ }
+ }
+ }
+ */
+ }
+ break;
}
+
+ // case kpidShortComment:
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
-STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
- NWindows::NCOM::CPropVariant prop;
+ NCOM::CPropVariant prop;
const CMvItem &mvItem = m_Database.Items[index];
const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];
- int itemIndex = mvItem.ItemIndex;
+ unsigned itemIndex = mvItem.ItemIndex;
const CItem &item = db.Items[itemIndex];
- switch(propID)
+ switch (propID)
{
case kpidPath:
{
@@ -146,9 +289,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
prop = (const wchar_t *)NItemName::WinNameToOSName(unicodeName);
break;
}
+
case kpidIsDir: prop = item.IsDir(); break;
case kpidSize: prop = item.Size; break;
- case kpidAttrib: prop = item.GetWinAttributes(); break;
+ case kpidAttrib: prop = item.GetWinAttrib(); break;
case kpidMTime:
{
@@ -168,24 +312,17 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
{
UInt32 realFolderIndex = item.GetFolderIndex(db.Folders.Size());
const CFolder &folder = db.Folders[realFolderIndex];
- int methodIndex = folder.GetCompressionMethod();
- AString method = (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
- if (methodIndex == NHeader::NCompressionMethodMajor::kLZX ||
- methodIndex == NHeader::NCompressionMethodMajor::kQuantum)
- {
- method += ':';
- char temp[32];
- ConvertUInt64ToString(folder.CompressionTypeMinor, temp);
- method += temp;
- }
- prop = method;
+ char s[kMethodNameBufSize];;
+ SetMethodName(s, folder.GetMethod(), folder.MethodMinor);
+ prop = s;
break;
}
+
case kpidBlock: prop = (Int32)m_Database.GetFolderIndex(&mvItem); break;
#ifdef _CAB_DETAILS
- case kpidBlockReal: prop = (UInt32)item.FolderIndex; break;
+ // case kpidBlockReal: prop = (UInt32)item.FolderIndex; break;
case kpidOffset: prop = (UInt32)item.Offset; break;
case kpidVolume: prop = (UInt32)mvItem.VolumeIndex; break;
@@ -196,39 +333,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
COM_TRY_END
}
-/*
-class CProgressImp: public CProgressVirt
-{
- CMyComPtr<IArchiveOpenCallback> m_OpenArchiveCallback;
-public:
- STDMETHOD(SetTotal)(const UInt64 *numFiles);
- STDMETHOD(SetCompleted)(const UInt64 *numFiles);
- void Init(IArchiveOpenCallback *openArchiveCallback)
- { m_OpenArchiveCallback = openArchiveCallback; }
-};
-
-STDMETHODIMP CProgressImp::SetTotal(const UInt64 *numFiles)
-{
- if (m_OpenArchiveCallback)
- return m_OpenArchiveCallback->SetCompleted(numFiles, NULL);
- return S_OK;
-}
-
-STDMETHODIMP CProgressImp::SetCompleted(const UInt64 *numFiles)
-{
- if (m_OpenArchiveCallback)
- return m_OpenArchiveCallback->SetCompleted(numFiles, NULL);
- return S_OK;
-}
-*/
-
STDMETHODIMP CHandler::Open(IInStream *inStream,
const UInt64 *maxCheckStartPosition,
IArchiveOpenCallback *callback)
{
COM_TRY_BEGIN
Close();
- HRESULT res = S_FALSE;
+
CInArchive archive;
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
@@ -236,96 +347,169 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
CMyComPtr<IInStream> nextStream = inStream;
bool prevChecked = false;
UInt64 numItems = 0;
- try
+ unsigned numTempVolumes = 0;
+ // try
{
- while (nextStream != 0)
+ while (nextStream != NULL)
{
CDatabaseEx db;
db.Stream = nextStream;
- res = archive.Open(maxCheckStartPosition, db);
- if (res == S_OK)
+ HRESULT res = archive.Open(db, maxCheckStartPosition);
+ _errorInHeaders |= archive.HeaderError;
+ _errorInHeaders |= archive.ErrorInNames;
+ _unexpectedEnd |= archive.UnexpectedEnd;
+
+ if (res == S_OK && !m_Database.Volumes.IsEmpty())
{
- if (!m_Database.Volumes.IsEmpty())
+ const CArchInfo &lastArc = m_Database.Volumes.Back().ArcInfo;
+ unsigned cabNumber = db.ArcInfo.CabinetNumber;
+ if (lastArc.SetID != db.ArcInfo.SetID)
+ res = S_FALSE;
+ else if (prevChecked)
+ {
+ if (cabNumber != lastArc.CabinetNumber + 1)
+ res = S_FALSE;
+ }
+ else if (cabNumber >= lastArc.CabinetNumber)
+ res = S_FALSE;
+ else if (numTempVolumes != 0)
{
- const CDatabaseEx &dbPrev = m_Database.Volumes[prevChecked ? m_Database.Volumes.Size() - 1 : 0];
- if (dbPrev.ArchiveInfo.SetID != db.ArchiveInfo.SetID ||
- dbPrev.ArchiveInfo.CabinetNumber + (prevChecked ? 1: - 1) !=
- db.ArchiveInfo.CabinetNumber)
+ const CArchInfo &prevArc = m_Database.Volumes[numTempVolumes - 1].ArcInfo;
+ if (cabNumber != prevArc.CabinetNumber + 1)
res = S_FALSE;
}
}
+
+ if (archive.IsArc || res == S_OK)
+ {
+ _isArc = true;
+ if (m_Database.Volumes.IsEmpty())
+ {
+ _offset = db.StartPosition;
+ _phySize = db.ArcInfo.Size;
+ }
+ }
+
if (res == S_OK)
- m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : 0, db);
- else if (res != S_FALSE)
- return res;
+ {
+ numItems += db.Items.Size();
+ m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : numTempVolumes, db);
+ if (!prevChecked && m_Database.Volumes.Size() > 1)
+ {
+ numTempVolumes++;
+ if (db.ArcInfo.CabinetNumber + 1 == m_Database.Volumes[numTempVolumes].ArcInfo.CabinetNumber)
+ numTempVolumes = 0;
+ }
+ }
else
{
+ if (res != S_FALSE)
+ return res;
if (m_Database.Volumes.IsEmpty())
return S_FALSE;
if (prevChecked)
break;
prevChecked = true;
+ if (numTempVolumes != 0)
+ {
+ m_Database.Volumes.DeleteFrontal(numTempVolumes);
+ numTempVolumes = 0;
+ }
}
- numItems += db.Items.Size();
RINOK(callback->SetCompleted(&numItems, NULL));
- nextStream = 0;
+ nextStream = NULL;
+
for (;;)
{
- const COtherArchive *otherArchive = 0;
+ const COtherArc *otherArc = NULL;
if (!prevChecked)
{
- const CInArchiveInfo &ai = m_Database.Volumes.Front().ArchiveInfo;
- if (ai.IsTherePrev())
- otherArchive = &ai.PrevArc;
+ if (numTempVolumes == 0)
+ {
+ const CInArcInfo &ai = m_Database.Volumes[0].ArcInfo;
+ if (ai.IsTherePrev())
+ otherArc = &ai.PrevArc;
+ else
+ prevChecked = true;
+ }
else
- prevChecked = true;
+ {
+ const CInArcInfo &ai = m_Database.Volumes[numTempVolumes - 1].ArcInfo;
+ if (ai.IsThereNext())
+ otherArc = &ai.NextArc;
+ else
+ {
+ prevChecked = true;
+ m_Database.Volumes.DeleteFrontal(numTempVolumes);
+ numTempVolumes = 0;
+ }
+ }
}
- if (otherArchive == 0)
+ if (!otherArc)
{
- const CInArchiveInfo &ai = m_Database.Volumes.Back().ArchiveInfo;
+ const CInArcInfo &ai = m_Database.Volumes.Back().ArcInfo;
if (ai.IsThereNext())
- otherArchive = &ai.NextArc;
+ otherArc = &ai.NextArc;
}
- if (!otherArchive)
+ if (!otherArc)
break;
- const UString fullName = MultiByteToUnicodeString(otherArchive->FileName, CP_ACP);
if (!openVolumeCallback)
break;
-
+ // printf("\n%s", otherArc->FileName);
+ const UString fullName = MultiByteToUnicodeString(otherArc->FileName, CP_ACP);
HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);
if (result == S_OK)
break;
if (result != S_FALSE)
return result;
+
+ if (!_errorMessage.IsEmpty())
+ _errorMessage += L"\n";
+ _errorMessage += L"Can't open volume: ";
+ _errorMessage += fullName;
+
if (prevChecked)
break;
prevChecked = true;
+ if (numTempVolumes != 0)
+ {
+ m_Database.Volumes.DeleteFrontal(numTempVolumes);
+ numTempVolumes = 0;
+ }
}
+
+ } // read nextStream iteration
+
+ if (numTempVolumes != 0)
+ {
+ m_Database.Volumes.DeleteFrontal(numTempVolumes);
+ numTempVolumes = 0;
}
- if (res == S_OK)
+ if (m_Database.Volumes.IsEmpty())
+ return S_FALSE;
+ else
{
m_Database.FillSortAndShrink();
if (!m_Database.Check())
- res = S_FALSE;
+ return S_FALSE;
}
}
- catch(...)
- {
- res = S_FALSE;
- }
- if (res != S_OK)
- {
- Close();
- return res;
- }
COM_TRY_END
return S_OK;
}
STDMETHODIMP CHandler::Close()
{
+ _errorMessage.Empty();
+ _isArc = false;
+ _errorInHeaders = false;
+ _unexpectedEnd = false;
+ // _mainVolIndex = -1;
+ _phySize = 0;
+ _offset = 0;
+
m_Database.Clear();
return S_OK;
}
@@ -348,8 +532,8 @@ private:
bool TempBufMode;
UInt32 m_BufStartFolderOffset;
- int m_StartIndex;
- int m_CurrentIndex;
+ unsigned m_StartIndex;
+ unsigned m_CurrentIndex;
CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;
bool m_TestMode;
@@ -379,7 +563,7 @@ public:
void Init(
const CMvDatabaseEx *database,
const CRecordVector<bool> *extractStatuses,
- int startIndex,
+ unsigned startIndex,
UInt64 folderSize,
IArchiveExtractCallback *extractCallback,
bool testMode);
@@ -393,7 +577,7 @@ public:
void CFolderOutStream::Init(
const CMvDatabaseEx *database,
const CRecordVector<bool> *extractStatuses,
- int startIndex,
+ unsigned startIndex,
UInt64 folderSize,
IArchiveExtractCallback *extractCallback,
bool testMode)
@@ -436,7 +620,7 @@ HRESULT CFolderOutStream::OpenFile()
const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
int numExtractItems = 0;
- int curIndex;
+ unsigned curIndex;
for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++)
{
const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex];
@@ -559,7 +743,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
if (!TempBuf && TempBufMode && m_RealOutStream)
{
- RINOK(CloseFileWithResOp(NExtract::NOperationResult::kUnSupportedMethod));
+ RINOK(CloseFileWithResOp(NExtract::NOperationResult::kUnsupportedMethod));
}
else
{
@@ -638,7 +822,7 @@ HRESULT CFolderOutStream::Unsupported()
if (result != S_FALSE && result != S_OK)
return result;
m_RealOutStream.Release();
- RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
+ RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod));
m_CurrentIndex++;
}
return S_OK;
@@ -649,7 +833,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
- bool allFilesMode = (numItems == (UInt32)-1);
+ bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
numItems = m_Database.Items.Size();
if (numItems == 0)
@@ -709,7 +893,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const CMvItem &mvItem = m_Database.Items[index];
const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];
- int itemIndex = mvItem.ItemIndex;
+ unsigned itemIndex = mvItem.ItemIndex;
const CItem &item = db.Items[itemIndex];
i++;
@@ -747,7 +931,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
extractStatuses.Add(true);
startIndex++;
UInt64 curUnpack = item.GetEndOffset();
- for(;i < numItems; i++)
+ for (; i < numItems; i++)
{
int indexNext = allFilesMode ? i : indices[i];
const CMvItem &mvItem = m_Database.Items[indexNext];
@@ -779,11 +963,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
cabBlockInStreamSpec->MsZip = false;
HRESULT res = S_OK;
- switch(folder.GetCompressionMethod())
+ switch (folder.GetMethod())
{
- case NHeader::NCompressionMethodMajor::kNone:
+ case NHeader::NMethod::kNone:
break;
- case NHeader::NCompressionMethodMajor::kMSZip:
+ case NHeader::NMethod::kMSZip:
if (!deflateDecoder)
{
deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder;
@@ -791,21 +975,21 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
cabBlockInStreamSpec->MsZip = true;
break;
- case NHeader::NCompressionMethodMajor::kLZX:
+ case NHeader::NMethod::kLZX:
if (!lzxDecoder)
{
lzxDecoderSpec = new NCompress::NLzx::CDecoder;
lzxDecoder = lzxDecoderSpec;
}
- res = lzxDecoderSpec->SetParams(folder.CompressionTypeMinor);
+ res = lzxDecoderSpec->SetParams(folder.MethodMinor);
break;
- case NHeader::NCompressionMethodMajor::kQuantum:
+ case NHeader::NMethod::kQuantum:
if (!quantumDecoder)
{
quantumDecoderSpec = new NCompress::NQuantum::CDecoder;
quantumDecoder = quantumDecoderSpec;
}
- res = quantumDecoderSpec->SetParams(folder.CompressionTypeMinor);
+ res = quantumDecoderSpec->SetParams(folder.MethodMinor);
break;
default:
res = E_INVALIDARG;
@@ -820,9 +1004,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
RINOK(res);
- cabBlockInStreamSpec->InitForNewFolder();
{
- int volIndex = mvItem.VolumeIndex;
+ unsigned volIndex = mvItem.VolumeIndex;
int locFolderIndex = item.GetFolderIndex(db.Folders.Size());
bool keepHistory = false;
bool keepInputBuffer = false;
@@ -838,8 +1021,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const CFolder &folder = db.Folders[locFolderIndex];
if (f == 0)
{
- cabBlockInStreamSpec->SetStream(db.Stream);
- cabBlockInStreamSpec->ReservedSize = db.ArchiveInfo.GetDataBlockReserveSize();
+ cabBlockInStreamSpec->ReservedSize = db.ArcInfo.GetDataBlockReserveSize();
RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL));
}
if (f == folder.NumDataBlocks)
@@ -851,13 +1033,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
f++;
- cabBlockInStreamSpec->DataError = false;
-
if (!keepInputBuffer)
cabBlockInStreamSpec->InitForNewBlock();
UInt32 packSize, unpackSize;
- res = cabBlockInStreamSpec->PreRead(packSize, unpackSize);
+ res = cabBlockInStreamSpec->PreRead(db.Stream, packSize, unpackSize);
if (res == S_FALSE)
break;
RINOK(res);
@@ -878,22 +1058,36 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (unpackRemain > kBlockSizeMax)
unpackRemain = kBlockSizeMax;
if (unpackRemain > unpackSize)
- unpackRemain = unpackSize;
+ unpackRemain = unpackSize;
- switch(folder.GetCompressionMethod())
+ switch (folder.GetMethod())
{
- case NHeader::NCompressionMethodMajor::kNone:
+ case NHeader::NMethod::kNone:
res = copyCoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
break;
- case NHeader::NCompressionMethodMajor::kMSZip:
- deflateDecoderSpec->SetKeepHistory(keepHistory);
+ case NHeader::NMethod::kMSZip:
+ deflateDecoderSpec->Set_KeepHistory(keepHistory);
+ /* v9.31: now we follow MSZIP specification that requires to finish deflate stream at the end of each block.
+ But PyCabArc can create CAB archives that doesn't have finish marker at the end of block.
+ Cabarc probably ignores such errors in cab archives.
+ Maybe we also should ignore that error?
+ Or we should extract full file and show the warning? */
+ deflateDecoderSpec->Set_NeedFinishInput(true);
res = deflateDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
+ if (res == S_OK)
+ {
+ if (!deflateDecoderSpec->IsFinished())
+ res = S_FALSE;
+ if (!deflateDecoderSpec->IsFinalBlock())
+ res = S_FALSE;
+ }
+
break;
- case NHeader::NCompressionMethodMajor::kLZX:
+ case NHeader::NMethod::kLZX:
lzxDecoderSpec->SetKeepHistory(keepHistory);
res = lzxDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
break;
- case NHeader::NCompressionMethodMajor::kQuantum:
+ case NHeader::NMethod::kQuantum:
quantumDecoderSpec->SetKeepHistory(keepHistory);
res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
break;
diff --git a/CPP/7zip/Archive/Cab/CabHandler.h b/CPP/7zip/Archive/Cab/CabHandler.h
index 1edcd11e..6f44b875 100755..100644
--- a/CPP/7zip/Archive/Cab/CabHandler.h
+++ b/CPP/7zip/Archive/Cab/CabHandler.h
@@ -3,8 +3,10 @@
#ifndef __CAB_HANDLER_H
#define __CAB_HANDLER_H
-#include "Common/MyCom.h"
+#include "../../../Common/MyCom.h"
+
#include "../IArchive.h"
+
#include "CabIn.h"
namespace NArchive {
@@ -21,6 +23,13 @@ public:
private:
CMvDatabaseEx m_Database;
+ UString _errorMessage;
+ bool _isArc;
+ bool _errorInHeaders;
+ bool _unexpectedEnd;
+ // int _mainVolIndex;
+ UInt32 _phySize;
+ UInt64 _offset;
};
}}
diff --git a/CPP/7zip/Archive/Cab/CabHeader.cpp b/CPP/7zip/Archive/Cab/CabHeader.cpp
index 0cba1b0b..0cba1b0b 100755..100644
--- a/CPP/7zip/Archive/Cab/CabHeader.cpp
+++ b/CPP/7zip/Archive/Cab/CabHeader.cpp
diff --git a/CPP/7zip/Archive/Cab/CabHeader.h b/CPP/7zip/Archive/Cab/CabHeader.h
index 0f0d2af3..9ec0760a 100755..100644
--- a/CPP/7zip/Archive/Cab/CabHeader.h
+++ b/CPP/7zip/Archive/Cab/CabHeader.h
@@ -3,7 +3,7 @@
#ifndef __ARCHIVE_CAB_HEADER_H
#define __ARCHIVE_CAB_HEADER_H
-#include "Common/Types.h"
+#include "../../../Common/MyTypes.h"
namespace NArchive {
namespace NCab {
@@ -12,17 +12,14 @@ namespace NHeader {
const unsigned kMarkerSize = 8;
extern Byte kMarker[kMarkerSize];
-namespace NArchive
+namespace NArcFlags
{
- namespace NFlags
- {
- const int kPrevCabinet = 0x0001;
- const int kNextCabinet = 0x0002;
- const int kReservePresent = 0x0004;
- }
+ const unsigned kPrevCabinet = 1;
+ const unsigned kNextCabinet = 2;
+ const unsigned kReservePresent = 4;
}
-namespace NCompressionMethodMajor
+namespace NMethod
{
const Byte kNone = 0;
const Byte kMSZip = 1;
@@ -30,13 +27,13 @@ namespace NCompressionMethodMajor
const Byte kLZX = 3;
}
-const int kFileNameIsUTFAttributeMask = 0x80;
+const unsigned kFileNameIsUtf8_Mask = 0x80;
namespace NFolderIndex
{
- const int kContinuedFromPrev = 0xFFFD;
- const int kContinuedToNext = 0xFFFE;
- const int kContinuedPrevAndNext = 0xFFFF;
+ const unsigned kContinuedFromPrev = 0xFFFD;
+ const unsigned kContinuedToNext = 0xFFFE;
+ const unsigned kContinuedPrevAndNext = 0xFFFF;
}
}}}
diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp
index c0bffa2d..c499f05f 100755..100644
--- a/CPP/7zip/Archive/Cab/CabIn.cpp
+++ b/CPP/7zip/Archive/Cab/CabIn.cpp
@@ -2,154 +2,353 @@
#include "StdAfx.h"
-#include "../Common/FindSignature.h"
+// #include <stdio.h>
+
+#include "../../../../C/CpuArch.h"
+
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/StreamUtils.h"
#include "CabIn.h"
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+
namespace NArchive {
namespace NCab {
-Byte CInArchive::Read8()
+struct CUnexpectedEndException {};
+
+void CInArchive::Skip(unsigned size)
{
- Byte b;
- if (!inBuffer.ReadByte(b))
- throw CInArchiveException(CInArchiveException::kUnsupported);
- return b;
+ if (_inBuffer.Skip(size) != size)
+ throw CUnexpectedEndException();
}
-UInt16 CInArchive::Read16()
+void CInArchive::Read(Byte *data, unsigned size)
{
- UInt16 value = 0;
- for (int i = 0; i < 2; i++)
- {
- Byte b = Read8();
- value |= (UInt16(b) << (8 * i));
- }
- return value;
+ if (_inBuffer.ReadBytes(data, size) != size)
+ throw CUnexpectedEndException();
}
-UInt32 CInArchive::Read32()
+void CInArchive::ReadName(AString &s)
{
- UInt32 value = 0;
- for (int i = 0; i < 4; i++)
+ for (size_t i = 0; i < ((size_t)1 << 13); i++)
{
- Byte b = Read8();
- value |= (UInt32(b) << (8 * i));
+ Byte b;
+ if (!_inBuffer.ReadByte(b))
+ throw CUnexpectedEndException();
+ if (b == 0)
+ {
+ memcpy(s.GetBuffer((unsigned)i), _tempBuf, i);
+ s.ReleaseBuffer((unsigned)i);
+ return;
+ }
+ if (_tempBuf.Size() == i)
+ _tempBuf.ChangeSize_KeepData(i * 2, i);
+ _tempBuf[i] = b;
}
- return value;
-}
-
-AString CInArchive::SafeReadName()
-{
- AString name;
+
for (;;)
{
- Byte b = Read8();
+ Byte b;
+ if (!_inBuffer.ReadByte(b))
+ throw CUnexpectedEndException();
if (b == 0)
- return name;
- name += (char)b;
+ break;
}
+
+ ErrorInNames = true;
+ s = "[ERROR-LONG-PATH]";
}
-void CInArchive::ReadOtherArchive(COtherArchive &oa)
+void CInArchive::ReadOtherArc(COtherArc &oa)
{
- oa.FileName = SafeReadName();
- oa.DiskName = SafeReadName();
+ ReadName(oa.FileName);
+ ReadName(oa.DiskName);
}
-void CInArchive::Skip(UInt32 size)
+struct CSignatureFinder
+{
+ Byte *Buf;
+ UInt32 Pos;
+ UInt32 End;
+ const Byte *Signature;
+ UInt32 SignatureSize;
+
+ UInt32 _HeaderSize;
+ UInt32 _AlignSize;
+ UInt32 _BufUseCapacity;
+
+ ISequentialInStream *Stream;
+ UInt64 Processed; // Global offset of start of Buf
+
+ const UInt64 *SearchLimit;
+
+ UInt32 GetTotalCapacity(UInt32 basicSize, UInt32 headerSize)
+ {
+ _HeaderSize = headerSize;
+ for (_AlignSize = (1 << 5); _AlignSize < _HeaderSize; _AlignSize <<= 1);
+ _BufUseCapacity = basicSize + _AlignSize;
+ return _BufUseCapacity + 16;
+ }
+
+ /*
+ returns:
+ S_OK - signature found (at Pos)
+ S_FALSE - signature not found
+ */
+ HRESULT Find();
+};
+
+HRESULT CSignatureFinder::Find()
{
- while (size-- != 0)
- Read8();
+ for (;;)
+ {
+ Buf[End] = Signature[0]; // it's for fast search;
+
+ while (End - Pos >= _HeaderSize)
+ {
+ const Byte *p = Buf + Pos;
+ Byte b = Signature[0];
+ for (;;)
+ {
+ if (*p == b) break; p++;
+ if (*p == b) break; p++;
+ }
+ Pos = (UInt32)(p - Buf);
+ if (End - Pos < _HeaderSize)
+ {
+ Pos = End - _HeaderSize + 1;
+ break;
+ }
+ UInt32 i;
+ for (i = 1; i < SignatureSize && p[i] == Signature[i]; i++);
+ if (i == SignatureSize)
+ return S_OK;
+ Pos++;
+ }
+
+ if (Pos >= _AlignSize)
+ {
+ UInt32 num = (Pos & ~(_AlignSize - 1));
+ Processed += num;
+ Pos -= num;
+ End -= num;
+ memmove(Buf, Buf + num, End);
+ }
+ UInt32 rem = _BufUseCapacity - End;
+ if (SearchLimit)
+ {
+ if (Processed + Pos > *SearchLimit)
+ return S_FALSE;
+ UInt64 rem2 = *SearchLimit - (Processed + End) + _HeaderSize;
+ if (rem > rem2)
+ rem = (UInt32)rem2;
+ }
+
+ UInt32 processedSize;
+ if (Processed == 0 && rem == _BufUseCapacity - _HeaderSize)
+ rem -= _AlignSize; // to make reads more aligned.
+ RINOK(Stream->Read(Buf + End, rem, &processedSize));
+ if (processedSize == 0)
+ return S_FALSE;
+ End += processedSize;
+ }
}
-HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit, CDatabaseEx &db)
+bool CInArcInfo::Parse(const Byte *p)
+{
+ if (Get32(p + 0x0C) != 0 ||
+ Get32(p + 0x14) != 0)
+ return false;
+ Size = Get32(p + 8);
+ if (Size < 36)
+ return false;
+ Flags = Get16(p + 0x1E);
+ if (Flags > 7)
+ return false;
+ FileHeadersOffset = Get32(p + 0x10);
+ if (FileHeadersOffset != 0 && FileHeadersOffset > Size)
+ return false;
+ VersionMinor = p[0x18];
+ VersionMajor = p[0x19];
+ NumFolders = Get16(p + 0x1A);
+ NumFiles = Get16(p + 0x1C);
+ return true;
+}
+
+HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
{
- IInStream *stream = db.Stream;
+ IsArc = false;
+ ErrorInNames = false;
+ UnexpectedEnd = false;
+ HeaderError = false;
+
db.Clear();
- RINOK(stream->Seek(0, STREAM_SEEK_SET, &db.StartPosition));
-
- RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize,
- searchHeaderSizeLimit, db.StartPosition));
-
- RINOK(stream->Seek(db.StartPosition + NHeader::kMarkerSize, STREAM_SEEK_SET, NULL));
- if (!inBuffer.Create(1 << 17))
- return E_OUTOFMEMORY;
- inBuffer.SetStream(stream);
- inBuffer.Init();
-
- CInArchiveInfo &ai = db.ArchiveInfo;
-
- ai.Size = Read32();
- if (Read32() != 0)
- return S_FALSE;
- ai.FileHeadersOffset = Read32();
- if (Read32() != 0)
- return S_FALSE;
-
- ai.VersionMinor = Read8();
- ai.VersionMajor = Read8();
- ai.NumFolders = Read16();
- ai.NumFiles = Read16();
- ai.Flags = Read16();
- if (ai.Flags > 7)
- return S_FALSE;
- ai.SetID = Read16();
- ai.CabinetNumber = Read16();
+ RINOK(db.Stream->Seek(0, STREAM_SEEK_CUR, &db.StartPosition));
+ // UInt64 temp = db.StartPosition;
- if (ai.ReserveBlockPresent())
+ CByteBuffer buffer;
+ CInArcInfo &ai = db.ArcInfo;
+ UInt64 startInBuf = 0;
+
+ CLimitedSequentialInStream *limitedStreamSpec = NULL;
+ CMyComPtr<ISequentialInStream> limitedStream;
+
+ // for (int iii = 0; iii < 10000; iii++)
{
- ai.PerCabinetAreaSize = Read16();
- ai.PerFolderAreaSize = Read8();
- ai.PerDataBlockAreaSize = Read8();
+ // db.StartPosition = temp; RINOK(db.Stream->Seek(db.StartPosition, STREAM_SEEK_SET, NULL));
+
+ const UInt32 kMainHeaderSize = 32;
+ Byte header[kMainHeaderSize];
+ const UInt32 kBufSize = 1 << 15;
+ RINOK(ReadStream_FALSE(db.Stream, header, kMainHeaderSize));
+ if (memcmp(header, NHeader::kMarker, NHeader::kMarkerSize) == 0 && ai.Parse(header))
+ {
+ limitedStreamSpec = new CLimitedSequentialInStream;
+ limitedStream = limitedStreamSpec;
+ limitedStreamSpec->SetStream(db.Stream);
+ limitedStreamSpec->Init(ai.Size - NHeader::kMarkerSize);
+ buffer.Alloc(kBufSize);
+ memcpy(buffer, header, kMainHeaderSize);
+ UInt32 numProcessedBytes;
+ RINOK(limitedStream->Read(buffer + kMainHeaderSize, kBufSize - kMainHeaderSize, &numProcessedBytes));
+ _inBuffer.SetBuf(buffer, (UInt32)kBufSize, kMainHeaderSize + numProcessedBytes, kMainHeaderSize);
+ }
+ else
+ {
+ if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)
+ return S_FALSE;
+
+ CSignatureFinder finder;
+
+ finder.Stream = db.Stream;
+ finder.Signature = NHeader::kMarker;
+ finder.SignatureSize = NHeader::kMarkerSize;
+ finder.SearchLimit = searchHeaderSizeLimit;
- Skip(ai.PerCabinetAreaSize);
+ buffer.Alloc(finder.GetTotalCapacity(kBufSize, kMainHeaderSize));
+ finder.Buf = buffer;
+
+ memcpy(buffer, header, kMainHeaderSize);
+ finder.Processed = db.StartPosition;
+ finder.End = kMainHeaderSize;
+ finder.Pos = 1;
+
+ for (;;)
+ {
+ RINOK(finder.Find());
+ if (ai.Parse(finder.Buf + finder.Pos))
+ {
+ db.StartPosition = finder.Processed + finder.Pos;
+ limitedStreamSpec = new CLimitedSequentialInStream;
+ limitedStreamSpec->SetStream(db.Stream);
+ limitedStream = limitedStreamSpec;
+ UInt32 remInFinder = finder.End - finder.Pos;
+ if (ai.Size <= remInFinder)
+ {
+ limitedStreamSpec->Init(0);
+ finder.End = finder.Pos + ai.Size;
+ }
+ else
+ limitedStreamSpec->Init(ai.Size - remInFinder);
+
+ startInBuf = finder.Pos;
+ _inBuffer.SetBuf(buffer, (UInt32)kBufSize, finder.End, finder.Pos + kMainHeaderSize);
+ break;
+ }
+ finder.Pos++;
+ }
+ }
}
+
+ IsArc = true;
+ _inBuffer.SetStream(limitedStream);
+ if (_tempBuf.Size() == 0)
+ _tempBuf.Alloc(1 << 12);
+
+ Byte p[16];
+ unsigned nextSize = 4 + (ai.ReserveBlockPresent() ? 4 : 0);
+ Read(p, nextSize);
+ ai.SetID = Get16(p);
+ ai.CabinetNumber = Get16(p + 2);
+
+ if (ai.ReserveBlockPresent())
{
- if (ai.IsTherePrev())
- ReadOtherArchive(ai.PrevArc);
- if (ai.IsThereNext())
- ReadOtherArchive(ai.NextArc);
+ ai.PerCabinet_AreaSize = Get16(p + 4);
+ ai.PerFolder_AreaSize = p[6];
+ ai.PerDataBlock_AreaSize = p[7];
+ Skip(ai.PerCabinet_AreaSize);
}
+
+ if (ai.IsTherePrev()) ReadOtherArc(ai.PrevArc);
+ if (ai.IsThereNext()) ReadOtherArc(ai.NextArc);
- int i;
+ UInt32 i;
+ db.Folders.ClearAndReserve(ai.NumFolders);
for (i = 0; i < ai.NumFolders; i++)
{
+ Read(p, 8);
CFolder folder;
-
- folder.DataStart = Read32();
- folder.NumDataBlocks = Read16();
- folder.CompressionTypeMajor = Read8();
- folder.CompressionTypeMinor = Read8();
-
- Skip(ai.PerFolderAreaSize);
- db.Folders.Add(folder);
+ folder.DataStart = Get32(p);
+ folder.NumDataBlocks = Get16(p + 4);
+ folder.MethodMajor = p[6];
+ folder.MethodMinor = p[7];
+ Skip(ai.PerFolder_AreaSize);
+ db.Folders.AddInReserved(folder);
}
- RINOK(stream->Seek(db.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL));
+ // for (int iii = 0; iii < 10000; iii++) {
+
+ if (_inBuffer.GetProcessedSize() - startInBuf != ai.FileHeadersOffset)
+ {
+ // printf("\n!!! Seek Error !!!!\n");
+ // fflush(stdout);
+ RINOK(db.Stream->Seek(db.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL));
+ limitedStreamSpec->Init(ai.Size - ai.FileHeadersOffset);
+ _inBuffer.Init();
+ }
- inBuffer.SetStream(stream);
- inBuffer.Init();
+ db.Items.ClearAndReserve(ai.NumFiles);
for (i = 0; i < ai.NumFiles; i++)
{
- CItem item;
- item.Size = Read32();
- item.Offset = Read32();
- item.FolderIndex = Read16();
- UInt16 pureDate = Read16();
- UInt16 pureTime = Read16();
- item.Time = ((UInt32(pureDate) << 16)) | pureTime;
- item.Attributes = Read16();
- item.Name = SafeReadName();
- int folderIndex = item.GetFolderIndex(db.Folders.Size());
- if (folderIndex >= db.Folders.Size())
+ Read(p, 16);
+ CItem &item = db.Items.AddNewInReserved();
+ item.Size = Get32(p);
+ item.Offset = Get32(p + 4);
+ item.FolderIndex = Get16(p + 8);
+ UInt16 pureDate = Get16(p + 10);
+ UInt16 pureTime = Get16(p + 12);
+ item.Time = (((UInt32)pureDate << 16)) | pureTime;
+ item.Attributes = Get16(p + 14);
+
+ ReadName(item.Name);
+ if (item.GetFolderIndex(db.Folders.Size()) >= (int)db.Folders.Size())
+ {
+ HeaderError = true;
return S_FALSE;
- db.Items.Add(item);
+ }
}
+
+ // }
+
return S_OK;
}
+HRESULT CInArchive::Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)
+{
+ try
+ {
+ return Open2(db, searchHeaderSizeLimit);
+ }
+ catch(const CInBufferException &e) { return e.ErrorCode; }
+ catch(CUnexpectedEndException &) { UnexpectedEnd = true; return S_FALSE; }
+}
+
+
+
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
@@ -161,10 +360,8 @@ static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
const CItem &item2 = db2.Items[p2->ItemIndex];;
bool isDir1 = item1.IsDir();
bool isDir2 = item2.IsDir();
- if (isDir1 && !isDir2)
- return -1;
- if (isDir2 && !isDir1)
- return 1;
+ if (isDir1 && !isDir2) return -1;
+ if (isDir2 && !isDir1) return 1;
int f1 = mvDb.GetFolderIndex(p1);
int f2 = mvDb.GetFolderIndex(p2);
RINOZ(MyCompare(f1, f2));
@@ -174,7 +371,7 @@ static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
return MyCompare(p1->ItemIndex, p2->ItemIndex);
}
-bool CMvDatabaseEx::AreItemsEqual(int i1, int i2)
+bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2)
{
const CMvItem *p1 = &Items[i1];
const CMvItem *p2 = &Items[i2];
@@ -182,10 +379,10 @@ bool CMvDatabaseEx::AreItemsEqual(int i1, int i2)
const CDatabaseEx &db2 = Volumes[p2->VolumeIndex];
const CItem &item1 = db1.Items[p1->ItemIndex];
const CItem &item2 = db2.Items[p2->ItemIndex];;
- return GetFolderIndex(p1) == GetFolderIndex(p2) &&
- item1.Offset == item2.Offset &&
- item1.Size == item2.Size &&
- item1.Name == item2.Name;
+ return GetFolderIndex(p1) == GetFolderIndex(p2)
+ && item1.Offset == item2.Offset
+ && item1.Size == item2.Size
+ && item1.Name == item2.Name;
}
void CMvDatabaseEx::FillSortAndShrink()
@@ -194,7 +391,7 @@ void CMvDatabaseEx::FillSortAndShrink()
StartFolderOfVol.Clear();
FolderStartFileIndex.Clear();
int offset = 0;
- for (int v = 0; v < Volumes.Size(); v++)
+ FOR_VECTOR (v, Volumes)
{
const CDatabaseEx &db = Volumes[v];
int curOffset = offset;
@@ -205,32 +402,35 @@ void CMvDatabaseEx::FillSortAndShrink()
CMvItem mvItem;
mvItem.VolumeIndex = v;
- for (int i = 0 ; i < db.Items.Size(); i++)
+ FOR_VECTOR (i, db.Items)
{
mvItem.ItemIndex = i;
Items.Add(mvItem);
}
}
- Items.Sort(CompareMvItems, (void *)this);
- int j = 1;
- int i;
- for (i = 1; i < Items.Size(); i++)
- if (!AreItemsEqual(i, i -1))
- Items[j++] = Items[i];
- Items.DeleteFrom(j);
+ if (Items.Size() > 1)
+ {
+ Items.Sort(CompareMvItems, (void *)this);
+ unsigned j = 1;
+ unsigned i = 1;
+ for (; i < Items.Size(); i++)
+ if (!AreItemsEqual(i, i - 1))
+ Items[j++] = Items[i];
+ Items.DeleteFrom(j);
+ }
- for (i = 0; i < Items.Size(); i++)
+ FOR_VECTOR (i, Items)
{
int folderIndex = GetFolderIndex(&Items[i]);
- if (folderIndex >= FolderStartFileIndex.Size())
+ if (folderIndex >= (int)FolderStartFileIndex.Size())
FolderStartFileIndex.Add(i);
}
}
bool CMvDatabaseEx::Check()
{
- for (int v = 1; v < Volumes.Size(); v++)
+ for (unsigned v = 1; v < Volumes.Size(); v++)
{
const CDatabaseEx &db1 = Volumes[v];
if (db1.IsTherePrevFolder())
@@ -240,19 +440,19 @@ bool CMvDatabaseEx::Check()
return false;
const CFolder &f0 = db0.Folders.Back();
const CFolder &f1 = db1.Folders.Front();
- if (f0.CompressionTypeMajor != f1.CompressionTypeMajor ||
- f0.CompressionTypeMinor != f1.CompressionTypeMinor)
+ if (f0.MethodMajor != f1.MethodMajor ||
+ f0.MethodMinor != f1.MethodMinor)
return false;
}
}
UInt32 beginPos = 0;
UInt64 endPos = 0;
int prevFolder = -2;
- for (int i = 0; i < Items.Size(); i++)
+ FOR_VECTOR (i, Items)
{
const CMvItem &mvItem = Items[i];
int fIndex = GetFolderIndex(&mvItem);
- if (fIndex >= FolderStartFileIndex.Size())
+ if (fIndex >= (int)FolderStartFileIndex.Size())
return false;
const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
if (item.IsDir())
diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h
index 1e9b188b..4fdab77b 100755..100644
--- a/CPP/7zip/Archive/Cab/CabIn.h
+++ b/CPP/7zip/Archive/Cab/CabIn.h
@@ -3,96 +3,88 @@
#ifndef __ARCHIVE_CAB_IN_H
#define __ARCHIVE_CAB_IN_H
-#include "../../IStream.h"
+#include "../../../Common/MyBuffer.h"
+#include "../../../Common/MyCom.h"
+
#include "../../Common/InBuffer.h"
-#include "CabHeader.h"
+
#include "CabItem.h"
namespace NArchive {
namespace NCab {
-class CInArchiveException
-{
-public:
- enum CCauseType
- {
- kUnexpectedEndOfArchive = 0,
- kIncorrectArchive,
- kUnsupported
- } Cause;
- CInArchiveException(CCauseType cause) : Cause(cause) {}
-};
-
-struct COtherArchive
+struct COtherArc
{
AString FileName;
AString DiskName;
};
-struct CArchiveInfo
+struct CArchInfo
{
- Byte VersionMinor; /* cabinet file format version, minor */
- Byte VersionMajor; /* cabinet file format version, major */
- UInt16 NumFolders; /* number of CFFOLDER entries in this cabinet */
- UInt16 NumFiles; /* number of CFFILE entries in this cabinet */
- UInt16 Flags; /* cabinet file option indicators */
- UInt16 SetID; /* must be the same for all cabinets in a set */
- UInt16 CabinetNumber; /* number of this cabinet file in a set */
-
- bool ReserveBlockPresent() const { return (Flags & NHeader::NArchive::NFlags::kReservePresent) != 0; }
-
- bool IsTherePrev() const { return (Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0; }
- bool IsThereNext() const { return (Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0; }
-
- UInt16 PerCabinetAreaSize; // (optional) size of per-cabinet reserved area
- Byte PerFolderAreaSize; // (optional) size of per-folder reserved area
- Byte PerDataBlockAreaSize; // (optional) size of per-datablock reserved area
-
- Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlockAreaSize : 0); }
-
- COtherArchive PrevArc;
- COtherArchive NextArc;
-
- CArchiveInfo()
+ Byte VersionMinor; // cabinet file format version, minor
+ Byte VersionMajor; // cabinet file format version, major
+ UInt32 NumFolders; // number of CFFOLDER entries in this cabinet
+ UInt32 NumFiles; // number of CFFILE entries in this cabinet
+ UInt32 Flags; // cabinet file option indicators
+ UInt32 SetID; // must be the same for all cabinets in a set
+ UInt32 CabinetNumber; // number of this cabinet file in a set
+
+ UInt16 PerCabinet_AreaSize; // (optional) size of per-cabinet reserved area
+ Byte PerFolder_AreaSize; // (optional) size of per-folder reserved area
+ Byte PerDataBlock_AreaSize; // (optional) size of per-datablock reserved area
+
+ COtherArc PrevArc; // prev link can skip some volumes !!!
+ COtherArc NextArc;
+
+ bool ReserveBlockPresent() const { return (Flags & NHeader::NArcFlags::kReservePresent) != 0; }
+ bool IsTherePrev() const { return (Flags & NHeader::NArcFlags::kPrevCabinet) != 0; }
+ bool IsThereNext() const { return (Flags & NHeader::NArcFlags::kNextCabinet) != 0; }
+ Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlock_AreaSize : 0); }
+
+ CArchInfo()
{
Clear();
}
void Clear()
{
- PerCabinetAreaSize = 0;
- PerFolderAreaSize = 0;
- PerDataBlockAreaSize = 0;
+ PerCabinet_AreaSize = 0;
+ PerFolder_AreaSize = 0;
+ PerDataBlock_AreaSize = 0;
}
};
-struct CInArchiveInfo: public CArchiveInfo
+struct CInArcInfo: public CArchInfo
{
- UInt32 Size; /* size of this cabinet file in bytes */
+ UInt32 Size; // size of this cabinet file in bytes
UInt32 FileHeadersOffset; // offset of the first CFFILE entry
+
+ bool Parse(const Byte *p);
};
struct CDatabase
{
- UInt64 StartPosition;
- CInArchiveInfo ArchiveInfo;
- CObjectVector<CFolder> Folders;
+ CRecordVector<CFolder> Folders;
CObjectVector<CItem> Items;
+ UInt64 StartPosition;
+ CInArcInfo ArcInfo;
void Clear()
{
- ArchiveInfo.Clear();
+ ArcInfo.Clear();
Folders.Clear();
Items.Clear();
}
+
bool IsTherePrevFolder() const
{
- for (int i = 0; i < Items.Size(); i++)
+ FOR_VECTOR (i, Items)
if (Items[i].ContinuedFromPrev())
return true;
return false;
}
+
int GetNumberOfNewFolders() const
{
int res = Folders.Size();
@@ -100,8 +92,6 @@ struct CDatabase
res--;
return res;
}
- UInt32 GetFileOffset(int index) const { return Items[index].Offset; }
- UInt32 GetFileSize(int index) const { return Items[index].Size; }
};
struct CDatabaseEx: public CDatabase
@@ -111,25 +101,27 @@ struct CDatabaseEx: public CDatabase
struct CMvItem
{
- int VolumeIndex;
- int ItemIndex;
+ unsigned VolumeIndex;
+ unsigned ItemIndex;
};
class CMvDatabaseEx
{
- bool AreItemsEqual(int i1, int i2);
+ bool AreItemsEqual(unsigned i1, unsigned i2);
+
public:
CObjectVector<CDatabaseEx> Volumes;
CRecordVector<CMvItem> Items;
- CRecordVector<int> StartFolderOfVol;
- CRecordVector<int> FolderStartFileIndex;
-
+ CRecordVector<int> StartFolderOfVol; // can be negative
+ CRecordVector<unsigned> FolderStartFileIndex;
+
int GetFolderIndex(const CMvItem *mvi) const
{
const CDatabaseEx &db = Volumes[mvi->VolumeIndex];
return StartFolderOfVol[mvi->VolumeIndex] +
db.Items[mvi->ItemIndex].GetFolderIndex(db.Folders.Size());
}
+
void Clear()
{
Volumes.Clear();
@@ -137,23 +129,30 @@ public:
StartFolderOfVol.Clear();
FolderStartFileIndex.Clear();
}
+
void FillSortAndShrink();
bool Check();
};
+
class CInArchive
{
- CInBuffer inBuffer;
+ CInBufferBase _inBuffer;
+ CByteBuffer _tempBuf;
- Byte Read8();
- UInt16 Read16();
- UInt32 Read32();
- AString SafeReadName();
- void Skip(UInt32 size);
- void ReadOtherArchive(COtherArchive &oa);
+ void Skip(unsigned size);
+ void Read(Byte *data, unsigned size);
+ void ReadName(AString &s);
+ void ReadOtherArc(COtherArc &oa);
+ HRESULT Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit);
public:
- HRESULT Open(const UInt64 *searchHeaderSizeLimit, CDatabaseEx &db);
+ bool IsArc;
+ bool ErrorInNames;
+ bool UnexpectedEnd;
+ bool HeaderError;
+
+ HRESULT Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit);
};
}}
diff --git a/CPP/7zip/Archive/Cab/CabItem.h b/CPP/7zip/Archive/Cab/CabItem.h
index 63a1e856..eda62bda 100755..100644
--- a/CPP/7zip/Archive/Cab/CabItem.h
+++ b/CPP/7zip/Archive/Cab/CabItem.h
@@ -3,20 +3,23 @@
#ifndef __ARCHIVE_CAB_ITEM_H
#define __ARCHIVE_CAB_ITEM_H
-#include "Common/Types.h"
-#include "Common/MyString.h"
+#include "../../../Common/MyString.h"
+
#include "CabHeader.h"
namespace NArchive {
namespace NCab {
+const unsigned kNumMethodsMax = 16;
+
struct CFolder
{
UInt32 DataStart; // offset of the first CFDATA block in this folder
UInt16 NumDataBlocks; // number of CFDATA blocks in this folder
- Byte CompressionTypeMajor;
- Byte CompressionTypeMinor;
- Byte GetCompressionMethod() const { return (Byte)(CompressionTypeMajor & 0xF); }
+ Byte MethodMajor;
+ Byte MethodMinor;
+
+ Byte GetMethod() const { return (Byte)(MethodMajor & 0xF); }
};
struct CItem
@@ -25,27 +28,27 @@ struct CItem
UInt32 Offset;
UInt32 Size;
UInt32 Time;
- UInt16 FolderIndex;
+ UInt32 FolderIndex;
UInt16 Flags;
UInt16 Attributes;
UInt64 GetEndOffset() const { return (UInt64)Offset + Size; }
- UInt32 GetWinAttributes() const { return (Attributes & ~NHeader::kFileNameIsUTFAttributeMask); }
- bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUTFAttributeMask) != 0; }
+ UInt32 GetWinAttrib() const { return (UInt32)Attributes & ~(UInt32)NHeader::kFileNameIsUtf8_Mask; }
+ bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUtf8_Mask) != 0; }
bool IsDir() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; }
bool ContinuedFromPrev() const
{
return
- (FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev) ||
- (FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext);
+ FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev ||
+ FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;
}
bool ContinuedToNext() const
{
return
- (FolderIndex == NHeader::NFolderIndex::kContinuedToNext) ||
- (FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext);
+ FolderIndex == NHeader::NFolderIndex::kContinuedToNext ||
+ FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;
}
int GetFolderIndex(int numFolders) const
@@ -53,7 +56,7 @@ struct CItem
if (ContinuedFromPrev())
return 0;
if (ContinuedToNext())
- return (numFolders - 1);
+ return numFolders - 1;
return FolderIndex;
}
};
diff --git a/CPP/7zip/Archive/Cab/CabRegister.cpp b/CPP/7zip/Archive/Cab/CabRegister.cpp
index 15fe4099..acad4c4a 100755..100644
--- a/CPP/7zip/Archive/Cab/CabRegister.cpp
+++ b/CPP/7zip/Archive/Cab/CabRegister.cpp
@@ -5,9 +5,19 @@
#include "../../Common/RegisterArc.h"
#include "CabHandler.h"
-static IInArchive *CreateArc() { return new NArchive::NCab::CHandler; }
+
+namespace NArchive {
+namespace NCab {
+
+IMP_CreateArcIn
static CArcInfo g_ArcInfo =
- { L"Cab", L"cab", 0, 8, { 0x4D, 0x53, 0x43, 0x46 }, 4, false, CreateArc, 0 };
+ { "Cab", "cab", 0, 8,
+ 8, { 'M', 'S', 'C', 'F', 0, 0, 0, 0 },
+ 0,
+ NArcInfoFlags::kFindSignature,
+ CreateArc };
REGISTER_ARC(Cab)
+
+}}
diff --git a/CPP/7zip/Archive/Cab/StdAfx.h b/CPP/7zip/Archive/Cab/StdAfx.h
index e7fb6986..2854ff3e 100755..100644
--- a/CPP/7zip/Archive/Cab/StdAfx.h
+++ b/CPP/7zip/Archive/Cab/StdAfx.h
@@ -3,6 +3,6 @@
#ifndef __STDAFX_H
#define __STDAFX_H
-#include "../../../Common/MyWindows.h"
+#include "../../../Common/Common.h"
#endif