1 // ExtractCallback.h
2 
3 #ifndef __EXTRACT_CALLBACK_H
4 #define __EXTRACT_CALLBACK_H
5 
6 #include "../../../../C/Alloc.h"
7 
8 #include "../../../Common/MyCom.h"
9 #include "../../../Common/StringConvert.h"
10 
11 #ifndef _SFX
12 #include "../Agent/IFolderArchive.h"
13 #endif
14 
15 #include "../Common/ArchiveExtractCallback.h"
16 #include "../Common/ArchiveOpenCallback.h"
17 
18 #ifndef _NO_CRYPTO
19 #include "../../IPassword.h"
20 #endif
21 
22 #ifndef _SFX
23 #include "IFolder.h"
24 #endif
25 
26 #include "ProgressDialog2.h"
27 
28 #ifdef LANG
29 #include "LangUtils.h"
30 #endif
31 
32 #ifndef _SFX
33 
34 class CGrowBuf
35 {
36   Byte *_items;
37   size_t _size;
38 
39   CLASS_NO_COPY(CGrowBuf);
40 
41 public:
ReAlloc_KeepData(size_t newSize,size_t keepSize)42   bool ReAlloc_KeepData(size_t newSize, size_t keepSize)
43   {
44     void *buf = MyAlloc(newSize);
45     if (!buf)
46       return false;
47     if (keepSize != 0)
48       memcpy(buf, _items, keepSize);
49     MyFree(_items);
50     _items = (Byte *)buf;
51     _size = newSize;
52     return true;
53   }
54 
CGrowBuf()55   CGrowBuf(): _items(0), _size(0) {}
~CGrowBuf()56   ~CGrowBuf() { MyFree(_items); }
57 
58   operator Byte *() { return _items; }
59   operator const Byte *() const { return _items; }
Size()60   size_t Size() const { return _size; }
61 };
62 
63 struct CVirtFile
64 {
65   CGrowBuf Data;
66 
67   UInt64 Size; // real size
68   UInt64 ExpectedSize; // the size from props request. 0 if unknown
69 
70   UString Name;
71 
72   bool CTimeDefined;
73   bool ATimeDefined;
74   bool MTimeDefined;
75   bool AttribDefined;
76 
77   bool IsDir;
78   bool IsAltStream;
79 
80   DWORD Attrib;
81 
82   FILETIME CTime;
83   FILETIME ATime;
84   FILETIME MTime;
85 
CVirtFileCVirtFile86   CVirtFile():
87     CTimeDefined(false),
88     ATimeDefined(false),
89     MTimeDefined(false),
90     AttribDefined(false),
91     IsDir(false),
92     IsAltStream(false) {}
93 };
94 
95 class CVirtFileSystem:
96   public ISequentialOutStream,
97   public CMyUnknownImp
98 {
99   UInt64 _totalAllocSize;
100 
101   size_t _pos;
102   unsigned _numFlushed;
103   bool _fileIsOpen;
104   bool _fileMode;
105   COutFileStream *_outFileStreamSpec;
106   CMyComPtr<ISequentialOutStream> _outFileStream;
107 public:
108   CObjectVector<CVirtFile> Files;
109   UInt64 MaxTotalAllocSize;
110   FString DirPrefix;
111 
AddNewFile()112   CVirtFile &AddNewFile()
113   {
114     if (!Files.IsEmpty())
115     {
116       MaxTotalAllocSize -= Files.Back().Data.Size();
117     }
118     return Files.AddNew();
119   }
CloseMemFile()120   HRESULT CloseMemFile()
121   {
122     if (_fileMode)
123     {
124       return FlushToDisk(true);
125     }
126     CVirtFile &file = Files.Back();
127     if (file.Data.Size() != file.Size)
128     {
129       file.Data.ReAlloc_KeepData((size_t)file.Size, (size_t)file.Size);
130     }
131     return S_OK;
132   }
133 
IsStreamInMem()134   bool IsStreamInMem() const
135   {
136     if (_fileMode)
137       return false;
138     if (Files.Size() < 1 || /* Files[0].IsAltStream || */ Files[0].IsDir)
139       return false;
140     return true;
141   }
142 
GetMemStreamWrittenSize()143   size_t GetMemStreamWrittenSize() const { return _pos; }
144 
CVirtFileSystem()145   CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {}
146 
Init()147   void Init()
148   {
149     _totalAllocSize = 0;
150     _fileMode = false;
151     _pos = 0;
152     _numFlushed = 0;
153     _fileIsOpen = false;
154   }
155 
156   HRESULT CloseFile(const FString &path);
157   HRESULT FlushToDisk(bool closeLast);
GetPos()158   size_t GetPos() const { return _pos; }
159 
160   MY_UNKNOWN_IMP
161   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
162 };
163 
164 #endif
165 
166 class CExtractCallbackImp:
167   public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback
168   public IOpenCallbackUI,
169   public IFolderArchiveExtractCallback2,
170   #ifndef _SFX
171   public IFolderOperationsExtractCallback,
172   public IFolderExtractToStreamCallback,
173   public ICompressProgressInfo,
174   #endif
175   #ifndef _NO_CRYPTO
176   public ICryptoGetTextPassword,
177   #endif
178   public CMyUnknownImp
179 {
180   HRESULT MessageError(const char *message, const FString &path);
181   void Add_ArchiveName_Error();
182 public:
183   MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)
184   MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2)
185   #ifndef _SFX
186   MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback)
187   MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback)
188   MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo)
189   #endif
190   #ifndef _NO_CRYPTO
191   MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
192   #endif
193   MY_QUERYINTERFACE_END
194   MY_ADDREF_RELEASE
195 
196   INTERFACE_IProgress(;)
197   INTERFACE_IOpenCallbackUI(;)
198   INTERFACE_IFolderArchiveExtractCallback(;)
199   INTERFACE_IFolderArchiveExtractCallback2(;)
200   // STDMETHOD(SetTotalFiles)(UInt64 total);
201   // STDMETHOD(SetCompletedFiles)(const UInt64 *value);
202 
203   INTERFACE_IExtractCallbackUI(;)
204 
205   #ifndef _SFX
206   // IFolderOperationsExtractCallback
207   STDMETHOD(AskWrite)(
208       const wchar_t *srcPath,
209       Int32 srcIsFolder,
210       const FILETIME *srcTime,
211       const UInt64 *srcSize,
212       const wchar_t *destPathRequest,
213       BSTR *destPathResult,
214       Int32 *writeAnswer);
215   STDMETHOD(ShowMessage)(const wchar_t *message);
216   STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath);
217   STDMETHOD(SetNumFiles)(UInt64 numFiles);
218   INTERFACE_IFolderExtractToStreamCallback(;)
219   STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
220   #endif
221 
222   // ICryptoGetTextPassword
223   #ifndef _NO_CRYPTO
224   STDMETHOD(CryptoGetTextPassword)(BSTR *password);
225   #endif
226 
227 private:
228   UString _currentArchivePath;
229   bool _needWriteArchivePath;
230 
231   UString _currentFilePath;
232   bool _isFolder;
233 
234   bool _isAltStream;
235   UInt64 _curSize;
236   bool _curSizeDefined;
237   UString _filePath;
238   // bool _extractMode;
239   // bool _testMode;
240   bool _newVirtFileWasAdded;
241   bool _needUpdateStat;
242 
243 
244   HRESULT SetCurrentFilePath2(const wchar_t *filePath);
245   void AddError_Message(LPCWSTR message);
246 
247   #ifndef _SFX
248   bool _hashStreamWasUsed;
249   COutStreamWithHash *_hashStreamSpec;
250   CMyComPtr<ISequentialOutStream> _hashStream;
251   IHashCalc *_hashCalc; // it's for stat in Test operation
252   #endif
253 
254 public:
255 
256   #ifndef _SFX
257   CVirtFileSystem *VirtFileSystemSpec;
258   CMyComPtr<ISequentialOutStream> VirtFileSystem;
259   #endif
260 
261   bool ProcessAltStreams;
262 
263   bool StreamMode;
264 
265   CProgressDialog *ProgressDialog;
266   #ifndef _SFX
267   UInt64 NumFolders;
268   UInt64 NumFiles;
269   bool NeedAddFile;
270   #endif
271   UInt32 NumArchiveErrors;
272   bool ThereAreMessageErrors;
273   NExtract::NOverwriteMode::EEnum OverwriteMode;
274 
275   #ifndef _NO_CRYPTO
276   bool PasswordIsDefined;
277   bool PasswordWasAsked;
278   UString Password;
279   #endif
280 
281 
282   UString _lang_Extracting;
283   UString _lang_Testing;
284   UString _lang_Skipping;
285   UString _lang_Empty;
286 
287   bool _totalFilesDefined;
288   bool _totalBytesDefined;
289   bool MultiArcMode;
290 
CExtractCallbackImp()291   CExtractCallbackImp():
292     #ifndef _NO_CRYPTO
293     PasswordIsDefined(false),
294     PasswordWasAsked(false),
295     #endif
296     OverwriteMode(NExtract::NOverwriteMode::kAsk),
297     StreamMode(false),
298     ProcessAltStreams(true),
299 
300     _totalFilesDefined(false),
301     _totalBytesDefined(false),
302     MultiArcMode(false)
303 
304     #ifndef _SFX
305     , _hashCalc(NULL)
306     #endif
307     {}
308 
309   ~CExtractCallbackImp();
310   void Init();
311 
312   #ifndef _SFX
SetHashCalc(IHashCalc * hashCalc)313   void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; }
314 
SetHashMethods(IHashCalc * hash)315   void SetHashMethods(IHashCalc *hash)
316   {
317     if (!hash)
318       return;
319     _hashStreamSpec = new COutStreamWithHash;
320     _hashStream = _hashStreamSpec;
321     _hashStreamSpec->_hash = hash;
322   }
323   #endif
324 
IsOK()325   bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; }
326 };
327 
328 #endif
329