1370b324cSopenharmony_ci// ExtractCallbackSfx.h
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "../../../Common/Wildcard.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "../../../Windows/FileDir.h"
8370b324cSopenharmony_ci#include "../../../Windows/FileFind.h"
9370b324cSopenharmony_ci#include "../../../Windows/FileName.h"
10370b324cSopenharmony_ci#include "../../../Windows/PropVariant.h"
11370b324cSopenharmony_ci
12370b324cSopenharmony_ci#include "ExtractCallbackSfx.h"
13370b324cSopenharmony_ci
14370b324cSopenharmony_ciusing namespace NWindows;
15370b324cSopenharmony_ciusing namespace NFile;
16370b324cSopenharmony_ciusing namespace NDir;
17370b324cSopenharmony_ci
18370b324cSopenharmony_cistatic LPCSTR const kCantDeleteFile = "Cannot delete output file";
19370b324cSopenharmony_cistatic LPCSTR const kCantOpenFile = "Cannot open output file";
20370b324cSopenharmony_cistatic LPCSTR const kUnsupportedMethod = "Unsupported Method";
21370b324cSopenharmony_ci
22370b324cSopenharmony_civoid CExtractCallbackImp::Init(IInArchive *archiveHandler,
23370b324cSopenharmony_ci    const FString &directoryPath,
24370b324cSopenharmony_ci    const UString &itemDefaultName,
25370b324cSopenharmony_ci    const FILETIME &defaultMTime,
26370b324cSopenharmony_ci    UInt32 defaultAttributes)
27370b324cSopenharmony_ci{
28370b324cSopenharmony_ci  _message.Empty();
29370b324cSopenharmony_ci  _isCorrupt = false;
30370b324cSopenharmony_ci  _itemDefaultName = itemDefaultName;
31370b324cSopenharmony_ci  _defaultMTime = defaultMTime;
32370b324cSopenharmony_ci  _defaultAttributes = defaultAttributes;
33370b324cSopenharmony_ci  _archiveHandler = archiveHandler;
34370b324cSopenharmony_ci  _directoryPath = directoryPath;
35370b324cSopenharmony_ci  NName::NormalizeDirPathPrefix(_directoryPath);
36370b324cSopenharmony_ci}
37370b324cSopenharmony_ci
38370b324cSopenharmony_ciHRESULT CExtractCallbackImp::Open_CheckBreak()
39370b324cSopenharmony_ci{
40370b324cSopenharmony_ci  #ifndef _NO_PROGRESS
41370b324cSopenharmony_ci  return ProgressDialog.Sync.ProcessStopAndPause();
42370b324cSopenharmony_ci  #else
43370b324cSopenharmony_ci  return S_OK;
44370b324cSopenharmony_ci  #endif
45370b324cSopenharmony_ci}
46370b324cSopenharmony_ci
47370b324cSopenharmony_ciHRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
48370b324cSopenharmony_ci{
49370b324cSopenharmony_ci  return S_OK;
50370b324cSopenharmony_ci}
51370b324cSopenharmony_ci
52370b324cSopenharmony_ciHRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)
53370b324cSopenharmony_ci{
54370b324cSopenharmony_ci  #ifndef _NO_PROGRESS
55370b324cSopenharmony_ci  return ProgressDialog.Sync.ProcessStopAndPause();
56370b324cSopenharmony_ci  #else
57370b324cSopenharmony_ci  return S_OK;
58370b324cSopenharmony_ci  #endif
59370b324cSopenharmony_ci}
60370b324cSopenharmony_ci
61370b324cSopenharmony_ciHRESULT CExtractCallbackImp::Open_Finished()
62370b324cSopenharmony_ci{
63370b324cSopenharmony_ci  return S_OK;
64370b324cSopenharmony_ci}
65370b324cSopenharmony_ci
66370b324cSopenharmony_ciZ7_COM7F_IMF(CExtractCallbackImp::SetTotal(UInt64 size))
67370b324cSopenharmony_ci{
68370b324cSopenharmony_ci  #ifndef _NO_PROGRESS
69370b324cSopenharmony_ci  ProgressDialog.Sync.SetProgress(size, 0);
70370b324cSopenharmony_ci  #endif
71370b324cSopenharmony_ci  return S_OK;
72370b324cSopenharmony_ci}
73370b324cSopenharmony_ci
74370b324cSopenharmony_ciZ7_COM7F_IMF(CExtractCallbackImp::SetCompleted(const UInt64 *completeValue))
75370b324cSopenharmony_ci{
76370b324cSopenharmony_ci  #ifndef _NO_PROGRESS
77370b324cSopenharmony_ci  RINOK(ProgressDialog.Sync.ProcessStopAndPause())
78370b324cSopenharmony_ci  if (completeValue != NULL)
79370b324cSopenharmony_ci    ProgressDialog.Sync.SetPos(*completeValue);
80370b324cSopenharmony_ci  #endif
81370b324cSopenharmony_ci  return S_OK;
82370b324cSopenharmony_ci}
83370b324cSopenharmony_ci
84370b324cSopenharmony_civoid CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts)
85370b324cSopenharmony_ci{
86370b324cSopenharmony_ci  FString fullPath = _directoryPath;
87370b324cSopenharmony_ci  FOR_VECTOR (i, dirPathParts)
88370b324cSopenharmony_ci  {
89370b324cSopenharmony_ci    fullPath += us2fs(dirPathParts[i]);
90370b324cSopenharmony_ci    CreateDir(fullPath);
91370b324cSopenharmony_ci    fullPath.Add_PathSepar();
92370b324cSopenharmony_ci  }
93370b324cSopenharmony_ci}
94370b324cSopenharmony_ci
95370b324cSopenharmony_ciZ7_COM7F_IMF(CExtractCallbackImp::GetStream(UInt32 index,
96370b324cSopenharmony_ci    ISequentialOutStream **outStream, Int32 askExtractMode))
97370b324cSopenharmony_ci{
98370b324cSopenharmony_ci  #ifndef _NO_PROGRESS
99370b324cSopenharmony_ci  if (ProgressDialog.Sync.GetStopped())
100370b324cSopenharmony_ci    return E_ABORT;
101370b324cSopenharmony_ci  #endif
102370b324cSopenharmony_ci  _outFileStream.Release();
103370b324cSopenharmony_ci
104370b324cSopenharmony_ci  UString fullPath;
105370b324cSopenharmony_ci  {
106370b324cSopenharmony_ci    NCOM::CPropVariant prop;
107370b324cSopenharmony_ci    RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop))
108370b324cSopenharmony_ci    if (prop.vt == VT_EMPTY)
109370b324cSopenharmony_ci      fullPath = _itemDefaultName;
110370b324cSopenharmony_ci    else
111370b324cSopenharmony_ci    {
112370b324cSopenharmony_ci      if (prop.vt != VT_BSTR)
113370b324cSopenharmony_ci        return E_FAIL;
114370b324cSopenharmony_ci      fullPath.SetFromBstr(prop.bstrVal);
115370b324cSopenharmony_ci    }
116370b324cSopenharmony_ci    _filePath = fullPath;
117370b324cSopenharmony_ci  }
118370b324cSopenharmony_ci
119370b324cSopenharmony_ci  if (askExtractMode == NArchive::NExtract::NAskMode::kExtract)
120370b324cSopenharmony_ci  {
121370b324cSopenharmony_ci    NCOM::CPropVariant prop;
122370b324cSopenharmony_ci    RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop))
123370b324cSopenharmony_ci    if (prop.vt == VT_EMPTY)
124370b324cSopenharmony_ci      _processedFileInfo.Attributes = _defaultAttributes;
125370b324cSopenharmony_ci    else
126370b324cSopenharmony_ci    {
127370b324cSopenharmony_ci      if (prop.vt != VT_UI4)
128370b324cSopenharmony_ci        return E_FAIL;
129370b324cSopenharmony_ci      _processedFileInfo.Attributes = prop.ulVal;
130370b324cSopenharmony_ci    }
131370b324cSopenharmony_ci
132370b324cSopenharmony_ci    RINOK(_archiveHandler->GetProperty(index, kpidIsDir, &prop))
133370b324cSopenharmony_ci    _processedFileInfo.IsDir = VARIANT_BOOLToBool(prop.boolVal);
134370b324cSopenharmony_ci
135370b324cSopenharmony_ci    bool isAnti = false;
136370b324cSopenharmony_ci    {
137370b324cSopenharmony_ci      NCOM::CPropVariant propTemp;
138370b324cSopenharmony_ci      RINOK(_archiveHandler->GetProperty(index, kpidIsAnti, &propTemp))
139370b324cSopenharmony_ci      if (propTemp.vt == VT_BOOL)
140370b324cSopenharmony_ci        isAnti = VARIANT_BOOLToBool(propTemp.boolVal);
141370b324cSopenharmony_ci    }
142370b324cSopenharmony_ci
143370b324cSopenharmony_ci    RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop))
144370b324cSopenharmony_ci    switch (prop.vt)
145370b324cSopenharmony_ci    {
146370b324cSopenharmony_ci      case VT_EMPTY: _processedFileInfo.MTime = _defaultMTime; break;
147370b324cSopenharmony_ci      case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; break;
148370b324cSopenharmony_ci      default: return E_FAIL;
149370b324cSopenharmony_ci    }
150370b324cSopenharmony_ci
151370b324cSopenharmony_ci    UStringVector pathParts;
152370b324cSopenharmony_ci    SplitPathToParts(fullPath, pathParts);
153370b324cSopenharmony_ci    if (pathParts.IsEmpty())
154370b324cSopenharmony_ci      return E_FAIL;
155370b324cSopenharmony_ci
156370b324cSopenharmony_ci    UString processedPath = fullPath;
157370b324cSopenharmony_ci
158370b324cSopenharmony_ci    if (!_processedFileInfo.IsDir)
159370b324cSopenharmony_ci      pathParts.DeleteBack();
160370b324cSopenharmony_ci    if (!pathParts.IsEmpty())
161370b324cSopenharmony_ci    {
162370b324cSopenharmony_ci      if (!isAnti)
163370b324cSopenharmony_ci        CreateComplexDirectory(pathParts);
164370b324cSopenharmony_ci    }
165370b324cSopenharmony_ci
166370b324cSopenharmony_ci    FString fullProcessedPath = _directoryPath + us2fs(processedPath);
167370b324cSopenharmony_ci
168370b324cSopenharmony_ci    if (_processedFileInfo.IsDir)
169370b324cSopenharmony_ci    {
170370b324cSopenharmony_ci      _diskFilePath = fullProcessedPath;
171370b324cSopenharmony_ci
172370b324cSopenharmony_ci      if (isAnti)
173370b324cSopenharmony_ci        RemoveDir(_diskFilePath);
174370b324cSopenharmony_ci      else
175370b324cSopenharmony_ci        SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime);
176370b324cSopenharmony_ci      return S_OK;
177370b324cSopenharmony_ci    }
178370b324cSopenharmony_ci
179370b324cSopenharmony_ci    NFind::CFileInfo fileInfo;
180370b324cSopenharmony_ci    if (fileInfo.Find(fullProcessedPath))
181370b324cSopenharmony_ci    {
182370b324cSopenharmony_ci      if (!DeleteFileAlways(fullProcessedPath))
183370b324cSopenharmony_ci      {
184370b324cSopenharmony_ci        _message = kCantDeleteFile;
185370b324cSopenharmony_ci        return E_FAIL;
186370b324cSopenharmony_ci      }
187370b324cSopenharmony_ci    }
188370b324cSopenharmony_ci
189370b324cSopenharmony_ci    if (!isAnti)
190370b324cSopenharmony_ci    {
191370b324cSopenharmony_ci      _outFileStreamSpec = new COutFileStream;
192370b324cSopenharmony_ci      CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
193370b324cSopenharmony_ci      if (!_outFileStreamSpec->Create(fullProcessedPath, true))
194370b324cSopenharmony_ci      {
195370b324cSopenharmony_ci        _message = kCantOpenFile;
196370b324cSopenharmony_ci        return E_FAIL;
197370b324cSopenharmony_ci      }
198370b324cSopenharmony_ci      _outFileStream = outStreamLoc;
199370b324cSopenharmony_ci      *outStream = outStreamLoc.Detach();
200370b324cSopenharmony_ci    }
201370b324cSopenharmony_ci    _diskFilePath = fullProcessedPath;
202370b324cSopenharmony_ci  }
203370b324cSopenharmony_ci  else
204370b324cSopenharmony_ci  {
205370b324cSopenharmony_ci    *outStream = NULL;
206370b324cSopenharmony_ci  }
207370b324cSopenharmony_ci  return S_OK;
208370b324cSopenharmony_ci}
209370b324cSopenharmony_ci
210370b324cSopenharmony_ciZ7_COM7F_IMF(CExtractCallbackImp::PrepareOperation(Int32 askExtractMode))
211370b324cSopenharmony_ci{
212370b324cSopenharmony_ci  _extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract);
213370b324cSopenharmony_ci  return S_OK;
214370b324cSopenharmony_ci}
215370b324cSopenharmony_ci
216370b324cSopenharmony_ciZ7_COM7F_IMF(CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult))
217370b324cSopenharmony_ci{
218370b324cSopenharmony_ci  switch (resultEOperationResult)
219370b324cSopenharmony_ci  {
220370b324cSopenharmony_ci    case NArchive::NExtract::NOperationResult::kOK:
221370b324cSopenharmony_ci      break;
222370b324cSopenharmony_ci
223370b324cSopenharmony_ci    default:
224370b324cSopenharmony_ci    {
225370b324cSopenharmony_ci      _outFileStream.Release();
226370b324cSopenharmony_ci      switch (resultEOperationResult)
227370b324cSopenharmony_ci      {
228370b324cSopenharmony_ci        case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
229370b324cSopenharmony_ci          _message = kUnsupportedMethod;
230370b324cSopenharmony_ci          break;
231370b324cSopenharmony_ci        default:
232370b324cSopenharmony_ci          _isCorrupt = true;
233370b324cSopenharmony_ci      }
234370b324cSopenharmony_ci      return E_FAIL;
235370b324cSopenharmony_ci    }
236370b324cSopenharmony_ci  }
237370b324cSopenharmony_ci  if (_outFileStream != NULL)
238370b324cSopenharmony_ci  {
239370b324cSopenharmony_ci    _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);
240370b324cSopenharmony_ci    RINOK(_outFileStreamSpec->Close())
241370b324cSopenharmony_ci  }
242370b324cSopenharmony_ci  _outFileStream.Release();
243370b324cSopenharmony_ci  if (_extractMode)
244370b324cSopenharmony_ci    SetFileAttrib(_diskFilePath, _processedFileInfo.Attributes);
245370b324cSopenharmony_ci  return S_OK;
246370b324cSopenharmony_ci}
247