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