This commit is contained in:
Igor Pavlov
2014-11-23 00:00:00 +00:00
committed by Kornel Lesiński
parent 83f8ddcc5b
commit f08f4dcc3c
1158 changed files with 76451 additions and 35082 deletions

221
CPP/7zip/Archive/Nsis/NsisDecode.cpp Executable file → Normal file
View File

@@ -2,66 +2,65 @@
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "NsisDecode.h"
#include "../../Common/StreamUtils.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/FilterCoder.h"
#include "../../Common/LimitedStreams.h"
#include "../../Common/MethodId.h"
#include "../../Compress/BcjCoder.h"
#include "../../Compress/BZip2Decoder.h"
#include "../../Compress/DeflateDecoder.h"
#include "../../Compress/LzmaDecoder.h"
#define Get32(p) GetUi32(p)
namespace NArchive {
namespace NNsis {
static const CMethodId k_BCJ_X86 = 0x03030103;
HRESULT CDecoder::Init(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter)
HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
{
useFilter = false;
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
if (_decoderInStream)
if (method != _method)
if (Method != _curMethod)
Release();
_method = method;
_curMethod = Method;
if (!_codecInStream)
{
switch (method)
switch (Method)
{
// 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;
case NMethodType::kLZMA:
_lzmaDecoder = new NCompress::NLzma::CDecoder();
_codecInStream = _lzmaDecoder;
break;
default: return E_NOTIMPL;
}
}
if (thereIsFilterFlag)
if (FilterFlag)
{
UInt32 processedSize;
BYTE flag;
RINOK(inStream->Read(&flag, 1, &processedSize));
if (processedSize != 1)
return E_FAIL;
Byte flag;
RINOK(ReadStream_FALSE(inStream, &flag, 1));
if (flag > 1)
return E_NOTIMPL;
useFilter = (flag != 0);
}
if (useFilter)
if (!useFilter)
_decoderInStream = _codecInStream;
else
{
if (!_filterInStream)
{
CMyComPtr<ICompressCoder> coder;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
k_BCJ_X86, coder, false));
if (!coder)
return E_NOTIMPL;
CFilterCoder *coderSpec = new CFilterCoder;
CMyComPtr<ICompressCoder> coder = coderSpec;
coderSpec->Filter = new CBCJ_x86_Decoder();
coder.QueryInterface(IID_ISequentialInStream, &_filterInStream);
if (!_filterInStream)
return E_NOTIMPL;
@@ -73,23 +72,13 @@ HRESULT CDecoder::Init(
RINOK(setInStream->SetInStream(_codecInStream));
_decoderInStream = _filterInStream;
}
else
_decoderInStream = _codecInStream;
if (method == NMethodType::kLZMA)
if (Method == NMethodType::kLZMA)
{
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
_codecInStream.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
if (setDecoderProperties)
{
static const UInt32 kPropertiesSize = 5;
BYTE properties[kPropertiesSize];
UInt32 processedSize;
RINOK(inStream->Read(properties, kPropertiesSize, &processedSize));
if (processedSize != kPropertiesSize)
return E_FAIL;
RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, kPropertiesSize));
}
const unsigned kPropsSize = LZMA_PROPS_SIZE;
Byte props[kPropsSize];
RINOK(ReadStream_FALSE(inStream, props, kPropsSize));
RINOK(_lzmaDecoder->SetDecoderProperties2((const Byte *)props, kPropsSize));
}
{
@@ -122,9 +111,155 @@ HRESULT CDecoder::Init(
return S_OK;
}
HRESULT CDecoder::Read(void *data, size_t *processedSize)
static const UInt32 kMask_IsCompressed = (UInt32)1 << 31;
HRESULT CDecoder::SetToPos(UInt64 pos, ICompressProgressInfo *progress)
{
return ReadStream(_decoderInStream, data, processedSize);;
if (StreamPos > pos)
return E_FAIL;
UInt64 inSizeStart = 0;
if (_lzmaDecoder)
inSizeStart = _lzmaDecoder->GetInputProcessedSize();
UInt64 offset = 0;
while (StreamPos < pos)
{
size_t size = (size_t)MyMin(pos - StreamPos, (UInt64)Buffer.Size());
RINOK(Read(Buffer, &size));
if (size == 0)
return S_FALSE;
StreamPos += size;
offset += size;
UInt64 inSize = 0;
if (_lzmaDecoder)
inSize = _lzmaDecoder->GetInputProcessedSize() - inSizeStart;
RINOK(progress->SetRatioInfo(&inSize, &offset));
}
return S_OK;
}
HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unpackSize,
ISequentialOutStream *realOutStream, ICompressProgressInfo *progress,
UInt32 &packSizeRes, UInt32 &unpackSizeRes)
{
CLimitedSequentialInStream *limitedStreamSpec = NULL;
CMyComPtr<ISequentialInStream> limitedStream;
packSizeRes = 0;
unpackSizeRes = 0;
if (Solid)
{
Byte temp[4];
size_t processedSize = 4;
RINOK(Read(temp, &processedSize));
if (processedSize != 4)
return S_FALSE;
StreamPos += processedSize;
UInt32 size = Get32(temp);
if (unpackSizeDefined && size != unpackSize)
return S_FALSE;
unpackSize = size;
unpackSizeDefined = true;
}
else
{
Byte temp[4];
RINOK(ReadStream_FALSE(InputStream, temp, 4));
StreamPos += 4;
UInt32 size = Get32(temp);
if ((size & kMask_IsCompressed) == 0)
{
if (unpackSizeDefined && size != unpackSize)
return S_FALSE;
packSizeRes = size;
if (outBuf)
outBuf->Alloc(size);
UInt64 offset = 0;
while (size > 0)
{
UInt32 curSize = (UInt32)MyMin((size_t)size, Buffer.Size());
UInt32 processedSize;
RINOK(InputStream->Read(Buffer, curSize, &processedSize));
if (processedSize == 0)
return S_FALSE;
if (outBuf)
memcpy((Byte *)*outBuf + (size_t)offset, Buffer, processedSize);
offset += processedSize;
size -= processedSize;
StreamPos += processedSize;
unpackSizeRes += processedSize;
if (realOutStream)
RINOK(WriteStream(realOutStream, Buffer, processedSize));
RINOK(progress->SetRatioInfo(&offset, &offset));
}
return S_OK;
}
size &= ~kMask_IsCompressed;
packSizeRes = size;
limitedStreamSpec = new CLimitedSequentialInStream;
limitedStream = limitedStreamSpec;
limitedStreamSpec->SetStream(InputStream);
limitedStreamSpec->Init(size);
{
bool useFilter;
RINOK(Init(limitedStream, useFilter));
}
}
if (outBuf)
{
if (!unpackSizeDefined)
return S_FALSE;
outBuf->Alloc(unpackSize);
}
UInt64 inSizeStart = 0;
if (_lzmaDecoder)
inSizeStart = _lzmaDecoder->GetInputProcessedSize();
// we don't allow files larger than 4 GB;
if (!unpackSizeDefined)
unpackSize = 0xFFFFFFFF;
UInt32 offset = 0;
for (;;)
{
size_t rem = unpackSize - offset;
if (rem == 0)
break;
size_t size = Buffer.Size();
if (size > rem)
size = rem;
RINOK(Read(Buffer, &size));
if (size == 0)
{
if (unpackSizeDefined)
return S_FALSE;
break;
}
if (outBuf)
memcpy((Byte *)*outBuf + (size_t)offset, Buffer, size);
StreamPos += size;
offset += (UInt32)size;
UInt64 inSize = 0; // it can be improved: we need inSize for Deflate and BZip2 too.
if (_lzmaDecoder)
inSize = _lzmaDecoder->GetInputProcessedSize() - inSizeStart;
if (Solid)
packSizeRes = (UInt32)inSize;
unpackSizeRes += (UInt32)size;
UInt64 outSize = offset;
RINOK(progress->SetRatioInfo(&inSize, &outSize));
if (realOutStream)
RINOK(WriteStream(realOutStream, Buffer, size));
}
return S_OK;
}
}}

41
CPP/7zip/Archive/Nsis/NsisDecode.h Executable file → Normal file
View File

@@ -3,9 +3,11 @@
#ifndef __NSIS_DECODE_H
#define __NSIS_DECODE_H
#include "../../IStream.h"
#include "../../../Common/MyBuffer.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/StreamUtils.h"
#include "../../Compress/LzmaDecoder.h"
namespace NArchive {
namespace NNsis {
@@ -21,25 +23,50 @@ namespace NMethodType
};
}
/* 7-Zip installers 4.38 - 9.08 used modified version of NSIS that
supported BCJ filter for better compression ratio.
We support such modified NSIS archives. */
class CDecoder
{
NMethodType::EEnum _method;
NMethodType::EEnum _curMethod; // method of created decoder
CMyComPtr<ISequentialInStream> _filterInStream;
CMyComPtr<ISequentialInStream> _codecInStream;
CMyComPtr<ISequentialInStream> _decoderInStream;
NCompress::NLzma::CDecoder *_lzmaDecoder;
public:
CMyComPtr<IInStream> InputStream; // for non-solid
UInt64 StreamPos; // the pos in unpacked for solid, the pos in Packed for non-solid
NMethodType::EEnum Method;
bool FilterFlag;
bool Solid;
CByteBuffer Buffer; // temp buf.
void Release()
{
_filterInStream.Release();
_codecInStream.Release();
_decoderInStream.Release();
InputStream.Release();
_lzmaDecoder = NULL;
}
HRESULT Init(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter);
HRESULT Read(void *data, size_t *processedSize);
HRESULT Init(ISequentialInStream *inStream, bool &useFilter);
HRESULT Read(void *data, size_t *processedSize)
{
return ReadStream(_decoderInStream, data, processedSize);;
}
HRESULT CDecoder::SetToPos(UInt64 pos, ICompressProgressInfo *progress); // for solid
HRESULT Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unpackSize,
ISequentialOutStream *realOutStream, ICompressProgressInfo *progress,
UInt32 &packSizeRes, UInt32 &unpackSizeRes);
};
}}

669
CPP/7zip/Archive/Nsis/NsisHandler.cpp Executable file → Normal file
View File

@@ -4,11 +4,12 @@
#include "../../../../C/CpuArch.h"
#include "Common/ComTry.h"
#include "Common/IntToString.h"
#include "../../../Common/ComTry.h"
#include "../../../Common/IntToString.h"
#include "Windows/PropVariant.h"
#include "../../../Windows/PropVariant.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamUtils.h"
#include "../Common/ItemNameUtils.h"
@@ -27,54 +28,160 @@ static const char *kUnknownMethod = "Unknown";
static const char *kMethods[] =
{
"Copy",
"Deflate",
"BZip2",
"LZMA"
"Copy"
, "Deflate"
, "BZip2"
, "LZMA"
};
static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
static STATPROPSTG kProps[] =
static const Byte kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidPackSize, VT_UI8},
{ NULL, kpidMTime, VT_FILETIME},
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidSolid, VT_BOOL}
kpidPath,
kpidSize,
kpidPackSize,
kpidMTime,
kpidAttrib,
kpidMethod,
kpidSolid,
kpidOffset
};
static STATPROPSTG kArcProps[] =
static const Byte kArcProps[] =
{
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidSolid, VT_BOOL}
kpidMethod,
kpidSolid,
kpidHeadersSize,
kpidEmbeddedStubSize,
kpidSubType
// kpidCodePage
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
static AString UInt32ToString(UInt32 val)
{
char s[16];
ConvertUInt32ToString(val, s);
return s;
}
static AString GetStringForSizeValue(UInt32 val)
{
for (int i = 31; i >= 0; i--)
if (((UInt32)1 << i) == val)
return UInt32ToString(i);
char c = 'b';
if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
return UInt32ToString(val) + c;
}
static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict)
{
AString s;
if (useFilter)
{
s += kBcjMethod;
s += ' ';
}
s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;
if (method == NMethodType::kLZMA)
{
s += ':';
s += GetStringForSizeValue(dict);
}
return s;
}
/*
AString CHandler::GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt32 dictionary) const
{
AString s;
if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter)
{
s += kBcjMethod;
s += ' ';
}
s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;
if (method == NMethodType::kLZMA)
{
s += ':';
s += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: dictionary);
}
return s;
}
*/
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
switch(propID)
NCOM::CPropVariant prop;
switch (propID)
{
case kpidMethod:
// case kpidCodePage: if (_archive.IsUnicode) prop = "UTF-16"; break;
case kpidSubType:
{
UInt32 dict = 1;
bool filter = false;
for (int i = 0; i < _archive.Items.Size(); i++)
AString s = _archive.GetFormatDescription();
if (!_archive.IsInstaller)
{
const CItem &item = _archive.Items[i];
filter |= item.UseFilter;
if (item.DictionarySize > dict)
dict = item.DictionarySize;
if (!s.IsEmpty())
s += ' ';
s += "(Uninstall)";
}
prop = GetMethod(filter, dict);
if (!s.IsEmpty())
prop = s;
break;
}
case kpidMethod: prop = _methodString; break;
case kpidSolid: prop = _archive.IsSolid; break;
case kpidOffset: prop = _archive.StartOffset; break;
case kpidPhySize: prop = _archive.ExeStub.Size() + _archive.FirstHeader.ArcSize; break;
case kpidEmbeddedStubSize: prop = _archive.ExeStub.Size(); break;
case kpidHeadersSize: prop = _archive.FirstHeader.HeaderSize; break;
case kpidErrorFlags:
{
UInt32 v = 0;
if (!_archive.IsArc) v |= kpv_ErrorFlags_IsNotArc;
if (_archive.IsTruncated()) v |= kpv_ErrorFlags_UnexpectedEnd;
prop = v;
break;
}
case kpidName:
{
AString s;
#ifdef NSIS_SCRIPT
if (!_archive.Name.IsEmpty())
s = _archive.Name;
if (!_archive.IsInstaller)
{
if (!s.IsEmpty())
s += '.';
s += "Uninstall";
}
#endif
if (s.IsEmpty())
s = _archive.IsInstaller ? "Install" : "Uninstall";
s += (_archive.ExeStub.Size() == 0) ? ".nsis" : ".exe";
prop = _archive.ConvertToUnicode(s);
break;
}
#ifdef NSIS_SCRIPT
case kpidShortComment:
{
if (!_archive.BrandingText.IsEmpty())
prop = _archive.ConvertToUnicode(_archive.BrandingText);
break;
}
#endif
}
prop.Detach(value);
return S_OK;
@@ -82,16 +189,26 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */)
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */)
{
COM_TRY_BEGIN
Close();
{
if (_archive.Open(
EXTERNAL_CODECS_VARS
stream, maxCheckStartPosition) != S_OK)
if (_archive.Open(stream, maxCheckStartPosition) != S_OK)
return S_FALSE;
_inStream = stream;
{
UInt32 dict = _archive.DictionarySize;
if (!_archive.IsSolid)
{
FOR_VECTOR (i, _archive.Items)
{
const CItem &item = _archive.Items[i];
if (item.DictionarySize > dict)
dict = item.DictionarySize;
}
}
_methodString = GetMethod(_archive.UseFilter, _archive.Method, dict);
}
}
return S_OK;
COM_TRY_END
@@ -101,7 +218,6 @@ STDMETHODIMP CHandler::Close()
{
_archive.Clear();
_archive.Release();
_inStream.Release();
return S_OK;
}
@@ -109,74 +225,30 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = _archive.Items.Size()
#ifdef NSIS_SCRIPT
+ 1
+ 1 + _archive.LicenseFiles.Size();
#endif
;
return S_OK;
}
static AString UInt32ToString(UInt32 value)
{
char buffer[16];
ConvertUInt32ToString(value, buffer);
return buffer;
}
static AString GetStringForSizeValue(UInt32 value)
{
for (int i = 31; i >= 0; i--)
if (((UInt32)1 << i) == value)
return UInt32ToString(i);
char c = 'b';
if (value % (1 << 20) == 0)
{
value >>= 20;
c = 'm';
}
else if (value % (1 << 10) == 0)
{
value >>= 10;
c = 'k';
}
return UInt32ToString(value) + c;
}
AString CHandler::GetMethod(bool useItemFilter, UInt32 dictionary) const
{
NMethodType::EEnum methodIndex = _archive.Method;
AString method;
if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter)
{
method += kBcjMethod;
method += ' ';
}
method += (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
if (methodIndex == NMethodType::kLZMA)
{
method += ':';
method += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: dictionary);
}
return method;
}
bool CHandler::GetUncompressedSize(int index, UInt32 &size)
bool CHandler::GetUncompressedSize(unsigned index, UInt32 &size) const
{
size = 0;
const CItem &item = _archive.Items[index];
if (item.SizeIsDefined)
size = item.Size;
else if (_archive.IsSolid && item.EstimatedSizeIsDefined)
size = item.EstimatedSize;
if (item.Size_Defined)
size = item.Size;
else if (_archive.IsSolid && item.EstimatedSize_Defined)
size = item.EstimatedSize;
else
return false;
return true;
}
bool CHandler::GetCompressedSize(int index, UInt32 &size)
bool CHandler::GetCompressedSize(unsigned index, UInt32 &size) const
{
size = 0;
const CItem &item = _archive.Items[index];
if (item.CompressedSizeIsDefined)
if (item.CompressedSize_Defined)
size = item.CompressedSize;
else
{
@@ -202,27 +274,42 @@ bool CHandler::GetCompressedSize(int index, UInt32 &size)
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
NCOM::CPropVariant prop;
#ifdef NSIS_SCRIPT
if (index >= (UInt32)_archive.Items.Size())
{
switch(propID)
if (index == (UInt32)_archive.Items.Size())
{
case kpidPath: prop = L"[NSIS].nsi"; break;
case kpidSize:
case kpidPackSize: prop = (UInt64)_archive.Script.Length(); break;
case kpidSolid: prop = false; break;
switch (propID)
{
case kpidPath: prop = "[NSIS].nsi"; break;
case kpidSize:
case kpidPackSize: prop = (UInt64)_archive.Script.Len(); break;
case kpidSolid: prop = false; break;
}
}
else
{
const CLicenseFile &lic = _archive.LicenseFiles[index - (_archive.Items.Size() + 1)];
switch (propID)
{
case kpidPath: prop = lic.Name; break;
case kpidSize:
case kpidPackSize: prop = (UInt64)lic.Size; break;
case kpidSolid: prop = false; break;
}
}
}
else
#endif
{
const CItem &item = _archive.Items[index];
switch(propID)
switch (propID)
{
case kpidOffset: prop = item.Pos; break;
case kpidPath:
{
UString s = NItemName::WinNameToOSName(item.GetReducedName(_archive.IsUnicode));
UString s = NItemName::WinNameToOSName(_archive.GetReducedName(index));
if (!s.IsEmpty())
prop = (const wchar_t *)s;
break;
@@ -248,7 +335,21 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = item.MTime;
break;
}
case kpidMethod: prop = GetMethod(item.UseFilter, item.DictionarySize); break;
case kpidAttrib:
{
if (item.Attrib_Defined)
prop = item.Attrib;
break;
}
case kpidMethod:
if (_archive.IsSolid)
prop = _methodString;
else
prop = GetMethod(_archive.UseFilter, item.IsCompressed ? _archive.Method :
NMethodType::kCopy, item.DictionarySize);
break;
case kpidSolid: prop = _archive.IsSolid; break;
}
}
@@ -257,24 +358,56 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END
}
static bool UninstallerPatch(const Byte *p, size_t size, CByteBuffer &dest)
{
for (;;)
{
if (size < 4)
return false;
UInt32 len = Get32(p);
if (len == 0)
return size == 4;
if (size < 8)
return false;
UInt32 offs = Get32(p + 4);
p += 8;
size -= 8;
if (size < len || offs > dest.Size() || len > dest.Size() - offs)
return false;
memcpy(dest + offs, p, len);
p += len;
size -= len;
}
}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)-1);
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
GetNumberOfItems(&numItems);
if (numItems == 0)
return S_OK;
UInt64 totalSize = 0;
UInt64 solidPosMax = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
{
UInt32 index = (allFilesMode ? i : indices[i]);
#ifdef NSIS_SCRIPT
if (index >= (UInt32)_archive.Items.Size())
totalSize += _archive.Script.Length();
if (index >= _archive.Items.Size())
{
if (index == _archive.Items.Size())
totalSize += _archive.Script.Len();
else
totalSize += _archive.LicenseFiles[index - (_archive.Items.Size() + 1)].Size;
}
else
#endif
{
@@ -282,9 +415,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (_archive.IsSolid)
{
GetUncompressedSize(index, size);
UInt64 pos = _archive.GetPosOfSolidItem(index);
if (pos > totalSize)
totalSize = pos + size;
UInt64 pos = (UInt64)_archive.GetPosOfSolidItem(index) + size;
if (solidPosMax < pos)
solidPosMax = pos;
}
else
{
@@ -293,33 +426,58 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
}
}
extractCallback->SetTotal(totalSize);
UInt64 currentTotalSize = 0;
UInt32 currentItemSize = 0;
extractCallback->SetTotal(totalSize + solidPosMax);
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, !_archive.IsSolid);
UInt64 streamPos = 0;
if (_archive.IsSolid)
{
RINOK(_inStream->Seek(_archive.StreamOffset, STREAM_SEEK_SET, NULL));
bool useFilter;
RINOK(_archive.Decoder.Init(
EXTERNAL_CODECS_VARS
_inStream, _archive.Method, _archive.FilterFlag, useFilter));
RINOK(_archive.SeekTo_DataStreamOffset());
RINOK(_archive.InitDecoder());
_archive.Decoder.StreamPos = 0;
}
CByteBuffer byteBuf;
const UInt32 kBufferLength = 1 << 16;
byteBuf.SetCapacity(kBufferLength);
Byte *buffer = byteBuf;
/* We use tempBuf for solid archives, if there is duplicate item.
We don't know uncompressed size for non-solid archives, so we can't
allocate exact buffer.
We use tempBuf also for first part (EXE stub) of unistall.exe
and tempBuf2 is used for second part (NSIS script). */
CByteBuffer tempBuf;
CByteBuffer tempBuf2;
/* tempPos is pos in uncompressed stream of previous item for solid archive, that
was written to tempBuf */
UInt64 tempPos = (UInt64)(Int64)-1;
/* prevPos is pos in uncompressed stream of previous item for solid archive.
It's used for test mode (where we don't need to test same file second time */
UInt64 prevPos = (UInt64)(Int64)-1;
// if there is error in solid archive, we show error for all subsequent files
bool solidDataError = false;
bool dataError = false;
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
UInt64 curTotalPacked = 0, curTotalUnpacked = 0;
UInt32 curPacked = 0;
UInt64 curUnpacked = 0;
for (i = 0; i < numItems; i++,
curTotalPacked += curPacked,
curTotalUnpacked += curUnpacked)
{
currentItemSize = 0;
RINOK(extractCallback->SetCompleted(&currentTotalSize));
lps->InSize = curTotalPacked;
lps->OutSize = curTotalUnpacked;
if (_archive.IsSolid)
lps->OutSize += _archive.Decoder.StreamPos;
curPacked = 0;
curUnpacked = 0;
RINOK(lps->SetCur());
// RINOK(extractCallback->SetCompleted(&currentTotalSize));
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
@@ -328,169 +486,184 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
bool dataError = false;
#ifdef NSIS_SCRIPT
if (index >= (UInt32)_archive.Items.Size())
{
currentItemSize = _archive.Script.Length();
const void *data;
size_t size;
if (index == (UInt32)_archive.Items.Size())
{
data = (const Byte *)_archive.Script;
size = _archive.Script.Len();
}
else
{
CLicenseFile &lic = _archive.LicenseFiles[index - (_archive.Items.Size() + 1)];
if (lic.Text.Size() != 0)
data = lic.Text;
else
data = _archive._data + lic.Offset;
size = lic.Size;
}
curUnpacked = size;
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
if (!testMode)
RINOK(WriteStream(realOutStream, (const char *)_archive.Script, (UInt32)_archive.Script.Length()));
if (realOutStream)
RINOK(WriteStream(realOutStream, data, size));
}
else
#endif
{
const CItem &item = _archive.Items[index];
if (_archive.IsSolid)
GetUncompressedSize(index, currentItemSize);
else
GetCompressedSize(index, currentItemSize);
if (!_archive.IsSolid)
GetCompressedSize(index, curPacked);
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
if (!dataError)
{
bool needDecompress = false;
bool sizeIsKnown = false;
UInt32 fullSize = 0;
dataError = solidDataError;
bool needDecompress = !solidDataError;
if (needDecompress)
{
if (testMode && _archive.IsSolid && _archive.GetPosOfSolidItem(index) == prevPos)
needDecompress = false;
}
if (needDecompress)
{
bool writeToTemp = false;
bool readFromTemp = false;
if (_archive.IsSolid)
if (!_archive.IsSolid)
{
RINOK(_archive.SeekToNonSolidItem(index));
}
else
{
UInt64 pos = _archive.GetPosOfSolidItem(index);
while (streamPos < pos)
if (pos < _archive.Decoder.StreamPos)
{
size_t processedSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength);
HRESULT res = _archive.Decoder.Read(buffer, &processedSize);
if (pos != tempPos)
solidDataError = dataError = true;
readFromTemp = true;
}
else
{
HRESULT res = _archive.Decoder.SetToPos(pos, progress);
if (res != S_OK)
{
if (res != S_FALSE)
return res;
solidDataError = dataError = true;
}
else if (!testMode && i + 1 < numItems)
{
UInt32 next = allFilesMode ? i + 1 : indices[i + 1];
if (next < _archive.Items.Size())
{
UInt64 nextPos = _archive.GetPosOfSolidItem(next);
if (nextPos == pos)
{
writeToTemp = true;
tempPos = pos;
}
}
}
}
prevPos = pos;
}
if (!dataError)
{
UInt32 unpackSize = 0;
bool unpackSize_Defined = false;
bool writeToTemp1 = writeToTemp;
if (item.IsUninstaller)
{
unpackSize = item.PatchSize;
unpackSize_Defined = true;
if (!readFromTemp)
writeToTemp = true;
writeToTemp1 = writeToTemp;
if (_archive.ExeStub.Size() == 0)
{
if (writeToTemp1 && !readFromTemp)
tempBuf.Free();
writeToTemp1 = false;
}
}
if (readFromTemp)
{
if (realOutStream && !item.IsUninstaller)
RINOK(WriteStream(realOutStream, tempBuf, tempBuf.Size()));
}
else
{
UInt32 curUnpacked32 = 0;
HRESULT res = _archive.Decoder.Decode(
writeToTemp1 ? &tempBuf : NULL,
item.IsUninstaller, item.PatchSize,
item.IsUninstaller ? NULL : realOutStream,
progress,
curPacked, curUnpacked32);
curUnpacked = curUnpacked32;
if (_archive.IsSolid)
curUnpacked = 0;
if (res != S_OK)
{
if (res != S_FALSE)
return res;
dataError = true;
break;
}
if (processedSize == 0)
{
dataError = true;
break;
}
streamPos += processedSize;
}
if (streamPos == pos)
{
Byte buffer2[4];
size_t processedSize = 4;
RINOK(_archive.Decoder.Read(buffer2, &processedSize));
if (processedSize != 4)
return E_FAIL;
streamPos += processedSize;
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
{
RINOK(_inStream->Seek(_archive.GetPosOfNonSolidItem(index) + 4, STREAM_SEEK_SET, NULL));
if (item.IsCompressed)
{
needDecompress = true;
bool useFilter;
RINOK(_archive.Decoder.Init(
EXTERNAL_CODECS_VARS
_inStream, _archive.Method, _archive.FilterFlag, useFilter));
// fullSize = Get32(buffer); // It's bug !!!
// Test it: what is exact fullSize?
fullSize = 0xFFFFFFFF;
}
else
fullSize = item.Size;
}
if (!dataError)
{
if (needDecompress)
{
UInt64 offset = 0;
while (!sizeIsKnown || fullSize > 0)
{
UInt32 curSize = kBufferLength;
if (sizeIsKnown && curSize > fullSize)
curSize = fullSize;
size_t processedSize = curSize;
HRESULT res = _archive.Decoder.Read(buffer, &processedSize);
if (res != S_OK)
{
if (res != S_FALSE)
return res;
dataError = true;
break;
}
if (processedSize == 0)
{
if (sizeIsKnown)
dataError = true;
break;
}
if (writeToTemp)
memcpy((Byte *)tempBuf + (size_t)offset, buffer, processedSize);
fullSize -= (UInt32)processedSize;
streamPos += processedSize;
offset += processedSize;
UInt64 completed;
if (_archive.IsSolid)
completed = currentTotalSize + offset;
else
completed = streamPos;
RINOK(extractCallback->SetCompleted(&completed));
if (!testMode)
RINOK(WriteStream(realOutStream, buffer, processedSize));
solidDataError = true;
}
}
}
if (!dataError && item.IsUninstaller)
{
if (_archive.ExeStub.Size() != 0)
{
CByteBuffer destBuf = _archive.ExeStub;
dataError = !UninstallerPatch(tempBuf, tempBuf.Size(), destBuf);
if (realOutStream)
RINOK(WriteStream(realOutStream, destBuf, destBuf.Size()));
}
if (readFromTemp)
{
if (realOutStream)
RINOK(WriteStream(realOutStream, tempBuf2, tempBuf2.Size()));
}
else
{
if (readFromTemp)
UInt32 curPacked2 = 0;
UInt32 curUnpacked2 = 0;
HRESULT res = _archive.Decoder.Decode(
writeToTemp ? &tempBuf2 : NULL,
false, 0,
realOutStream,
progress,
curPacked2, curUnpacked2);
curPacked += curPacked2;
if (!_archive.IsSolid)
curUnpacked += curUnpacked2;
if (res != S_OK)
{
if (!testMode)
RINOK(WriteStream(realOutStream, tempBuf, tempBuf.GetCapacity()));
}
else
while (fullSize > 0)
{
UInt32 curSize = MyMin(fullSize, kBufferLength);
UInt32 processedSize;
RINOK(_inStream->Read(buffer, curSize, &processedSize));
if (processedSize == 0)
{
dataError = true;
break;
}
fullSize -= processedSize;
streamPos += processedSize;
if (!testMode)
RINOK(WriteStream(realOutStream, buffer, processedSize));
if (res != S_FALSE)
return res;
dataError = true;
if (_archive.IsSolid)
solidDataError = true;
}
}
}
@@ -505,6 +678,4 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
IMPL_ISetCompressCodecsInfo
}}

25
CPP/7zip/Archive/Nsis/NsisHandler.h Executable file → Normal file
View File

@@ -3,39 +3,32 @@
#ifndef __NSIS_HANDLER_H
#define __NSIS_HANDLER_H
#include "Common/MyCom.h"
#include "../../../Common/MyCom.h"
#include "../../Common/CreateCoder.h"
#include "../IArchive.h"
#include "NsisIn.h"
#include "../../Common/CreateCoder.h"
namespace NArchive {
namespace NNsis {
class CHandler:
public IInArchive,
PUBLIC_ISetCompressCodecsInfo
public CMyUnknownImp
{
CMyComPtr<IInStream> _inStream;
CInArchive _archive;
AString _methodString;
DECL_EXTERNAL_CODECS_VARS
bool GetUncompressedSize(unsigned index, UInt32 &size) const;
bool GetCompressedSize(unsigned index, UInt32 &size) const;
bool GetUncompressedSize(int index, UInt32 &size);
bool GetCompressedSize(int index, UInt32 &size);
AString GetMethod(bool useItemFilter, UInt32 dictionary) const;
// AString GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt32 dictionary) const;
public:
MY_QUERYINTERFACE_BEGIN2(IInArchive)
QUERY_ENTRY_ISetCompressCodecsInfo
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
MY_UNKNOWN_IMP1(IInArchive)
INTERFACE_IInArchive(;)
DECL_ISetCompressCodecsInfo
};
}}

6599
CPP/7zip/Archive/Nsis/NsisIn.cpp Executable file → Normal file
View File

File diff suppressed because it is too large Load Diff

431
CPP/7zip/Archive/Nsis/NsisIn.h Executable file → Normal file
View File

@@ -3,21 +3,28 @@
#ifndef __ARCHIVE_NSIS_IN_H
#define __ARCHIVE_NSIS_IN_H
#include "Common/Buffer.h"
#include "Common/MyCom.h"
#include "Common/StringConvert.h"
#include "../../../../C/CpuArch.h"
#include "../../../Common/DynLimBuf.h"
#include "../../../Common/MyBuffer.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/UTFConvert.h"
#include "NsisDecode.h"
// #define NSIS_SCRIPT
/* If NSIS_SCRIPT is defined, it will decompile NSIS script to [NSIS].nsi file.
The code is much larger in that case. */
#define NSIS_SCRIPT
namespace NArchive {
namespace NNsis {
const int kSignatureSize = 16;
#define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 0x4E, 0x75, 0x6C, 0x6C, 0x73, 0x6F, 0x66, 0x74, 0x49, 0x6E, 0x73, 0x74}
const size_t kScriptSizeLimit = 1 << 27;
extern Byte kSignature[kSignatureSize];
const unsigned kSignatureSize = 16;
#define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 'N', 'u', 'l', 'l', 's', 'o', 'f', 't', 'I', 'n', 's', 't' }
const UInt32 kFlagsMask = 0xF;
namespace NFlags
@@ -31,18 +38,17 @@ namespace NFlags
struct CFirstHeader
{
UInt32 Flags;
UInt32 HeaderLength;
UInt32 ArchiveSize;
UInt32 HeaderSize;
UInt32 ArcSize;
bool ThereIsCrc() const
{
if ((Flags & NFlags::kForceCrc ) != 0)
return true;
return ((Flags & NFlags::kNoCrc) == 0);
return
(Flags & NFlags::kForceCrc) != 0 ||
(Flags & NFlags::kNoCrc) == 0;
}
UInt32 GetDataSize() const { return ArchiveSize - (ThereIsCrc() ? 4 : 0); }
UInt32 GetDataSize() const { return ArcSize - (ThereIsCrc() ? 4 : 0); }
};
@@ -50,123 +56,330 @@ struct CBlockHeader
{
UInt32 Offset;
UInt32 Num;
void Parse(const Byte *p)
{
Offset = GetUi32(p);
Num = GetUi32(p + 4);
}
};
struct CItem
{
AString PrefixA;
UString PrefixU;
AString NameA;
UString NameU;
FILETIME MTime;
bool IsUnicode;
bool UseFilter;
bool IsCompressed;
bool SizeIsDefined;
bool CompressedSizeIsDefined;
bool EstimatedSizeIsDefined;
bool Size_Defined;
bool CompressedSize_Defined;
bool EstimatedSize_Defined;
bool Attrib_Defined;
bool IsUninstaller;
// bool UseFilter;
UInt32 Attrib;
UInt32 Pos;
UInt32 Size;
UInt32 CompressedSize;
UInt32 EstimatedSize;
UInt32 DictionarySize;
CItem(): IsUnicode(false), UseFilter(false), IsCompressed(true), SizeIsDefined(false),
CompressedSizeIsDefined(false), EstimatedSizeIsDefined(false), Size(0), DictionarySize(1) {}
UInt32 PatchSize; // for Uninstaller.exe
int Prefix; // - 1 means no prefix
FILETIME MTime;
AString NameA;
UString NameU;
CItem():
IsCompressed(true),
Size_Defined(false),
CompressedSize_Defined(false),
EstimatedSize_Defined(false),
Attrib_Defined(false),
IsUninstaller(false),
// UseFilter(false),
Attrib(0),
Pos(0),
Size(0),
CompressedSize(0),
EstimatedSize(0),
DictionarySize(1),
PatchSize(0),
Prefix(-1)
{
MTime.dwLowDateTime = 0;
MTime.dwHighDateTime = 0;
}
/*
bool IsINSTDIR() const
{
return (PrefixA.Length() >= 3 || PrefixU.Length() >= 3);
}
UString GetReducedName(bool unicode) const
{
UString s;
if (unicode)
s = PrefixU;
else
s = MultiByteToUnicodeString(PrefixA);
if (s.Length() > 0)
if (s.Back() != L'\\')
s += L'\\';
if (unicode)
s += NameU;
else
s += MultiByteToUnicodeString(NameA);
const int len = 9;
if (s.Left(len).CompareNoCase(L"$INSTDIR\\") == 0)
s = s.Mid(len);
return s;
return (PrefixA.Len() >= 3 || PrefixU.Len() >= 3);
}
*/
};
enum ENsisType
{
k_NsisType_Nsis2,
k_NsisType_Nsis3,
k_NsisType_Park1, // Park 2.46.1-
k_NsisType_Park2, // Park 2.46.2 : GetFontVersion
k_NsisType_Park3 // Park 2.46.3+ : GetFontName
};
#ifdef NSIS_SCRIPT
struct CSection
{
UInt32 InstallTypes; // bits set for each of the different install_types, if any.
UInt32 Flags; // SF_* - defined above
UInt32 StartCmdIndex; // code;
UInt32 NumCommands; // code_size;
UInt32 SizeKB;
UInt32 Name;
void Parse(const Byte *data);
};
struct CLicenseFile
{
UInt32 Offset;
UInt32 Size;
AString Name;
CByteBuffer Text;
};
#endif
class CInArchive
{
UInt64 _archiveSize;
CMyComPtr<IInStream> _stream;
Byte ReadByte();
UInt32 ReadUInt32();
HRESULT Open2(
DECL_EXTERNAL_CODECS_LOC_VARS2
);
void ReadBlockHeader(CBlockHeader &bh);
AString ReadStringA(UInt32 pos) const;
UString ReadStringU(UInt32 pos) const;
AString ReadString2A(UInt32 pos) const;
UString ReadString2U(UInt32 pos) const;
AString ReadString2(UInt32 pos) const;
AString ReadString2Qw(UInt32 pos) const;
HRESULT ReadEntries(const CBlockHeader &bh);
HRESULT Parse();
public:
#ifdef NSIS_SCRIPT
CDynLimBuf Script;
#endif
CByteBuffer _data;
UInt64 _size;
CObjectVector<CItem> Items;
bool IsUnicode;
private:
UInt32 _stringsPos; // relative to _data
UInt32 NumStringChars;
size_t _size; // it's Header Size
size_t _posInData;
AString Raw_AString;
UString Raw_UString;
UInt32 _stringsPos;
ENsisType NsisType;
bool IsNsis200; // NSIS 2.03 and before
bool IsNsis225; // NSIS 2.25 and before
bool LogCmdIsEnabled;
int BadCmd; // -1: no bad command; in another cases lowest bad command id
bool IsPark() const { return NsisType >= k_NsisType_Park1; }
UInt64 _fileSize;
bool _headerIsCompressed;
UInt32 _nonSolidStartOffset;
public:
HRESULT Open(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream, const UInt64 *maxCheckStartPosition);
void Clear();
UInt64 StreamOffset;
#ifdef NSIS_SCRIPT
CByteBuffer strUsed;
CBlockHeader bhPages;
CBlockHeader bhSections;
CBlockHeader bhCtlColors;
CBlockHeader bhData;
UInt32 AfterHeaderSize;
CByteBuffer _afterHeader;
UInt32 SectionSize;
const Byte *_mainLang;
UInt32 _numLangStrings;
AString LangComment;
CRecordVector<UInt32> langStrIDs;
UInt32 numOnFunc;
UInt32 onFuncOffset;
// CRecordVector<UInt32> OnFuncs;
unsigned _numRootLicenses;
CRecordVector<UInt32> noParseStringIndexes;
AString _tempString_for_GetVar;
AString _tempString_for_AddFuncName;
AString _tempString;
#endif
public:
CMyComPtr<IInStream> _stream; // it's limited stream that contains only NSIS archive
UInt64 StartOffset; // offset in original stream.
UInt64 DataStreamOffset; // = sizeof(FirstHeader) = offset of Header in _stream
bool IsArc;
CDecoder Decoder;
CObjectVector<CItem> Items;
CByteBuffer ExeStub;
CFirstHeader FirstHeader;
NMethodType::EEnum Method;
UInt32 DictionarySize;
bool IsSolid;
bool UseFilter;
bool FilterFlag;
bool IsUnicode;
bool IsInstaller;
AString Name;
AString BrandingText;
UStringVector UPrefixes;
AStringVector APrefixes;
#ifdef NSIS_SCRIPT
AString Script;
CObjectVector<CLicenseFile> LicenseFiles;
#endif
UInt32 GetOffset() const { return IsSolid ? 4 : 0; }
UInt64 GetDataPos(int index)
private:
void GetShellString(AString &s, unsigned index1, unsigned index2);
void GetNsisString_Raw(const Byte *s);
void GetNsisString_Unicode_Raw(const Byte *s);
void ReadString2_Raw(UInt32 pos);
bool IsGoodString(UInt32 param) const;
bool AreTwoParamStringsEqual(UInt32 param1, UInt32 param2) const;
void Add_LangStr(AString &res, UInt32 id);
#ifdef NSIS_SCRIPT
void Add_UInt(UInt32 v);
void AddLicense(UInt32 param, Int32 langID);
void Add_LangStr_Simple(UInt32 id);
void Add_FuncName(const UInt32 *labels, UInt32 index);
void AddParam_Func(const UInt32 *labels, UInt32 index);
void Add_LabelName(UInt32 index);
void Add_Color2(UInt32 v);
void Add_ColorParam(UInt32 v);
void Add_Color(UInt32 index);
void Add_ButtonID(UInt32 buttonID);
void Add_ShowWindow_Cmd(UInt32 cmd);
void Add_TypeFromList(const char **table, unsigned tableSize, UInt32 type);
void Add_ExecFlags(UInt32 flagsType);
void Add_SectOp(UInt32 opType);
void Add_Var(UInt32 index);
void AddParam_Var(UInt32 value);
void AddParam_UInt(UInt32 value);
void Add_GotoVar(UInt32 param);
void Add_GotoVar1(UInt32 param);
void Add_GotoVars2(const UInt32 *params);
bool PrintSectionBegin(const CSection &sect, unsigned index);
void PrintSectionEnd();
void GetNsisString(AString &res, const Byte *s);
void GetNsisString_Unicode(AString &res, const Byte *s);
UInt32 GetNumUsedVars() const;
void ReadString2(AString &s, UInt32 pos);
void MessageBox_MB_Part(UInt32 param);
void AddParam(UInt32 pos);
void AddOptionalParam(UInt32 pos);
void AddParams(const UInt32 *params, unsigned num);
void AddPageOption1(UInt32 param, const char *name);
void AddPageOption(const UInt32 *params, unsigned num, const char *name);
void AddOptionalParams(const UInt32 *params, unsigned num);
void AddRegRoot(UInt32 value);
void ClearLangComment();
void Separator();
void Space();
void Tab();
void Tab(bool commented);
void BigSpaceComment();
void SmallSpaceComment();
void AddCommentAndString(const char *s);
void AddError(const char *s);
void AddErrorLF(const char *s);
void CommentOpen();
void CommentClose();
void AddLF();
void AddQuotes();
void TabString(const char *s);
void AddStringLF(const char *s);
void NewLine();
void PrintNumComment(const char *name, UInt32 value);
void Add_QuStr(const AString &s);
void SpaceQuStr(const AString &s);
bool CompareCommands(const Byte *rawCmds, const Byte *sequence, size_t numCommands);
#endif
#ifdef NSIS_SCRIPT
unsigned GetNumSupportedCommands() const;
#endif
UInt32 GetCmd(UInt32 a);
void FindBadCmd(const CBlockHeader &bh, const Byte *);
void DetectNsisType(const CBlockHeader &bh, const Byte *);
HRESULT ReadEntries(const CBlockHeader &bh);
HRESULT SortItems();
HRESULT Parse();
HRESULT Open2(const Byte *data, size_t size);
void Clear2();
void GetVar2(AString &res, UInt32 index);
void GetVar(AString &res, UInt32 index);
Int32 GetVarIndex(UInt32 strPos) const;
Int32 GetVarIndex(UInt32 strPos, UInt32 &resOffset) const;
Int32 GetVarIndexFinished(UInt32 strPos, Byte endChar, UInt32 &resOffset) const;
bool IsVarStr(UInt32 strPos, UInt32 varIndex) const;
bool IsAbsolutePathVar(UInt32 strPos) const;
void SetItemName(CItem &item, UInt32 strPos);
public:
HRESULT Open(IInStream *inStream, const UInt64 *maxCheckStartPosition);
AString GetFormatDescription() const;
HRESULT InitDecoder()
{
const CItem &item = Items[index];
return GetOffset() + FirstHeader.HeaderLength + item.Pos;
bool useFilter;
return Decoder.Init(_stream, useFilter);
}
UInt64 GetPosOfSolidItem(int index) const
HRESULT SeekTo_DataStreamOffset()
{
return _stream->Seek(DataStreamOffset, STREAM_SEEK_SET, NULL);
}
HRESULT SeekToNonSolidItem(unsigned index)
{
return _stream->Seek(GetPosOfNonSolidItem(index), STREAM_SEEK_SET, NULL);
}
void Clear();
bool IsDirectString_Equal(UInt32 offset, const char *s) const;
/*
UInt64 GetDataPos(unsigned index)
{
const CItem &item = Items[index];
return 4 + FirstHeader.HeaderLength + item.Pos;
return GetOffset() + FirstHeader.HeaderSize + item.Pos;
}
*/
UInt64 GetPosOfSolidItem(unsigned index) const
{
const CItem &item = Items[index];
return 4 + (UInt64)FirstHeader.HeaderSize + item.Pos;
}
UInt64 GetPosOfNonSolidItem(int index) const
UInt64 GetPosOfNonSolidItem(unsigned index) const
{
const CItem &item = Items[index];
return StreamOffset + _nonSolidStartOffset + 4 + item.Pos;
return DataStreamOffset + _nonSolidStartOffset + 4 + item.Pos;
}
void Release()
@@ -174,6 +387,52 @@ public:
Decoder.Release();
}
bool IsTruncated() const { return (_fileSize - StartOffset < FirstHeader.ArcSize); }
UString GetReducedName(unsigned index) const
{
const CItem &item = Items[index];
UString s;
if (item.Prefix >= 0)
{
if (IsUnicode)
s = UPrefixes[item.Prefix];
else
s = MultiByteToUnicodeString(APrefixes[item.Prefix]);
if (s.Len() > 0)
if (s.Back() != L'\\')
s += L'\\';
}
if (IsUnicode)
{
s += item.NameU;
if (item.NameU.IsEmpty())
s += L"file";
}
else
{
s += MultiByteToUnicodeString(item.NameA);
if (item.NameA.IsEmpty())
s += L"file";
}
const char *kRemoveStr = "$INSTDIR\\";
if (s.IsPrefixedBy_Ascii_NoCase(kRemoveStr))
s.Delete(0, MyStringLen(kRemoveStr));
if (item.IsUninstaller && ExeStub.Size() == 0)
s += L".nsis";
return s;
}
UString ConvertToUnicode(const AString &s) const;
CInArchive()
#ifdef NSIS_SCRIPT
: Script(kScriptSizeLimit)
#endif
{}
};
}}

15
CPP/7zip/Archive/Nsis/NsisRegister.cpp Executable file → Normal file
View File

@@ -5,9 +5,20 @@
#include "../../Common/RegisterArc.h"
#include "NsisHandler.h"
static IInArchive *CreateArc() { return new NArchive::NNsis::CHandler; }
namespace NArchive {
namespace NNsis {
IMP_CreateArcIn
static CArcInfo g_ArcInfo =
{ L"Nsis", L"", 0, 0x9, NSIS_SIGNATURE, NArchive::NNsis::kSignatureSize, false, CreateArc, 0 };
{ "Nsis", "nsis", 0, 0x9,
NArchive::NNsis::kSignatureSize, NSIS_SIGNATURE,
4,
NArcInfoFlags::kFindSignature |
NArcInfoFlags::kUseGlobalOffset,
CreateArc };
REGISTER_ARC(Nsis)
}}

3
CPP/7zip/Archive/Nsis/StdAfx.h Executable file → Normal file
View File

@@ -3,7 +3,6 @@
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#include "../../../Common/NewHandler.h"
#include "../../../Common/Common.h"
#endif