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   CLASS_NO_COPY(CGrowBuf);
     40 
     41 public:
     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 
     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 
    143   size_t GetMemStreamWrittenSize() const { return _pos; }
    144 
    145   CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {}
    146 
    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);
    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 
    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
    313   void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; }
    314 
    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 
    325   bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; }
    326 };
    327 
    328 #endif
    329