Welcome to mirror list, hosted at ThFree Co, Russian Federation.

ZipIn.h « Zip « Archive « 7zip « CPP - github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9b10905e83a40b8b7d25c64f9be22e0d1000d1e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
// Archive/ZipIn.h

#ifndef __ZIP_IN_H
#define __ZIP_IN_H

#include "../../../Common/MyCom.h"

#include "../../IStream.h"

#include "../../Common/InBuffer.h"

#include "ZipHeader.h"
#include "ZipItem.h"

API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size);

namespace NArchive {
namespace NZip {
  
class CItemEx: public CItem
{
public:
  UInt32 LocalFullHeaderSize; // including Name and Extra
  
  UInt64 GetLocalFullSize() const
    { return LocalFullHeaderSize + PackSize + (HasDescriptor() ? kDataDescriptorSize : 0); }
  UInt64 GetDataPosition() const
    { return LocalHeaderPos + LocalFullHeaderSize; }
};


struct CInArchiveInfo
{
  Int64 Base; /* Base offset of start of archive in stream.
                 Offsets in headers must be calculated from that Base.
                 Base is equal to MarkerPos for normal ZIPs.
                 Base can point to PE stub for some ZIP SFXs.
                 if CentralDir was read,
                   Base can be negative, if start of data is not available,
                 if CentralDirs was not read,
                   Base = ArcInfo.MarkerPos; */

  /* The following *Pos variables contain absolute offsets in Stream */

  UInt64 MarkerPos;  /* Pos of first signature, it can point to kSpan/kNoSpan signature
                        = MarkerPos2      in most archives
                        = MarkerPos2 - 4  if there is kSpan/kNoSpan signature */
  UInt64 MarkerPos2; // Pos of first local item signature in stream
  UInt64 FinishPos;  // Finish pos of archive data in starting volume
  UInt64 FileEndPos; // Finish pos of stream

  UInt64 FirstItemRelatOffset; /* Relative offset of first local (read from cd) (relative to Base).
                                  = 0 in most archives
                                  = size of stub for some SFXs */
  bool CdWasRead;
  bool IsSpanMode;
  bool ThereIsTail;

  // UInt32 BaseVolIndex;

  CByteBuffer Comment;


  CInArchiveInfo():
      Base(0),
      MarkerPos(0),
      MarkerPos2(0),
      FinishPos(0),
      FileEndPos(0),
      FirstItemRelatOffset(0),
      CdWasRead(false),
      IsSpanMode(false),
      ThereIsTail(false)
      // BaseVolIndex(0)
      {}
  
  void Clear()
  {
    // BaseVolIndex = 0;
    Base = 0;
    MarkerPos = 0;
    MarkerPos2 = 0;
    FinishPos = 0;
    FileEndPos = 0;
    ThereIsTail = false;

    FirstItemRelatOffset = 0;

    CdWasRead = false;
    IsSpanMode = false;

    Comment.Free();
  }
};


struct CCdInfo
{
  // 64
  UInt16 VersionMade;
  UInt16 VersionNeedExtract;

  // old zip
  UInt32 ThisDisk;
  UInt32 CdDisk;
  UInt64 NumEntries_in_ThisDisk;
  UInt64 NumEntries;
  UInt64 Size;
  UInt64 Offset;

  UInt16 CommentSize;

  CCdInfo() { memset(this, 0, sizeof(*this)); }

  void ParseEcd32(const Byte *p);   // (p) includes signature
  void ParseEcd64e(const Byte *p);  // (p) exclude signature
};


class CVols
{
public:

  struct CSubStreamInfo
  {
    CMyComPtr<IInStream> Stream;
    UInt64 Size;

    CSubStreamInfo(): Size(0) {}
  };
  
  CObjectVector<CSubStreamInfo> Streams;
  int StreamIndex;
  bool NeedSeek;

  CMyComPtr<IInStream> ZipStream;

  bool StartIsExe;  // is .exe
  bool StartIsZ;    // is .zip or .zNN
  bool StartIsZip;  // is .zip
  bool IsUpperCase;
  Int32 StartVolIndex; // = (NN - 1), if StartStream is .zNN

  Int32 StartParsingVol; // if we need local parsing, we must use that stream
  unsigned NumVols;

  int EndVolIndex; // index of last volume (ecd volume),
                   // -1, if is not multivol

  UString BaseName; // including '.'

  UString MissingName;

  CCdInfo ecd;
  bool ecd_wasRead;

  void Clear()
  {
    StreamIndex = -1;
    NeedSeek = false;


    StartIsExe = false;
    StartIsZ = false;
    StartIsZip = false;
    IsUpperCase = false;

    StartVolIndex = -1;
    StartParsingVol = 0;
    NumVols = 0;
    EndVolIndex = -1;

    BaseName.Empty();
    MissingName.Empty();

    ecd_wasRead = false;

    Streams.Clear();
    ZipStream.Release();
  }

  HRESULT ParseArcName(IArchiveOpenVolumeCallback *volCallback);

  HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
  
  UInt64 GetTotalSize() const
  {
    UInt64 total = 0;
    FOR_VECTOR (i, Streams)
      total += Streams[i].Size;
    return total;
  }
};


class CVolStream:
  public ISequentialInStream,
  public CMyUnknownImp
{
public:
  CVols *Vols;
  
  MY_UNKNOWN_IMP1(ISequentialInStream)

  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};


class CInArchive
{
  CInBuffer _inBuffer;
  bool _inBufMode;
  UInt32 m_Signature;
  UInt64 m_Position;

  UInt64 _processedCnt;
  
  bool CanStartNewVol;

  CMyComPtr<IInStream> StreamRef;
  IInStream *Stream;
  IInStream *StartStream;

  bool IsArcOpen;

  HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback,
      unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols);
  HRESULT ReadVols();

  HRESULT Seek(UInt64 offset);
  HRESULT FindMarker(IInStream *stream, const UInt64 *searchLimit);
  HRESULT IncreaseRealPosition(Int64 addValue, bool &isFinished);

  HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize);
  void SafeReadBytes(void *data, unsigned size);
  void ReadBuffer(CByteBuffer &buffer, unsigned size);
  Byte ReadByte();
  UInt16 ReadUInt16();
  UInt32 ReadUInt32();
  UInt64 ReadUInt64();
  void Skip(unsigned num);
  void Skip64(UInt64 num);
  void ReadFileName(unsigned nameSize, AString &dest);

  bool ReadExtra(unsigned extraSize, CExtraBlock &extraBlock,
      UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber);
  bool ReadLocalItem(CItemEx &item);
  HRESULT ReadLocalItemDescriptor(CItemEx &item);
  HRESULT ReadCdItem(CItemEx &item);
  HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo);
  HRESULT FindCd(bool checkOffsetMode);
  HRESULT TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize);
  HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize);
  HRESULT ReadLocals(CObjectVector<CItemEx> &localItems);

  HRESULT ReadHeaders2(CObjectVector<CItemEx> &items);

  HRESULT GetVolStream(unsigned vol, UInt64 pos, CMyComPtr<ISequentialInStream> &stream);
public:
  CInArchiveInfo ArcInfo;
  
  bool IsArc;
  bool IsZip64;
  bool HeadersError;
  bool HeadersWarning;
  bool ExtraMinorError;
  bool UnexpectedEnd;
  bool NoCentralDir;

  bool MarkerIsFound;

  bool IsMultiVol;
  bool UseDisk_in_SingleVol;
  UInt32 EcdVolIndex;

  CVols Vols;
 
  IArchiveOpenCallback *Callback;

  CInArchive(): Stream(NULL), Callback(NULL), IsArcOpen(false) {}

  UInt64 GetPhySize() const
  {
    if (IsMultiVol)
      return ArcInfo.FinishPos;
    else
      return ArcInfo.FinishPos - ArcInfo.Base;
  }

  UInt64 GetOffset() const
  {
    if (IsMultiVol)
      return 0;
    else
      return ArcInfo.Base;
  }

  
  void ClearRefs();
  void Close();
  HRESULT Open(IInStream *stream, const UInt64 *searchLimit, IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items);
  HRESULT ReadHeaders(CObjectVector<CItemEx> &items);

  bool IsOpen() const { return IsArcOpen; }
  
  bool AreThereErrors() const
  {
    return HeadersError
        || UnexpectedEnd
        || !Vols.MissingName.IsEmpty();
  }

  bool IsLocalOffsetOK(const CItemEx &item) const
  {
    if (item.FromLocal)
      return true;
    return (Int64)GetOffset() + (Int64)item.LocalHeaderPos >= 0;
  }

  UInt64 GetEmbeddedStubSize() const
  {
    if (ArcInfo.CdWasRead)
      return ArcInfo.FirstItemRelatOffset;
    if (IsMultiVol)
      return 0;
    return ArcInfo.MarkerPos2 - ArcInfo.Base;
  }


  HRESULT ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail);
  HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item);

  HRESULT GetItemStream(const CItemEx &item, bool seekPackData, CMyComPtr<ISequentialInStream> &stream);

  IInStream *GetBaseStream() { return StreamRef; }

  bool CanUpdate() const
  {
    if (AreThereErrors()
       || IsMultiVol
       || ArcInfo.Base < 0
       || (Int64)ArcInfo.MarkerPos2 < ArcInfo.Base
       || ArcInfo.ThereIsTail
       || GetEmbeddedStubSize() != 0)
      return false;
   
    // 7-zip probably can update archives with embedded stubs.
    // we just disable that feature for more safety.

    return true;
  }
};
  
}}
  
#endif