p7zip/CPP/7zip/Archive/Nsis/NsisIn.h
2017-10-11 12:35:36 +02:00

446 lines
10 KiB
C++

// NsisIn.h
#ifndef __ARCHIVE_NSIS_IN_H
#define __ARCHIVE_NSIS_IN_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"
/* 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 size_t kScriptSizeLimit = 1 << 27;
const unsigned kSignatureSize = 16;
extern const Byte kSignature[kSignatureSize];
#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
{
const UInt32 kUninstall = 1;
const UInt32 kSilent = 2;
const UInt32 kNoCrc = 4;
const UInt32 kForceCrc = 8;
}
struct CFirstHeader
{
UInt32 Flags;
UInt32 HeaderSize;
UInt32 ArcSize;
bool ThereIsCrc() const
{
return
(Flags & NFlags::kForceCrc) != 0 ||
(Flags & NFlags::kNoCrc) == 0;
}
UInt32 GetDataSize() const { return ArcSize - (ThereIsCrc() ? 4 : 0); }
};
struct CBlockHeader
{
UInt32 Offset;
UInt32 Num;
void Parse(const Byte *p)
{
Offset = GetUi32(p);
Num = GetUi32(p + 4);
}
};
struct CItem
{
bool IsCompressed;
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;
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.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
{
public:
#ifdef NSIS_SCRIPT
CDynLimBuf Script;
#endif
CByteBuffer _data;
CObjectVector<CItem> Items;
bool IsUnicode;
private:
UInt32 _stringsPos; // relative to _data
UInt32 NumStringChars;
size_t _size; // it's Header Size
AString Raw_AString;
UString Raw_UString;
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;
#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;
CByteBuffer ExeStub;
CFirstHeader FirstHeader;
NMethodType::EEnum Method;
UInt32 DictionarySize;
bool IsSolid;
bool UseFilter;
bool FilterFlag;
bool IsInstaller;
AString Name;
AString BrandingText;
UStringVector UPrefixes;
AStringVector APrefixes;
#ifdef NSIS_SCRIPT
CObjectVector<CLicenseFile> LicenseFiles;
#endif
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 * const *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()
{
bool useFilter;
return Decoder.Init(_stream, useFilter);
}
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 GetOffset() + FirstHeader.HeaderSize + item.Pos;
}
*/
UInt64 GetPosOfSolidItem(unsigned index) const
{
const CItem &item = Items[index];
return 4 + (UInt64)FirstHeader.HeaderSize + item.Pos;
}
UInt64 GetPosOfNonSolidItem(unsigned index) const
{
const CItem &item = Items[index];
return DataStreamOffset + _nonSolidStartOffset + 4 + item.Pos;
}
void Release()
{
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 (s[0] == L'\\')
s.DeleteFrontal(1);
}
if (item.IsUninstaller && ExeStub.Size() == 0)
s += L".nsis";
return s;
}
UString ConvertToUnicode(const AString &s) const;
CInArchive()
#ifdef NSIS_SCRIPT
: Script(kScriptSizeLimit)
#endif
{}
};
}}
#endif