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
24class COutStreamWithHash:
25  public ISequentialOutStream,
26  public CMyUnknownImp
27{
28  CMyComPtr<ISequentialOutStream> _stream;
29  UInt64 _size;
30  bool _calculate;
31public:
32  IHashCalc *_hash;
33
34  MY_UNKNOWN_IMP
35  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
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 HardLinks;
56  CBoolPair AltStreams;
57  bool ReplaceColonForAltStream;
58  bool WriteToAltStreamIfColon;
59
60  CExtractNtOptions():
61      ReplaceColonForAltStream(false),
62      WriteToAltStreamIfColon(false)
63  {
64    SymLinks.Val = true;
65    HardLinks.Val = true;
66    AltStreams.Val = true;
67  }
68};
69
70#ifndef _SFX
71
72class CGetProp:
73  public IGetProp,
74  public CMyUnknownImp
75{
76public:
77  const CArc *Arc;
78  UInt32 IndexInArc;
79  // UString Name; // relative path
80
81  MY_UNKNOWN_IMP1(IGetProp)
82  INTERFACE_IGetProp(;)
83};
84
85#endif
86
87#ifndef _SFX
88#ifndef UNDER_CE
89
90#define SUPPORT_LINKS
91
92#endif
93#endif
94
95
96#ifdef SUPPORT_LINKS
97
98struct CHardLinkNode
99{
100  UInt64 StreamId;
101  UInt64 INode;
102
103  int Compare(const CHardLinkNode &a) const;
104};
105
106class CHardLinks
107{
108public:
109  CRecordVector<CHardLinkNode> IDs;
110  CObjectVector<FString> Links;
111
112  void Clear()
113  {
114    IDs.Clear();
115    Links.Clear();
116  }
117
118  void PrepareLinks()
119  {
120    while (Links.Size() < IDs.Size())
121      Links.AddNew();
122  }
123};
124
125#endif
126
127#ifdef SUPPORT_ALT_STREAMS
128
129struct CIndexToPathPair
130{
131  UInt32 Index;
132  FString Path;
133
134  CIndexToPathPair(UInt32 index): Index(index) {}
135  CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {}
136
137  int Compare(const CIndexToPathPair &pair) const
138  {
139    return MyCompare(Index, pair.Index);
140  }
141};
142
143#endif
144
145class CArchiveExtractCallback:
146  public IArchiveExtractCallback,
147  public IArchiveExtractCallbackMessage,
148  public ICryptoGetTextPassword,
149  public ICompressProgressInfo,
150  public CMyUnknownImp
151{
152  const CArc *_arc;
153  CExtractNtOptions _ntOptions;
154
155  const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)
156  CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
157  CMyComPtr<ICompressProgressInfo> _compressProgress;
158  CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
159  CMyComPtr<IArchiveExtractCallbackMessage> _callbackMessage;
160  CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2;
161
162  FString _dirPathPrefix;
163  FString _dirPathPrefix_Full;
164  NExtract::NPathMode::EEnum _pathMode;
165  NExtract::NOverwriteMode::EEnum _overwriteMode;
166
167  #ifndef _SFX
168
169  CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
170  CGetProp *GetProp_Spec;
171  CMyComPtr<IGetProp> GetProp;
172
173  #endif
174
175  CReadArcItem _item;
176  FString _diskFilePath;
177  UInt64 _position;
178  bool _isSplit;
179
180  bool _extractMode;
181
182  bool WriteCTime;
183  bool WriteATime;
184  bool WriteMTime;
185
186  bool _encrypted;
187
188  struct CProcessedFileInfo
189  {
190    FILETIME CTime;
191    FILETIME ATime;
192    FILETIME MTime;
193    UInt32 Attrib;
194
195    bool CTimeDefined;
196    bool ATimeDefined;
197    bool MTimeDefined;
198    bool AttribDefined;
199  } _fi;
200
201  UInt32 _index;
202  UInt64 _curSize;
203  bool _curSizeDefined;
204  COutFileStream *_outFileStreamSpec;
205  CMyComPtr<ISequentialOutStream> _outFileStream;
206
207  #ifndef _SFX
208
209  COutStreamWithHash *_hashStreamSpec;
210  CMyComPtr<ISequentialOutStream> _hashStream;
211  bool _hashStreamWasUsed;
212
213  #endif
214
215  bool _removePartsForAltStreams;
216  UStringVector _removePathParts;
217
218  #ifndef _SFX
219  bool _use_baseParentFolder_mode;
220  UInt32 _baseParentFolder;
221  #endif
222
223  bool _stdOutMode;
224  bool _testMode;
225  bool _multiArchives;
226
227  CMyComPtr<ICompressProgressInfo> _localProgress;
228  UInt64 _packTotal;
229
230  UInt64 _progressTotal;
231  bool _progressTotal_Defined;
232
233  FStringVector _extractedFolderPaths;
234  CRecordVector<UInt32> _extractedFolderIndices;
235
236  #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
237  bool _saclEnabled;
238  #endif
239
240  void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
241  HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
242  HRESULT GetUnpackSize();
243
244  HRESULT SendMessageError(const char *message, const FString &path);
245  HRESULT SendMessageError_with_LastError(const char *message, const FString &path);
246  HRESULT SendMessageError2(const char *message, const FString &path1, const FString &path2);
247
248public:
249
250  CLocalProgress *LocalProgressSpec;
251
252  UInt64 NumFolders;
253  UInt64 NumFiles;
254  UInt64 NumAltStreams;
255  UInt64 UnpackSize;
256  UInt64 AltStreams_UnpackSize;
257
258  MY_UNKNOWN_IMP3(IArchiveExtractCallbackMessage, ICryptoGetTextPassword, ICompressProgressInfo)
259
260  INTERFACE_IArchiveExtractCallback(;)
261  INTERFACE_IArchiveExtractCallbackMessage(;)
262
263  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
264
265  STDMETHOD(CryptoGetTextPassword)(BSTR *password);
266
267  CArchiveExtractCallback();
268
269  void InitForMulti(bool multiArchives,
270      NExtract::NPathMode::EEnum pathMode,
271      NExtract::NOverwriteMode::EEnum overwriteMode)
272  {
273    _multiArchives = multiArchives;
274    _pathMode = pathMode;
275    _overwriteMode = overwriteMode;
276    NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
277  }
278
279  #ifndef _SFX
280
281  void SetHashMethods(IHashCalc *hash)
282  {
283    if (!hash)
284      return;
285    _hashStreamSpec = new COutStreamWithHash;
286    _hashStream = _hashStreamSpec;
287    _hashStreamSpec->_hash = hash;
288  }
289
290  #endif
291
292  void Init(
293      const CExtractNtOptions &ntOptions,
294      const NWildcard::CCensorNode *wildcardCensor,
295      const CArc *arc,
296      IFolderArchiveExtractCallback *extractCallback2,
297      bool stdOutMode, bool testMode,
298      const FString &directoryPath,
299      const UStringVector &removePathParts, bool removePartsForAltStreams,
300      UInt64 packSize);
301
302
303  #ifdef SUPPORT_LINKS
304
305private:
306  CHardLinks _hardLinks;
307  UString linkPath;
308
309  // FString _CopyFile_Path;
310  // HRESULT MyCopyFile(ISequentialOutStream *outStream);
311
312public:
313  // call PrepareHardLinks() after Init()
314  HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices);  // NULL means all items
315
316  #endif
317
318
319  #ifdef SUPPORT_ALT_STREAMS
320  CObjectVector<CIndexToPathPair> _renamedFiles;
321  #endif
322
323  // call it after Init()
324
325  #ifndef _SFX
326  void SetBaseParentFolderIndex(UInt32 indexInArc)
327  {
328    _baseParentFolder = indexInArc;
329    _use_baseParentFolder_mode = true;
330  }
331  #endif
332
333  HRESULT SetDirsTimes();
334};
335
336bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
337
338#endif
339