xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/FileManager/ExtractCallback.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // ExtractCallback.h
2 
3 #ifndef ZIP7_INC_EXTRACT_CALLBACK_H
4 #define ZIP7_INC_EXTRACT_CALLBACK_H
5 
6 #include "../../../../C/Alloc.h"
7 
8 #include "../../../Common/MyCom.h"
9 #include "../../../Common/StringConvert.h"
10 
11 #ifndef Z7_SFX
12 #include "../Agent/IFolderArchive.h"
13 #endif
14 
15 #include "../Common/ArchiveExtractCallback.h"
16 #include "../Common/ArchiveOpenCallback.h"
17 
18 #ifndef Z7_NO_CRYPTO
19 #include "../../IPassword.h"
20 #endif
21 
22 #ifndef Z7_SFX
23 #include "IFolder.h"
24 #endif
25 
26 #include "ProgressDialog2.h"
27 
28 #ifndef Z7_SFX
29 
30 class CGrowBuf
31 {
32   Byte *_items;
33   size_t _size;
34 
Z7_CLASS_NO_COPY(CGrowBuf)35   Z7_CLASS_NO_COPY(CGrowBuf)
36 
37 public:
38   void Free()
39   {
40     MyFree(_items);
41     _items = NULL;
42     _size = 0;
43   }
44 
45   // newSize >= keepSize
ReAlloc_KeepData(size_t newSize,size_t keepSize)46   bool ReAlloc_KeepData(size_t newSize, size_t keepSize)
47   {
48     void *buf = NULL;
49     if (newSize)
50     {
51       buf = MyAlloc(newSize);
52       if (!buf)
53         return false;
54     }
55     if (keepSize)
56       memcpy(buf, _items, keepSize);
57     MyFree(_items);
58     _items = (Byte *)buf;
59     _size = newSize;
60     return true;
61   }
62 
CGrowBuf()63   CGrowBuf(): _items(NULL), _size(0) {}
~CGrowBuf()64   ~CGrowBuf() { MyFree(_items); }
65 
66   operator Byte *() { return _items; }
67   operator const Byte *() const { return _items; }
Size()68   size_t Size() const { return _size; }
69 };
70 
71 
72 struct CVirtFile
73 {
74   CGrowBuf Data;
75 
76   UInt64 ExpectedSize; // size from props request. 0 if unknown
77   size_t WrittenSize;  // size of written data in (Data) buffer
78                        //   use (WrittenSize) only if (CVirtFileSystem::_newVirtFileStream_IsReadyToWrite == false)
79   UString BaseName;    // original name of file inside archive,
80                        // It's not path. So any path separators
81                        // should be treated as part of name (or as incorrect chars)
82   UString AltStreamName;
83 
84   bool CTime_Defined;
85   bool ATime_Defined;
86   bool MTime_Defined;
87   bool Attrib_Defined;
88 
89   // bool IsDir;
90   bool IsAltStream;
91   bool ColonWasUsed;
92   DWORD Attrib;
93 
94   FILETIME CTime;
95   FILETIME ATime;
96   FILETIME MTime;
97 
CVirtFileCVirtFile98   CVirtFile():
99     CTime_Defined(false),
100     ATime_Defined(false),
101     MTime_Defined(false),
102     Attrib_Defined(false),
103     // IsDir(false),
104     IsAltStream(false),
105     ColonWasUsed(false)
106     {}
107 };
108 
109 
110 /*
111   We use CVirtFileSystem only for single file extraction:
112   It supports the following cases and names:
113      - "fileName" : single file
114      - "fileName" item (main base file) and additional "fileName:altStream" items
115      - "altStream" : single item without "fileName:" prefix.
116   If file is flushed to disk, it uses Get_Correct_FsFile_Name(name).
117 */
118 
119 Z7_CLASS_IMP_NOQIB_1(
120   CVirtFileSystem,
121   ISequentialOutStream
122 )
123   unsigned _numFlushed;
124 public:
125   bool IsAltStreamFile; // in:
126       // = true,  if extracting file is alt stream without "fileName:" prefix.
127       // = false, if extracting file is normal file, but additional
128       //          alt streams "fileName:altStream" items are possible.
129 private:
130   bool _newVirtFileStream_IsReadyToWrite;    // it can non real file (if can't open alt stream)
131   bool _needWriteToRealFile;  // we need real writing to open file.
132   bool _wasSwitchedToFsMode;
133   bool _altStream_NeedRestore_Attrib_bool;
134   DWORD _altStream_NeedRestore_AttribVal;
135 
136   CMyComPtr2<ISequentialOutStream, COutFileStream> _outFileStream;
137 public:
138   CObjectVector<CVirtFile> Files;
139   size_t MaxTotalAllocSize; // remain size, including Files.Back()
140   FString DirPrefix; // files will be flushed to this FS directory.
141   UString FileName; // name of file that will be extracted.
142                     // it can be name of alt stream without "fileName:" prefix, if (IsAltStreamFile == trye).
143                     // we use that name to detect altStream part in "FileName:altStream".
144   CByteBuffer ZoneBuf;
145   int Index_of_MainExtractedFile_in_Files; // out: index in Files. == -1, if expected file was not extracted
146   int Index_of_ZoneBuf_AltStream_in_Files; // out: index in Files. == -1, if no zonbuf alt stream
147 
148 
CVirtFileSystem()149   CVirtFileSystem()
150   {
151     _numFlushed = 0;
152     IsAltStreamFile = false;
153     _newVirtFileStream_IsReadyToWrite = false;
154     _needWriteToRealFile = false;
155     _wasSwitchedToFsMode = false;
156     _altStream_NeedRestore_Attrib_bool = false;
157     MaxTotalAllocSize = (size_t)0 - 1;
158     Index_of_MainExtractedFile_in_Files = -1;
159     Index_of_ZoneBuf_AltStream_in_Files = -1;
160   }
161 
WasStreamFlushedToFS()162   bool WasStreamFlushedToFS() const { return _wasSwitchedToFsMode; }
163 
CloseMemFile()164   HRESULT CloseMemFile()
165   {
166     if (_wasSwitchedToFsMode)
167       return FlushToDisk(true); // closeLast
168     CVirtFile &file = Files.Back();
169     if (file.Data.Size() != file.WrittenSize)
170       file.Data.ReAlloc_KeepData(file.WrittenSize, file.WrittenSize);
171     return S_OK;
172   }
173 
174   HRESULT FlushToDisk(bool closeLast);
175 };
176 
177 #endif
178 
179 
180 
181 class CExtractCallbackImp Z7_final:
182   public IFolderArchiveExtractCallback,
183   /* IExtractCallbackUI:
184        before v23.00 : it         included IFolderArchiveExtractCallback
185        since  v23.00 : it doesn't include  IFolderArchiveExtractCallback
186   */
187   public IExtractCallbackUI, // NON-COM interface since 23.00
188   public IOpenCallbackUI,    // NON-COM interface
189   public IFolderArchiveExtractCallback2,
190  #ifndef Z7_SFX
191   public IFolderOperationsExtractCallback,
192   public IFolderExtractToStreamCallback,
193   public ICompressProgressInfo,
194   public IArchiveRequestMemoryUseCallback,
195  #endif
196  #ifndef Z7_NO_CRYPTO
197   public ICryptoGetTextPassword,
198  #endif
199   public CMyUnknownImp
200 {
201   Z7_COM_QI_BEGIN2(IFolderArchiveExtractCallback)
202   Z7_COM_QI_ENTRY(IFolderArchiveExtractCallback2)
203  #ifndef Z7_SFX
204   Z7_COM_QI_ENTRY(IFolderOperationsExtractCallback)
205   Z7_COM_QI_ENTRY(IFolderExtractToStreamCallback)
206   Z7_COM_QI_ENTRY(ICompressProgressInfo)
207   Z7_COM_QI_ENTRY(IArchiveRequestMemoryUseCallback)
208  #endif
209  #ifndef Z7_NO_CRYPTO
210   Z7_COM_QI_ENTRY(ICryptoGetTextPassword)
211  #endif
212   Z7_COM_QI_END
213   Z7_COM_ADDREF_RELEASE
214 
215   Z7_IFACE_IMP(IExtractCallbackUI)
216   Z7_IFACE_IMP(IOpenCallbackUI)
217   Z7_IFACE_COM7_IMP(IProgress)
218   Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback)
219   Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback2)
220  #ifndef Z7_SFX
221   Z7_IFACE_COM7_IMP(IFolderOperationsExtractCallback)
222   Z7_IFACE_COM7_IMP(IFolderExtractToStreamCallback)
223   Z7_IFACE_COM7_IMP(ICompressProgressInfo)
224   Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback)
225  #endif
226  #ifndef Z7_NO_CRYPTO
227   Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)
228  #endif
229 
230   bool _needWriteArchivePath;
231   bool _isFolder;
232   bool _totalFiles_Defined;
233   bool _totalBytes_Defined;
234 public:
235   bool MultiArcMode;
236   bool ProcessAltStreams;
237   bool StreamMode; // set to true, if you want the callee to call GetStream7()
238   bool ThereAreMessageErrors;
239   bool Src_Is_IO_FS_Folder;
240 
241 #ifndef Z7_NO_CRYPTO
242   bool PasswordIsDefined;
243   bool PasswordWasAsked;
244 #endif
245 
246 private:
247 #ifndef Z7_SFX
248   bool _needUpdateStat;
249   bool _newVirtFileWasAdded;
250   bool _isAltStream;
251   // bool _extractMode;
252   // bool _testMode;
253   bool _hashStream_WasUsed;
254   bool _curSize_Defined;
255   bool NeedAddFile;
256 
257   bool _remember;
258   bool _skipArc;
259 #endif
260 
261 public:
262   bool YesToAll;
263   bool TestMode;
264 
265   UInt32 NumArchiveErrors;
266   NExtract::NOverwriteMode::EEnum OverwriteMode;
267 
268 private:
269   UString _currentArchivePath;
270   UString _currentFilePath;
271   UString _filePath;  // virtual path than will be sent via IFolderExtractToStreamCallback
272 
273 #ifndef Z7_SFX
274   UInt64 _curSize;
275   CMyComPtr2<ISequentialOutStream, COutStreamWithHash> _hashStream;
276   IHashCalc *_hashCalc; // it's for stat in Test operation
277 #endif
278 
279 public:
280   CProgressDialog *ProgressDialog;
281 
282 #ifndef Z7_SFX
283   CVirtFileSystem *VirtFileSystemSpec;
284   CMyComPtr<ISequentialOutStream> VirtFileSystem;
285   UInt64 NumFolders;
286   UInt64 NumFiles;
287 #endif
288 
289 #ifndef Z7_NO_CRYPTO
290   UString Password;
291 #endif
292 
293   UString _lang_Extracting;
294   UString _lang_Testing;
295   UString _lang_Skipping;
296   UString _lang_Reading;
297   UString _lang_Empty;
298 
299   CExtractCallbackImp():
300       _totalFiles_Defined(false)
301     , _totalBytes_Defined(false)
302     , MultiArcMode(false)
303     , ProcessAltStreams(true)
304     , StreamMode(false)
305     , ThereAreMessageErrors(false)
306     , Src_Is_IO_FS_Folder(false)
307 #ifndef Z7_NO_CRYPTO
308     , PasswordIsDefined(false)
309     , PasswordWasAsked(false)
310 #endif
311 #ifndef Z7_SFX
312     , _remember(false)
313     , _skipArc(false)
314 #endif
315     , YesToAll(false)
316     , TestMode(false)
317     , OverwriteMode(NExtract::NOverwriteMode::kAsk)
318 #ifndef Z7_SFX
319     , _hashCalc(NULL)
320 #endif
321     {}
322 
323   ~CExtractCallbackImp();
324   void Init();
325 
326   HRESULT SetCurrentFilePath2(const wchar_t *filePath);
327   void AddError_Message(LPCWSTR message);
328   void AddError_Message_ShowArcPath(LPCWSTR message);
329   HRESULT MessageError(const char *message, const FString &path);
330   void Add_ArchiveName_Error();
331 
332   #ifndef Z7_SFX
333   void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; }
334 
335   void SetHashMethods(IHashCalc *hash)
336   {
337     if (!hash)
338       return;
339     _hashStream.Create_if_Empty();
340     _hashStream->_hash = hash;
341   }
342   #endif
343 
344   bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; }
345 };
346 
347 #endif
348