xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Nsis/NsisIn.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // NsisIn.h
2 
3 #ifndef ZIP7_INC_ARCHIVE_NSIS_IN_H
4 #define ZIP7_INC_ARCHIVE_NSIS_IN_H
5 
6 #include "../../../../C/CpuArch.h"
7 
8 #include "../../../Common/DynLimBuf.h"
9 #include "../../../Common/MyBuffer.h"
10 #include "../../../Common/MyCom.h"
11 #include "../../../Common/StringConvert.h"
12 #include "../../../Common/UTFConvert.h"
13 
14 #include "../../Common/StreamUtils.h"
15 
16 #include "NsisDecode.h"
17 
18 /* If NSIS_SCRIPT is defined, it will decompile NSIS script to [NSIS].nsi file.
19    The code is much larger in that case. */
20 
21 // #define NSIS_SCRIPT
22 
23 namespace NArchive {
24 namespace NNsis {
25 
26 const size_t kScriptSizeLimit = 1 << 27;
27 
28 const unsigned kSignatureSize = 16;
29 extern const Byte kSignature[kSignatureSize];
30 #define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 'N', 'u', 'l', 'l', 's', 'o', 'f', 't', 'I', 'n', 's', 't' }
31 
32 const UInt32 kFlagsMask = 0xF;
33 namespace NFlags
34 {
35   const UInt32 kUninstall = 1;
36   const UInt32 kSilent = 2;
37   const UInt32 kNoCrc = 4;
38   const UInt32 kForceCrc = 8;
39   // NSISBI fork flags:
40   const UInt32 k_BI_LongOffset = 16;
41   const UInt32 k_BI_ExternalFileSupport = 32;
42   const UInt32 k_BI_ExternalFile = 64;
43   const UInt32 k_BI_IsStubInstaller = 128;
44 }
45 
46 struct CFirstHeader
47 {
48   UInt32 Flags;
49   UInt32 HeaderSize;
50   UInt32 ArcSize;
51 
ThereIsCrcCFirstHeader52   bool ThereIsCrc() const
53   {
54     return
55         (Flags & NFlags::kForceCrc) != 0 ||
56         (Flags & NFlags::kNoCrc) == 0;
57   }
58 
GetDataSizeCFirstHeader59   UInt32 GetDataSize() const { return ArcSize - (ThereIsCrc() ? 4 : 0); }
60 };
61 
62 
63 struct CBlockHeader
64 {
65   UInt32 Offset;
66   UInt32 Num;
67 
68   void Parse(const Byte *p, unsigned bhoSize);
69 };
70 
71 struct CItem
72 {
73   bool IsEmptyFile;
74   bool IsCompressed;
75   bool Size_Defined;
76   bool CompressedSize_Defined;
77   bool EstimatedSize_Defined;
78   bool Attrib_Defined;
79   bool IsUninstaller;
80   // bool UseFilter;
81 
82   UInt32 Attrib;
83   UInt32 Pos;       // = 0, if (IsEmptyFile == true)
84   UInt32 Size;
85   UInt32 CompressedSize;
86   UInt32 EstimatedSize;
87   UInt32 DictionarySize;
88   UInt32 PatchSize; // for Uninstaller.exe
89   int Prefix; // - 1 means no prefix
90 
91   FILETIME MTime;
92   AString NameA;
93   UString NameU;
94 
Is_PatchedUninstallerCItem95   bool Is_PatchedUninstaller() const { return PatchSize != 0; }
96 
CItemCItem97   CItem():
98       IsEmptyFile(false),
99       IsCompressed(true),
100       Size_Defined(false),
101       CompressedSize_Defined(false),
102       EstimatedSize_Defined(false),
103       Attrib_Defined(false),
104       IsUninstaller(false),
105       // UseFilter(false),
106       Attrib(0),
107       Pos(0),
108       Size(0),
109       CompressedSize(0),
110       EstimatedSize(0),
111       DictionarySize(1),
112       PatchSize(0),
113       Prefix(-1)
114   {
115     MTime.dwLowDateTime = 0;
116     MTime.dwHighDateTime = 0;
117   }
118 
119   /*
120   bool IsINSTDIR() const
121   {
122     return (PrefixA.Len() >= 3 || PrefixU.Len() >= 3);
123   }
124   */
125 };
126 
127 enum ENsisType
128 {
129   k_NsisType_Nsis2,
130   k_NsisType_Nsis3,
131   k_NsisType_Park1, // Park 2.46.1-
132   k_NsisType_Park2, // Park 2.46.2  : GetFontVersion
133   k_NsisType_Park3  // Park 2.46.3+ : GetFontName
134 };
135 
136 #ifdef NSIS_SCRIPT
137 
138 struct CSection
139 {
140   UInt32 InstallTypes; // bits set for each of the different install_types, if any.
141   UInt32 Flags; // SF_* - defined above
142   UInt32 StartCmdIndex; // code;
143   UInt32 NumCommands; // code_size;
144   UInt32 SizeKB;
145   UInt32 Name;
146 
147   void Parse(const Byte *data);
148 };
149 
150 struct CLicenseFile
151 {
152   UInt32 Offset;
153   UInt32 Size;
154   AString Name;
155   CByteBuffer Text;
156 };
157 
158 #endif
159 
160 class CInArchive
161 {
162 public:
163   #ifdef NSIS_SCRIPT
164   CDynLimBuf Script;
165   #endif
166   CByteBuffer _data;
167   CObjectVector<CItem> Items;
168   bool IsUnicode;
169   bool Is64Bit;
170 private:
171   UInt32 _stringsPos;     // relative to _data
172   UInt32 NumStringChars;
173   size_t _size;           // it's Header Size
174 
175   AString Raw_AString;
176   UString Raw_UString;
177 
178   ENsisType NsisType;
179   bool IsNsis200; // NSIS 2.03 and before
180   bool IsNsis225; // NSIS 2.25 and before
181   bool LogCmdIsEnabled;
182   int BadCmd; // -1: no bad command; in another cases lowest bad command id
183 
IsPark()184   bool IsPark() const { return NsisType >= k_NsisType_Park1; }
IsNsis3_OrHigher()185   bool IsNsis3_OrHigher() const { return NsisType == k_NsisType_Nsis3; }
186 
187   UInt64 _fileSize;
188 
189   bool _headerIsCompressed;
190   UInt32 _nonSolidStartOffset;
191 
192   #ifdef NSIS_SCRIPT
193 
194   CByteBuffer strUsed;
195 
196   CBlockHeader bhPages;
197   CBlockHeader bhSections;
198   CBlockHeader bhCtlColors;
199   CBlockHeader bhData;
200   UInt32 AfterHeaderSize;
201   CByteBuffer _afterHeader;
202 
203   UInt32 SectionSize;
204   const Byte *_mainLang;
205   UInt32 _numLangStrings;
206   AString LangComment;
207   CRecordVector<UInt32> langStrIDs;
208   UInt32 numOnFunc;
209   UInt32 onFuncOffset;
210   // CRecordVector<UInt32> OnFuncs;
211   unsigned _numRootLicenses;
212   CRecordVector<UInt32> noParseStringIndexes;
213   AString _tempString_for_GetVar;
214   AString _tempString_for_AddFuncName;
215   AString _tempString;
216 
217   #endif
218 
219 
220 public:
221   CMyComPtr<IInStream> _stream; // it's limited stream that contains only NSIS archive
222   UInt64 StartOffset;           // offset in original stream.
223   UInt64 DataStreamOffset;      // = sizeof(FirstHeader) = offset of Header in _stream
224 
225   bool IsArc;
226 
227   CDecoder Decoder;
228   CByteBuffer ExeStub;
229   CFirstHeader FirstHeader;
230   NMethodType::EEnum Method;
231   UInt32 DictionarySize;
232   bool IsSolid;
233   bool UseFilter;
234   bool FilterFlag;
235 
236   bool IsInstaller;
237   AString Name;
238   AString BrandingText;
239   UStringVector UPrefixes;
240   AStringVector APrefixes;
241 
242   #ifdef NSIS_SCRIPT
243   CObjectVector<CLicenseFile> LicenseFiles;
244   #endif
245 
246 private:
247   void GetShellString(AString &s, unsigned index1, unsigned index2);
248   void GetNsisString_Raw(const Byte *s);
249   void GetNsisString_Unicode_Raw(const Byte *s);
250   void ReadString2_Raw(UInt32 pos);
251   bool IsGoodString(UInt32 param) const;
252   bool AreTwoParamStringsEqual(UInt32 param1, UInt32 param2) const;
253 
254   void Add_LangStr(AString &res, UInt32 id);
255 
256   #ifdef NSIS_SCRIPT
257 
258   void Add_UInt(UInt32 v);
259   void AddLicense(UInt32 param, Int32 langID);
260 
261   void Add_LangStr_Simple(UInt32 id);
262   void Add_FuncName(const UInt32 *labels, UInt32 index);
263   void AddParam_Func(const UInt32 *labels, UInt32 index);
264   void Add_LabelName(UInt32 index);
265 
266   void Add_Color2(UInt32 v);
267   void Add_ColorParam(UInt32 v);
268   void Add_Color(UInt32 index);
269 
270   void Add_ButtonID(UInt32 buttonID);
271 
272   void Add_ShowWindow_Cmd(UInt32 cmd);
273   void Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type);
274   void Add_ExecFlags(UInt32 flagsType);
275   void Add_SectOp(UInt32 opType);
276 
277   void Add_Var(UInt32 index);
278   void AddParam_Var(UInt32 value);
279   void AddParam_UInt(UInt32 value);
280 
281   void Add_GotoVar(UInt32 param);
282   void Add_GotoVar1(UInt32 param);
283   void Add_GotoVars2(const UInt32 *params);
284 
285 
286 
287   bool PrintSectionBegin(const CSection &sect, unsigned index);
288   void PrintSectionEnd();
289 
290   void GetNsisString(AString &res, const Byte *s);
291   void GetNsisString_Unicode(AString &res, const Byte *s);
292   UInt32 GetNumUsedVars() const;
293   void ReadString2(AString &s, UInt32 pos);
294 
295   void MessageBox_MB_Part(UInt32 param);
296   void AddParam(UInt32 pos);
297   void AddOptionalParam(UInt32 pos);
298   void AddParams(const UInt32 *params, unsigned num);
299   void AddPageOption1(UInt32 param, const char *name);
300   void AddPageOption(const UInt32 *params, unsigned num, const char *name);
301   void AddOptionalParams(const UInt32 *params, unsigned num);
302   void AddRegRoot(UInt32 value);
303 
304 
305   void ClearLangComment();
306   void Separator();
307   void Space();
308   void Tab();
309   void Tab(bool commented);
310   void BigSpaceComment();
311   void SmallSpaceComment();
312   void AddCommentAndString(const char *s);
313   void AddError(const char *s);
314   void AddErrorLF(const char *s);
315   void CommentOpen();
316   void CommentClose();
317   void AddLF();
318   void AddQuotes();
319   void TabString(const char *s);
320   void AddStringLF(const char *s);
321   void NewLine();
322   void PrintNumComment(const char *name, UInt32 value);
323   void Add_QuStr(const AString &s);
324   void SpaceQuStr(const AString &s);
325   bool CompareCommands(const Byte *rawCmds, const Byte *sequence, size_t numCommands);
326 
327   #endif
328 
329   #ifdef NSIS_SCRIPT
330   unsigned GetNumSupportedCommands() const;
331   #endif
332 
333   UInt32 GetCmd(UInt32 a);
334   void FindBadCmd(const CBlockHeader &bh, const Byte *);
335   void DetectNsisType(const CBlockHeader &bh, const Byte *);
336 
337   HRESULT ReadEntries(const CBlockHeader &bh);
338   HRESULT SortItems();
339   HRESULT Parse();
340   HRESULT Open2(const Byte *data, size_t size);
341   void Clear2();
342 
343   void GetVar2(AString &res, UInt32 index);
344   void GetVar(AString &res, UInt32 index);
345   Int32 GetVarIndex(UInt32 strPos) const;
346   Int32 GetVarIndex(UInt32 strPos, UInt32 &resOffset) const;
347   Int32 GetVarIndexFinished(UInt32 strPos, Byte endChar, UInt32 &resOffset) const;
348   bool IsVarStr(UInt32 strPos, UInt32 varIndex) const;
349   bool IsAbsolutePathVar(UInt32 strPos) const;
350   void SetItemName(CItem &item, UInt32 strPos);
351 
352 public:
353   HRESULT Open(IInStream *inStream, const UInt64 *maxCheckStartPosition);
354   AString GetFormatDescription() const;
InitDecoder()355   HRESULT InitDecoder()
356   {
357     bool useFilter;
358     return Decoder.Init(_stream, useFilter);
359   }
360 
SeekTo(UInt64 pos)361   HRESULT SeekTo(UInt64 pos)
362   {
363     return InStream_SeekSet(_stream, pos);
364   }
365 
SeekTo_DataStreamOffset()366   HRESULT SeekTo_DataStreamOffset()
367   {
368     return SeekTo(DataStreamOffset);
369   }
370 
SeekToNonSolidItem(unsigned index)371   HRESULT SeekToNonSolidItem(unsigned index)
372   {
373     return SeekTo(GetPosOfNonSolidItem(index));
374   }
375 
376   void Clear();
377 
378   bool IsDirectString_Equal(UInt32 offset, const char *s) const;
379   /*
380   UInt64 GetDataPos(unsigned index)
381   {
382     const CItem &item = Items[index];
383     return GetOffset() + FirstHeader.HeaderSize + item.Pos;
384   }
385   */
386 
GetPosOfSolidItem(unsigned index)387   UInt64 GetPosOfSolidItem(unsigned index) const
388   {
389     const CItem &item = Items[index];
390     return 4 + (UInt64)FirstHeader.HeaderSize + item.Pos;
391   }
392 
GetPosOfNonSolidItem(unsigned index)393   UInt64 GetPosOfNonSolidItem(unsigned index) const
394   {
395     const CItem &item = Items[index];
396     return DataStreamOffset + _nonSolidStartOffset + 4 + item.Pos;
397   }
398 
Release()399   void Release()
400   {
401     Decoder.Release();
402   }
403 
IsTruncated()404   bool IsTruncated() const { return (_fileSize - StartOffset < FirstHeader.ArcSize); }
405 
GetReducedName(unsigned index)406   UString GetReducedName(unsigned index) const
407   {
408     const CItem &item = Items[index];
409 
410     UString s;
411     if (item.Prefix >= 0)
412     {
413       if (IsUnicode)
414         s = UPrefixes[item.Prefix];
415       else
416         s = MultiByteToUnicodeString(APrefixes[item.Prefix]);
417       if (s.Len() > 0)
418         if (s.Back() != L'\\')
419           s.Add_Char('\\');
420     }
421 
422     if (IsUnicode)
423     {
424       s += item.NameU;
425       if (item.NameU.IsEmpty())
426         s += "file";
427     }
428     else
429     {
430       s += MultiByteToUnicodeString(item.NameA);
431       if (item.NameA.IsEmpty())
432         s += "file";
433     }
434 
435     const char * const kRemoveStr = "$INSTDIR\\";
436     if (s.IsPrefixedBy_Ascii_NoCase(kRemoveStr))
437     {
438       s.Delete(0, MyStringLen(kRemoveStr));
439       if (s[0] == L'\\')
440         s.DeleteFrontal(1);
441     }
442     if (item.Is_PatchedUninstaller() && ExeStub.Size() == 0)
443       s += ".nsis";
444     return s;
445   }
446 
447   UString ConvertToUnicode(const AString &s) const;
448 
CInArchive()449   CInArchive()
450     #ifdef NSIS_SCRIPT
451       : Script(kScriptSizeLimit)
452     #endif
453     {}
454 };
455 
456 }}
457 
458 #endif
459