1 // ArchiveExtractCallback.h
2 
3 #ifndef __ARCHIVE_EXTRACT_CALLBACK_H
4 #define __ARCHIVE_EXTRACT_CALLBACK_H
5 
6 #include "../../../Common/MyCom.h"
7 #include "../../../Common/Wildcard.h"
8 
9 #include "../../IPassword.h"
10 
11 #include "../../Common/FileStreams.h"
12 #include "../../Common/ProgressUtils.h"
13 
14 #include "../../Archive/IArchive.h"
15 
16 #include "ExtractMode.h"
17 #include "IFileExtractCallback.h"
18 #include "OpenArchive.h"
19 
20 #include "HashCalc.h"
21 
22 #ifndef _SFX
23 
24 class COutStreamWithHash:
25   public ISequentialOutStream,
26   public CMyUnknownImp
27 {
28   CMyComPtr<ISequentialOutStream> _stream;
29   UInt64 _size;
30   bool _calculate;
31 public:
32   IHashCalc *_hash;
33 
34   MY_UNKNOWN_IMP
35   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
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 HardLinks;
56   CBoolPair AltStreams;
57   bool ReplaceColonForAltStream;
58   bool WriteToAltStreamIfColon;
59 
60   bool PreAllocateOutFile;
61 
CExtractNtOptionsCExtractNtOptions62   CExtractNtOptions():
63       ReplaceColonForAltStream(false),
64       WriteToAltStreamIfColon(false)
65   {
66     SymLinks.Val = true;
67     HardLinks.Val = true;
68     AltStreams.Val = true;
69 
70     PreAllocateOutFile =
71       #ifdef _WIN32
72         true;
73       #else
74         false;
75       #endif
76   }
77 };
78 
79 #ifndef _SFX
80 
81 class CGetProp:
82   public IGetProp,
83   public CMyUnknownImp
84 {
85 public:
86   const CArc *Arc;
87   UInt32 IndexInArc;
88   // UString Name; // relative path
89 
90   MY_UNKNOWN_IMP1(IGetProp)
91   INTERFACE_IGetProp(;)
92 };
93 
94 #endif
95 
96 #ifndef _SFX
97 #ifndef UNDER_CE
98 
99 #define SUPPORT_LINKS
100 
101 #endif
102 #endif
103 
104 
105 #ifdef SUPPORT_LINKS
106 
107 struct CHardLinkNode
108 {
109   UInt64 StreamId;
110   UInt64 INode;
111 
112   int Compare(const CHardLinkNode &a) const;
113 };
114 
115 class CHardLinks
116 {
117 public:
118   CRecordVector<CHardLinkNode> IDs;
119   CObjectVector<FString> Links;
120 
Clear()121   void Clear()
122   {
123     IDs.Clear();
124     Links.Clear();
125   }
126 
PrepareLinks()127   void PrepareLinks()
128   {
129     while (Links.Size() < IDs.Size())
130       Links.AddNew();
131   }
132 };
133 
134 #endif
135 
136 #ifdef SUPPORT_ALT_STREAMS
137 
138 struct CIndexToPathPair
139 {
140   UInt32 Index;
141   FString Path;
142 
CIndexToPathPairCIndexToPathPair143   CIndexToPathPair(UInt32 index): Index(index) {}
CIndexToPathPairCIndexToPathPair144   CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {}
145 
CompareCIndexToPathPair146   int Compare(const CIndexToPathPair &pair) const
147   {
148     return MyCompare(Index, pair.Index);
149   }
150 };
151 
152 #endif
153 
154 
155 
156 struct CDirPathTime
157 {
158   FILETIME CTime;
159   FILETIME ATime;
160   FILETIME MTime;
161 
162   bool CTimeDefined;
163   bool ATimeDefined;
164   bool MTimeDefined;
165 
166   FString Path;
167 
168   bool SetDirTime();
169 };
170 
171 
172 
173 class CArchiveExtractCallback:
174   public IArchiveExtractCallback,
175   public IArchiveExtractCallbackMessage,
176   public ICryptoGetTextPassword,
177   public ICompressProgressInfo,
178   public CMyUnknownImp
179 {
180   const CArc *_arc;
181   CExtractNtOptions _ntOptions;
182 
183   const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)
184   CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
185   CMyComPtr<ICompressProgressInfo> _compressProgress;
186   CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
187   CMyComPtr<IArchiveExtractCallbackMessage> _callbackMessage;
188   CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2;
189 
190   FString _dirPathPrefix;
191   FString _dirPathPrefix_Full;
192   NExtract::NPathMode::EEnum _pathMode;
193   NExtract::NOverwriteMode::EEnum _overwriteMode;
194   bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_";
195 
196   #ifndef _SFX
197 
198   CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
199   CGetProp *GetProp_Spec;
200   CMyComPtr<IGetProp> GetProp;
201 
202   #endif
203 
204   CReadArcItem _item;
205   FString _diskFilePath;
206   UInt64 _position;
207   bool _isSplit;
208 
209   bool _extractMode;
210 
211   bool WriteCTime;
212   bool WriteATime;
213   bool WriteMTime;
214 
215   bool _encrypted;
216 
217   struct CProcessedFileInfo
218   {
219     FILETIME CTime;
220     FILETIME ATime;
221     FILETIME MTime;
222     UInt32 Attrib;
223 
224     bool CTimeDefined;
225     bool ATimeDefined;
226     bool MTimeDefined;
227     bool AttribDefined;
228   } _fi;
229 
230   UInt32 _index;
231   UInt64 _curSize;
232   bool _curSizeDefined;
233   bool _fileLengthWasSet;
234   COutFileStream *_outFileStreamSpec;
235   CMyComPtr<ISequentialOutStream> _outFileStream;
236 
237   #ifndef _SFX
238 
239   COutStreamWithHash *_hashStreamSpec;
240   CMyComPtr<ISequentialOutStream> _hashStream;
241   bool _hashStreamWasUsed;
242 
243   #endif
244 
245   bool _removePartsForAltStreams;
246   UStringVector _removePathParts;
247 
248   #ifndef _SFX
249   bool _use_baseParentFolder_mode;
250   UInt32 _baseParentFolder;
251   #endif
252 
253   bool _stdOutMode;
254   bool _testMode;
255   bool _multiArchives;
256 
257   CMyComPtr<ICompressProgressInfo> _localProgress;
258   UInt64 _packTotal;
259 
260   UInt64 _progressTotal;
261   bool _progressTotal_Defined;
262 
263   CObjectVector<CDirPathTime> _extractedFolders;
264 
265   #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
266   bool _saclEnabled;
267   #endif
268 
269   void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
270   HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
271   HRESULT GetUnpackSize();
272 
273   HRESULT SendMessageError(const char *message, const FString &path);
274   HRESULT SendMessageError_with_LastError(const char *message, const FString &path);
275   HRESULT SendMessageError2(const char *message, const FString &path1, const FString &path2);
276 
277 public:
278 
279   CLocalProgress *LocalProgressSpec;
280 
281   UInt64 NumFolders;
282   UInt64 NumFiles;
283   UInt64 NumAltStreams;
284   UInt64 UnpackSize;
285   UInt64 AltStreams_UnpackSize;
286 
287   MY_UNKNOWN_IMP3(IArchiveExtractCallbackMessage, ICryptoGetTextPassword, ICompressProgressInfo)
288 
289   INTERFACE_IArchiveExtractCallback(;)
290   INTERFACE_IArchiveExtractCallbackMessage(;)
291 
292   STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
293 
294   STDMETHOD(CryptoGetTextPassword)(BSTR *password);
295 
296   CArchiveExtractCallback();
297 
InitForMulti(bool multiArchives,NExtract::NPathMode::EEnum pathMode,NExtract::NOverwriteMode::EEnum overwriteMode,bool keepAndReplaceEmptyDirPrefixes)298   void InitForMulti(bool multiArchives,
299       NExtract::NPathMode::EEnum pathMode,
300       NExtract::NOverwriteMode::EEnum overwriteMode,
301       bool keepAndReplaceEmptyDirPrefixes)
302   {
303     _multiArchives = multiArchives;
304     _pathMode = pathMode;
305     _overwriteMode = overwriteMode;
306     _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;
307     NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
308   }
309 
310   #ifndef _SFX
311 
SetHashMethods(IHashCalc * hash)312   void SetHashMethods(IHashCalc *hash)
313   {
314     if (!hash)
315       return;
316     _hashStreamSpec = new COutStreamWithHash;
317     _hashStream = _hashStreamSpec;
318     _hashStreamSpec->_hash = hash;
319   }
320 
321   #endif
322 
323   void Init(
324       const CExtractNtOptions &ntOptions,
325       const NWildcard::CCensorNode *wildcardCensor,
326       const CArc *arc,
327       IFolderArchiveExtractCallback *extractCallback2,
328       bool stdOutMode, bool testMode,
329       const FString &directoryPath,
330       const UStringVector &removePathParts, bool removePartsForAltStreams,
331       UInt64 packSize);
332 
333 
334   #ifdef SUPPORT_LINKS
335 
336 private:
337   CHardLinks _hardLinks;
338   UString linkPath;
339 
340   // FString _CopyFile_Path;
341   // HRESULT MyCopyFile(ISequentialOutStream *outStream);
342 
343 public:
344   // call PrepareHardLinks() after Init()
345   HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices);  // NULL means all items
346 
347   #endif
348 
349 
350   #ifdef SUPPORT_ALT_STREAMS
351   CObjectVector<CIndexToPathPair> _renamedFiles;
352   #endif
353 
354   // call it after Init()
355 
356   #ifndef _SFX
SetBaseParentFolderIndex(UInt32 indexInArc)357   void SetBaseParentFolderIndex(UInt32 indexInArc)
358   {
359     _baseParentFolder = indexInArc;
360     _use_baseParentFolder_mode = true;
361   }
362   #endif
363 
364   HRESULT CloseArc();
365 
366 private:
ClearExtractedDirsInfo()367   void ClearExtractedDirsInfo()
368   {
369     _extractedFolders.Clear();
370   }
371 
372   HRESULT CloseFile();
373   HRESULT SetDirsTimes();
374 };
375 
376 
377 struct CArchiveExtractCallback_Closer
378 {
379   CArchiveExtractCallback *_ref;
380 
CArchiveExtractCallback_CloserCArchiveExtractCallback_Closer381   CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {}
382 
CloseCArchiveExtractCallback_Closer383   HRESULT Close()
384   {
385     HRESULT res = S_OK;
386     if (_ref)
387     {
388       res = _ref->CloseArc();
389       _ref = NULL;
390     }
391     return res;
392   }
393 
~CArchiveExtractCallback_CloserCArchiveExtractCallback_Closer394   ~CArchiveExtractCallback_Closer()
395   {
396     Close();
397   }
398 };
399 
400 
401 bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
402 
403 #endif
404