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