mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-09 00:07:00 -06:00
9.16
This commit is contained in:
committed by
Kornel Lesiński
parent
e279500d76
commit
044e4bb741
@@ -526,7 +526,14 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
|
||||
item.Attrib = attrib;
|
||||
item.Flags = p[12];
|
||||
item.Size = Get32(p + 28);
|
||||
item.Cluster = Get16(p + 26) | ((UInt32)Get16(p + 20) << 16);
|
||||
item.Cluster = Get16(p + 26);
|
||||
if (Header.NumFatBits > 16)
|
||||
item.Cluster |= ((UInt32)Get16(p + 20) << 16);
|
||||
else
|
||||
{
|
||||
// OS/2 and WinNT probably can store EA (extended atributes) in that field.
|
||||
}
|
||||
|
||||
item.CTime = Get32(p + 14);
|
||||
item.CTime2 = p[13];
|
||||
item.ADate = Get16(p + 18);
|
||||
|
||||
@@ -7,15 +7,14 @@
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "../../Common/MethodId.h"
|
||||
#include "../../Common/CreateCoder.h"
|
||||
|
||||
#include "../../Compress/BZip2Decoder.h"
|
||||
#include "../../Compress/DeflateDecoder.h"
|
||||
#include "../../Compress/LzmaDecoder.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NNsis {
|
||||
|
||||
static const CMethodId k_Copy = 0x0;
|
||||
static const CMethodId k_Deflate = 0x040901;
|
||||
static const CMethodId k_BZip2 = 0x040902;
|
||||
static const CMethodId k_LZMA = 0x030101;
|
||||
static const CMethodId k_BCJ_X86 = 0x03030103;
|
||||
|
||||
HRESULT CDecoder::Init(
|
||||
@@ -31,24 +30,14 @@ HRESULT CDecoder::Init(
|
||||
_method = method;
|
||||
if (!_codecInStream)
|
||||
{
|
||||
CMethodId methodID;
|
||||
switch (method)
|
||||
{
|
||||
case NMethodType::kCopy: methodID = k_Copy; break;
|
||||
case NMethodType::kDeflate: methodID = k_Deflate; break;
|
||||
case NMethodType::kBZip2: methodID = k_BZip2; break;
|
||||
case NMethodType::kLZMA: methodID = k_LZMA; break;
|
||||
// case NMethodType::kCopy: return E_NOTIMPL;
|
||||
case NMethodType::kDeflate: _codecInStream = new NCompress::NDeflate::NDecoder::CNsisCOMCoder(); break;
|
||||
case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break;
|
||||
case NMethodType::kLZMA: _codecInStream = new NCompress::NLzma::CDecoder(); break;
|
||||
default: return E_NOTIMPL;
|
||||
}
|
||||
CMyComPtr<ICompressCoder> coder;
|
||||
RINOK(CreateCoder(
|
||||
EXTERNAL_CODECS_LOC_VARS
|
||||
methodID, coder, false));
|
||||
if (!coder)
|
||||
return E_NOTIMPL;
|
||||
coder.QueryInterface(IID_ISequentialInStream, &_codecInStream);
|
||||
if (!_codecInStream)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
if (thereIsFilterFlag)
|
||||
|
||||
@@ -87,7 +87,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * maxCheckStartPosit
|
||||
COM_TRY_BEGIN
|
||||
Close();
|
||||
{
|
||||
if(_archive.Open(
|
||||
if (_archive.Open(
|
||||
EXTERNAL_CODECS_VARS
|
||||
stream, maxCheckStartPosition) != S_OK)
|
||||
return S_FALSE;
|
||||
@@ -264,12 +264,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
bool allFilesMode = (numItems == (UInt32)-1);
|
||||
if (allFilesMode)
|
||||
GetNumberOfItems(&numItems);
|
||||
if(numItems == 0)
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
UInt64 totalSize = 0;
|
||||
|
||||
UInt32 i;
|
||||
for(i = 0; i < numItems; i++)
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
UInt32 index = (allFilesMode ? i : indices[i]);
|
||||
#ifdef NSIS_SCRIPT
|
||||
@@ -313,6 +313,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
byteBuf.SetCapacity(kBufferLength);
|
||||
Byte *buffer = byteBuf;
|
||||
|
||||
CByteBuffer tempBuf;
|
||||
|
||||
bool dataError = false;
|
||||
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
|
||||
{
|
||||
@@ -330,7 +332,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if (index >= (UInt32)_archive.Items.Size())
|
||||
{
|
||||
currentItemSize = _archive.Script.Length();
|
||||
if(!testMode && !realOutStream)
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
if (!testMode)
|
||||
@@ -346,7 +348,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
else
|
||||
GetCompressedSize(index, currentItemSize);
|
||||
|
||||
if(!testMode && !realOutStream)
|
||||
if (!testMode && !realOutStream)
|
||||
continue;
|
||||
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
@@ -357,10 +359,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
bool sizeIsKnown = false;
|
||||
UInt32 fullSize = 0;
|
||||
|
||||
bool writeToTemp = false;
|
||||
bool readFromTemp = false;
|
||||
|
||||
if (_archive.IsSolid)
|
||||
{
|
||||
UInt64 pos = _archive.GetPosOfSolidItem(index);
|
||||
while(streamPos < pos)
|
||||
while (streamPos < pos)
|
||||
{
|
||||
size_t processedSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength);
|
||||
HRESULT res = _archive.Decoder.Read(buffer, &processedSize);
|
||||
@@ -389,7 +394,20 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
fullSize = Get32(buffer2);
|
||||
sizeIsKnown = true;
|
||||
needDecompress = true;
|
||||
|
||||
if (!testMode && i + 1 < numItems)
|
||||
{
|
||||
UInt64 nextPos = _archive.GetPosOfSolidItem(allFilesMode ? i : indices[i + 1]);
|
||||
if (nextPos < streamPos + fullSize)
|
||||
{
|
||||
tempBuf.Free();
|
||||
tempBuf.SetCapacity(fullSize);
|
||||
writeToTemp = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
readFromTemp = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -413,7 +431,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
if (needDecompress)
|
||||
{
|
||||
UInt64 offset = 0;
|
||||
while(!sizeIsKnown || fullSize > 0)
|
||||
while (!sizeIsKnown || fullSize > 0)
|
||||
{
|
||||
UInt32 curSize = kBufferLength;
|
||||
if (sizeIsKnown && curSize > fullSize)
|
||||
@@ -433,6 +451,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
dataError = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (writeToTemp)
|
||||
memcpy((Byte *)tempBuf + (size_t)offset, buffer, processedSize);
|
||||
|
||||
fullSize -= (UInt32)processedSize;
|
||||
streamPos += processedSize;
|
||||
@@ -450,7 +471,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
}
|
||||
else
|
||||
{
|
||||
while(fullSize > 0)
|
||||
if (readFromTemp)
|
||||
{
|
||||
if (!testMode)
|
||||
RINOK(WriteStream(realOutStream, tempBuf, tempBuf.GetCapacity()));
|
||||
}
|
||||
else
|
||||
while (fullSize > 0)
|
||||
{
|
||||
UInt32 curSize = MyMin(fullSize, kBufferLength);
|
||||
UInt32 processedSize;
|
||||
|
||||
@@ -1151,16 +1151,25 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
|
||||
bool sameName = IsUnicode ?
|
||||
(Items[i].NameU == Items[i + 1].NameU) :
|
||||
(Items[i].NameA == Items[i + 1].NameA);
|
||||
if (Items[i].Pos == Items[i + 1].Pos && (IsSolid || sameName))
|
||||
if (Items[i].Pos == Items[i + 1].Pos && sameName)
|
||||
Items.Delete(i + 1);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
for (i = 0; i + 1 < Items.Size(); i++)
|
||||
for (i = 0; i < Items.Size(); i++)
|
||||
{
|
||||
CItem &item = Items[i];
|
||||
item.EstimatedSizeIsDefined = true;
|
||||
item.EstimatedSize = Items[i + 1].Pos - item.Pos - 4;
|
||||
UInt32 curPos = item.Pos + 4;
|
||||
for (int nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++)
|
||||
{
|
||||
UInt32 nextPos = Items[nextIndex].Pos;
|
||||
if (curPos <= nextPos)
|
||||
{
|
||||
item.EstimatedSizeIsDefined = true;
|
||||
item.EstimatedSize = nextPos - curPos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!IsSolid)
|
||||
{
|
||||
@@ -1275,6 +1284,11 @@ static bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool IsBZip2(const Byte *p)
|
||||
{
|
||||
return (p[0] == 0x31 && p[1] < 14);
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open2(
|
||||
DECL_EXTERNAL_CODECS_LOC_VARS2
|
||||
)
|
||||
@@ -1312,7 +1326,14 @@ HRESULT CInArchive::Open2(
|
||||
else if (sig[3] == 0x80)
|
||||
{
|
||||
IsSolid = false;
|
||||
Method = NMethodType::kDeflate;
|
||||
if (IsBZip2(sig + 4))
|
||||
Method = NMethodType::kBZip2;
|
||||
else
|
||||
Method = NMethodType::kDeflate;
|
||||
}
|
||||
else if (IsBZip2(sig))
|
||||
{
|
||||
Method = NMethodType::kBZip2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -107,8 +107,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
if (prop.vt != VT_UI8)
|
||||
return E_INVALIDARG;
|
||||
ui.Size = prop.uhVal.QuadPart;
|
||||
/*
|
||||
// now we support GNU extension for big files
|
||||
if (ui.Size >= ((UInt64)1 << 33))
|
||||
return E_INVALIDARG;
|
||||
*/
|
||||
}
|
||||
updateItems.Add(ui);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "Common/StringToInt.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
@@ -92,7 +94,16 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
|
||||
if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8;
|
||||
if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8;
|
||||
|
||||
RIF(OctalToNumber(p, 12, item.Size)); p += 12;
|
||||
if (GetBe32(p) == (UInt32)1 << 31)
|
||||
{
|
||||
// GNU extension
|
||||
item.Size = GetBe64(p + 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
RIF(OctalToNumber(p, 12, item.Size));
|
||||
}
|
||||
p += 12;
|
||||
RIF(OctalToNumber32(p, 12, item.MTime)); p += 12;
|
||||
|
||||
UInt32 checkSum;
|
||||
|
||||
@@ -53,17 +53,23 @@ static bool MakeOctalString8(char *s, UInt32 value)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool MakeOctalString12(char *s, UInt64 value)
|
||||
static void MakeOctalString12(char *s, UInt64 value)
|
||||
{
|
||||
AString tempString = MakeOctalString(value);
|
||||
const int kMaxSize = 12;
|
||||
if (tempString.Length() > kMaxSize)
|
||||
return false;
|
||||
{
|
||||
// GNU extension;
|
||||
s[0] = (char)(Byte)0x80;
|
||||
s[1] = s[2] = s[3] = 0;
|
||||
for (int i = 0; i < 8; i++, value <<= 8)
|
||||
s[4 + i] = (char)(value >> 56);
|
||||
return;
|
||||
}
|
||||
int numSpaces = kMaxSize - tempString.Length();
|
||||
for(int i = 0; i < numSpaces; i++)
|
||||
s[i] = ' ';
|
||||
memmove(s + numSpaces, (const char *)tempString, tempString.Length());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CopyString(char *dest, const AString &src, int maxSize)
|
||||
@@ -90,17 +96,12 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item)
|
||||
MyStrNCpy(cur, item.Name, NFileHeader::kNameSize);
|
||||
cur += NFileHeader::kNameSize;
|
||||
|
||||
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode));
|
||||
cur += 8;
|
||||
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID));
|
||||
cur += 8;
|
||||
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID));
|
||||
cur += 8;
|
||||
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode)); cur += 8;
|
||||
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); cur += 8;
|
||||
RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID)); cur += 8;
|
||||
|
||||
RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.Size));
|
||||
cur += 12;
|
||||
RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.MTime));
|
||||
cur += 12;
|
||||
MakeOctalString12(cur, item.Size); cur += 12;
|
||||
MakeOctalString12(cur, item.MTime); cur += 12;
|
||||
|
||||
memmove(cur, NFileHeader::kCheckSumBlanks, 8);
|
||||
cur += 8;
|
||||
|
||||
@@ -258,12 +258,23 @@ void CResource::Parse(const Byte *p)
|
||||
|
||||
#define GetResource(p, res) res.Parse(p)
|
||||
|
||||
static void GetStream(const Byte *p, CStreamInfo &s)
|
||||
static void GetStream(bool oldVersion, const Byte *p, CStreamInfo &s)
|
||||
{
|
||||
s.Resource.Parse(p);
|
||||
s.PartNumber = Get16(p + 24);
|
||||
s.RefCount = Get32(p + 26);
|
||||
memcpy(s.Hash, p + 30, kHashSize);
|
||||
if (oldVersion)
|
||||
{
|
||||
s.PartNumber = 1;
|
||||
s.RefCount = 1;
|
||||
// UInt32 id = Get32(p + 24);
|
||||
// UInt32 unknown = Get32(p + 28);
|
||||
memcpy(s.Hash, p + 32, kHashSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
s.PartNumber = Get16(p + 24);
|
||||
s.RefCount = Get32(p + 26);
|
||||
memcpy(s.Hash, p + 30, kHashSize);
|
||||
}
|
||||
}
|
||||
|
||||
static const wchar_t *kLongPath = L"[LongPath]";
|
||||
@@ -386,7 +397,7 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
|
||||
UInt32 fileNameLen = Get16(p + 0x24);
|
||||
if ((fileNameLen & 1) != 0)
|
||||
return S_FALSE;
|
||||
/* Probably different versions of ImageX can use different number of
|
||||
/* Probably different versions of ImageX can use different number of
|
||||
additional ZEROs. So we don't use exact check. */
|
||||
UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
|
||||
if (((0x26 + fileNameLen2 + 6) & ~7) > len)
|
||||
@@ -527,9 +538,7 @@ HRESULT CDatabase::ParseImageDirs(const CByteBuffer &buf, int parent)
|
||||
|
||||
HRESULT CHeader::Parse(const Byte *p)
|
||||
{
|
||||
UInt32 haderSize = Get32(p + 8);
|
||||
if (haderSize < 0x74)
|
||||
return S_FALSE;
|
||||
UInt32 headerSize = Get32(p + 8);
|
||||
Version = Get32(p + 0x0C);
|
||||
Flags = Get32(p + 0x10);
|
||||
if (!IsSupported())
|
||||
@@ -537,25 +546,42 @@ HRESULT CHeader::Parse(const Byte *p)
|
||||
ChunkSize = Get32(p + 0x14);
|
||||
if (ChunkSize != kChunkSize && ChunkSize != 0)
|
||||
return S_FALSE;
|
||||
memcpy(Guid, p + 0x18, 16);
|
||||
PartNumber = Get16(p + 0x28);
|
||||
NumParts = Get16(p + 0x2A);
|
||||
int offset = 0x2C;
|
||||
if (IsNewVersion())
|
||||
int offset;
|
||||
if (IsOldVersion())
|
||||
{
|
||||
NumImages = Get32(p + offset);
|
||||
offset += 4;
|
||||
if (headerSize != 0x60)
|
||||
return S_FALSE;
|
||||
memset(Guid, 0, 16);
|
||||
offset = 0x18;
|
||||
PartNumber = 1;
|
||||
NumParts = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (headerSize < 0x74)
|
||||
return S_FALSE;
|
||||
memcpy(Guid, p + 0x18, 16);
|
||||
PartNumber = Get16(p + 0x28);
|
||||
NumParts = Get16(p + 0x2A);
|
||||
offset = 0x2C;
|
||||
if (IsNewVersion())
|
||||
{
|
||||
NumImages = Get32(p + offset);
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
GetResource(p + offset, OffsetResource);
|
||||
GetResource(p + offset + 0x18, XmlResource);
|
||||
GetResource(p + offset + 0x30, MetadataResource);
|
||||
if (IsNewVersion())
|
||||
{
|
||||
if (haderSize < 0xD0)
|
||||
if (headerSize < 0xD0)
|
||||
return S_FALSE;
|
||||
BootIndex = Get32(p + 0x48);
|
||||
IntegrityResource.Parse(p + offset + 0x4C);
|
||||
}
|
||||
if (IsOldVersion())
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -570,15 +596,16 @@ HRESULT ReadHeader(IInStream *inStream, CHeader &h)
|
||||
return h.Parse(p);
|
||||
}
|
||||
|
||||
static HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)
|
||||
static HRESULT ReadStreams(bool oldVersion, IInStream *inStream, const CHeader &h, CDatabase &db)
|
||||
{
|
||||
CByteBuffer offsetBuf;
|
||||
RINOK(UnpackData(inStream, h.OffsetResource, h.IsLzxMode(), offsetBuf, NULL));
|
||||
size_t i;
|
||||
for (i = 0; offsetBuf.GetCapacity() - i >= kStreamInfoSize; i += kStreamInfoSize)
|
||||
size_t streamInfoSize = oldVersion ? kStreamInfoSize + 2 : kStreamInfoSize;
|
||||
for (i = 0; offsetBuf.GetCapacity() - i >= streamInfoSize; i += streamInfoSize)
|
||||
{
|
||||
CStreamInfo s;
|
||||
GetStream((const Byte *)offsetBuf + i, s);
|
||||
GetStream(oldVersion, (const Byte *)offsetBuf + i, s);
|
||||
if (s.PartNumber == h.PartNumber)
|
||||
db.Streams.Add(s);
|
||||
}
|
||||
@@ -589,7 +616,7 @@ HRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml,
|
||||
{
|
||||
OpenCallback = openCallback;
|
||||
RINOK(UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL));
|
||||
RINOK(ReadStreams(inStream, h, *this));
|
||||
RINOK(ReadStreams(h.IsOldVersion(), inStream, h, *this));
|
||||
bool needBootMetadata = !h.MetadataResource.IsEmpty();
|
||||
Order = 0;
|
||||
if (h.PartNumber == 1)
|
||||
|
||||
@@ -155,6 +155,7 @@ struct CHeader
|
||||
bool IsSupported() const { return (!IsCompressed() || (Flags & NHeaderFlags::kLZX) != 0 || (Flags & NHeaderFlags::kXPRESS) != 0 ) ; }
|
||||
bool IsLzxMode() const { return (Flags & NHeaderFlags::kLZX) != 0; }
|
||||
bool IsSpanned() const { return (!IsCompressed() || (Flags & NHeaderFlags::kSpanned) != 0); }
|
||||
bool IsOldVersion() const { return (Version == 0x010A00); }
|
||||
bool IsNewVersion()const { return (Version > 0x010C00); }
|
||||
|
||||
bool AreFromOnArchive(const CHeader &h)
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace NFileHeader
|
||||
kWzAES = 0x63
|
||||
};
|
||||
const int kNumCompressionMethods = 11;
|
||||
const Byte kMadeByProgramVersion = 20;
|
||||
const Byte kMadeByProgramVersion = 63;
|
||||
|
||||
const Byte kExtractVersion_Default = 10;
|
||||
const Byte kExtractVersion_Dir = 20;
|
||||
|
||||
Reference in New Issue
Block a user