| // Main.cpp |
| |
| #include "StdAfx.h" |
| |
| #include "../../../../C/CpuArch.h" |
| #include "../../../../C/DllSecur.h" |
| |
| #include "../../../Common/MyWindows.h" |
| #include "../../../Common/MyInitGuid.h" |
| |
| #include "../../../Common/CommandLineParser.h" |
| #include "../../../Common/MyException.h" |
| |
| #ifdef _WIN32 |
| #include "../../../Windows/DLL.h" |
| #else |
| #include "../../../Common/StringConvert.h" |
| #endif |
| #include "../../../Windows/FileDir.h" |
| #include "../../../Windows/FileName.h" |
| |
| #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 NDir; |
| using namespace NCommandLineParser; |
| |
| #ifdef _WIN32 |
| extern |
| HINSTANCE g_hInstance; |
| HINSTANCE g_hInstance = NULL; |
| #endif |
| extern |
| int g_CodePage; |
| int g_CodePage = -1; |
| extern CStdOutStream *g_StdStream; |
| |
| static const char * const kCopyrightString = |
| "\n7-Zip SFX " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n"; |
| |
| 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'; |
| |
| 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 |
| */ |
| |
| #define SWFRM_3(t, mu, mi) t, mu, mi, NULL |
| #define SWFRM_1(t) SWFRM_3(t, false, 0) |
| #define SWFRM_SIMPLE SWFRM_1(NSwitchType::kSimple) |
| #define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi) |
| |
| static const CSwitchForm kSwitchForms[kNumSwitches] = |
| { |
| { "?", SWFRM_SIMPLE }, |
| { "H", SWFRM_SIMPLE }, |
| { "BD", SWFRM_SIMPLE }, |
| { "Y", SWFRM_SIMPLE }, |
| { "P", SWFRM_STRING_SINGL(1) }, |
| { "O", SWFRM_STRING_SINGL(1) }, |
| }; |
| |
| static const int kNumCommandForms = 3; |
| |
| static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] = |
| { |
| NRecursedType::kRecursed |
| }; |
| |
| // static const bool kTestExtractRecursedDefault = true; |
| // static const bool kAddRecursedDefault = false; |
| |
| static const char * const kUniversalWildcard = "*"; |
| |
| static const char * const kHelpString = |
| "\nUsage: 7zSFX [<command>] [<switches>...] [<file_name>...]\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 * const kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError |
| // static const char * const kIncorrectListFile = "Incorrect wildcard in listfile"; |
| static const char * const kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line"; |
| |
| // static const CSysString kFileIsNotArchiveMessageBefore = "File \""; |
| // static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive"; |
| |
| // static const char * const kProcessArchiveMessage = " archive: "; |
| |
| static const char * const kCantFindSFX = " cannot find sfx"; |
| |
| namespace NCommandType |
| { |
| enum EEnum |
| { |
| kTest = 0, |
| kFullExtract, |
| kList |
| }; |
| } |
| |
| static const char *g_Commands = "txl"; |
| |
| struct CArchiveCommand |
| { |
| NCommandType::EEnum CommandType; |
| |
| NRecursedType::EEnum DefaultRecursedType() const; |
| }; |
| |
| static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) |
| { |
| UString s = commandString; |
| s.MakeLower_Ascii(); |
| if (s.Len() != 1) |
| return false; |
| if (s[0] >= 0x80) |
| return false; |
| int index = FindCharPosInString(g_Commands, (char)s[0]); |
| if (index < 0) |
| return false; |
| command.CommandType = (NCommandType::EEnum)index; |
| return true; |
| } |
| |
| NRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const |
| { |
| return kCommandRecursedDefault[CommandType]; |
| } |
| |
| static void PrintHelp(void) |
| { |
| g_StdOut << kHelpString; |
| } |
| |
| Z7_ATTR_NORETURN |
| static void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code) |
| { |
| g_StdOut << message << endl; |
| throw code; |
| } |
| |
| Z7_ATTR_NORETURN |
| static void PrintHelpAndExit() // yyy |
| { |
| PrintHelp(); |
| ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError); |
| } |
| |
| // ------------------------------------------------------------------ |
| // filenames functions |
| |
| static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, |
| const UString &name, bool include, NRecursedType::EEnum type) |
| { |
| /* |
| if (!IsWildcardFilePathLegal(name)) |
| return false; |
| */ |
| const 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; |
| } |
| |
| NWildcard::CCensorPathProps props; |
| props.Recursive = recursed; |
| wildcardCensor.AddPreItem(include, name, props); |
| return true; |
| } |
| |
| static void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor, |
| const UString &name, bool include, NRecursedType::EEnum type) |
| { |
| if (!AddNameToCensor(wildcardCensor, name, include, type)) |
| ShowMessageAndThrowException(kIncorrectWildcardInCommandLine, NExitCode::kUserError); |
| } |
| |
| |
| #ifndef _WIN32 |
| static void GetArguments(int numArgs, 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, char *args[] |
| #endif |
| ); |
| int Main2( |
| #ifndef _WIN32 |
| int numArgs, char *args[] |
| #endif |
| ) |
| { |
| #ifdef _WIN32 |
| // do we need load Security DLLs for console program? |
| LoadSecurityDlls(); |
| #endif |
| |
| #if defined(_WIN32) && !defined(UNDER_CE) |
| SetFileApisToOEM(); |
| #endif |
| |
| #ifdef ENV_HAVE_LOCALE |
| MY_SetLocale(); |
| #endif |
| |
| g_StdOut << kCopyrightString; |
| |
| UStringVector commandStrings; |
| #ifdef _WIN32 |
| NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); |
| #else |
| GetArguments(numArgs, args, commandStrings); |
| #endif |
| |
| #ifdef _WIN32 |
| |
| FString arcPath; |
| { |
| FString path; |
| NDLL::MyGetModuleFileName(path); |
| if (!MyGetFullPathName(path, arcPath)) |
| { |
| g_StdOut << "GetFullPathName Error"; |
| return NExitCode::kFatalError; |
| } |
| } |
| |
| #else |
| |
| if (commandStrings.IsEmpty()) |
| return NExitCode::kFatalError; |
| |
| const FString arcPath = us2fs(commandStrings.Front()); |
| |
| #endif |
| |
| #ifndef UNDER_CE |
| if (commandStrings.Size() > 0) |
| commandStrings.Delete(0); |
| #endif |
| |
| NCommandLineParser::CParser parser; |
| |
| try |
| { |
| if (!parser.ParseStrings(kSwitchForms, kNumSwitches, commandStrings)) |
| { |
| g_StdOut << "Command line error:" << endl |
| << parser.ErrorMessage << endl |
| << parser.ErrorLine << endl; |
| return NExitCode::kUserError; |
| } |
| } |
| catch(...) |
| { |
| PrintHelpAndExit(); |
| } |
| |
| if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) |
| { |
| PrintHelp(); |
| return 0; |
| } |
| |
| const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; |
| |
| unsigned curCommandIndex = 0; |
| |
| CArchiveCommand command; |
| if (nonSwitchStrings.IsEmpty()) |
| command.CommandType = NCommandType::kFullExtract; |
| else |
| { |
| const UString &cmd = nonSwitchStrings[curCommandIndex]; |
| if (!ParseArchiveCommand(cmd, command)) |
| { |
| g_StdOut << "ERROR: Unknown command:" << endl << cmd << endl; |
| return NExitCode::kUserError; |
| } |
| curCommandIndex = 1; |
| } |
| |
| |
| NRecursedType::EEnum recursedType; |
| recursedType = command.DefaultRecursedType(); |
| |
| NWildcard::CCensor wildcardCensor; |
| |
| { |
| if (nonSwitchStrings.Size() == curCommandIndex) |
| AddCommandLineWildcardToCensor(wildcardCensor, (UString)kUniversalWildcard, true, recursedType); |
| for (; curCommandIndex < nonSwitchStrings.Size(); curCommandIndex++) |
| { |
| const UString &s = nonSwitchStrings[curCommandIndex]; |
| if (s.IsEmpty()) |
| throw "Empty file path"; |
| AddCommandLineWildcardToCensor(wildcardCensor, s, true, recursedType); |
| } |
| } |
| |
| const bool yesToAll = parser[NKey::kYes].ThereIs; |
| |
| // NExtractMode::EEnum extractMode; |
| // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode); |
| |
| const bool passwordEnabled = parser[NKey::kPassword].ThereIs; |
| |
| UString password; |
| if (passwordEnabled) |
| password = parser[NKey::kPassword].PostStrings[0]; |
| |
| if (!NFind::DoesFileExist_FollowLink(arcPath)) |
| throw kCantFindSFX; |
| |
| FString outputDir; |
| if (parser[NKey::kOutputDir].ThereIs) |
| { |
| outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); |
| NName::NormalizeDirPathPrefix(outputDir); |
| } |
| |
| |
| wildcardCensor.AddPathsToCensor(NWildcard::k_RelatPath); |
| |
| { |
| UStringVector v1, v2; |
| v1.Add(fs2us(arcPath)); |
| v2.Add(fs2us(arcPath)); |
| const NWildcard::CCensorNode &wildcardCensorHead = |
| wildcardCensor.Pairs.Front().Head; |
| |
| CCodecs *codecs = new CCodecs; |
| CMyComPtr< |
| #ifdef Z7_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->Init(g_StdStream, &g_StdErr, g_StdStream); |
| |
| #ifndef Z7_NO_CRYPTO |
| ecs->PasswordIsDefined = passwordEnabled; |
| ecs->Password = password; |
| #endif |
| |
| /* |
| COpenCallbackConsole openCallback; |
| openCallback.Init(g_StdStream, g_StdStream); |
| |
| #ifndef Z7_NO_CRYPTO |
| openCallback.PasswordIsDefined = passwordEnabled; |
| openCallback.Password = password; |
| #endif |
| */ |
| |
| CExtractOptions eo; |
| eo.StdOutMode = false; |
| eo.YesToAll = yesToAll; |
| eo.TestMode = command.CommandType == NCommandType::kTest; |
| eo.PathMode = NExtract::NPathMode::kFullPaths; |
| eo.OverwriteMode = yesToAll ? |
| NExtract::NOverwriteMode::kOverwrite : |
| NExtract::NOverwriteMode::kAsk; |
| eo.OutputDir = outputDir; |
| |
| UString errorMessage; |
| CDecompressStat stat; |
| HRESULT result = Extract( |
| codecs, CObjectVector<COpenType>(), CIntVector(), |
| v1, v2, |
| wildcardCensorHead, |
| eo, |
| ecs, ecs, ecs, |
| // NULL, // hash |
| errorMessage, stat); |
| |
| ecs->ClosePercents(); |
| |
| if (!errorMessage.IsEmpty()) |
| { |
| (*g_StdStream) << endl << "Error: " << errorMessage; |
| if (result == S_OK) |
| result = E_FAIL; |
| } |
| |
| if ( 0 != ecs->NumCantOpenArcs |
| || 0 != ecs->NumArcsWithError |
| || 0 != ecs->NumFileErrors |
| || 0 != ecs->NumOpenArcErrors) |
| { |
| if (ecs->NumCantOpenArcs != 0) |
| (*g_StdStream) << endl << "Can't open as archive" << endl; |
| if (ecs->NumArcsWithError != 0) |
| (*g_StdStream) << endl << "Archive Errors" << endl; |
| if (ecs->NumFileErrors != 0) |
| (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl; |
| if (ecs->NumOpenArcErrors != 0) |
| (*g_StdStream) << endl << "Open Errors: " << ecs->NumOpenArcErrors << endl; |
| return NExitCode::kFatalError; |
| } |
| if (result != S_OK) |
| throw CSystemException(result); |
| } |
| else |
| { |
| throw CSystemException(E_NOTIMPL); |
| |
| /* |
| UInt64 numErrors = 0; |
| UInt64 numWarnings = 0; |
| HRESULT result = ListArchives( |
| codecs, CObjectVector<COpenType>(), CIntVector(), |
| false, // stdInMode |
| v1, v2, |
| true, // processAltStreams |
| false, // showAltStreams |
| wildcardCensorHead, |
| true, // enableHeaders |
| false, // techMode |
| #ifndef Z7_NO_CRYPTO |
| passwordEnabled, password, |
| #endif |
| numErrors, numWarnings); |
| if (numErrors > 0) |
| { |
| g_StdOut << endl << "Errors: " << numErrors; |
| return NExitCode::kFatalError; |
| } |
| if (result != S_OK) |
| throw CSystemException(result); |
| */ |
| } |
| } |
| return 0; |
| } |