| // Main.cpp |
| |
| #include "StdAfx.h" |
| |
| #include "Common/MyInitGuid.h" |
| |
| #include "Common/CommandLineParser.h" |
| #include "Common/MyException.h" |
| |
| #ifdef _WIN32 |
| #include "Windows/DLL.h" |
| #include "Windows/FileDir.h" |
| #else |
| #include "Common/StringConvert.h" |
| #include "Windows/System.h" |
| #include "myPrivate.h" |
| #endif |
| |
| #include "../../UI/Common/ExitCode.h" |
| #include "../../UI/Common/Extract.h" |
| |
| #include "../../UI/Console/ExtractCallbackConsole.h" |
| #include "../../UI/Console/List.h" |
| #include "../../UI/Console/OpenCallbackConsole.h" |
| |
| #include "../../MyVersion.h" |
| |
| using namespace NWindows; |
| using namespace NFile; |
| using namespace NCommandLineParser; |
| |
| extern CStdOutStream *g_StdStream; |
| |
| static const char *kCopyrightString = |
| "\n7-Zip SFX " MY_VERSION_COPYRIGHT_DATE "\n" |
| "p7zip Version " P7ZIP_VERSION ; |
| |
| static const int kNumSwitches = 6; |
| |
| namespace NKey { |
| enum Enum |
| { |
| kHelp1 = 0, |
| kHelp2, |
| kDisablePercents, |
| kYes, |
| kPassword, |
| kOutputDir |
| }; |
| |
| } |
| |
| namespace NRecursedType { |
| enum EEnum |
| { |
| kRecursed, |
| kWildCardOnlyRecursed, |
| kNonRecursed |
| }; |
| } |
| /* |
| static const char kRecursedIDChar = 'R'; |
| static const wchar_t *kRecursedPostCharSet = L"0-"; |
| |
| namespace NRecursedPostCharIndex { |
| enum EEnum |
| { |
| kWildCardRecursionOnly = 0, |
| kNoRecursion = 1 |
| }; |
| } |
| |
| static const char kFileListID = '@'; |
| static const char kImmediateNameID = '!'; |
| |
| static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be |
| static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be |
| */ |
| static const CSwitchForm kSwitchForms[kNumSwitches] = |
| { |
| { L"?", NSwitchType::kSimple, false }, |
| { L"H", NSwitchType::kSimple, false }, |
| { L"BD", NSwitchType::kSimple, false }, |
| { L"Y", NSwitchType::kSimple, false }, |
| { L"P", NSwitchType::kUnLimitedPostString, false, 1 }, |
| { L"O", NSwitchType::kUnLimitedPostString, false, 1 }, |
| }; |
| |
| static const int kNumCommandForms = 3; |
| |
| namespace NCommandType { |
| enum EEnum |
| { |
| kTest = 0, |
| // kExtract, |
| kFullExtract, |
| kList |
| }; |
| |
| } |
| |
| static const CCommandForm commandForms[kNumCommandForms] = |
| { |
| { L"T", false }, |
| // { "E", false }, |
| { L"X", false }, |
| { L"L", false } |
| }; |
| |
| static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] = |
| { |
| NRecursedType::kRecursed |
| }; |
| |
| // static const bool kTestExtractRecursedDefault = true; |
| // static const bool kAddRecursedDefault = false; |
| |
| static const wchar_t *kUniversalWildcard = L"*"; |
| static const int kCommandIndex = 0; |
| |
| static const char *kHelpString = |
| "\nUsage: 7zSFX [<command>] [<switches>...]\n" |
| "\n" |
| "<Commands>\n" |
| " l: List contents of archive\n" |
| " t: Test integrity of archive\n" |
| " x: eXtract files with full pathname (default)\n" |
| "<Switches>\n" |
| // " -bd Disable percentage indicator\n" |
| " -o{Directory}: set Output directory\n" |
| " -p{Password}: set Password\n" |
| " -y: assume Yes on all queries\n"; |
| |
| |
| // --------------------------- |
| // exception messages |
| |
| static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError |
| // static const char *kIncorrectListFile = "Incorrect wildcard in listfile"; |
| static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; |
| |
| // static const CSysString kFileIsNotArchiveMessageBefore = "File \""; |
| // static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive"; |
| |
| // static const char *kProcessArchiveMessage = " archive: "; |
| |
| static const char *kCantFindSFX = " cannot find sfx"; |
| |
| |
| struct CArchiveCommand |
| { |
| NCommandType::EEnum CommandType; |
| NRecursedType::EEnum DefaultRecursedType() const; |
| }; |
| |
| NRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const |
| { |
| return kCommandRecursedDefault[CommandType]; |
| } |
| |
| void PrintHelp(void) |
| { |
| g_StdOut << kHelpString; |
| } |
| |
| static void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code) |
| { |
| g_StdOut << message << endl; |
| throw code; |
| } |
| |
| static void PrintHelpAndExit() // yyy |
| { |
| PrintHelp(); |
| ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError); |
| } |
| |
| bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) |
| { |
| UString commandStringUpper = commandString; |
| commandStringUpper.MakeUpper(); |
| UString postString; |
| int commandIndex = ParseCommand(kNumCommandForms, commandForms, commandStringUpper, |
| postString) ; |
| if (commandIndex < 0) |
| return false; |
| command.CommandType = (NCommandType::EEnum)commandIndex; |
| return true; |
| } |
| |
| // ------------------------------------------------------------------ |
| // filenames functions |
| |
| static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, |
| const UString &name, bool include, NRecursedType::EEnum type) |
| { |
| /* |
| if(!IsWildCardFilePathLegal(name)) |
| return false; |
| */ |
| bool isWildCard = DoesNameContainWildCard(name); |
| bool recursed = false; |
| |
| switch (type) |
| { |
| case NRecursedType::kWildCardOnlyRecursed: |
| recursed = isWildCard; |
| break; |
| case NRecursedType::kRecursed: |
| recursed = true; |
| break; |
| case NRecursedType::kNonRecursed: |
| recursed = false; |
| break; |
| } |
| wildcardCensor.AddItem(include, name, recursed); |
| return true; |
| } |
| |
| void AddCommandLineWildCardToCensor(NWildcard::CCensor &wildcardCensor, |
| const UString &name, bool include, NRecursedType::EEnum type) |
| { |
| if (!AddNameToCensor(wildcardCensor, name, include, type)) |
| ShowMessageAndThrowException(kIncorrectWildCardInCommandLine, NExitCode::kUserError); |
| } |
| |
| void AddToCensorFromNonSwitchesStrings(NWildcard::CCensor &wildcardCensor, |
| const UStringVector & /* nonSwitchStrings */, NRecursedType::EEnum type, |
| bool /* thereAreSwitchIncludeWildCards */) |
| { |
| AddCommandLineWildCardToCensor(wildcardCensor, kUniversalWildcard, true, type); |
| } |
| |
| |
| #ifndef _WIN32 |
| static void GetArguments(int numArgs, const char *args[], UStringVector &parts) |
| { |
| parts.Clear(); |
| for(int i = 0; i < numArgs; i++) |
| { |
| UString s = MultiByteToUnicodeString(args[i]); |
| parts.Add(s); |
| } |
| } |
| #endif |
| |
| int Main2( |
| #ifndef _WIN32 |
| int numArgs, const char *args[] |
| #endif |
| ) |
| { |
| #if defined(_WIN32) && !defined(UNDER_CE) |
| SetFileApisToOEM(); |
| #endif |
| |
| UStringVector commandStrings; |
| #ifdef _WIN32 |
| NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); |
| #else |
| extern void mySplitCommandLine(int numArgs,const char *args[],UStringVector &parts); |
| mySplitCommandLine(numArgs,args,commandStrings); |
| #endif |
| |
| // After mySplitCommandLine |
| g_StdOut << kCopyrightString << " (locale=" << my_getlocale() <<",Utf16="; |
| if (global_use_utf16_conversion) g_StdOut << "on"; |
| else g_StdOut << "off"; |
| g_StdOut << ",HugeFiles="; |
| if (sizeof(off_t) >= 8) g_StdOut << "on,"; |
| else g_StdOut << "off,"; |
| int nbcpu = NWindows::NSystem::GetNumberOfProcessors(); |
| if (nbcpu > 1) g_StdOut << nbcpu << " CPUs)\n"; |
| else g_StdOut << nbcpu << " CPU)\n"; |
| |
| UString arcPath = commandStrings.Front(); |
| |
| commandStrings.Delete(0); |
| |
| NCommandLineParser::CParser parser(kNumSwitches); |
| try |
| { |
| parser.ParseStrings(kSwitchForms, commandStrings); |
| } |
| catch(...) |
| { |
| PrintHelpAndExit(); |
| } |
| |
| if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) |
| { |
| PrintHelp(); |
| return 0; |
| } |
| const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; |
| |
| int numNonSwitchStrings = nonSwitchStrings.Size(); |
| |
| CArchiveCommand command; |
| if (numNonSwitchStrings == 0) |
| command.CommandType = NCommandType::kFullExtract; |
| else |
| { |
| if (numNonSwitchStrings > 1) |
| PrintHelpAndExit(); |
| if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], command)) |
| PrintHelpAndExit(); |
| } |
| |
| |
| NRecursedType::EEnum recursedType; |
| recursedType = command.DefaultRecursedType(); |
| |
| NWildcard::CCensor wildcardCensor; |
| |
| bool thereAreSwitchIncludeWildCards; |
| thereAreSwitchIncludeWildCards = false; |
| AddToCensorFromNonSwitchesStrings(wildcardCensor, nonSwitchStrings, recursedType, |
| thereAreSwitchIncludeWildCards); |
| |
| bool yesToAll = parser[NKey::kYes].ThereIs; |
| |
| // NExtractMode::EEnum extractMode; |
| // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode); |
| |
| bool passwordEnabled = parser[NKey::kPassword].ThereIs; |
| |
| UString password; |
| if(passwordEnabled) |
| password = parser[NKey::kPassword].PostStrings[0]; |
| |
| if (!NFind::DoesFileExist(arcPath)) |
| throw kCantFindSFX; |
| |
| UString outputDir; |
| if (parser[NKey::kOutputDir].ThereIs) |
| { |
| outputDir = parser[NKey::kOutputDir].PostStrings[0]; |
| NName::NormalizeDirPathPrefix(outputDir); |
| } |
| |
| { |
| UStringVector v1, v2; |
| v1.Add(arcPath); |
| v2.Add(arcPath); |
| const NWildcard::CCensorNode &wildcardCensorHead = |
| wildcardCensor.Pairs.Front().Head; |
| |
| CCodecs *codecs = new CCodecs; |
| CMyComPtr< |
| #ifdef EXTERNAL_CODECS |
| ICompressCodecsInfo |
| #else |
| IUnknown |
| #endif |
| > compressCodecsInfo = codecs; |
| HRESULT result = codecs->Load(); |
| if (result != S_OK) |
| throw CSystemException(result); |
| |
| if(command.CommandType != NCommandType::kList) |
| { |
| CExtractCallbackConsole *ecs = new CExtractCallbackConsole; |
| CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; |
| ecs->OutStream = g_StdStream; |
| |
| #ifndef _NO_CRYPTO |
| ecs->PasswordIsDefined = passwordEnabled; |
| ecs->Password = password; |
| #endif |
| |
| ecs->Init(); |
| |
| COpenCallbackConsole openCallback; |
| openCallback.OutStream = g_StdStream; |
| |
| #ifndef _NO_CRYPTO |
| openCallback.PasswordIsDefined = passwordEnabled; |
| openCallback.Password = password; |
| #endif |
| |
| CExtractOptions eo; |
| eo.StdOutMode = false; |
| eo.PathMode = NExtract::NPathMode::kFullPathnames; |
| eo.TestMode = command.CommandType == NCommandType::kTest; |
| eo.OverwriteMode = yesToAll ? |
| NExtract::NOverwriteMode::kWithoutPrompt : |
| NExtract::NOverwriteMode::kAskBefore; |
| eo.OutputDir = outputDir; |
| eo.YesToAll = yesToAll; |
| |
| UString errorMessage; |
| CDecompressStat stat; |
| HRESULT result = DecompressArchives( |
| codecs, CIntVector(), |
| v1, v2, |
| wildcardCensorHead, |
| eo, &openCallback, ecs, errorMessage, stat); |
| if (!errorMessage.IsEmpty()) |
| { |
| (*g_StdStream) << endl << "Error: " << errorMessage;; |
| if (result == S_OK) |
| result = E_FAIL; |
| } |
| |
| if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) |
| { |
| if (ecs->NumArchiveErrors != 0) |
| (*g_StdStream) << endl << "Archive Errors: " << ecs->NumArchiveErrors << endl; |
| if (ecs->NumFileErrors != 0) |
| (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl; |
| return NExitCode::kFatalError; |
| } |
| if (result != S_OK) |
| throw CSystemException(result); |
| } |
| else |
| { |
| UInt64 numErrors = 0; |
| HRESULT result = ListArchives( |
| codecs, CIntVector(), |
| false, |
| v1, v2, |
| wildcardCensorHead, |
| true, false, |
| #ifndef _NO_CRYPTO |
| passwordEnabled, password, |
| #endif |
| numErrors); |
| if (numErrors > 0) |
| { |
| g_StdOut << endl << "Errors: " << numErrors; |
| return NExitCode::kFatalError; |
| } |
| if (result != S_OK) |
| throw CSystemException(result); |
| } |
| } |
| return 0; |
| } |