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