xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Zip/ZipIn.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // Archive/ZipIn.h
2 
3 #ifndef ZIP7_INC_ZIP_IN_H
4 #define ZIP7_INC_ZIP_IN_H
5 
6 #include "../../../Common/MyBuffer2.h"
7 #include "../../../Common/MyCom.h"
8 
9 #include "../../Common/StreamUtils.h"
10 #include "../../IStream.h"
11 
12 #include "ZipHeader.h"
13 #include "ZipItem.h"
14 
15 API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size);
16 
17 namespace NArchive {
18 namespace NZip {
19 
20 class CItemEx: public CItem
21 {
22 public:
23   UInt32 LocalFullHeaderSize; // including Name and Extra
24   // int ParentOfAltStream; // -1, if not AltStream
25 
26   bool DescriptorWasRead;
27 
CItemEx()28   CItemEx():
29     // ParentOfAltStream(-1),
30     DescriptorWasRead(false) {}
31 
GetLocalFullSize()32   UInt64 GetLocalFullSize() const
33     { return LocalFullHeaderSize + GetPackSizeWithDescriptor(); }
GetDataPosition()34   UInt64 GetDataPosition() const
35     { return LocalHeaderPos + LocalFullHeaderSize; }
36 
IsBadDescriptor()37   bool IsBadDescriptor() const
38   {
39     return !FromCentral && FromLocal && HasDescriptor() && !DescriptorWasRead;
40   }
41 };
42 
43 
44 struct CInArchiveInfo
45 {
46   Int64 Base; /* Base offset of start of archive in stream.
47                  Offsets in headers must be calculated from that Base.
48                  Base is equal to MarkerPos for normal ZIPs.
49                  Base can point to PE stub for some ZIP SFXs.
50                  if CentralDir was read,
51                    Base can be negative, if start of data is not available,
52                  if CentralDirs was not read,
53                    Base = ArcInfo.MarkerPos; */
54 
55   /* The following *Pos variables contain absolute offsets in Stream */
56 
57   UInt64 MarkerPos;  /* Pos of first signature, it can point to kSpan/kNoSpan signature
58                         = MarkerPos2      in most archives
59                         = MarkerPos2 - 4  if there is kSpan/kNoSpan signature */
60   UInt64 MarkerPos2; // Pos of first local item signature in stream
61   UInt64 FinishPos;  // Finish pos of archive data in starting volume
62   UInt64 FileEndPos; // Finish pos of stream
63 
64   UInt64 FirstItemRelatOffset; /* Relative offset of first local (read from cd) (relative to Base).
65                                   = 0 in most archives
66                                   = size of stub for some SFXs */
67 
68 
69   int MarkerVolIndex;
70 
71   bool CdWasRead;
72   bool IsSpanMode;
73   bool ThereIsTail;
74 
75   // UInt32 BaseVolIndex;
76 
77   CByteBuffer Comment;
78 
79 
CInArchiveInfoCInArchiveInfo80   CInArchiveInfo():
81       Base(0),
82       MarkerPos(0),
83       MarkerPos2(0),
84       FinishPos(0),
85       FileEndPos(0),
86       FirstItemRelatOffset(0),
87       MarkerVolIndex(-1),
88       CdWasRead(false),
89       IsSpanMode(false),
90       ThereIsTail(false)
91       // BaseVolIndex(0)
92       {}
93 
ClearCInArchiveInfo94   void Clear()
95   {
96     // BaseVolIndex = 0;
97     Base = 0;
98     MarkerPos = 0;
99     MarkerPos2 = 0;
100     FinishPos = 0;
101     FileEndPos = 0;
102     MarkerVolIndex = -1;
103     ThereIsTail = false;
104 
105     FirstItemRelatOffset = 0;
106 
107     CdWasRead = false;
108     IsSpanMode = false;
109 
110     Comment.Free();
111   }
112 };
113 
114 
115 struct CCdInfo
116 {
117   bool IsFromEcd64;
118 
119   UInt16 CommentSize;
120 
121   // 64
122   UInt16 VersionMade;
123   UInt16 VersionNeedExtract;
124 
125   // old zip
126   UInt32 ThisDisk;
127   UInt32 CdDisk;
128   UInt64 NumEntries_in_ThisDisk;
129   UInt64 NumEntries;
130   UInt64 Size;
131   UInt64 Offset;
132 
CCdInfoCCdInfo133   CCdInfo() { memset(this, 0, sizeof(*this)); IsFromEcd64 = false; }
134 
135   void ParseEcd32(const Byte *p);   // (p) includes signature
136   void ParseEcd64e(const Byte *p);  // (p) exclude signature
137 
IsEmptyArcCCdInfo138   bool IsEmptyArc() const
139   {
140     return ThisDisk == 0
141         && CdDisk == 0
142         && NumEntries_in_ThisDisk == 0
143         && NumEntries == 0
144         && Size == 0
145         && Offset == 0 // test it
146     ;
147   }
148 };
149 
150 
151 struct CVols
152 {
153   struct CSubStreamInfo
154   {
155     CMyComPtr<IInStream> Stream;
156     UInt64 Size;
157 
SeekToStartCVols::CSubStreamInfo158     HRESULT SeekToStart() const { return InStream_SeekToBegin(Stream); }
159 
CSubStreamInfoCVols::CSubStreamInfo160     CSubStreamInfo(): Size(0) {}
161   };
162 
163   CObjectVector<CSubStreamInfo> Streams;
164 
165   int StreamIndex;   // -1 for StartStream
166                      // -2 for ZipStream at multivol detection code
167                      // >=0 volume index in multivol
168 
169   bool NeedSeek;
170 
171   bool DisableVolsSearch;
172   bool StartIsExe;  // is .exe
173   bool StartIsZ;    // is .zip or .zNN
174   bool StartIsZip;  // is .zip
175   bool IsUpperCase;
176   bool MissingZip;
177 
178   bool ecd_wasRead;
179 
180   Int32 StartVolIndex; // -1, if unknown vol index
181                        // = (NN - 1), if StartStream is .zNN
182                        // = 0, if start vol is exe
183 
184   Int32 StartParsingVol; // if we need local parsing, we must use that stream
185   unsigned NumVols;
186 
187   int EndVolIndex; // index of last volume (ecd volume),
188                    // -1, if is not multivol
189 
190   UString BaseName; // name of archive including '.'
191   UString MissingName;
192 
193   CMyComPtr<IInStream> ZipStream;
194 
195   CCdInfo ecd;
196 
197   UInt64 TotalBytesSize; // for MultiVol only
198 
ClearRefsCVols199   void ClearRefs()
200   {
201     Streams.Clear();
202     ZipStream.Release();
203     TotalBytesSize = 0;
204   }
205 
ClearCVols206   void Clear()
207   {
208     StreamIndex = -1;
209     NeedSeek = false;
210 
211     DisableVolsSearch = false;
212     StartIsExe = false;
213     StartIsZ = false;
214     StartIsZip = false;
215     IsUpperCase = false;
216 
217     StartVolIndex = -1;
218     StartParsingVol = 0;
219     NumVols = 0;
220     EndVolIndex = -1;
221 
222     BaseName.Empty();
223     MissingName.Empty();
224 
225     MissingZip = false;
226     ecd_wasRead = false;
227 
228     ClearRefs();
229   }
230 
231   HRESULT ParseArcName(IArchiveOpenVolumeCallback *volCallback);
232 
233   HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
234 };
235 
236 
237 Z7_CLASS_IMP_COM_1(
238   CVolStream
239   , ISequentialInStream
240 )
241 public:
242   CVols *Vols;
243 };
244 
245 
246 class CInArchive
247 {
248   CMidBuffer Buffer;
249   size_t _bufPos;
250   size_t _bufCached;
251 
252   UInt64 _streamPos;
253   UInt64 _cnt;
254 
255   // UInt32 _startLocalFromCd_Disk;
256   // UInt64 _startLocalFromCd_Offset;
257 
258   size_t GetAvail() const { return _bufCached - _bufPos; }
259 
260   void InitBuf() { _bufPos = 0; _bufCached = 0; }
261   void DisableBufMode() { InitBuf(); _inBufMode = false; }
262 
263   void SkipLookahed(size_t skip)
264   {
265     _bufPos += skip;
266     _cnt += skip;
267   }
268 
269   HRESULT AllocateBuffer(size_t size);
270 
271   UInt64 GetVirtStreamPos() { return _streamPos - _bufCached + _bufPos; }
272 
273   bool _inBufMode;
274 
275   bool IsArcOpen;
276   bool CanStartNewVol;
277 
278   UInt32 _signature;
279 
280   CMyComPtr<IInStream> StreamRef;
281   IInStream *Stream;
282   IInStream *StartStream;
283   IArchiveOpenCallback *Callback;
284 
285   HRESULT Seek_SavePos(UInt64 offset);
286   HRESULT SeekToVol(int volIndex, UInt64 offset);
287 
288   HRESULT ReadFromCache(Byte *data, unsigned size, unsigned &processed);
289   HRESULT ReadFromCache_FALSE(Byte *data, unsigned size);
290 
291   HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback,
292       unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols);
293   HRESULT ReadVols();
294 
295   HRESULT FindMarker(const UInt64 *searchLimit);
296   HRESULT IncreaseRealPosition(UInt64 addValue, bool &isFinished);
297 
298   HRESULT LookAhead(size_t minRequiredInBuffer);
299   void SafeRead(Byte *data, unsigned size);
300   void ReadBuffer(CByteBuffer &buffer, unsigned size);
301   // Byte ReadByte();
302   // UInt16 ReadUInt16();
303   UInt32 ReadUInt32();
304   UInt64 ReadUInt64();
305 
306   void ReadSignature();
307 
308   void Skip(size_t num);
309   HRESULT Skip64(UInt64 num, unsigned numFiles);
310 
311   bool ReadFileName(unsigned nameSize, AString &dest);
312 
313   bool ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlock &extra,
314       UInt64 &unpackSize, UInt64 &packSize, CItem *cdItem);
315   bool ReadLocalItem(CItemEx &item);
316   HRESULT FindDescriptor(CItemEx &item, unsigned numFiles);
317   HRESULT ReadCdItem(CItemEx &item);
318   HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo);
319   HRESULT FindCd(bool checkOffsetMode);
320   HRESULT TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize);
321   HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize);
322   HRESULT ReadLocals(CObjectVector<CItemEx> &localItems);
323 
324   HRESULT ReadHeaders(CObjectVector<CItemEx> &items);
325 
326   HRESULT GetVolStream(unsigned vol, UInt64 pos, CMyComPtr<ISequentialInStream> &stream);
327 
328 public:
329   CInArchiveInfo ArcInfo;
330 
331   bool IsArc;
332   bool IsZip64;
333 
334   bool IsApk;
335   bool IsCdUnsorted;
336 
337   bool HeadersError;
338   bool HeadersWarning;
339   bool ExtraMinorError;
340   bool UnexpectedEnd;
341   bool LocalsWereRead;
342   bool LocalsCenterMerged;
343   bool NoCentralDir;
344   bool Overflow32bit; // = true, if zip without Zip64 extension support and it has some fields values truncated to 32-bits.
345   bool Cd_NumEntries_Overflow_16bit; // = true, if no Zip64 and 16-bit ecd:NumEntries was overflowed.
346 
347   bool MarkerIsFound;
348   bool MarkerIsSafe;
349 
350   bool IsMultiVol;
351   bool UseDisk_in_SingleVol;
352   UInt32 EcdVolIndex;
353 
354   CVols Vols;
355 
356   bool Force_ReadLocals_Mode;
357   bool Disable_VolsRead;
358   bool Disable_FindMarker;
359 
360   CInArchive():
361       IsArcOpen(false),
362       Stream(NULL),
363       StartStream(NULL),
364       Callback(NULL),
365       Force_ReadLocals_Mode(false),
366       Disable_VolsRead(false),
367       Disable_FindMarker(false)
368       {}
369 
370   UInt64 GetPhySize() const
371   {
372     if (IsMultiVol)
373       return ArcInfo.FinishPos;
374     else
375       return (UInt64)((Int64)ArcInfo.FinishPos - ArcInfo.Base);
376   }
377 
378   UInt64 GetOffset() const
379   {
380     if (IsMultiVol)
381       return 0;
382     else
383       return (UInt64)ArcInfo.Base;
384   }
385 
386 
387   void ClearRefs();
388   void Close();
389   HRESULT Open(IInStream *stream, const UInt64 *searchLimit, IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items);
390 
391   bool IsOpen() const { return IsArcOpen; }
392 
393   bool AreThereErrors() const
394   {
395     return HeadersError
396         || UnexpectedEnd
397         || !Vols.MissingName.IsEmpty();
398   }
399 
400   bool IsLocalOffsetOK(const CItemEx &item) const
401   {
402     if (item.FromLocal)
403       return true;
404     return (Int64)GetOffset() + (Int64)item.LocalHeaderPos >= 0;
405   }
406 
407   UInt64 GetEmbeddedStubSize() const
408   {
409     // it's possible that first item in CD doesn refers to first local item
410     // so FirstItemRelatOffset is not first local item
411 
412     if (ArcInfo.CdWasRead)
413       return ArcInfo.FirstItemRelatOffset;
414     if (IsMultiVol)
415       return 0;
416     return (UInt64)((Int64)ArcInfo.MarkerPos2 - ArcInfo.Base);
417   }
418 
419 
420   HRESULT CheckDescriptor(const CItemEx &item);
421   HRESULT Read_LocalItem_After_CdItem(CItemEx &item, bool &isAvail, bool &headersError);
422   HRESULT Read_LocalItem_After_CdItem_Full(CItemEx &item);
423 
424   HRESULT GetItemStream(const CItemEx &item, bool seekPackData, CMyComPtr<ISequentialInStream> &stream);
425 
426   IInStream *GetBaseStream() { return StreamRef; }
427 
428   bool CanUpdate() const
429   {
430     if (AreThereErrors()
431        || IsMultiVol
432        || ArcInfo.Base < 0
433        || (Int64)ArcInfo.MarkerPos2 < ArcInfo.Base
434        || ArcInfo.ThereIsTail
435        || GetEmbeddedStubSize() != 0
436        || IsApk
437        || IsCdUnsorted)
438       return false;
439 
440     // 7-zip probably can update archives with embedded stubs.
441     // we just disable that feature for more safety.
442 
443     return true;
444   }
445 };
446 
447 }}
448 
449 #endif
450