// ExtractCallbackConsole.cpp #include "StdAfx.h" // #undef sprintf #include "ConsoleClose.h" #include "ExtractCallbackConsole.h" #include "UserInputUtils.h" #include "../../../Common/IntToString.h" #include "../../../Common/Wildcard.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/TimeUtils.h" #include "../../../Windows/ErrorMsg.h" #include "../../../Windows/PropVariantConv.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" using namespace NWindows; using namespace NFile; using namespace NDir; static const char *kTestString = "Testing "; static const char *kExtractString = "Extracting "; static const char *kSkipString = "Skipping "; // static const char *kCantAutoRename = "can not create file with auto name\n"; // static const char *kCantRenameFile = "can not rename existing file\n"; // static const char *kCantDeleteOutputFile = "can not delete output file "; static const char *kError = "ERROR: "; static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; static const char *kProcessing = "Processing archive: "; static const char *kEverythingIsOk = "Everything is Ok"; static const char *kNoFiles = "No files to process"; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCrcFailed = "CRC Failed"; static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; static const char *kDataError = "Data Error"; static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; static const char *kUnavailableData = "Unavailable data"; static const char *kUnexpectedEnd = "Unexpected end of data"; static const char *kDataAfterEnd = "There are some data after the end of the payload data"; static const char *kIsNotArc = "Is not archive"; static const char *kHeadersError = "Headers Error"; static const char *k_ErrorFlagsMessages[] = { "Is not archive" , "Headers Error" , "Headers Error in encrypted archive. Wrong password?" , "Unavailable start of archive" , "Unconfirmed start of archive" , "Unexpected end of archive" , "There are data after the end of archive" , "Unsupported method" , "Unsupported feature" , "Data Error" , "CRC Error" }; STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::AskOverwrite( const wchar_t *existName, const FILETIME *, const UInt64 *, const wchar_t *newName, const FILETIME *, const UInt64 *, Int32 *answer) { (*OutStream) << "file " << existName << endl << "already exists. Overwrite with" << endl << newName; NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); switch (overwriteAnswer) { case NUserAnswerMode::kQuit: return E_ABORT; case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break; case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break; default: return E_FAIL; } return S_OK; } STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) { const char *s; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break; case NArchive::NExtract::NAskMode::kTest: s = kTestString; break; case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; break; default: s = ""; // return E_FAIL; }; (*OutStream) << s << name; if (position != 0) (*OutStream) << " <" << *position << ">"; return S_OK; } STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) { (*OutStream) << message << endl; NumFileErrorsInCurrent++; NumFileErrors++; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) { switch (operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumFileErrorsInCurrent++; NumFileErrors++; (*OutStream) << " : "; const char *s = NULL; switch (operationResult) { case NArchive::NExtract::NOperationResult::kUnsupportedMethod: s = kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: s = (encrypted ? kCrcFailedEncrypted : kCrcFailed); break; case NArchive::NExtract::NOperationResult::kDataError: s = (encrypted ? kDataErrorEncrypted : kDataError); break; case NArchive::NExtract::NOperationResult::kUnavailable: s = kUnavailableData; break; case NArchive::NExtract::NOperationResult::kUnexpectedEnd: s = kUnexpectedEnd; break; case NArchive::NExtract::NOperationResult::kDataAfterEnd: s = kDataAfterEnd; break; case NArchive::NExtract::NOperationResult::kIsNotArc: s = kIsNotArc; break; case NArchive::NExtract::NOperationResult::kHeadersError: s = kHeadersError; break; } if (s) (*OutStream) << "Error : " << s; else { char temp[16]; ConvertUInt32ToString(operationResult, temp); (*OutStream) << "Error #" << temp; } } } (*OutStream) << endl; return S_OK; } #ifndef _NO_CRYPTO HRESULT CExtractCallbackConsole::SetPassword(const UString &password) { PasswordIsDefined = true; Password = password; return S_OK; } STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } return StringToBstr(Password, password); } #endif HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) { NumTryArcs++; ThereIsErrorInCurrent = false; ThereIsWarningInCurrent = false; NumFileErrorsInCurrent = 0; (*OutStream) << endl << kProcessing << name << endl; return S_OK; } HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted) { (*OutStream) << endl; if (result != S_OK) { (*OutStream) << "Error: "; if (result == S_FALSE) { (*OutStream) << (encrypted ? "Can not open encrypted archive. Wrong password?" : "Can not open file as archive"); } else { if (result == E_OUTOFMEMORY) (*OutStream) << "Can't allocate required memory"; else (*OutStream) << NError::MyFormatMessage(result); } (*OutStream) << endl; NumCantOpenArcs++; ThereIsErrorInCurrent = true; } return S_OK; } AString GetOpenArcErrorMessage(UInt32 errorFlags) { AString s; for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsMessages); i++) { UInt32 f = (1 << i); if ((errorFlags & f) == 0) continue; const char *m = k_ErrorFlagsMessages[i]; if (!s.IsEmpty()) s += '\n'; s += m; errorFlags &= ~f; } if (errorFlags != 0) { char sz[16]; sz[0] = '0'; sz[1] = 'x'; ConvertUInt32ToHex(errorFlags, sz + 2); if (!s.IsEmpty()) s += '\n'; s += sz; } return s; } HRESULT CExtractCallbackConsole::SetError(int level, const wchar_t *name, UInt32 errorFlags, const wchar_t *errors, UInt32 warningFlags, const wchar_t *warnings) { if (level != 0) { (*OutStream) << name << endl; } if (errorFlags != 0) { (*OutStream) << "Errors: "; (*OutStream) << endl; (*OutStream) << GetOpenArcErrorMessage(errorFlags); (*OutStream) << endl; NumOpenArcErrors++; ThereIsErrorInCurrent = true; } if (errors && wcslen(errors) != 0) { (*OutStream) << "Errors: "; (*OutStream) << endl; (*OutStream) << errors; (*OutStream) << endl; NumOpenArcErrors++; ThereIsErrorInCurrent = true; } if (warningFlags != 0) { (*OutStream) << "Warnings: "; (*OutStream) << endl; (*OutStream) << GetOpenArcErrorMessage(warningFlags); (*OutStream) << endl; NumOpenArcWarnings++; ThereIsWarningInCurrent = true; } if (warnings && wcslen(warnings) != 0) { (*OutStream) << "Warnings: "; (*OutStream) << endl; (*OutStream) << warnings; (*OutStream) << endl; NumOpenArcWarnings++; ThereIsWarningInCurrent = true; } (*OutStream) << endl; return S_OK; } HRESULT CExtractCallbackConsole::ThereAreNoFiles() { (*OutStream) << endl << kNoFiles << endl; return S_OK; } HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) { if (result == S_OK) { (*OutStream) << endl; if (NumFileErrorsInCurrent == 0 && !ThereIsErrorInCurrent) { if (ThereIsWarningInCurrent) NumArcsWithWarnings++; else NumOkArcs++; (*OutStream) << kEverythingIsOk << endl; } else { NumArcsWithError++; if (NumFileErrorsInCurrent != 0) (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrent << endl; } return S_OK; } NumArcsWithError++; if (result == E_ABORT || result == ERROR_DISK_FULL) return result; (*OutStream) << endl << kError; if (result == E_OUTOFMEMORY) (*OutStream) << kMemoryExceptionMessage; else (*OutStream) << NError::MyFormatMessage(result); (*OutStream) << endl; return S_OK; } HRESULT CExtractCallbackConsole::OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType) { UString s = L"Warning:\n"; if (wcscmp(okType, errorType) == 0) { s += L"The archive is open with offset"; } else { s += name; s += L"\nCan not open the file as ["; s += errorType; s += L"] archive\n"; s += L"The file is open as ["; s += okType; s += L"] archive"; } (*OutStream) << s << endl << endl; ThereIsWarningInCurrent = true; return S_OK; }