• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // ExtractCallbackConsole.cpp
2 
3 #include "StdAfx.h"
4 
5 // #undef sprintf
6 
7 #include "ConsoleClose.h"
8 #include "ExtractCallbackConsole.h"
9 #include "UserInputUtils.h"
10 
11 #include "../../../Common/IntToString.h"
12 #include "../../../Common/Wildcard.h"
13 
14 #include "../../../Windows/FileDir.h"
15 #include "../../../Windows/FileFind.h"
16 #include "../../../Windows/TimeUtils.h"
17 #include "../../../Windows/ErrorMsg.h"
18 #include "../../../Windows/PropVariantConv.h"
19 
20 #include "../../Common/FilePathAutoRename.h"
21 
22 #include "../Common/ExtractingFilePath.h"
23 
24 using namespace NWindows;
25 using namespace NFile;
26 using namespace NDir;
27 
28 static const char *kTestString    =  "Testing     ";
29 static const char *kExtractString =  "Extracting  ";
30 static const char *kSkipString    =  "Skipping    ";
31 
32 // static const char *kCantAutoRename = "can not create file with auto name\n";
33 // static const char *kCantRenameFile = "can not rename existing file\n";
34 // static const char *kCantDeleteOutputFile = "can not delete output file ";
35 static const char *kError = "ERROR: ";
36 static const char *kMemoryExceptionMessage = "Can't allocate required memory!";
37 
38 static const char *kProcessing = "Processing archive: ";
39 static const char *kEverythingIsOk = "Everything is Ok";
40 static const char *kNoFiles = "No files to process";
41 
42 static const char *kUnsupportedMethod = "Unsupported Method";
43 static const char *kCrcFailed = "CRC Failed";
44 static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";
45 static const char *kDataError = "Data Error";
46 static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";
47 static const char *kUnavailableData = "Unavailable data";
48 static const char *kUnexpectedEnd = "Unexpected end of data";
49 static const char *kDataAfterEnd = "There are some data after the end of the payload data";
50 static const char *kIsNotArc = "Is not archive";
51 static const char *kHeadersError = "Headers Error";
52 
53 static const char *k_ErrorFlagsMessages[] =
54 {
55     "Is not archive"
56   , "Headers Error"
57   , "Headers Error in encrypted archive. Wrong password?"
58   , "Unavailable start of archive"
59   , "Unconfirmed start of archive"
60   , "Unexpected end of archive"
61   , "There are data after the end of archive"
62   , "Unsupported method"
63   , "Unsupported feature"
64   , "Data Error"
65   , "CRC Error"
66 };
67 
68 
SetTotal(UInt64)69 STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64)
70 {
71   if (NConsoleClose::TestBreakSignal())
72     return E_ABORT;
73   return S_OK;
74 }
75 
SetCompleted(const UInt64 *)76 STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *)
77 {
78   if (NConsoleClose::TestBreakSignal())
79     return E_ABORT;
80   return S_OK;
81 }
82 
AskOverwrite(const wchar_t * existName,const FILETIME *,const UInt64 *,const wchar_t * newName,const FILETIME *,const UInt64 *,Int32 * answer)83 STDMETHODIMP CExtractCallbackConsole::AskOverwrite(
84     const wchar_t *existName, const FILETIME *, const UInt64 *,
85     const wchar_t *newName, const FILETIME *, const UInt64 *,
86     Int32 *answer)
87 {
88   (*OutStream) << "file " << existName << endl <<
89         "already exists. Overwrite with" << endl <<
90         newName;
91 
92   NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream);
93 
94   switch (overwriteAnswer)
95   {
96     case NUserAnswerMode::kQuit:  return E_ABORT;
97     case NUserAnswerMode::kNo:     *answer = NOverwriteAnswer::kNo; break;
98     case NUserAnswerMode::kNoAll:  *answer = NOverwriteAnswer::kNoToAll; break;
99     case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break;
100     case NUserAnswerMode::kYes:    *answer = NOverwriteAnswer::kYes; break;
101     case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break;
102     default: return E_FAIL;
103   }
104   return S_OK;
105 }
106 
PrepareOperation(const wchar_t * name,bool,Int32 askExtractMode,const UInt64 * position)107 STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position)
108 {
109   const char *s;
110   switch (askExtractMode)
111   {
112     case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break;
113     case NArchive::NExtract::NAskMode::kTest:    s = kTestString; break;
114     case NArchive::NExtract::NAskMode::kSkip:    s = kSkipString; break;
115     default: s = ""; // return E_FAIL;
116   };
117   (*OutStream) << s << name;
118   if (position != 0)
119     (*OutStream) << " <" << *position << ">";
120   return S_OK;
121 }
122 
MessageError(const wchar_t * message)123 STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)
124 {
125   (*OutStream) << message << endl;
126   NumFileErrorsInCurrent++;
127   NumFileErrors++;
128   return S_OK;
129 }
130 
SetOperationResult(Int32 operationResult,bool encrypted)131 STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted)
132 {
133   switch (operationResult)
134   {
135     case NArchive::NExtract::NOperationResult::kOK:
136       break;
137     default:
138     {
139       NumFileErrorsInCurrent++;
140       NumFileErrors++;
141       (*OutStream) << "  :  ";
142       const char *s = NULL;
143       switch (operationResult)
144       {
145         case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
146           s = kUnsupportedMethod;
147           break;
148         case NArchive::NExtract::NOperationResult::kCRCError:
149           s = (encrypted ? kCrcFailedEncrypted : kCrcFailed);
150           break;
151         case NArchive::NExtract::NOperationResult::kDataError:
152           s = (encrypted ? kDataErrorEncrypted : kDataError);
153           break;
154         case NArchive::NExtract::NOperationResult::kUnavailable:
155           s = kUnavailableData;
156           break;
157         case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
158           s = kUnexpectedEnd;
159           break;
160         case NArchive::NExtract::NOperationResult::kDataAfterEnd:
161           s = kDataAfterEnd;
162           break;
163         case NArchive::NExtract::NOperationResult::kIsNotArc:
164           s = kIsNotArc;
165           break;
166         case NArchive::NExtract::NOperationResult::kHeadersError:
167           s = kHeadersError;
168           break;
169       }
170       if (s)
171         (*OutStream) << "Error : " << s;
172       else
173       {
174         char temp[16];
175         ConvertUInt32ToString(operationResult, temp);
176         (*OutStream) << "Error #" << temp;
177       }
178     }
179   }
180   (*OutStream) << endl;
181   return S_OK;
182 }
183 
184 #ifndef _NO_CRYPTO
185 
SetPassword(const UString & password)186 HRESULT CExtractCallbackConsole::SetPassword(const UString &password)
187 {
188   PasswordIsDefined = true;
189   Password = password;
190   return S_OK;
191 }
192 
CryptoGetTextPassword(BSTR * password)193 STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)
194 {
195   if (!PasswordIsDefined)
196   {
197     Password = GetPassword(OutStream);
198     PasswordIsDefined = true;
199   }
200   return StringToBstr(Password, password);
201 }
202 
203 #endif
204 
BeforeOpen(const wchar_t * name)205 HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name)
206 {
207   NumTryArcs++;
208   ThereIsErrorInCurrent = false;
209   ThereIsWarningInCurrent = false;
210   NumFileErrorsInCurrent = 0;
211   (*OutStream) << endl << kProcessing << name << endl;
212   return S_OK;
213 }
214 
OpenResult(const wchar_t *,HRESULT result,bool encrypted)215 HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted)
216 {
217   (*OutStream) << endl;
218   if (result != S_OK)
219   {
220     (*OutStream) << "Error: ";
221     if (result == S_FALSE)
222     {
223       (*OutStream) << (encrypted ?
224         "Can not open encrypted archive. Wrong password?" :
225         "Can not open file as archive");
226     }
227     else
228     {
229       if (result == E_OUTOFMEMORY)
230         (*OutStream) << "Can't allocate required memory";
231       else
232         (*OutStream) << NError::MyFormatMessage(result);
233     }
234     (*OutStream) << endl;
235     NumCantOpenArcs++;
236     ThereIsErrorInCurrent = true;
237   }
238   return S_OK;
239 }
240 
GetOpenArcErrorMessage(UInt32 errorFlags)241 AString GetOpenArcErrorMessage(UInt32 errorFlags)
242 {
243   AString s;
244   for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsMessages); i++)
245   {
246     UInt32 f = (1 << i);
247     if ((errorFlags & f) == 0)
248       continue;
249     const char *m = k_ErrorFlagsMessages[i];
250     if (!s.IsEmpty())
251       s += '\n';
252     s += m;
253     errorFlags &= ~f;
254   }
255   if (errorFlags != 0)
256   {
257     char sz[16];
258     sz[0] = '0';
259     sz[1] = 'x';
260     ConvertUInt32ToHex(errorFlags, sz + 2);
261     if (!s.IsEmpty())
262       s += '\n';
263     s += sz;
264   }
265   return s;
266 }
267 
268 
SetError(int level,const wchar_t * name,UInt32 errorFlags,const wchar_t * errors,UInt32 warningFlags,const wchar_t * warnings)269 HRESULT CExtractCallbackConsole::SetError(int level, const wchar_t *name,
270     UInt32 errorFlags, const wchar_t *errors,
271     UInt32 warningFlags, const wchar_t *warnings)
272 {
273   if (level != 0)
274   {
275     (*OutStream) << name << endl;
276   }
277 
278   if (errorFlags != 0)
279   {
280     (*OutStream) << "Errors: ";
281     (*OutStream) << endl;
282     (*OutStream) << GetOpenArcErrorMessage(errorFlags);
283     (*OutStream) << endl;
284     NumOpenArcErrors++;
285     ThereIsErrorInCurrent = true;
286   }
287 
288   if (errors && wcslen(errors) != 0)
289   {
290     (*OutStream) << "Errors: ";
291     (*OutStream) << endl;
292     (*OutStream) << errors;
293     (*OutStream) << endl;
294     NumOpenArcErrors++;
295     ThereIsErrorInCurrent = true;
296   }
297 
298   if (warningFlags != 0)
299   {
300     (*OutStream) << "Warnings: ";
301     (*OutStream) << endl;
302     (*OutStream) << GetOpenArcErrorMessage(warningFlags);
303     (*OutStream) << endl;
304     NumOpenArcWarnings++;
305     ThereIsWarningInCurrent = true;
306   }
307 
308   if (warnings && wcslen(warnings) != 0)
309   {
310     (*OutStream) << "Warnings: ";
311     (*OutStream) << endl;
312     (*OutStream) << warnings;
313     (*OutStream) << endl;
314     NumOpenArcWarnings++;
315     ThereIsWarningInCurrent = true;
316   }
317 
318   (*OutStream) << endl;
319   return S_OK;
320 }
321 
ThereAreNoFiles()322 HRESULT CExtractCallbackConsole::ThereAreNoFiles()
323 {
324   (*OutStream) << endl << kNoFiles << endl;
325   return S_OK;
326 }
327 
ExtractResult(HRESULT result)328 HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
329 {
330   if (result == S_OK)
331   {
332     (*OutStream) << endl;
333 
334     if (NumFileErrorsInCurrent == 0 && !ThereIsErrorInCurrent)
335     {
336       if (ThereIsWarningInCurrent)
337         NumArcsWithWarnings++;
338       else
339         NumOkArcs++;
340       (*OutStream) << kEverythingIsOk << endl;
341     }
342     else
343     {
344       NumArcsWithError++;
345       if (NumFileErrorsInCurrent != 0)
346         (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrent << endl;
347     }
348     return S_OK;
349   }
350 
351   NumArcsWithError++;
352   if (result == E_ABORT || result == ERROR_DISK_FULL)
353     return result;
354   (*OutStream) << endl << kError;
355   if (result == E_OUTOFMEMORY)
356     (*OutStream) << kMemoryExceptionMessage;
357   else
358     (*OutStream) << NError::MyFormatMessage(result);
359   (*OutStream) << endl;
360   return S_OK;
361 }
362 
OpenTypeWarning(const wchar_t * name,const wchar_t * okType,const wchar_t * errorType)363 HRESULT CExtractCallbackConsole::OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType)
364 {
365   UString s = L"Warning:\n";
366   if (wcscmp(okType, errorType) == 0)
367   {
368     s += L"The archive is open with offset";
369   }
370   else
371   {
372     s += name;
373     s += L"\nCan not open the file as [";
374     s += errorType;
375     s += L"] archive\n";
376     s += L"The file is open as [";
377     s += okType;
378     s += L"] archive";
379   }
380  (*OutStream) << s << endl << endl;
381  ThereIsWarningInCurrent = true;
382   return S_OK;
383 }
384