blob: a01389b3f1f06c483c009c06624a8e4640e1efd9 [file] [log] [blame]
// 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;
}