diff options
Diffstat (limited to 'CPP/7zip/Bundles/SFXCon/Main.cpp')
-rwxr-xr-x | CPP/7zip/Bundles/SFXCon/Main.cpp | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/CPP/7zip/Bundles/SFXCon/Main.cpp b/CPP/7zip/Bundles/SFXCon/Main.cpp new file mode 100755 index 00000000..65ed8931 --- /dev/null +++ b/CPP/7zip/Bundles/SFXCon/Main.cpp @@ -0,0 +1,416 @@ +// Main.cpp + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" + +#include "Common/CommandLineParser.h" +#include "Common/StdOutStream.h" +#include "Common/Wildcard.h" +#include "Common/StringConvert.h" +#include "Common/MyCom.h" +#include "Common/Exception.h" + +#include "Windows/FileDir.h" +#include "Windows/FileName.h" +#include "Windows/Defs.h" + +#include "../../IPassword.h" +#include "../../ICoder.h" + +#include "../../UI/Common/OpenArchive.h" +#include "../../UI/Common/DefaultName.h" +#include "../../UI/Common/ExitCode.h" +#include "../../UI/Common/Extract.h" + +#include "../../UI/Console/List.h" +#include "../../UI/Console/OpenCallbackConsole.h" +#include "../../UI/Console/ExtractCallbackConsole.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"; + +static const int kNumSwitches = 6; + +#ifdef _WIN32 +static const wchar_t *kDefaultExt = L".exe"; +static const int kDefaultExtLength = 4; +#endif + +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 int kMaxCmdLineSize = 1000; +static const wchar_t *kUniversalWildcard = L"*"; +static const int kMinNonSwitchWords = 1; +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 numArguments, const char *arguments[], UStringVector &parts) +{ + parts.Clear(); + for(int i = 0; i < numArguments; i++) + { + UString s = MultiByteToUnicodeString(arguments[i]); + parts.Add(s); + } +} +#endif + +int Main2( + #ifndef _WIN32 + int numArguments, const char *arguments[] + #endif +) +{ + #ifdef _WIN32 + SetFileApisToOEM(); + #endif + + g_StdOut << kCopyrightString; + + UStringVector commandStrings; + #ifdef _WIN32 + NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); + #else + GetArguments(numArguments, arguments, commandStrings); + #endif + + UString archiveName = 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; + + #ifdef _WIN32 + if (archiveName.Right(kDefaultExtLength).CompareNoCase(kDefaultExt) != 0) + archiveName += kDefaultExt; + #endif + + // NExtractMode::EEnum extractMode; + // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode); + + bool passwordEnabled = parser[NKey::kPassword].ThereIs; + + UString password; + if(passwordEnabled) + password = parser[NKey::kPassword].PostStrings[0]; + + NFind::CFileInfoW archiveFileInfo; + if (!NFind::FindFile(archiveName, archiveFileInfo)) + throw kCantFindSFX; + if (archiveFileInfo.IsDirectory()) + throw kCantFindSFX; + + UString outputDir; + if(parser[NKey::kOutputDir].ThereIs) + { + outputDir = parser[NKey::kOutputDir].PostStrings[0]; + NName::NormalizeDirPathPrefix(outputDir); + } + + { + UStringVector v1, v2; + v1.Add(archiveName); + v2.Add(archiveName); + const NWildcard::CCensorNode &wildcardCensorHead = + wildcardCensor.Pairs.Front().Head; + if(command.CommandType != NCommandType::kList) + { + CExtractCallbackConsole *ecs = new CExtractCallbackConsole; + CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; + ecs->OutStream = g_StdStream; + ecs->PasswordIsDefined = passwordEnabled; + ecs->Password = password; + ecs->Init(); + + COpenCallbackConsole openCallback; + openCallback.OutStream = g_StdStream; + openCallback.PasswordIsDefined = passwordEnabled; + openCallback.Password = password; + + 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; + HRESULT result = DecompressArchives( + v1, v2, + wildcardCensorHead, + eo, &openCallback, ecs, errorMessage); + 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 + { + HRESULT result = ListArchives( + v1, v2, + wildcardCensorHead, + true, false, + passwordEnabled, + password); + if (result != S_OK) + throw CSystemException(result); + } + } + return 0; +} |