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