Home | History | Annotate | Download | only in Console
      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 
     69 STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64)
     70 {
     71   if (NConsoleClose::TestBreakSignal())
     72     return E_ABORT;
     73   return S_OK;
     74 }
     75 
     76 STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *)
     77 {
     78   if (NConsoleClose::TestBreakSignal())
     79     return E_ABORT;
     80   return S_OK;
     81 }
     82 
     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 
    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 
    123 STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)
    124 {
    125   (*OutStream) << message << endl;
    126   NumFileErrorsInCurrent++;
    127   NumFileErrors++;
    128   return S_OK;
    129 }
    130 
    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 
    186 HRESULT CExtractCallbackConsole::SetPassword(const UString &password)
    187 {
    188   PasswordIsDefined = true;
    189   Password = password;
    190   return S_OK;
    191 }
    192 
    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 
    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 
    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 
    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 
    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 
    322 HRESULT CExtractCallbackConsole::ThereAreNoFiles()
    323 {
    324   (*OutStream) << endl << kNoFiles << endl;
    325   return S_OK;
    326 }
    327 
    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 
    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