1 // Main.cpp 2 3 #include "StdAfx.h" 4 5 #include "../../../Common/MyWindows.h" 6 7 #include "../../../Common/MyInitGuid.h" 8 9 #include "../../../Common/CommandLineParser.h" 10 #include "../../../Common/MyException.h" 11 12 #ifdef _WIN32 13 #include "../../../Windows/DLL.h" 14 #include "../../../Windows/FileDir.h" 15 #endif 16 #include "../../../Windows/FileName.h" 17 18 #include "../../UI/Common/ExitCode.h" 19 #include "../../UI/Common/Extract.h" 20 21 #include "../../UI/Console/ExtractCallbackConsole.h" 22 #include "../../UI/Console/List.h" 23 #include "../../UI/Console/OpenCallbackConsole.h" 24 25 #include "../../MyVersion.h" 26 27 #include "../../../../C/DllSecur.h" 28 29 using namespace NWindows; 30 using namespace NFile; 31 using namespace NDir; 32 using namespace NCommandLineParser; 33 34 #ifdef _WIN32 35 HINSTANCE g_hInstance = 0; 36 #endif 37 int g_CodePage = -1; 38 extern CStdOutStream *g_StdStream; 39 40 static const char *kCopyrightString = 41 "\n7-Zip SFX " MY_VERSION_COPYRIGHT_DATE "\n"; 42 43 static const int kNumSwitches = 6; 44 45 namespace NKey { 46 enum Enum 47 { 48 kHelp1 = 0, 49 kHelp2, 50 kDisablePercents, 51 kYes, 52 kPassword, 53 kOutputDir 54 }; 55 56 } 57 58 namespace NRecursedType { 59 enum EEnum 60 { 61 kRecursed, 62 kWildcardOnlyRecursed, 63 kNonRecursed 64 }; 65 } 66 /* 67 static const char kRecursedIDChar = 'R'; 68 static const wchar_t *kRecursedPostCharSet = L"0-"; 69 70 namespace NRecursedPostCharIndex { 71 enum EEnum 72 { 73 kWildcardRecursionOnly = 0, 74 kNoRecursion = 1 75 }; 76 } 77 78 static const char kFileListID = '@'; 79 static const char kImmediateNameID = '!'; 80 81 static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be 82 static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be 83 */ 84 static const CSwitchForm kSwitchForms[kNumSwitches] = 85 { 86 { "?", NSwitchType::kSimple }, 87 { "H", NSwitchType::kSimple }, 88 { "BD", NSwitchType::kSimple }, 89 { "Y", NSwitchType::kSimple }, 90 { "P", NSwitchType::kString, false, 1 }, 91 { "O", NSwitchType::kString, false, 1 }, 92 }; 93 94 static const int kNumCommandForms = 3; 95 96 static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] = 97 { 98 NRecursedType::kRecursed 99 }; 100 101 // static const bool kTestExtractRecursedDefault = true; 102 // static const bool kAddRecursedDefault = false; 103 104 static const wchar_t *kUniversalWildcard = L"*"; 105 static const int kCommandIndex = 0; 106 107 static const char *kHelpString = 108 "\nUsage: 7zSFX [<command>] [<switches>...] [<file_name>...]\n" 109 "\n" 110 "<Commands>\n" 111 // " l: List contents of archive\n" 112 " t: Test integrity of archive\n" 113 " x: eXtract files with full pathname (default)\n" 114 "<Switches>\n" 115 // " -bd Disable percentage indicator\n" 116 " -o{Directory}: set Output directory\n" 117 " -p{Password}: set Password\n" 118 " -y: assume Yes on all queries\n"; 119 120 121 // --------------------------- 122 // exception messages 123 124 static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError 125 // static const char *kIncorrectListFile = "Incorrect wildcard in listfile"; 126 static const char *kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line"; 127 128 // static const CSysString kFileIsNotArchiveMessageBefore = "File \""; 129 // static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive"; 130 131 // static const char *kProcessArchiveMessage = " archive: "; 132 133 static const char *kCantFindSFX = " cannot find sfx"; 134 135 namespace NCommandType 136 { 137 enum EEnum 138 { 139 kTest = 0, 140 kFullExtract, 141 kList 142 }; 143 } 144 145 static const char *g_Commands = "txl"; 146 147 struct CArchiveCommand 148 { 149 NCommandType::EEnum CommandType; 150 151 NRecursedType::EEnum DefaultRecursedType() const; 152 }; 153 154 bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) 155 { 156 UString s = commandString; 157 s.MakeLower_Ascii(); 158 if (s.Len() != 1) 159 return false; 160 if (s[0] >= 0x80) 161 return false; 162 int index = FindCharPosInString(g_Commands, (char)s[0]); 163 if (index < 0) 164 return false; 165 command.CommandType = (NCommandType::EEnum)index; 166 return true; 167 } 168 169 NRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const 170 { 171 return kCommandRecursedDefault[CommandType]; 172 } 173 174 void PrintHelp(void) 175 { 176 g_StdOut << kHelpString; 177 } 178 179 static void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code) 180 { 181 g_StdOut << message << endl; 182 throw code; 183 } 184 185 static void PrintHelpAndExit() // yyy 186 { 187 PrintHelp(); 188 ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError); 189 } 190 191 // ------------------------------------------------------------------ 192 // filenames functions 193 194 static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, 195 const UString &name, bool include, NRecursedType::EEnum type) 196 { 197 /* 198 if (!IsWildcardFilePathLegal(name)) 199 return false; 200 */ 201 bool isWildcard = DoesNameContainWildcard(name); 202 bool recursed = false; 203 204 switch (type) 205 { 206 case NRecursedType::kWildcardOnlyRecursed: 207 recursed = isWildcard; 208 break; 209 case NRecursedType::kRecursed: 210 recursed = true; 211 break; 212 case NRecursedType::kNonRecursed: 213 recursed = false; 214 break; 215 } 216 wildcardCensor.AddPreItem(include, name, recursed, true); 217 return true; 218 } 219 220 void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor, 221 const UString &name, bool include, NRecursedType::EEnum type) 222 { 223 if (!AddNameToCensor(wildcardCensor, name, include, type)) 224 ShowMessageAndThrowException(kIncorrectWildcardInCommandLine, NExitCode::kUserError); 225 } 226 227 228 #ifndef _WIN32 229 static void GetArguments(int numArgs, const char *args[], UStringVector &parts) 230 { 231 parts.Clear(); 232 for (int i = 0; i < numArgs; i++) 233 { 234 UString s = MultiByteToUnicodeString(args[i]); 235 parts.Add(s); 236 } 237 } 238 #endif 239 240 int Main2( 241 #ifndef _WIN32 242 int numArgs, const char *args[] 243 #endif 244 ) 245 { 246 #ifdef _WIN32 247 // do we need load Security DLLs for console program? 248 LoadSecurityDlls(); 249 #endif 250 251 #if defined(_WIN32) && !defined(UNDER_CE) 252 SetFileApisToOEM(); 253 #endif 254 255 g_StdOut << kCopyrightString; 256 257 UStringVector commandStrings; 258 #ifdef _WIN32 259 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); 260 #else 261 GetArguments(numArgs, args, commandStrings); 262 #endif 263 264 #ifdef _WIN32 265 266 FString arcPath; 267 { 268 FString path; 269 NDLL::MyGetModuleFileName(path); 270 if (!MyGetFullPathName(path, arcPath)) 271 { 272 g_StdOut << "GetFullPathName Error"; 273 return NExitCode::kFatalError; 274 } 275 } 276 277 #else 278 279 UString arcPath = commandStrings.Front(); 280 281 #endif 282 283 commandStrings.Delete(0); 284 285 NCommandLineParser::CParser parser(kNumSwitches); 286 287 try 288 { 289 if (!parser.ParseStrings(kSwitchForms, commandStrings)) 290 { 291 g_StdOut << "Command line error:" << endl 292 << parser.ErrorMessage << endl 293 << parser.ErrorLine << endl; 294 return NExitCode::kUserError; 295 } 296 } 297 catch(...) 298 { 299 PrintHelpAndExit(); 300 } 301 302 if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) 303 { 304 PrintHelp(); 305 return 0; 306 } 307 308 const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; 309 310 unsigned curCommandIndex = 0; 311 312 CArchiveCommand command; 313 if (nonSwitchStrings.IsEmpty()) 314 command.CommandType = NCommandType::kFullExtract; 315 else 316 { 317 const UString &cmd = nonSwitchStrings[curCommandIndex]; 318 if (!ParseArchiveCommand(cmd, command)) 319 { 320 g_StdOut << "ERROR: Unknown command:" << endl << cmd << endl; 321 return NExitCode::kUserError; 322 } 323 curCommandIndex = 1; 324 } 325 326 327 NRecursedType::EEnum recursedType; 328 recursedType = command.DefaultRecursedType(); 329 330 NWildcard::CCensor wildcardCensor; 331 332 { 333 if (nonSwitchStrings.Size() == curCommandIndex) 334 AddCommandLineWildcardToCensor(wildcardCensor, kUniversalWildcard, true, recursedType); 335 for (; curCommandIndex < nonSwitchStrings.Size(); curCommandIndex++) 336 { 337 const UString &s = nonSwitchStrings[curCommandIndex]; 338 if (s.IsEmpty()) 339 throw "Empty file path"; 340 AddCommandLineWildcardToCensor(wildcardCensor, s, true, recursedType); 341 } 342 } 343 344 bool yesToAll = parser[NKey::kYes].ThereIs; 345 346 // NExtractMode::EEnum extractMode; 347 // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode); 348 349 bool passwordEnabled = parser[NKey::kPassword].ThereIs; 350 351 UString password; 352 if (passwordEnabled) 353 password = parser[NKey::kPassword].PostStrings[0]; 354 355 if (!NFind::DoesFileExist(arcPath)) 356 throw kCantFindSFX; 357 358 FString outputDir; 359 if (parser[NKey::kOutputDir].ThereIs) 360 { 361 outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); 362 NName::NormalizeDirPathPrefix(outputDir); 363 } 364 365 366 wildcardCensor.AddPathsToCensor(NWildcard::k_RelatPath); 367 368 { 369 UStringVector v1, v2; 370 v1.Add(fs2us(arcPath)); 371 v2.Add(fs2us(arcPath)); 372 const NWildcard::CCensorNode &wildcardCensorHead = 373 wildcardCensor.Pairs.Front().Head; 374 375 CCodecs *codecs = new CCodecs; 376 CMyComPtr< 377 #ifdef EXTERNAL_CODECS 378 ICompressCodecsInfo 379 #else 380 IUnknown 381 #endif 382 > compressCodecsInfo = codecs; 383 { 384 HRESULT result = codecs->Load(); 385 if (result != S_OK) 386 throw CSystemException(result); 387 } 388 389 if (command.CommandType != NCommandType::kList) 390 { 391 CExtractCallbackConsole *ecs = new CExtractCallbackConsole; 392 CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; 393 ecs->Init(g_StdStream, &g_StdErr, g_StdStream); 394 395 #ifndef _NO_CRYPTO 396 ecs->PasswordIsDefined = passwordEnabled; 397 ecs->Password = password; 398 #endif 399 400 /* 401 COpenCallbackConsole openCallback; 402 openCallback.Init(g_StdStream, g_StdStream); 403 404 #ifndef _NO_CRYPTO 405 openCallback.PasswordIsDefined = passwordEnabled; 406 openCallback.Password = password; 407 #endif 408 */ 409 410 CExtractOptions eo; 411 eo.StdOutMode = false; 412 eo.YesToAll = yesToAll; 413 eo.TestMode = command.CommandType == NCommandType::kTest; 414 eo.PathMode = NExtract::NPathMode::kFullPaths; 415 eo.OverwriteMode = yesToAll ? 416 NExtract::NOverwriteMode::kOverwrite : 417 NExtract::NOverwriteMode::kAsk; 418 eo.OutputDir = outputDir; 419 420 UString errorMessage; 421 CDecompressStat stat; 422 HRESULT result = Extract( 423 codecs, CObjectVector<COpenType>(), CIntVector(), 424 v1, v2, 425 wildcardCensorHead, 426 eo, ecs, ecs, 427 // NULL, // hash 428 errorMessage, stat); 429 if (!errorMessage.IsEmpty()) 430 { 431 (*g_StdStream) << endl << "Error: " << errorMessage;; 432 if (result == S_OK) 433 result = E_FAIL; 434 } 435 436 if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0) 437 { 438 if (ecs->NumArcsWithError != 0) 439 (*g_StdStream) << endl << "Archive Errors" << endl; 440 if (ecs->NumFileErrors != 0) 441 (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl; 442 return NExitCode::kFatalError; 443 } 444 if (result != S_OK) 445 throw CSystemException(result); 446 } 447 else 448 { 449 throw CSystemException(E_NOTIMPL); 450 451 /* 452 UInt64 numErrors = 0; 453 UInt64 numWarnings = 0; 454 HRESULT result = ListArchives( 455 codecs, CObjectVector<COpenType>(), CIntVector(), 456 false, // stdInMode 457 v1, v2, 458 true, // processAltStreams 459 false, // showAltStreams 460 wildcardCensorHead, 461 true, // enableHeaders 462 false, // techMode 463 #ifndef _NO_CRYPTO 464 passwordEnabled, password, 465 #endif 466 numErrors, numWarnings); 467 if (numErrors > 0) 468 { 469 g_StdOut << endl << "Errors: " << numErrors; 470 return NExitCode::kFatalError; 471 } 472 if (result != S_OK) 473 throw CSystemException(result); 474 */ 475 } 476 } 477 return 0; 478 } 479