Normalize all the line endings

This commit is contained in:
Tino Reichardt
2020-05-31 13:08:03 +02:00
parent d8345ee3b3
commit 9c3c277ad7
1156 changed files with 292304 additions and 292304 deletions

View File

@@ -1,100 +1,100 @@
// CabBlockInStream.cpp
#include "StdAfx.h"
#include "../../../../C/Alloc.h"
#include "../../../../C/CpuArch.h"
#include "../../Common/StreamUtils.h"
#include "CabBlockInStream.h"
namespace NArchive {
namespace NCab {
static const UInt32 kBlockSize = (1 << 16);
bool CCabBlockInStream::Create()
{
if (!_buf)
_buf = (Byte *)::MyAlloc(kBlockSize);
return _buf != 0;
}
CCabBlockInStream::~CCabBlockInStream()
{
::MyFree(_buf);
}
static UInt32 CheckSum(const Byte *p, UInt32 size)
{
UInt32 sum = 0;
for (; size >= 8; size -= 8)
{
sum ^= GetUi32(p) ^ GetUi32(p + 4);
p += 8;
}
if (size >= 4)
{
sum ^= GetUi32(p);
p += 4;
}
size &= 3;
if (size > 2) sum ^= (UInt32)(*p++) << 16;
if (size > 1) sum ^= (UInt32)(*p++) << 8;
if (size > 0) sum ^= (UInt32)(*p++);
return sum;
}
HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize)
{
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 (_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;
}
if (GetUi32(header) != 0) // checkSum
if (CheckSum(header, kHeaderSize + ReservedSize) != CheckSum(_buf + _size, packSize))
return S_FALSE;
_size += packSize;
return S_OK;
}
STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
if (size != 0)
{
UInt32 rem = _size - _pos;
if (size > rem)
size = rem;
memcpy(data, _buf + _pos, size);
_pos += size;
}
if (processedSize)
*processedSize = size;
return S_OK;
}
}}
// CabBlockInStream.cpp
#include "StdAfx.h"
#include "../../../../C/Alloc.h"
#include "../../../../C/CpuArch.h"
#include "../../Common/StreamUtils.h"
#include "CabBlockInStream.h"
namespace NArchive {
namespace NCab {
static const UInt32 kBlockSize = (1 << 16);
bool CCabBlockInStream::Create()
{
if (!_buf)
_buf = (Byte *)::MyAlloc(kBlockSize);
return _buf != 0;
}
CCabBlockInStream::~CCabBlockInStream()
{
::MyFree(_buf);
}
static UInt32 CheckSum(const Byte *p, UInt32 size)
{
UInt32 sum = 0;
for (; size >= 8; size -= 8)
{
sum ^= GetUi32(p) ^ GetUi32(p + 4);
p += 8;
}
if (size >= 4)
{
sum ^= GetUi32(p);
p += 4;
}
size &= 3;
if (size > 2) sum ^= (UInt32)(*p++) << 16;
if (size > 1) sum ^= (UInt32)(*p++) << 8;
if (size > 0) sum ^= (UInt32)(*p++);
return sum;
}
HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize)
{
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 (_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;
}
if (GetUi32(header) != 0) // checkSum
if (CheckSum(header, kHeaderSize + ReservedSize) != CheckSum(_buf + _size, packSize))
return S_FALSE;
_size += packSize;
return S_OK;
}
STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
if (size != 0)
{
UInt32 rem = _size - _pos;
if (size > rem)
size = rem;
memcpy(data, _buf + _pos, size);
_pos += size;
}
if (processedSize)
*processedSize = size;
return S_OK;
}
}}

View File

@@ -1,43 +1,43 @@
// CabBlockInStream.h
#ifndef __CAB_BLOCK_IN_STREAM_H
#define __CAB_BLOCK_IN_STREAM_H
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
namespace NArchive {
namespace NCab {
class CCabBlockInStream:
public ISequentialInStream,
public CMyUnknownImp
{
Byte *_buf;
UInt32 _size;
UInt32 _pos;
public:
UInt32 ReservedSize; // < 256
bool MsZip;
MY_UNKNOWN_IMP
CCabBlockInStream(): _buf(0), ReservedSize(0), MsZip(false) {}
~CCabBlockInStream();
bool Create();
void InitForNewBlock() { _size = 0; _pos = 0; }
HRESULT PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize);
UInt32 GetPackSizeAvail() const { return _size - _pos; }
const Byte *GetData() const { return _buf + _pos; }
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
}}
#endif
// CabBlockInStream.h
#ifndef __CAB_BLOCK_IN_STREAM_H
#define __CAB_BLOCK_IN_STREAM_H
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
namespace NArchive {
namespace NCab {
class CCabBlockInStream:
public ISequentialInStream,
public CMyUnknownImp
{
Byte *_buf;
UInt32 _size;
UInt32 _pos;
public:
UInt32 ReservedSize; // < 256
bool MsZip;
MY_UNKNOWN_IMP
CCabBlockInStream(): _buf(0), ReservedSize(0), MsZip(false) {}
~CCabBlockInStream();
bool Create();
void InitForNewBlock() { _size = 0; _pos = 0; }
HRESULT PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize);
UInt32 GetPackSizeAvail() const { return _size - _pos; }
const Byte *GetData() const { return _buf + _pos; }
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
}}
#endif

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +1,37 @@
// CabHandler.h
#ifndef __CAB_HANDLER_H
#define __CAB_HANDLER_H
#include "../../../Common/MyCom.h"
#include "../IArchive.h"
#include "CabIn.h"
namespace NArchive {
namespace NCab {
class CHandler:
public IInArchive,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(IInArchive)
INTERFACE_IInArchive(;)
private:
CMvDatabaseEx m_Database;
UString _errorMessage;
bool _isArc;
bool _errorInHeaders;
bool _unexpectedEnd;
// int _mainVolIndex;
UInt32 _phySize;
UInt64 _offset;
};
}}
#endif
// CabHandler.h
#ifndef __CAB_HANDLER_H
#define __CAB_HANDLER_H
#include "../../../Common/MyCom.h"
#include "../IArchive.h"
#include "CabIn.h"
namespace NArchive {
namespace NCab {
class CHandler:
public IInArchive,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(IInArchive)
INTERFACE_IInArchive(;)
private:
CMvDatabaseEx m_Database;
UString _errorMessage;
bool _isArc;
bool _errorInHeaders;
bool _unexpectedEnd;
// int _mainVolIndex;
UInt32 _phySize;
UInt64 _offset;
};
}}
#endif

View File

@@ -1,15 +1,15 @@
// CabHeader.cpp
#include "StdAfx.h"
#include "CabHeader.h"
namespace NArchive {
namespace NCab {
namespace NHeader {
const Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 };
// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; } } g_SignatureInitializer;
}}}
// CabHeader.cpp
#include "StdAfx.h"
#include "CabHeader.h"
namespace NArchive {
namespace NCab {
namespace NHeader {
const Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 };
// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; } } g_SignatureInitializer;
}}}

View File

@@ -1,41 +1,41 @@
// Archive/CabHeader.h
#ifndef __ARCHIVE_CAB_HEADER_H
#define __ARCHIVE_CAB_HEADER_H
#include "../../../Common/MyTypes.h"
namespace NArchive {
namespace NCab {
namespace NHeader {
const unsigned kMarkerSize = 8;
extern const Byte kMarker[kMarkerSize];
namespace NArcFlags
{
const unsigned kPrevCabinet = 1;
const unsigned kNextCabinet = 2;
const unsigned kReservePresent = 4;
}
namespace NMethod
{
const Byte kNone = 0;
const Byte kMSZip = 1;
const Byte kQuantum = 2;
const Byte kLZX = 3;
}
const unsigned kFileNameIsUtf8_Mask = 0x80;
namespace NFolderIndex
{
const unsigned kContinuedFromPrev = 0xFFFD;
const unsigned kContinuedToNext = 0xFFFE;
const unsigned kContinuedPrevAndNext = 0xFFFF;
}
}}}
#endif
// Archive/CabHeader.h
#ifndef __ARCHIVE_CAB_HEADER_H
#define __ARCHIVE_CAB_HEADER_H
#include "../../../Common/MyTypes.h"
namespace NArchive {
namespace NCab {
namespace NHeader {
const unsigned kMarkerSize = 8;
extern const Byte kMarker[kMarkerSize];
namespace NArcFlags
{
const unsigned kPrevCabinet = 1;
const unsigned kNextCabinet = 2;
const unsigned kReservePresent = 4;
}
namespace NMethod
{
const Byte kNone = 0;
const Byte kMSZip = 1;
const Byte kQuantum = 2;
const Byte kLZX = 3;
}
const unsigned kFileNameIsUtf8_Mask = 0x80;
namespace NFolderIndex
{
const unsigned kContinuedFromPrev = 0xFFFD;
const unsigned kContinuedToNext = 0xFFFE;
const unsigned kContinuedPrevAndNext = 0xFFFF;
}
}}}
#endif

View File

@@ -1,491 +1,491 @@
// Archive/CabIn.cpp
#include "StdAfx.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 {
struct CUnexpectedEndException {};
void CInArchive::Skip(unsigned size)
{
if (_inBuffer.Skip(size) != size)
throw CUnexpectedEndException();
}
void CInArchive::Read(Byte *data, unsigned size)
{
if (_inBuffer.ReadBytes(data, size) != size)
throw CUnexpectedEndException();
}
void CInArchive::ReadName(AString &s)
{
for (size_t i = 0; i < ((size_t)1 << 13); i++)
{
Byte b;
if (!_inBuffer.ReadByte(b))
throw CUnexpectedEndException();
if (b == 0)
{
s.SetFrom((const char *)(const Byte *)_tempBuf, (unsigned)i);
return;
}
if (_tempBuf.Size() == i)
_tempBuf.ChangeSize_KeepData(i * 2, i);
_tempBuf[i] = b;
}
for (;;)
{
Byte b;
if (!_inBuffer.ReadByte(b))
throw CUnexpectedEndException();
if (b == 0)
break;
}
ErrorInNames = true;
s = "[ERROR-LONG-PATH]";
}
void CInArchive::ReadOtherArc(COtherArc &oa)
{
ReadName(oa.FileName);
ReadName(oa.DiskName);
}
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()
{
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;
}
}
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)
{
IsArc = false;
ErrorInNames = false;
UnexpectedEnd = false;
HeaderError = false;
db.Clear();
RINOK(db.Stream->Seek(0, STREAM_SEEK_CUR, &db.StartPosition));
// UInt64 temp = db.StartPosition;
CByteBuffer buffer;
CInArcInfo &ai = db.ArcInfo;
UInt64 startInBuf = 0;
CLimitedSequentialInStream *limitedStreamSpec = NULL;
CMyComPtr<ISequentialInStream> limitedStream;
// for (int iii = 0; iii < 10000; iii++)
{
// 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;
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())
{
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);
UInt32 i;
db.Folders.ClearAndReserve(ai.NumFolders);
for (i = 0; i < ai.NumFolders; i++)
{
Read(p, 8);
CFolder 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);
}
// 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();
}
db.Items.ClearAndReserve(ai.NumFiles);
for (i = 0; i < ai.NumFiles; i++)
{
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;
}
}
// }
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)
{
const CMvDatabaseEx &mvDb = *(const CMvDatabaseEx *)param;
const CDatabaseEx &db1 = mvDb.Volumes[p1->VolumeIndex];
const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex];
const CItem &item1 = db1.Items[p1->ItemIndex];
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;
int f1 = mvDb.GetFolderIndex(p1);
int f2 = mvDb.GetFolderIndex(p2);
RINOZ(MyCompare(f1, f2));
RINOZ(MyCompare(item1.Offset, item2.Offset));
RINOZ(MyCompare(item1.Size, item2.Size));
RINOZ(MyCompare(p1->VolumeIndex, p2->VolumeIndex));
return MyCompare(p1->ItemIndex, p2->ItemIndex);
}
bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2)
{
const CMvItem *p1 = &Items[i1];
const CMvItem *p2 = &Items[i2];
const CDatabaseEx &db1 = Volumes[p1->VolumeIndex];
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;
}
void CMvDatabaseEx::FillSortAndShrink()
{
Items.Clear();
StartFolderOfVol.Clear();
FolderStartFileIndex.Clear();
int offset = 0;
FOR_VECTOR (v, Volumes)
{
const CDatabaseEx &db = Volumes[v];
int curOffset = offset;
if (db.IsTherePrevFolder())
curOffset--;
StartFolderOfVol.Add(curOffset);
offset += db.GetNumberOfNewFolders();
CMvItem mvItem;
mvItem.VolumeIndex = v;
FOR_VECTOR (i, db.Items)
{
mvItem.ItemIndex = i;
Items.Add(mvItem);
}
}
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_VECTOR (i, Items)
{
int folderIndex = GetFolderIndex(&Items[i]);
while (folderIndex >= (int)FolderStartFileIndex.Size())
FolderStartFileIndex.Add(i);
}
}
bool CMvDatabaseEx::Check()
{
for (unsigned v = 1; v < Volumes.Size(); v++)
{
const CDatabaseEx &db1 = Volumes[v];
if (db1.IsTherePrevFolder())
{
const CDatabaseEx &db0 = Volumes[v - 1];
if (db0.Folders.IsEmpty() || db1.Folders.IsEmpty())
return false;
const CFolder &f0 = db0.Folders.Back();
const CFolder &f1 = db1.Folders.Front();
if (f0.MethodMajor != f1.MethodMajor ||
f0.MethodMinor != f1.MethodMinor)
return false;
}
}
UInt32 beginPos = 0;
UInt64 endPos = 0;
int prevFolder = -2;
FOR_VECTOR (i, Items)
{
const CMvItem &mvItem = Items[i];
int fIndex = GetFolderIndex(&mvItem);
if (fIndex >= (int)FolderStartFileIndex.Size())
return false;
const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
if (item.IsDir())
continue;
int folderIndex = GetFolderIndex(&mvItem);
if (folderIndex != prevFolder)
prevFolder = folderIndex;
else if (item.Offset < endPos &&
(item.Offset != beginPos || item.GetEndOffset() != endPos))
return false;
beginPos = item.Offset;
endPos = item.GetEndOffset();
}
return true;
}
}}
// Archive/CabIn.cpp
#include "StdAfx.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 {
struct CUnexpectedEndException {};
void CInArchive::Skip(unsigned size)
{
if (_inBuffer.Skip(size) != size)
throw CUnexpectedEndException();
}
void CInArchive::Read(Byte *data, unsigned size)
{
if (_inBuffer.ReadBytes(data, size) != size)
throw CUnexpectedEndException();
}
void CInArchive::ReadName(AString &s)
{
for (size_t i = 0; i < ((size_t)1 << 13); i++)
{
Byte b;
if (!_inBuffer.ReadByte(b))
throw CUnexpectedEndException();
if (b == 0)
{
s.SetFrom((const char *)(const Byte *)_tempBuf, (unsigned)i);
return;
}
if (_tempBuf.Size() == i)
_tempBuf.ChangeSize_KeepData(i * 2, i);
_tempBuf[i] = b;
}
for (;;)
{
Byte b;
if (!_inBuffer.ReadByte(b))
throw CUnexpectedEndException();
if (b == 0)
break;
}
ErrorInNames = true;
s = "[ERROR-LONG-PATH]";
}
void CInArchive::ReadOtherArc(COtherArc &oa)
{
ReadName(oa.FileName);
ReadName(oa.DiskName);
}
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()
{
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;
}
}
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)
{
IsArc = false;
ErrorInNames = false;
UnexpectedEnd = false;
HeaderError = false;
db.Clear();
RINOK(db.Stream->Seek(0, STREAM_SEEK_CUR, &db.StartPosition));
// UInt64 temp = db.StartPosition;
CByteBuffer buffer;
CInArcInfo &ai = db.ArcInfo;
UInt64 startInBuf = 0;
CLimitedSequentialInStream *limitedStreamSpec = NULL;
CMyComPtr<ISequentialInStream> limitedStream;
// for (int iii = 0; iii < 10000; iii++)
{
// 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;
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())
{
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);
UInt32 i;
db.Folders.ClearAndReserve(ai.NumFolders);
for (i = 0; i < ai.NumFolders; i++)
{
Read(p, 8);
CFolder 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);
}
// 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();
}
db.Items.ClearAndReserve(ai.NumFiles);
for (i = 0; i < ai.NumFiles; i++)
{
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;
}
}
// }
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)
{
const CMvDatabaseEx &mvDb = *(const CMvDatabaseEx *)param;
const CDatabaseEx &db1 = mvDb.Volumes[p1->VolumeIndex];
const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex];
const CItem &item1 = db1.Items[p1->ItemIndex];
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;
int f1 = mvDb.GetFolderIndex(p1);
int f2 = mvDb.GetFolderIndex(p2);
RINOZ(MyCompare(f1, f2));
RINOZ(MyCompare(item1.Offset, item2.Offset));
RINOZ(MyCompare(item1.Size, item2.Size));
RINOZ(MyCompare(p1->VolumeIndex, p2->VolumeIndex));
return MyCompare(p1->ItemIndex, p2->ItemIndex);
}
bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2)
{
const CMvItem *p1 = &Items[i1];
const CMvItem *p2 = &Items[i2];
const CDatabaseEx &db1 = Volumes[p1->VolumeIndex];
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;
}
void CMvDatabaseEx::FillSortAndShrink()
{
Items.Clear();
StartFolderOfVol.Clear();
FolderStartFileIndex.Clear();
int offset = 0;
FOR_VECTOR (v, Volumes)
{
const CDatabaseEx &db = Volumes[v];
int curOffset = offset;
if (db.IsTherePrevFolder())
curOffset--;
StartFolderOfVol.Add(curOffset);
offset += db.GetNumberOfNewFolders();
CMvItem mvItem;
mvItem.VolumeIndex = v;
FOR_VECTOR (i, db.Items)
{
mvItem.ItemIndex = i;
Items.Add(mvItem);
}
}
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_VECTOR (i, Items)
{
int folderIndex = GetFolderIndex(&Items[i]);
while (folderIndex >= (int)FolderStartFileIndex.Size())
FolderStartFileIndex.Add(i);
}
}
bool CMvDatabaseEx::Check()
{
for (unsigned v = 1; v < Volumes.Size(); v++)
{
const CDatabaseEx &db1 = Volumes[v];
if (db1.IsTherePrevFolder())
{
const CDatabaseEx &db0 = Volumes[v - 1];
if (db0.Folders.IsEmpty() || db1.Folders.IsEmpty())
return false;
const CFolder &f0 = db0.Folders.Back();
const CFolder &f1 = db1.Folders.Front();
if (f0.MethodMajor != f1.MethodMajor ||
f0.MethodMinor != f1.MethodMinor)
return false;
}
}
UInt32 beginPos = 0;
UInt64 endPos = 0;
int prevFolder = -2;
FOR_VECTOR (i, Items)
{
const CMvItem &mvItem = Items[i];
int fIndex = GetFolderIndex(&mvItem);
if (fIndex >= (int)FolderStartFileIndex.Size())
return false;
const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
if (item.IsDir())
continue;
int folderIndex = GetFolderIndex(&mvItem);
if (folderIndex != prevFolder)
prevFolder = folderIndex;
else if (item.Offset < endPos &&
(item.Offset != beginPos || item.GetEndOffset() != endPos))
return false;
beginPos = item.Offset;
endPos = item.GetEndOffset();
}
return true;
}
}}

View File

@@ -1,176 +1,176 @@
// Archive/CabIn.h
#ifndef __ARCHIVE_CAB_IN_H
#define __ARCHIVE_CAB_IN_H
#include "../../../Common/MyBuffer.h"
#include "../../../Common/MyCom.h"
#include "../../Common/InBuffer.h"
#include "CabItem.h"
namespace NArchive {
namespace NCab {
struct COtherArc
{
AString FileName;
AString DiskName;
void Clear()
{
FileName.Empty();
DiskName.Empty();
}
};
struct CArchInfo
{
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()
{
PerCabinet_AreaSize = 0;
PerFolder_AreaSize = 0;
PerDataBlock_AreaSize = 0;
}
void Clear()
{
PerCabinet_AreaSize = 0;
PerFolder_AreaSize = 0;
PerDataBlock_AreaSize = 0;
PrevArc.Clear();
NextArc.Clear();
}
};
struct CInArcInfo: public CArchInfo
{
UInt32 Size; // size of this cabinet file in bytes
UInt32 FileHeadersOffset; // offset of the first CFFILE entry
bool Parse(const Byte *p);
};
struct CDatabase
{
CRecordVector<CFolder> Folders;
CObjectVector<CItem> Items;
UInt64 StartPosition;
CInArcInfo ArcInfo;
void Clear()
{
ArcInfo.Clear();
Folders.Clear();
Items.Clear();
}
bool IsTherePrevFolder() const
{
FOR_VECTOR (i, Items)
if (Items[i].ContinuedFromPrev())
return true;
return false;
}
int GetNumberOfNewFolders() const
{
int res = Folders.Size();
if (IsTherePrevFolder())
res--;
return res;
}
};
struct CDatabaseEx: public CDatabase
{
CMyComPtr<IInStream> Stream;
};
struct CMvItem
{
unsigned VolumeIndex;
unsigned ItemIndex;
};
class CMvDatabaseEx
{
bool AreItemsEqual(unsigned i1, unsigned i2);
public:
CObjectVector<CDatabaseEx> Volumes;
CRecordVector<CMvItem> Items;
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();
Items.Clear();
StartFolderOfVol.Clear();
FolderStartFileIndex.Clear();
}
void FillSortAndShrink();
bool Check();
};
class CInArchive
{
CInBufferBase _inBuffer;
CByteBuffer _tempBuf;
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:
bool IsArc;
bool ErrorInNames;
bool UnexpectedEnd;
bool HeaderError;
HRESULT Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit);
};
}}
#endif
// Archive/CabIn.h
#ifndef __ARCHIVE_CAB_IN_H
#define __ARCHIVE_CAB_IN_H
#include "../../../Common/MyBuffer.h"
#include "../../../Common/MyCom.h"
#include "../../Common/InBuffer.h"
#include "CabItem.h"
namespace NArchive {
namespace NCab {
struct COtherArc
{
AString FileName;
AString DiskName;
void Clear()
{
FileName.Empty();
DiskName.Empty();
}
};
struct CArchInfo
{
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()
{
PerCabinet_AreaSize = 0;
PerFolder_AreaSize = 0;
PerDataBlock_AreaSize = 0;
}
void Clear()
{
PerCabinet_AreaSize = 0;
PerFolder_AreaSize = 0;
PerDataBlock_AreaSize = 0;
PrevArc.Clear();
NextArc.Clear();
}
};
struct CInArcInfo: public CArchInfo
{
UInt32 Size; // size of this cabinet file in bytes
UInt32 FileHeadersOffset; // offset of the first CFFILE entry
bool Parse(const Byte *p);
};
struct CDatabase
{
CRecordVector<CFolder> Folders;
CObjectVector<CItem> Items;
UInt64 StartPosition;
CInArcInfo ArcInfo;
void Clear()
{
ArcInfo.Clear();
Folders.Clear();
Items.Clear();
}
bool IsTherePrevFolder() const
{
FOR_VECTOR (i, Items)
if (Items[i].ContinuedFromPrev())
return true;
return false;
}
int GetNumberOfNewFolders() const
{
int res = Folders.Size();
if (IsTherePrevFolder())
res--;
return res;
}
};
struct CDatabaseEx: public CDatabase
{
CMyComPtr<IInStream> Stream;
};
struct CMvItem
{
unsigned VolumeIndex;
unsigned ItemIndex;
};
class CMvDatabaseEx
{
bool AreItemsEqual(unsigned i1, unsigned i2);
public:
CObjectVector<CDatabaseEx> Volumes;
CRecordVector<CMvItem> Items;
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();
Items.Clear();
StartFolderOfVol.Clear();
FolderStartFileIndex.Clear();
}
void FillSortAndShrink();
bool Check();
};
class CInArchive
{
CInBufferBase _inBuffer;
CByteBuffer _tempBuf;
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:
bool IsArc;
bool ErrorInNames;
bool UnexpectedEnd;
bool HeaderError;
HRESULT Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit);
};
}}
#endif

View File

@@ -1,66 +1,66 @@
// Archive/CabItem.h
#ifndef __ARCHIVE_CAB_ITEM_H
#define __ARCHIVE_CAB_ITEM_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 MethodMajor;
Byte MethodMinor;
Byte GetMethod() const { return (Byte)(MethodMajor & 0xF); }
};
struct CItem
{
AString Name;
UInt32 Offset;
UInt32 Size;
UInt32 Time;
UInt32 FolderIndex;
UInt16 Flags;
UInt16 Attributes;
UInt64 GetEndOffset() const { return (UInt64)Offset + Size; }
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;
}
bool ContinuedToNext() const
{
return
FolderIndex == NHeader::NFolderIndex::kContinuedToNext ||
FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;
}
int GetFolderIndex(unsigned numFolders) const
{
if (ContinuedFromPrev())
return 0;
if (ContinuedToNext())
return numFolders - 1;
return FolderIndex;
}
};
}}
#endif
// Archive/CabItem.h
#ifndef __ARCHIVE_CAB_ITEM_H
#define __ARCHIVE_CAB_ITEM_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 MethodMajor;
Byte MethodMinor;
Byte GetMethod() const { return (Byte)(MethodMajor & 0xF); }
};
struct CItem
{
AString Name;
UInt32 Offset;
UInt32 Size;
UInt32 Time;
UInt32 FolderIndex;
UInt16 Flags;
UInt16 Attributes;
UInt64 GetEndOffset() const { return (UInt64)Offset + Size; }
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;
}
bool ContinuedToNext() const
{
return
FolderIndex == NHeader::NFolderIndex::kContinuedToNext ||
FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;
}
int GetFolderIndex(unsigned numFolders) const
{
if (ContinuedFromPrev())
return 0;
if (ContinuedToNext())
return numFolders - 1;
return FolderIndex;
}
};
}}
#endif

View File

@@ -1,19 +1,19 @@
// CabRegister.cpp
#include "StdAfx.h"
#include "../../Common/RegisterArc.h"
#include "CabHandler.h"
namespace NArchive {
namespace NCab {
REGISTER_ARC_I(
"Cab", "cab", 0, 8,
NHeader::kMarker,
0,
NArcInfoFlags::kFindSignature,
NULL)
}}
// CabRegister.cpp
#include "StdAfx.h"
#include "../../Common/RegisterArc.h"
#include "CabHandler.h"
namespace NArchive {
namespace NCab {
REGISTER_ARC_I(
"Cab", "cab", 0, 8,
NHeader::kMarker,
0,
NArcInfoFlags::kFindSignature,
NULL)
}}

View File

@@ -1,8 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif