Home | History | Annotate | Download | only in FileManager
      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   CGrowBuf(const CGrowBuf &buffer);
     40   void operator=(const CGrowBuf &buffer);
     41 
     42 public:
     43   bool ReAlloc_KeepData(size_t newSize, size_t keepSize)
     44   {
     45     void *buf = MyAlloc(newSize);
     46     if (!buf)
     47       return false;
     48     memcpy(buf, _items, keepSize);
     49     MyFree(_items);
     50     _items = (Byte *)buf;
     51     _size = newSize;
     52     return true;
     53   }
     54 
     55   CGrowBuf(): _items(0), _size(0) {}
     56   ~CGrowBuf() { MyFree(_items); }
     57 
     58   operator Byte *() { return _items; };
     59   operator const Byte *() const { return _items; };
     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 
     86   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 
    112   CVirtFile &AddNewFile()
    113   {
    114     if (!Files.IsEmpty())
    115     {
    116       MaxTotalAllocSize -= Files.Back().Data.Size();
    117     }
    118     return Files.AddNew();
    119   }
    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 
    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   size_t GetMemStreamWrittenSize() const { return _pos; }
    143 
    144   CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {}
    145 
    146   void Init()
    147   {
    148     _totalAllocSize = 0;
    149     _fileMode = false;
    150     _pos = 0;
    151     _numFlushed = 0;
    152     _fileIsOpen = false;
    153   }
    154 
    155   HRESULT CloseFile(const FString &path);
    156   HRESULT FlushToDisk(bool closeLast);
    157   size_t GetPos() const { return _pos; }
    158 
    159   MY_UNKNOWN_IMP
    160   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
    161 };
    162 
    163 #endif
    164 
    165 class CExtractCallbackImp:
    166   public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback
    167   public IOpenCallbackUI,
    168   #ifndef _SFX
    169   public IFolderOperationsExtractCallback,
    170   public IFolderExtractToStreamCallback,
    171   public ICompressProgressInfo,
    172   #endif
    173   #ifndef _NO_CRYPTO
    174   public ICryptoGetTextPassword,
    175   #endif
    176   public CMyUnknownImp
    177 {
    178   HRESULT MessageError(const char *message, const FString &path);
    179 public:
    180   MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)
    181   #ifndef _SFX
    182   MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback)
    183   MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback)
    184   MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo)
    185   #endif
    186   #ifndef _NO_CRYPTO
    187   MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
    188   #endif
    189   MY_QUERYINTERFACE_END
    190   MY_ADDREF_RELEASE
    191 
    192   INTERFACE_IProgress(;)
    193   INTERFACE_IOpenCallbackUI(;)
    194 
    195   // IFolderArchiveExtractCallback
    196   // STDMETHOD(SetTotalFiles)(UInt64 total);
    197   // STDMETHOD(SetCompletedFiles)(const UInt64 *value);
    198   STDMETHOD(AskOverwrite)(
    199       const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
    200       const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
    201       Int32 *answer);
    202   STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);
    203 
    204   STDMETHOD(MessageError)(const wchar_t *message);
    205   STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted);
    206 
    207   // IExtractCallbackUI
    208 
    209   HRESULT BeforeOpen(const wchar_t *name);
    210   HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted);
    211   HRESULT SetError(int level, const wchar_t *name,
    212       UInt32 errorFlags, const wchar_t *errors,
    213       UInt32 warningFlags, const wchar_t *warnings);
    214   HRESULT ThereAreNoFiles();
    215   HRESULT ExtractResult(HRESULT result);
    216   HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType);
    217 
    218   #ifndef _NO_CRYPTO
    219   HRESULT SetPassword(const UString &password);
    220   #endif
    221 
    222   #ifndef _SFX
    223   // IFolderOperationsExtractCallback
    224   STDMETHOD(AskWrite)(
    225       const wchar_t *srcPath,
    226       Int32 srcIsFolder,
    227       const FILETIME *srcTime,
    228       const UInt64 *srcSize,
    229       const wchar_t *destPathRequest,
    230       BSTR *destPathResult,
    231       Int32 *writeAnswer);
    232   STDMETHOD(ShowMessage)(const wchar_t *message);
    233   STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath);
    234   STDMETHOD(SetNumFiles)(UInt64 numFiles);
    235   INTERFACE_IFolderExtractToStreamCallback(;)
    236   STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
    237   #endif
    238 
    239   // ICryptoGetTextPassword
    240   #ifndef _NO_CRYPTO
    241   STDMETHOD(CryptoGetTextPassword)(BSTR *password);
    242   #endif
    243 
    244 private:
    245   UString _currentArchivePath;
    246   bool _needWriteArchivePath;
    247 
    248   UString _currentFilePath;
    249   bool _isFolder;
    250 
    251   bool _isAltStream;
    252   UInt64 _curSize;
    253   bool _curSizeDefined;
    254   UString _filePath;
    255   // bool _extractMode;
    256   // bool _testMode;
    257   bool _newVirtFileWasAdded;
    258   bool _needUpdateStat;
    259 
    260 
    261   HRESULT SetCurrentFilePath2(const wchar_t *filePath);
    262   void AddError_Message(LPCWSTR message);
    263 
    264   #ifndef _SFX
    265   bool _hashStreamWasUsed;
    266   COutStreamWithHash *_hashStreamSpec;
    267   CMyComPtr<ISequentialOutStream> _hashStream;
    268   IHashCalc *_hashCalc; // it's for stat in Test operation
    269   #endif
    270 
    271 public:
    272 
    273   #ifndef _SFX
    274   CVirtFileSystem *VirtFileSystemSpec;
    275   CMyComPtr<ISequentialOutStream> VirtFileSystem;
    276   #endif
    277 
    278   bool ProcessAltStreams;
    279 
    280   bool StreamMode;
    281 
    282   CProgressDialog *ProgressDialog;
    283   #ifndef _SFX
    284   UInt64 NumFolders;
    285   UInt64 NumFiles;
    286   bool NeedAddFile;
    287   #endif
    288   UInt32 NumArchiveErrors;
    289   bool ThereAreMessageErrors;
    290   NExtract::NOverwriteMode::EEnum OverwriteMode;
    291 
    292   #ifndef _NO_CRYPTO
    293   bool PasswordIsDefined;
    294   bool PasswordWasAsked;
    295   UString Password;
    296   #endif
    297 
    298   CExtractCallbackImp():
    299     #ifndef _NO_CRYPTO
    300     PasswordIsDefined(false),
    301     PasswordWasAsked(false),
    302     #endif
    303     OverwriteMode(NExtract::NOverwriteMode::kAsk),
    304     StreamMode(false),
    305     ProcessAltStreams(true)
    306     #ifndef _SFX
    307     , _hashCalc(NULL)
    308     #endif
    309     {}
    310 
    311   ~CExtractCallbackImp();
    312   void Init();
    313 
    314   #ifndef _SFX
    315   void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; }
    316 
    317   void SetHashMethods(IHashCalc *hash)
    318   {
    319     if (!hash)
    320       return;
    321     _hashStreamSpec = new COutStreamWithHash;
    322     _hashStream = _hashStreamSpec;
    323     _hashStreamSpec->_hash = hash;
    324   }
    325   #endif
    326 
    327   bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; }
    328 };
    329 
    330 #endif
    331