diff options
Diffstat (limited to 'src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp')
-rw-r--r-- | src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp | 1257 |
1 files changed, 0 insertions, 1257 deletions
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp deleted file mode 100644 index 769d21604..000000000 --- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ /dev/null @@ -1,1257 +0,0 @@ -// ArchiveCommandLine.cpp - -#include "StdAfx.h" -#undef printf -#undef sprintf - -#ifdef _WIN32 -#ifndef UNDER_CE -#include <io.h> -#endif -#endif -#include <stdio.h> - -#include "../../../Common/ListFileUtils.h" -#include "../../../Common/StringConvert.h" -#include "../../../Common/StringToInt.h" - -#include "../../../Windows/FileDir.h" -#include "../../../Windows/FileName.h" -#ifdef _WIN32 -#include "../../../Windows/FileMapping.h" -#include "../../../Windows/Synchronization.h" -#endif - -#include "ArchiveCommandLine.h" -#include "EnumDirItems.h" -#include "SortUtils.h" -#include "Update.h" -#include "UpdateAction.h" - -extern bool g_CaseSensitive; - -#ifdef UNDER_CE - -#define MY_IS_TERMINAL(x) false; - -#else - -#if _MSC_VER >= 1400 -#define MY_isatty_fileno(x) _isatty(_fileno(x)) -#else -#define MY_isatty_fileno(x) isatty(fileno(x)) -#endif - -#define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); - -#endif - -using namespace NCommandLineParser; -using namespace NWindows; -using namespace NFile; - -static bool StringToUInt32(const wchar_t *s, UInt32 &v) -{ - if (*s == 0) - return false; - const wchar_t *end; - v = ConvertStringToUInt32(s, &end); - return *end == 0; -} - -static void AddNewLine(UString &s) -{ - s += L'\n'; -} - -CArcCmdLineException::CArcCmdLineException(const char *a, const wchar_t *u) -{ - (*this) += MultiByteToUnicodeString(a); - if (u) - { - AddNewLine(*this); - (*this) += u; - } -} - -int g_CodePage = -1; - -namespace NKey { -enum Enum -{ - kHelp1 = 0, - kHelp2, - kHelp3, - kDisableHeaders, - kDisablePercents, - kArchiveType, - kYes, - #ifndef _NO_CRYPTO - kPassword, - #endif - kProperty, - kOutputDir, - kWorkingDir, - kInclude, - kExclude, - kArInclude, - kArExclude, - kNoArName, - kUpdate, - kVolume, - kRecursed, - kSfx, - kStdIn, - kStdOut, - kOverwrite, - kEmail, - kShowDialog, - kLargePages, - kListfileCharSet, - kConsoleCharSet, - kTechMode, - kShareForWrite, - kCaseSensitive, - kHash, - kArcNameMode, - - kDisableWildcardParsing, - kElimDup, - kFullPathMode, - - kHardLinks, - kSymLinks, - kNtSecurity, - kAltStreams, - kReplaceColonForAltStream, - kWriteToAltStreamIfColon, - - kDeleteAfterCompressing, - kSetArcMTime, - kExcludedArcType -}; - -} - - -static const wchar_t kRecursedIDChar = 'r'; -static const char *kRecursedPostCharSet = "0-"; - -static const char *k_ArcNameMode_PostCharSet = "sea"; - -static inline const EArcNameMode ParseArcNameMode(int postCharIndex) -{ - switch (postCharIndex) - { - case 1: return k_ArcNameMode_Exact; - case 2: return k_ArcNameMode_Add; - default: return k_ArcNameMode_Smart; - } -} - -namespace NRecursedPostCharIndex { - enum EEnum - { - kWildcardRecursionOnly = 0, - kNoRecursion = 1 - }; -} - -static const char kImmediateNameID = '!'; -static const char kMapNameID = '#'; -static const char kFileListID = '@'; - -static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be -static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be - -static const char *kOverwritePostCharSet = "asut"; - -NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = -{ - NExtract::NOverwriteMode::kOverwrite, - NExtract::NOverwriteMode::kSkip, - NExtract::NOverwriteMode::kRename, - NExtract::NOverwriteMode::kRenameExisting -}; - -static const CSwitchForm kSwitchForms[] = -{ - { "?" }, - { "h" }, - { "-help" }, - { "ba" }, - { "bd" }, - { "t", NSwitchType::kString, false, 1 }, - { "y" }, - #ifndef _NO_CRYPTO - { "p", NSwitchType::kString }, - #endif - { "m", NSwitchType::kString, true, 1 }, - { "o", NSwitchType::kString, false, 1 }, - { "w", NSwitchType::kString }, - { "i", NSwitchType::kString, true, kSomeCludePostStringMinSize}, - { "x", NSwitchType::kString, true, kSomeCludePostStringMinSize}, - { "ai", NSwitchType::kString, true, kSomeCludePostStringMinSize}, - { "ax", NSwitchType::kString, true, kSomeCludePostStringMinSize}, - { "an" }, - { "u", NSwitchType::kString, true, 1}, - { "v", NSwitchType::kString, true, 1}, - { "r", NSwitchType::kChar, false, 0, kRecursedPostCharSet }, - { "sfx", NSwitchType::kString }, - { "si", NSwitchType::kString }, - { "so" }, - { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet}, - { "seml", NSwitchType::kString, false, 0}, - { "ad" }, - { "slp", NSwitchType::kMinus }, - { "scs", NSwitchType::kString }, - { "scc", NSwitchType::kString }, - { "slt" }, - { "ssw" }, - { "ssc", NSwitchType::kMinus }, - { "scrc", NSwitchType::kString, true, 0 }, - { "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet }, - - { "spd" }, - { "spe", NSwitchType::kMinus }, - { "spf", NSwitchType::kString, false, 0 }, - - { "snh", NSwitchType::kMinus }, - { "snl", NSwitchType::kMinus }, - { "sni" }, - { "sns", NSwitchType::kMinus }, - - { "snr" }, - { "snc" }, - - { "sdel" }, - { "stl" }, - { "stx", NSwitchType::kString, true, 1 } -}; - -static const wchar_t *kUniversalWildcard = L"*"; -static const int kMinNonSwitchWords = 1; -static const int kCommandIndex = 0; - -// static const char *kUserErrorMessage = "Incorrect command line"; -static const char *kCannotFindListFile = "Cannot find listfile"; -static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; -// static const char *kIncorrectWildcardInListFile = "Incorrect wildcard in listfile"; -// static const char *kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line"; -static const char *kTerminalOutError = "I won't write compressed data to a terminal"; -static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; -static const char *kEmptyFilePath = "Empty file path"; -static const char *kCannotFindArchive = "Cannot find archive"; - -bool CArcCommand::IsFromExtractGroup() const -{ - switch (CommandType) - { - case NCommandType::kTest: - case NCommandType::kExtract: - case NCommandType::kExtractFull: - return true; - } - return false; -} - -NExtract::NPathMode::EEnum CArcCommand::GetPathMode() const -{ - switch (CommandType) - { - case NCommandType::kTest: - case NCommandType::kExtractFull: - return NExtract::NPathMode::kFullPaths; - } - return NExtract::NPathMode::kNoPaths; -} - -bool CArcCommand::IsFromUpdateGroup() const -{ - switch (CommandType) - { - case NCommandType::kAdd: - case NCommandType::kUpdate: - case NCommandType::kDelete: - case NCommandType::kRename: - return true; - } - return false; -} - -static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) -{ - switch (index) - { - case NRecursedPostCharIndex::kWildcardRecursionOnly: - return NRecursedType::kWildcardOnlyRecursed; - case NRecursedPostCharIndex::kNoRecursion: - return NRecursedType::kNonRecursed; - default: - return NRecursedType::kRecursed; - } -} - -static const char *g_Commands = "audtexlbih"; - -static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command) -{ - UString s = commandString; - s.MakeLower_Ascii(); - if (s.Len() == 1) - { - if (s[0] > 0x7F) - return false; - int index = FindCharPosInString(g_Commands, (char)s[0]); - if (index < 0) - return false; - command.CommandType = (NCommandType::EEnum)index; - return true; - } - if (s.Len() == 2 && s[0] == 'r' && s[1] == 'n') - { - command.CommandType = (NCommandType::kRename); - return true; - } - return false; -} - -// ------------------------------------------------------------------ -// filenames functions - -static void AddNameToCensor(NWildcard::CCensor &censor, - const UString &name, bool include, NRecursedType::EEnum type, bool wildcardMatching) -{ - bool recursed = false; - - switch (type) - { - case NRecursedType::kWildcardOnlyRecursed: - recursed = DoesNameContainWildcard(name); - break; - case NRecursedType::kRecursed: - recursed = true; - break; - } - censor.AddPreItem(include, name, recursed, wildcardMatching); -} - -static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs, - const UString &oldName, const UString &newName, NRecursedType::EEnum type, - bool wildcardMatching) -{ - CRenamePair &pair = renamePairs->AddNew(); - pair.OldName = oldName; - pair.NewName = newName; - pair.RecursedType = type; - pair.WildcardParsing = wildcardMatching; - - if (!pair.Prepare()) - { - UString val; - val += pair.OldName; - AddNewLine(val); - val += pair.NewName; - AddNewLine(val); - if (type == NRecursedType::kRecursed) - val += L"-r"; - else if (type == NRecursedType::kRecursed) - val += L"-r0"; - throw CArcCmdLineException("Unsupported rename command:", val); - } -} - -static void AddToCensorFromListFile( - CObjectVector<CRenamePair> *renamePairs, - NWildcard::CCensor &censor, - LPCWSTR fileName, bool include, NRecursedType::EEnum type, bool wildcardMatching, Int32 codePage) -{ - UStringVector names; - if (!NFind::DoesFileExist(us2fs(fileName))) - throw CArcCmdLineException(kCannotFindListFile, fileName); - if (!ReadNamesFromListFile(us2fs(fileName), names, codePage)) - throw CArcCmdLineException(kIncorrectListFile, fileName); - if (renamePairs) - { - if ((names.Size() & 1) != 0) - throw CArcCmdLineException(kIncorrectListFile, fileName); - for (unsigned i = 0; i < names.Size(); i += 2) - { - // change type !!!! - AddRenamePair(renamePairs, names[i], names[i + 1], type, wildcardMatching); - } - } - else - FOR_VECTOR (i, names) - AddNameToCensor(censor, names[i], include, type, wildcardMatching); -} - -static void AddToCensorFromNonSwitchesStrings( - CObjectVector<CRenamePair> *renamePairs, - unsigned startIndex, - NWildcard::CCensor &censor, - const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, - bool wildcardMatching, - bool thereAreSwitchIncludes, Int32 codePage) -{ - if ((renamePairs || nonSwitchStrings.Size() == startIndex) && !thereAreSwitchIncludes) - AddNameToCensor(censor, kUniversalWildcard, true, type, - true // wildcardMatching - ); - - int oldIndex = -1; - - for (unsigned i = startIndex; i < nonSwitchStrings.Size(); i++) - { - const UString &s = nonSwitchStrings[i]; - if (s.IsEmpty()) - throw CArcCmdLineException(kEmptyFilePath); - if (s[0] == kFileListID) - AddToCensorFromListFile(renamePairs, censor, s.Ptr(1), true, type, wildcardMatching, codePage); - else if (renamePairs) - { - if (oldIndex == -1) - oldIndex = startIndex; - else - { - // NRecursedType::EEnum type is used for global wildcard (-i! switches) - AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, NRecursedType::kNonRecursed, wildcardMatching); - // AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, type); - oldIndex = -1; - } - } - else - AddNameToCensor(censor, s, true, type, wildcardMatching); - } - - if (oldIndex != -1) - { - throw CArcCmdLineException("There is no second file name for rename pair:", nonSwitchStrings[oldIndex]); - } -} - -#ifdef _WIN32 - -struct CEventSetEnd -{ - UString Name; - - CEventSetEnd(const wchar_t *name): Name(name) {} - ~CEventSetEnd() - { - NSynchronization::CManualResetEvent event; - if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(Name)) == 0) - event.Set(); - } -}; - -const char *k_IncorrectMapCommand = "Incorrect Map command"; - -static const char *ParseMapWithPaths( - NWildcard::CCensor &censor, - const UString &s2, bool include, - NRecursedType::EEnum commonRecursedType, - bool wildcardMatching) -{ - UString s = s2; - int pos = s.Find(L':'); - if (pos < 0) - return k_IncorrectMapCommand; - int pos2 = s.Find(L':', pos + 1); - if (pos2 < 0) - return k_IncorrectMapCommand; - - CEventSetEnd eventSetEnd((const wchar_t *)s + (pos2 + 1)); - s.DeleteFrom(pos2); - UInt32 size; - if (!StringToUInt32(s.Ptr(pos + 1), size) - || size < sizeof(wchar_t) - || size > ((UInt32)1 << 31) - || size % sizeof(wchar_t) != 0) - return "Unsupported Map data size"; - - s.DeleteFrom(pos); - CFileMapping map; - if (map.Open(FILE_MAP_READ, GetSystemString(s)) != 0) - return "Can not open mapping"; - LPVOID data = map.Map(FILE_MAP_READ, 0, size); - if (!data) - return "MapViewOfFile error"; - CFileUnmapper unmapper(data); - - UString name; - const wchar_t *p = (const wchar_t *)data; - if (*p != 0) // data format marker - return "Unsupported Map data"; - UInt32 numChars = size / sizeof(wchar_t); - for (UInt32 i = 1; i < numChars; i++) - { - wchar_t c = p[i]; - if (c == 0) - { - // MessageBoxW(0, name, L"7-Zip", 0); - AddNameToCensor(censor, name, include, commonRecursedType, wildcardMatching); - name.Empty(); - } - else - name += c; - } - if (!name.IsEmpty()) - return "Map data error"; - - return NULL; -} - -#endif - -static void AddSwitchWildcardsToCensor( - NWildcard::CCensor &censor, - const UStringVector &strings, bool include, - NRecursedType::EEnum commonRecursedType, - bool wildcardMatching, - Int32 codePage) -{ - const char *errorMessage = NULL; - unsigned i; - for (i = 0; i < strings.Size(); i++) - { - const UString &name = strings[i]; - NRecursedType::EEnum recursedType; - unsigned pos = 0; - - if (name.Len() < kSomeCludePostStringMinSize) - { - errorMessage = "Too short switch"; - break; - } - - if (::MyCharLower_Ascii(name[pos]) == kRecursedIDChar) - { - pos++; - wchar_t c = name[pos]; - int index = -1; - if (c <= 0x7F) - index = FindCharPosInString(kRecursedPostCharSet, (char)c); - recursedType = GetRecursedTypeFromIndex(index); - if (index >= 0) - pos++; - } - else - recursedType = commonRecursedType; - - if (name.Len() < pos + kSomeCludeAfterRecursedPostStringMinSize) - { - errorMessage = "Too short switch"; - break; - } - - UString tail = name.Ptr(pos + 1); - - if (name[pos] == kImmediateNameID) - AddNameToCensor(censor, tail, include, recursedType, wildcardMatching); - else if (name[pos] == kFileListID) - AddToCensorFromListFile(NULL, censor, tail, include, recursedType, wildcardMatching, codePage); - #ifdef _WIN32 - else if (name[pos] == kMapNameID) - { - errorMessage = ParseMapWithPaths(censor, tail, include, recursedType, wildcardMatching); - if (errorMessage) - break; - } - #endif - else - { - errorMessage = "Incorrect wildcarc type marker"; - break; - } - } - if (i != strings.Size()) - throw CArcCmdLineException(errorMessage, strings[i]); -} - -#ifdef _WIN32 - -// This code converts all short file names to long file names. - -static void ConvertToLongName(const UString &prefix, UString &name) -{ - if (name.IsEmpty() || DoesNameContainWildcard(name)) - return; - NFind::CFileInfo fi; - const FString path = us2fs(prefix + name); - if (NFile::NName::IsDevicePath(path)) - return; - if (fi.Find(path)) - name = fs2us(fi.Name); -} - -static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items) -{ - FOR_VECTOR (i, items) - { - NWildcard::CItem &item = items[i]; - if (item.Recursive || item.PathParts.Size() != 1) - continue; - if (prefix.IsEmpty() && item.IsDriveItem()) - continue; - ConvertToLongName(prefix, item.PathParts.Front()); - } -} - -static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node) -{ - ConvertToLongNames(prefix, node.IncludeItems); - ConvertToLongNames(prefix, node.ExcludeItems); - unsigned i; - for (i = 0; i < node.SubNodes.Size(); i++) - { - UString &name = node.SubNodes[i].Name; - if (prefix.IsEmpty() && NWildcard::IsDriveColonName(name)) - continue; - ConvertToLongName(prefix, name); - } - // mix folders with same name - for (i = 0; i < node.SubNodes.Size(); i++) - { - NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; - for (unsigned j = i + 1; j < node.SubNodes.Size();) - { - const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; - if (nextNode1.Name.IsEqualToNoCase(nextNode2.Name)) - { - nextNode1.IncludeItems += nextNode2.IncludeItems; - nextNode1.ExcludeItems += nextNode2.ExcludeItems; - node.SubNodes.Delete(j); - } - else - j++; - } - } - for (i = 0; i < node.SubNodes.Size(); i++) - { - NWildcard::CCensorNode &nextNode = node.SubNodes[i]; - ConvertToLongNames(prefix + nextNode.Name + WCHAR_PATH_SEPARATOR, nextNode); - } -} - -void ConvertToLongNames(NWildcard::CCensor &censor) -{ - FOR_VECTOR (i, censor.Pairs) - { - NWildcard::CPair &pair = censor.Pairs[i]; - ConvertToLongNames(pair.Prefix, pair.Head); - } -} - -#endif - -/* -static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) -{ - switch (i) - { - case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; - case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; - case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress; - case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti; - } - throw 98111603; -} -*/ - -static const wchar_t *kUpdatePairStateIDSet = L"pqrxyzw"; -static const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; - -static const unsigned kNumUpdatePairActions = 4; -static const char *kUpdateIgnoreItselfPostStringID = "-"; -static const wchar_t kUpdateNewArchivePostCharID = '!'; - - -static bool ParseUpdateCommandString2(const UString &command, - NUpdateArchive::CActionSet &actionSet, UString &postString) -{ - for (unsigned i = 0; i < command.Len();) - { - wchar_t c = MyCharLower_Ascii(command[i]); - int statePos = FindCharPosInString(kUpdatePairStateIDSet, c); - if (statePos < 0) - { - postString = command.Ptr(i); - return true; - } - i++; - if (i >= command.Len()) - return false; - c = command[i]; - if (c < '0' || c >= '0' + kNumUpdatePairActions) - return false; - int actionPos = c - '0'; - actionSet.StateActions[statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos); - if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) - return false; - i++; - } - postString.Empty(); - return true; -} - -static void ParseUpdateCommandString(CUpdateOptions &options, - const UStringVector &updatePostStrings, - const NUpdateArchive::CActionSet &defaultActionSet) -{ - const char *errorMessage = "incorrect update switch command"; - unsigned i; - for (i = 0; i < updatePostStrings.Size(); i++) - { - const UString &updateString = updatePostStrings[i]; - if (updateString.IsEqualTo(kUpdateIgnoreItselfPostStringID)) - { - if (options.UpdateArchiveItself) - { - options.UpdateArchiveItself = false; - options.Commands.Delete(0); - } - } - else - { - NUpdateArchive::CActionSet actionSet = defaultActionSet; - - UString postString; - if (!ParseUpdateCommandString2(updateString, actionSet, postString)) - break; - if (postString.IsEmpty()) - { - if (options.UpdateArchiveItself) - options.Commands[0].ActionSet = actionSet; - } - else - { - if (postString[0] != kUpdateNewArchivePostCharID) - break; - CUpdateArchiveCommand uc; - UString archivePath = postString.Ptr(1); - if (archivePath.IsEmpty()) - break; - uc.UserArchivePath = archivePath; - uc.ActionSet = actionSet; - options.Commands.Add(uc); - } - } - } - if (i != updatePostStrings.Size()) - throw CArcCmdLineException(errorMessage, updatePostStrings[i]); -} - -bool ParseComplexSize(const wchar_t *s, UInt64 &result); - -static void SetAddCommandOptions( - NCommandType::EEnum commandType, - const CParser &parser, - CUpdateOptions &options) -{ - NUpdateArchive::CActionSet defaultActionSet; - switch (commandType) - { - case NCommandType::kAdd: - defaultActionSet = NUpdateArchive::k_ActionSet_Add; - break; - case NCommandType::kDelete: - defaultActionSet = NUpdateArchive::k_ActionSet_Delete; - break; - default: - defaultActionSet = NUpdateArchive::k_ActionSet_Update; - } - - options.UpdateArchiveItself = true; - - options.Commands.Clear(); - CUpdateArchiveCommand updateMainCommand; - updateMainCommand.ActionSet = defaultActionSet; - options.Commands.Add(updateMainCommand); - if (parser[NKey::kUpdate].ThereIs) - ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings, - defaultActionSet); - if (parser[NKey::kWorkingDir].ThereIs) - { - const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; - if (postString.IsEmpty()) - NDir::MyGetTempPath(options.WorkingDir); - else - options.WorkingDir = us2fs(postString); - } - options.SfxMode = parser[NKey::kSfx].ThereIs; - if (options.SfxMode) - options.SfxModule = us2fs(parser[NKey::kSfx].PostStrings[0]); - - if (parser[NKey::kVolume].ThereIs) - { - const UStringVector &sv = parser[NKey::kVolume].PostStrings; - FOR_VECTOR (i, sv) - { - UInt64 size; - if (!ParseComplexSize(sv[i], size) || size == 0) - throw CArcCmdLineException("Incorrect volume size:", sv[i]); - options.VolumesSizes.Add(size); - } - } -} - -static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties) -{ - if (parser[NKey::kProperty].ThereIs) - { - FOR_VECTOR (i, parser[NKey::kProperty].PostStrings) - { - CProperty prop; - prop.Name = parser[NKey::kProperty].PostStrings[i]; - int index = prop.Name.Find(L'='); - if (index >= 0) - { - prop.Value = prop.Name.Ptr(index + 1); - prop.Name.DeleteFrom(index); - } - properties.Add(prop); - } - } -} - -CArcCmdLineParser::CArcCmdLineParser(): parser(ARRAY_SIZE(kSwitchForms)) {} - -void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, - CArcCmdLineOptions &options) -{ - if (!parser.ParseStrings(kSwitchForms, commandStrings)) - throw CArcCmdLineException(parser.ErrorMessage, parser.ErrorLine); - - options.IsInTerminal = MY_IS_TERMINAL(stdin); - options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); - options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); - options.StdInMode = parser[NKey::kStdIn].ThereIs; - options.StdOutMode = parser[NKey::kStdOut].ThereIs; - options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; - options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; - - if (parser[NKey::kCaseSensitive].ThereIs) - { - g_CaseSensitive = !parser[NKey::kCaseSensitive].WithMinus; - options.CaseSensitiveChange = true; - options.CaseSensitive = g_CaseSensitive; - } - - #ifdef _WIN32 - options.LargePages = false; - if (parser[NKey::kLargePages].ThereIs) - { - options.LargePages = !parser[NKey::kLargePages].WithMinus; - } - #endif -} - -struct CCodePagePair -{ - const char *Name; - Int32 CodePage; -}; - -static const unsigned kNumByteOnlyCodePages = 3; - -static CCodePagePair g_CodePagePairs[] = -{ - { "utf-8", CP_UTF8 }, - { "win", CP_ACP }, - { "dos", CP_OEMCP }, - { "utf-16le", MY__CP_UTF16 }, - { "utf-16be", MY__CP_UTF16BE } -}; - -static Int32 FindCharset(const NCommandLineParser::CParser &parser, int keyIndex, - bool byteOnlyCodePages, Int32 defaultVal) -{ - if (!parser[keyIndex].ThereIs) - return defaultVal; - - UString name = parser[keyIndex].PostStrings.Back(); - UInt32 v; - if (StringToUInt32(name, v)) - if (v < ((UInt32)1 << 16)) - return (Int32)v; - name.MakeLower_Ascii(); - unsigned num = byteOnlyCodePages ? kNumByteOnlyCodePages : ARRAY_SIZE(g_CodePagePairs); - for (unsigned i = 0;; i++) - { - if (i == num) // to disable warnings from different compilers - throw CArcCmdLineException("Unsupported charset:", name); - const CCodePagePair &pair = g_CodePagePairs[i]; - if (name.IsEqualTo(pair.Name)) - return pair.CodePage; - } -} - -void EnumerateDirItemsAndSort( - bool storeAltStreams, - NWildcard::CCensor &censor, - NWildcard::ECensorPathMode censorPathMode, - const UString &addPathPrefix, - UStringVector &sortedPaths, - UStringVector &sortedFullPaths) -{ - UStringVector paths; - { - CDirItems dirItems; - { - dirItems.ScanAltStreams = storeAltStreams; - HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems, NULL); - if (res != S_OK || dirItems.ErrorPaths.Size() > 0) - { - UString errorPath; - if (dirItems.ErrorPaths.Size() > 0) - errorPath = fs2us(dirItems.ErrorPaths[0]); - throw CArcCmdLineException(kCannotFindArchive, - dirItems.ErrorPaths.Size() > 0 ? (const wchar_t *)errorPath : NULL); - } - } - FOR_VECTOR (i, dirItems.Items) - { - const CDirItem &dirItem = dirItems.Items[i]; - if (!dirItem.IsDir()) - paths.Add(dirItems.GetPhyPath(i)); - } - } - - if (paths.Size() == 0) - throw CArcCmdLineException(kCannotFindArchive); - - UStringVector fullPaths; - - unsigned i; - for (i = 0; i < paths.Size(); i++) - { - FString fullPath; - NFile::NDir::MyGetFullPathName(us2fs(paths[i]), fullPath); - fullPaths.Add(fs2us(fullPath)); - } - CUIntVector indices; - SortFileNames(fullPaths, indices); - sortedPaths.ClearAndReserve(indices.Size()); - sortedFullPaths.ClearAndReserve(indices.Size()); - for (i = 0; i < indices.Size(); i++) - { - unsigned index = indices[i]; - sortedPaths.AddInReserved(paths[index]); - sortedFullPaths.AddInReserved(fullPaths[index]); - if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0) - throw CArcCmdLineException("Duplicate archive path:", sortedFullPaths[i]); - } -} - -static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, CBoolPair &bp) -{ - bp.Def = parser[switchID].ThereIs; - if (bp.Def) - bp.Val = !parser[switchID].WithMinus; -} - -void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) -{ - const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; - int numNonSwitchStrings = nonSwitchStrings.Size(); - if (numNonSwitchStrings < kMinNonSwitchWords) - throw CArcCmdLineException("The command must be spcified"); - - if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) - throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]); - - options.TechMode = parser[NKey::kTechMode].ThereIs; - if (parser[NKey::kHash].ThereIs) - options.HashMethods = parser[NKey::kHash].PostStrings; - - if (parser[NKey::kElimDup].ThereIs) - { - options.ExtractOptions.ElimDup.Def = true; - options.ExtractOptions.ElimDup.Val = !parser[NKey::kElimDup].WithMinus; - } - - NWildcard::ECensorPathMode censorPathMode = NWildcard::k_RelatPath; - bool fullPathMode = parser[NKey::kFullPathMode].ThereIs; - if (fullPathMode) - { - censorPathMode = NWildcard::k_AbsPath; - const UString &s = parser[NKey::kFullPathMode].PostStrings[0]; - if (!s.IsEmpty()) - { - if (s == L"2") - censorPathMode = NWildcard::k_FullPath; - else - throw CArcCmdLineException("Unsupported -spf:", s); - } - } - - NRecursedType::EEnum recursedType; - if (parser[NKey::kRecursed].ThereIs) - recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); - else - recursedType = NRecursedType::kNonRecursed; - - bool wildcardMatching = true; - if (parser[NKey::kDisableWildcardParsing].ThereIs) - wildcardMatching = false; - - g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, true, -1); - Int32 codePage = FindCharset(parser, NKey::kListfileCharSet, false, CP_UTF8); - - bool thereAreSwitchIncludes = false; - - if (parser[NKey::kInclude].ThereIs) - { - thereAreSwitchIncludes = true; - AddSwitchWildcardsToCensor(options.Censor, - parser[NKey::kInclude].PostStrings, true, recursedType, wildcardMatching, codePage); - } - - if (parser[NKey::kExclude].ThereIs) - AddSwitchWildcardsToCensor(options.Censor, - parser[NKey::kExclude].PostStrings, false, recursedType, wildcardMatching, codePage); - - int curCommandIndex = kCommandIndex + 1; - bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && - options.Command.CommandType != NCommandType::kBenchmark && - options.Command.CommandType != NCommandType::kInfo && - options.Command.CommandType != NCommandType::kHash; - - bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); - bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList; - bool isRename = options.Command.CommandType == NCommandType::kRename; - - if ((isExtractOrList || isRename) && options.StdInMode) - thereIsArchiveName = false; - - if (parser[NKey::kArcNameMode].ThereIs) - options.UpdateOptions.ArcNameMode = ParseArcNameMode(parser[NKey::kArcNameMode].PostCharIndex); - - if (thereIsArchiveName) - { - if (curCommandIndex >= numNonSwitchStrings) - throw CArcCmdLineException("Cannot find archive name"); - options.ArchiveName = nonSwitchStrings[curCommandIndex++]; - if (options.ArchiveName.IsEmpty()) - throw CArcCmdLineException("Archive name cannot by empty"); - } - - AddToCensorFromNonSwitchesStrings(isRename ? &options.UpdateOptions.RenamePairs : NULL, - curCommandIndex, options.Censor, - nonSwitchStrings, recursedType, wildcardMatching, - thereAreSwitchIncludes, codePage); - - options.YesToAll = parser[NKey::kYes].ThereIs; - - - #ifndef _NO_CRYPTO - options.PasswordEnabled = parser[NKey::kPassword].ThereIs; - if (options.PasswordEnabled) - options.Password = parser[NKey::kPassword].PostStrings[0]; - #endif - - options.ShowDialog = parser[NKey::kShowDialog].ThereIs; - - if (parser[NKey::kArchiveType].ThereIs) - options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; - - options.ExcludedArcTypes = parser[NKey::kExcludedArcType].PostStrings; - - SetMethodOptions(parser, options.Properties); - - options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; - - if (options.EnablePercents) - { - if ((options.StdOutMode && !options.IsStdErrTerminal) || - (!options.StdOutMode && !options.IsStdOutTerminal)) - options.EnablePercents = false; - } - - if (parser[NKey::kNtSecurity].ThereIs) options.NtSecurity.SetTrueTrue(); - - SetBoolPair(parser, NKey::kAltStreams, options.AltStreams); - SetBoolPair(parser, NKey::kHardLinks, options.HardLinks); - SetBoolPair(parser, NKey::kSymLinks, options.SymLinks); - - if (isExtractOrList) - { - CExtractOptionsBase &eo = options.ExtractOptions; - - { - CExtractNtOptions &nt = eo.NtOptions; - nt.NtSecurity = options.NtSecurity; - - nt.AltStreams = options.AltStreams; - if (!options.AltStreams.Def) - nt.AltStreams.Val = true; - - nt.HardLinks = options.HardLinks; - if (!options.HardLinks.Def) - nt.HardLinks.Val = true; - - nt.SymLinks = options.SymLinks; - if (!options.SymLinks.Def) - nt.SymLinks.Val = true; - - nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs; - nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs; - } - - options.Censor.AddPathsToCensor(NWildcard::k_AbsPath); - options.Censor.ExtendExclude(); - - // are there paths that look as non-relative (!Prefix.IsEmpty()) - if (!options.Censor.AllAreRelative()) - throw CArcCmdLineException("Cannot use absolute pathnames for this command"); - - NWildcard::CCensor arcCensor; - - if (parser[NKey::kArInclude].ThereIs) - AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, wildcardMatching, codePage); - if (parser[NKey::kArExclude].ThereIs) - AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, wildcardMatching, codePage); - - if (thereIsArchiveName) - AddNameToCensor(arcCensor, options.ArchiveName, true, NRecursedType::kNonRecursed, wildcardMatching); - - arcCensor.AddPathsToCensor(NWildcard::k_RelatPath); - - #ifdef _WIN32 - ConvertToLongNames(arcCensor); - #endif - - arcCensor.ExtendExclude(); - - if (options.StdInMode) - { - UString arcName = parser[NKey::kStdIn].PostStrings.Front(); - options.ArchivePathsSorted.Add(arcName); - options.ArchivePathsFullSorted.Add(arcName); - } - else - { - EnumerateDirItemsAndSort( - false, // scanAltStreams - arcCensor, - NWildcard::k_RelatPath, - UString(), // addPathPrefix - options.ArchivePathsSorted, - options.ArchivePathsFullSorted); - } - - if (isExtractGroupCommand) - { - if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) - throw CArcCmdLineException(kSameTerminalError); - if (parser[NKey::kOutputDir].ThereIs) - { - eo.OutputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); - NFile::NName::NormalizeDirPathPrefix(eo.OutputDir); - } - - eo.OverwriteMode = NExtract::NOverwriteMode::kAsk; - if (parser[NKey::kOverwrite].ThereIs) - { - eo.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; - eo.OverwriteMode_Force = true; - } - else if (options.YesToAll) - { - eo.OverwriteMode = NExtract::NOverwriteMode::kOverwrite; - eo.OverwriteMode_Force = true; - } - } - - eo.PathMode = options.Command.GetPathMode(); - if (censorPathMode == NWildcard::k_AbsPath) - { - eo.PathMode = NExtract::NPathMode::kAbsPaths; - eo.PathMode_Force = true; - } - else if (censorPathMode == NWildcard::k_FullPath) - { - eo.PathMode = NExtract::NPathMode::kFullPaths; - eo.PathMode_Force = true; - } - } - else if (options.Command.IsFromUpdateGroup()) - { - if (parser[NKey::kArInclude].ThereIs) - throw CArcCmdLineException("-ai switch is not supported for this command"); - - CUpdateOptions &updateOptions = options.UpdateOptions; - - SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); - - updateOptions.MethodMode.Properties = options.Properties; - - if (parser[NKey::kShareForWrite].ThereIs) - updateOptions.OpenShareForWrite = true; - - updateOptions.PathMode = censorPathMode; - - updateOptions.AltStreams = options.AltStreams; - updateOptions.NtSecurity = options.NtSecurity; - updateOptions.HardLinks = options.HardLinks; - updateOptions.SymLinks = options.SymLinks; - - updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; - if (updateOptions.EMailMode) - { - updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); - if (updateOptions.EMailAddress.Len() > 0) - if (updateOptions.EMailAddress[0] == L'.') - { - updateOptions.EMailRemoveAfter = true; - updateOptions.EMailAddress.Delete(0); - } - } - - updateOptions.StdOutMode = options.StdOutMode; - updateOptions.StdInMode = options.StdInMode; - - updateOptions.DeleteAfterCompressing = parser[NKey::kDeleteAfterCompressing].ThereIs; - updateOptions.SetArcMTime = parser[NKey::kSetArcMTime].ThereIs; - - if (updateOptions.StdOutMode && updateOptions.EMailMode) - throw CArcCmdLineException("stdout mode and email mode cannot be combined"); - if (updateOptions.StdOutMode && options.IsStdOutTerminal) - throw CArcCmdLineException(kTerminalOutError); - if (updateOptions.StdInMode) - updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); - - if (options.Command.CommandType == NCommandType::kRename) - if (updateOptions.Commands.Size() != 1) - throw CArcCmdLineException("Only one archive can be created with rename command"); - } - else if (options.Command.CommandType == NCommandType::kBenchmark) - { - options.NumIterations = 1; - if (curCommandIndex < numNonSwitchStrings) - { - if (!StringToUInt32(nonSwitchStrings[curCommandIndex], options.NumIterations)) - throw CArcCmdLineException("Incorrect Number of benmchmark iterations", nonSwitchStrings[curCommandIndex]); - curCommandIndex++; - } - } - else if (options.Command.CommandType == NCommandType::kHash) - { - options.Censor.AddPathsToCensor(censorPathMode); - options.Censor.ExtendExclude(); - - CHashOptions &hashOptions = options.HashOptions; - hashOptions.PathMode = censorPathMode; - hashOptions.Methods = options.HashMethods; - if (parser[NKey::kShareForWrite].ThereIs) - hashOptions.OpenShareForWrite = true; - hashOptions.StdInMode = options.StdInMode; - hashOptions.AltStreamsMode = options.AltStreams.Val; - } - else if (options.Command.CommandType == NCommandType::kInfo) - { - } - else - throw 9815676711; -} |