1// ArchiveExtractCallback.h
2
3#ifndef ZIP7_INC_ARCHIVE_EXTRACT_CALLBACK_H
4#define ZIP7_INC_ARCHIVE_EXTRACT_CALLBACK_H
5
6#include "../../../Common/MyCom.h"
7#include "../../../Common/MyLinux.h"
8#include "../../../Common/Wildcard.h"
9
10#include "../../IPassword.h"
11
12#include "../../Common/FileStreams.h"
13#include "../../Common/ProgressUtils.h"
14#include "../../Common/StreamObjects.h"
15
16#include "../../Archive/IArchive.h"
17
18#include "ExtractMode.h"
19#include "IFileExtractCallback.h"
20#include "OpenArchive.h"
21
22#include "HashCalc.h"
23
24#ifndef Z7_SFX
25
26Z7_CLASS_IMP_NOQIB_1(
27  COutStreamWithHash
28  , ISequentialOutStream
29)
30  CMyComPtr<ISequentialOutStream> _stream;
31  UInt64 _size;
32  bool _calculate;
33public:
34  IHashCalc *_hash;
35
36  void SetStream(ISequentialOutStream *stream) { _stream = stream; }
37  void ReleaseStream() { _stream.Release(); }
38  void Init(bool calculate = true)
39  {
40    InitCRC();
41    _size = 0;
42    _calculate = calculate;
43  }
44  void EnableCalc(bool calculate) { _calculate = calculate; }
45  void InitCRC() { _hash->InitForNewFile(); }
46  UInt64 GetSize() const { return _size; }
47};
48
49#endif
50
51struct CExtractNtOptions
52{
53  CBoolPair NtSecurity;
54  CBoolPair SymLinks;
55  CBoolPair SymLinks_AllowDangerous;
56  CBoolPair HardLinks;
57  CBoolPair AltStreams;
58  bool ReplaceColonForAltStream;
59  bool WriteToAltStreamIfColon;
60
61  bool ExtractOwner;
62
63  bool PreAllocateOutFile;
64
65  // used for hash arcs only, when we open external files
66  bool PreserveATime;
67  bool OpenShareForWrite;
68
69  CExtractNtOptions():
70      ReplaceColonForAltStream(false),
71      WriteToAltStreamIfColon(false),
72      ExtractOwner(false),
73      PreserveATime(false),
74      OpenShareForWrite(false)
75  {
76    SymLinks.Val = true;
77    SymLinks_AllowDangerous.Val = false;
78    HardLinks.Val = true;
79    AltStreams.Val = true;
80
81    PreAllocateOutFile =
82      #ifdef _WIN32
83        true;
84      #else
85        false;
86      #endif
87  }
88};
89
90#ifndef Z7_SFX
91
92Z7_CLASS_IMP_COM_1(
93  CGetProp
94  , IGetProp
95)
96public:
97  UInt32 IndexInArc;
98  const CArc *Arc;
99  // UString Name; // relative path
100};
101
102#endif
103
104#ifndef Z7_SFX
105#ifndef UNDER_CE
106
107#define SUPPORT_LINKS
108
109#endif
110#endif
111
112
113#ifdef SUPPORT_LINKS
114
115struct CHardLinkNode
116{
117  UInt64 StreamId;
118  UInt64 INode;
119
120  int Compare(const CHardLinkNode &a) const;
121};
122
123class CHardLinks
124{
125public:
126  CRecordVector<CHardLinkNode> IDs;
127  CObjectVector<FString> Links;
128
129  void Clear()
130  {
131    IDs.Clear();
132    Links.Clear();
133  }
134
135  void PrepareLinks()
136  {
137    while (Links.Size() < IDs.Size())
138      Links.AddNew();
139  }
140};
141
142#endif
143
144#ifdef SUPPORT_ALT_STREAMS
145
146struct CIndexToPathPair
147{
148  UInt32 Index;
149  FString Path;
150
151  CIndexToPathPair(UInt32 index): Index(index) {}
152  CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {}
153
154  int Compare(const CIndexToPathPair &pair) const
155  {
156    return MyCompare(Index, pair.Index);
157  }
158};
159
160#endif
161
162
163
164struct CFiTimesCAM
165{
166  CFiTime CTime;
167  CFiTime ATime;
168  CFiTime MTime;
169
170  bool CTime_Defined;
171  bool ATime_Defined;
172  bool MTime_Defined;
173
174  bool IsSomeTimeDefined() const
175  {
176    return
177      CTime_Defined |
178      ATime_Defined |
179      MTime_Defined;
180  }
181};
182
183struct CDirPathTime: public CFiTimesCAM
184{
185  FString Path;
186
187  bool SetDirTime() const;
188};
189
190
191#ifdef SUPPORT_LINKS
192
193struct CLinkInfo
194{
195  // bool isCopyLink;
196  bool isHardLink;
197  bool isJunction;
198  bool isRelative;
199  bool isWSL;
200  UString linkPath;
201
202  bool IsSymLink() const { return !isHardLink; }
203
204  CLinkInfo():
205    // IsCopyLink(false),
206    isHardLink(false),
207    isJunction(false),
208    isRelative(false),
209    isWSL(false)
210    {}
211
212  void Clear()
213  {
214    // IsCopyLink = false;
215    isHardLink = false;
216    isJunction = false;
217    isRelative = false;
218    isWSL = false;
219    linkPath.Empty();
220  }
221
222  bool Parse(const Byte *data, size_t dataSize, bool isLinuxData);
223};
224
225#endif // SUPPORT_LINKS
226
227
228#ifndef _WIN32
229
230struct COwnerInfo
231{
232  bool Id_Defined;
233  UInt32 Id;
234  AString Name;
235
236  void Clear()
237  {
238    Id_Defined = false;
239    Id = 0;
240    Name.Empty();
241  }
242};
243
244#endif
245
246
247class CArchiveExtractCallback Z7_final:
248  public IArchiveExtractCallback,
249  public IArchiveExtractCallbackMessage2,
250  public ICryptoGetTextPassword,
251  public ICompressProgressInfo,
252  public IArchiveUpdateCallbackFile,
253  public IArchiveGetDiskProperty,
254  public CMyUnknownImp
255{
256  Z7_COM_UNKNOWN_IMP_5(
257      /* IArchiveExtractCallback, */
258      IArchiveExtractCallbackMessage2,
259      ICryptoGetTextPassword,
260      ICompressProgressInfo,
261      IArchiveUpdateCallbackFile,
262      IArchiveGetDiskProperty)
263
264  Z7_IFACE_COM7_IMP(IProgress)
265  Z7_IFACE_COM7_IMP(IArchiveExtractCallback)
266  Z7_IFACE_COM7_IMP(IArchiveExtractCallbackMessage2)
267  Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)
268  Z7_IFACE_COM7_IMP(ICompressProgressInfo)
269  Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackFile)
270  Z7_IFACE_COM7_IMP(IArchiveGetDiskProperty)
271
272  const CArc *_arc;
273  CExtractNtOptions _ntOptions;
274
275  bool _isSplit;
276
277  bool _extractMode;
278
279  bool Write_CTime;
280  bool Write_ATime;
281  bool Write_MTime;
282  bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_";
283
284  bool _encrypted;
285
286  // bool _is_SymLink_in_Data;
287  bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX
288
289  bool _needSetAttrib;
290  bool _isSymLinkCreated;
291  bool _itemFailure;
292
293  bool _curSize_Defined;
294  bool _fileLength_WasSet;
295
296  bool _removePartsForAltStreams;
297
298  bool _stdOutMode;
299  bool _testMode;
300  bool _multiArchives;
301
302  NExtract::NPathMode::EEnum _pathMode;
303  NExtract::NOverwriteMode::EEnum _overwriteMode;
304
305  const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)
306  CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
307  // CMyComPtr<ICompressProgressInfo> _compressProgress;
308  // CMyComPtr<IArchiveExtractCallbackMessage2> _callbackMessage;
309  CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2;
310  CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
311
312  FString _dirPathPrefix;
313  FString _dirPathPrefix_Full;
314
315  #ifndef Z7_SFX
316
317  CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
318  CGetProp *GetProp_Spec;
319  CMyComPtr<IGetProp> GetProp;
320
321  #endif
322
323  CReadArcItem _item;
324  FString _diskFilePath;
325  UInt64 _position;
326
327  struct CProcessedFileInfo
328  {
329    CArcTime CTime;
330    CArcTime ATime;
331    CArcTime MTime;
332    UInt32 Attrib;
333    bool Attrib_Defined;
334
335   #ifndef _WIN32
336    COwnerInfo Owner;
337    COwnerInfo Group;
338   #endif
339
340    bool IsReparse() const
341    {
342      return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0);
343    }
344
345    bool IsLinuxSymLink() const
346    {
347      return (Attrib_Defined && MY_LIN_S_ISLNK(Attrib >> 16));
348    }
349
350    void SetFromPosixAttrib(UInt32 a)
351    {
352      // here we set only part of combined attribute required by SetFileAttrib() call
353      #ifdef _WIN32
354      // Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute.
355      Attrib = MY_LIN_S_ISDIR(a) ?
356          FILE_ATTRIBUTE_DIRECTORY :
357          FILE_ATTRIBUTE_ARCHIVE;
358      if ((a & 0222) == 0) // (& S_IWUSR) in p7zip
359        Attrib |= FILE_ATTRIBUTE_READONLY;
360      // 22.00 : we need type bits for (MY_LIN_S_IFLNK) for IsLinuxSymLink()
361      a &= MY_LIN_S_IFMT;
362      if (a == MY_LIN_S_IFLNK)
363        Attrib |= (a << 16);
364      #else
365      Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION;
366      #endif
367      Attrib_Defined = true;
368    }
369  } _fi;
370
371  UInt32 _index;
372  UInt64 _curSize;
373  UInt64 _fileLength_that_WasSet;
374
375  COutFileStream *_outFileStreamSpec;
376  CMyComPtr<ISequentialOutStream> _outFileStream;
377
378  CByteBuffer _outMemBuf;
379  CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec;
380  CMyComPtr<ISequentialOutStream> _bufPtrSeqOutStream;
381
382
383 #ifndef Z7_SFX
384
385  COutStreamWithHash *_hashStreamSpec;
386  CMyComPtr<ISequentialOutStream> _hashStream;
387  bool _hashStreamWasUsed;
388
389  bool _use_baseParentFolder_mode;
390  UInt32 _baseParentFolder;
391 #endif
392
393  UStringVector _removePathParts;
394
395  CMyComPtr<ICompressProgressInfo> _localProgress;
396  UInt64 _packTotal;
397
398  UInt64 _progressTotal;
399  bool _progressTotal_Defined;
400
401  CObjectVector<CDirPathTime> _extractedFolders;
402
403  #ifndef _WIN32
404  // CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks;
405  #endif
406
407  #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
408  bool _saclEnabled;
409  #endif
410
411  void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
412  HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft);
413  HRESULT GetUnpackSize();
414
415  FString Hash_GetFullFilePath();
416
417  void SetAttrib();
418
419public:
420  HRESULT SendMessageError(const char *message, const FString &path);
421  HRESULT SendMessageError_with_LastError(const char *message, const FString &path);
422  HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2);
423
424public:
425  #if defined(_WIN32) && !defined(UNDER_CE)
426  NExtract::NZoneIdMode::EEnum ZoneMode;
427  CByteBuffer ZoneBuf;
428  #endif
429
430  CLocalProgress *LocalProgressSpec;
431
432  UInt64 NumFolders;
433  UInt64 NumFiles;
434  UInt64 NumAltStreams;
435  UInt64 UnpackSize;
436  UInt64 AltStreams_UnpackSize;
437
438  FString DirPathPrefix_for_HashFiles;
439
440  CArchiveExtractCallback();
441
442  void InitForMulti(bool multiArchives,
443      NExtract::NPathMode::EEnum pathMode,
444      NExtract::NOverwriteMode::EEnum overwriteMode,
445      NExtract::NZoneIdMode::EEnum zoneMode,
446      bool keepAndReplaceEmptyDirPrefixes)
447  {
448    _multiArchives = multiArchives;
449    _pathMode = pathMode;
450    _overwriteMode = overwriteMode;
451   #if defined(_WIN32) && !defined(UNDER_CE)
452     ZoneMode = zoneMode;
453   #else
454     UNUSED_VAR(zoneMode)
455   #endif
456    _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;
457    NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
458  }
459
460  #ifndef Z7_SFX
461
462  void SetHashMethods(IHashCalc *hash)
463  {
464    if (!hash)
465      return;
466    _hashStreamSpec = new COutStreamWithHash;
467    _hashStream = _hashStreamSpec;
468    _hashStreamSpec->_hash = hash;
469  }
470
471  #endif
472
473  void InitBeforeNewArchive();
474
475  void Init(
476      const CExtractNtOptions &ntOptions,
477      const NWildcard::CCensorNode *wildcardCensor,
478      const CArc *arc,
479      IFolderArchiveExtractCallback *extractCallback2,
480      bool stdOutMode, bool testMode,
481      const FString &directoryPath,
482      const UStringVector &removePathParts, bool removePartsForAltStreams,
483      UInt64 packSize);
484
485
486  #ifdef SUPPORT_LINKS
487
488private:
489  CHardLinks _hardLinks;
490  CLinkInfo _link;
491
492  // FString _copyFile_Path;
493  // HRESULT MyCopyFile(ISequentialOutStream *outStream);
494  HRESULT Link(const FString &fullProcessedPath);
495  HRESULT ReadLink();
496
497public:
498  // call PrepareHardLinks() after Init()
499  HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices);  // NULL means all items
500
501  #endif
502
503
504  #ifdef SUPPORT_ALT_STREAMS
505  CObjectVector<CIndexToPathPair> _renamedFiles;
506  #endif
507
508  // call it after Init()
509
510  #ifndef Z7_SFX
511  void SetBaseParentFolderIndex(UInt32 indexInArc)
512  {
513    _baseParentFolder = indexInArc;
514    _use_baseParentFolder_mode = true;
515  }
516  #endif
517
518  HRESULT CloseArc();
519
520private:
521  void ClearExtractedDirsInfo()
522  {
523    _extractedFolders.Clear();
524    #ifndef _WIN32
525    // _delayedSymLinks.Clear();
526    #endif
527  }
528
529  HRESULT Read_fi_Props();
530  void CorrectPathParts();
531  void GetFiTimesCAM(CFiTimesCAM &pt);
532  void CreateFolders();
533
534  bool _isRenamed;
535  HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit);
536  HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit);
537  HRESULT GetItem(UInt32 index);
538
539  HRESULT CloseFile();
540  HRESULT CloseReparseAndFile();
541  HRESULT CloseReparseAndFile2();
542  HRESULT SetDirsTimes();
543
544  const void *NtReparse_Data;
545  UInt32 NtReparse_Size;
546
547  #ifdef SUPPORT_LINKS
548  HRESULT SetFromLinkPath(
549      const FString &fullProcessedPath,
550      const CLinkInfo &linkInfo,
551      bool &linkWasSet);
552  #endif
553};
554
555
556struct CArchiveExtractCallback_Closer
557{
558  CArchiveExtractCallback *_ref;
559
560  CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {}
561
562  HRESULT Close()
563  {
564    HRESULT res = S_OK;
565    if (_ref)
566    {
567      res = _ref->CloseArc();
568      _ref = NULL;
569    }
570    return res;
571  }
572
573  ~CArchiveExtractCallback_Closer()
574  {
575    Close();
576  }
577};
578
579
580bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
581
582void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf);
583
584#endif
585