mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-10 20:07:05 -06:00
4.20
This commit is contained in:
committed by
Kornel Lesiński
parent
8c1b5c7b7e
commit
3c510ba80b
830
7zip/UI/Common/ArchiveCommandLine.cpp
Executable file
830
7zip/UI/Common/ArchiveCommandLine.cpp
Executable file
@@ -0,0 +1,830 @@
|
||||
// ArchiveCommandLine.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Common/ListFileUtils.h"
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/StringToInt.h"
|
||||
|
||||
#include "Windows/FileName.h"
|
||||
#include "Windows/FileDir.h"
|
||||
#ifdef _WIN32
|
||||
#include "Windows/FileMapping.h"
|
||||
#include "Windows/Synchronization.h"
|
||||
#endif
|
||||
|
||||
#include "ArchiveCommandLine.h"
|
||||
#include "UpdateAction.h"
|
||||
#include "Update.h"
|
||||
#include "ArchiverInfo.h"
|
||||
#include "SortUtils.h"
|
||||
#include "EnumDirItems.h"
|
||||
|
||||
using namespace NCommandLineParser;
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
|
||||
static const int kNumSwitches = 24;
|
||||
|
||||
namespace NKey {
|
||||
enum Enum
|
||||
{
|
||||
kHelp1 = 0,
|
||||
kHelp2,
|
||||
kDisableHeaders,
|
||||
kDisablePercents,
|
||||
kArchiveType,
|
||||
kYes,
|
||||
kPassword,
|
||||
kProperty,
|
||||
kOutputDir,
|
||||
kWorkingDir,
|
||||
kInclude,
|
||||
kExclude,
|
||||
kArInclude,
|
||||
kArExclude,
|
||||
kNoArName,
|
||||
kUpdate,
|
||||
kVolume,
|
||||
kRecursed,
|
||||
kSfx,
|
||||
kStdIn,
|
||||
kStdOut,
|
||||
kOverwrite,
|
||||
kEmail,
|
||||
kShowDialog
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
static const wchar_t kRecursedIDChar = 'R';
|
||||
static const wchar_t *kRecursedPostCharSet = L"0-";
|
||||
|
||||
static const wchar_t *kDefaultArchiveType = L"7z";
|
||||
static const wchar_t *kSFXExtension = L"exe";
|
||||
|
||||
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 wchar_t *kOverwritePostCharSet = L"asut";
|
||||
|
||||
NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =
|
||||
{
|
||||
NExtract::NOverwriteMode::kWithoutPrompt,
|
||||
NExtract::NOverwriteMode::kSkipExisting,
|
||||
NExtract::NOverwriteMode::kAutoRename,
|
||||
NExtract::NOverwriteMode::kAutoRenameExisting
|
||||
};
|
||||
|
||||
static const CSwitchForm kSwitchForms[kNumSwitches] =
|
||||
{
|
||||
{ L"?", NSwitchType::kSimple, false },
|
||||
{ L"H", NSwitchType::kSimple, false },
|
||||
{ L"BA", NSwitchType::kSimple, false },
|
||||
{ L"BD", NSwitchType::kSimple, false },
|
||||
{ L"T", NSwitchType::kUnLimitedPostString, false, 1 },
|
||||
{ L"Y", NSwitchType::kSimple, false },
|
||||
{ L"P", NSwitchType::kUnLimitedPostString, false, 0 },
|
||||
{ L"M", NSwitchType::kUnLimitedPostString, true, 1 },
|
||||
{ L"O", NSwitchType::kUnLimitedPostString, false, 1 },
|
||||
{ L"W", NSwitchType::kUnLimitedPostString, false, 0 },
|
||||
{ L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
|
||||
{ L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
|
||||
{ L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
|
||||
{ L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
|
||||
{ L"AN", NSwitchType::kSimple, false },
|
||||
{ L"U", NSwitchType::kUnLimitedPostString, true, 1},
|
||||
{ L"V", NSwitchType::kUnLimitedPostString, true, 1},
|
||||
{ L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet },
|
||||
{ L"SFX", NSwitchType::kUnLimitedPostString, false, 0 },
|
||||
{ L"SI", NSwitchType::kUnLimitedPostString, false, 0 },
|
||||
{ L"SO", NSwitchType::kSimple, false, 0 },
|
||||
{ L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet},
|
||||
{ L"SEML", NSwitchType::kUnLimitedPostString, false, 0},
|
||||
{ L"AD", NSwitchType::kSimple, false }
|
||||
};
|
||||
|
||||
static const int kNumCommandForms = 7;
|
||||
|
||||
static const CCommandForm g_CommandForms[kNumCommandForms] =
|
||||
{
|
||||
{ L"A", false },
|
||||
{ L"U", false },
|
||||
{ L"D", false },
|
||||
{ L"T", false },
|
||||
{ L"E", false },
|
||||
{ L"X", false },
|
||||
{ L"L", false }
|
||||
};
|
||||
|
||||
static const int kMaxCmdLineSize = 1000;
|
||||
static const wchar_t *kUniversalWildcard = L"*";
|
||||
static const int kMinNonSwitchWords = 1;
|
||||
static const int kCommandIndex = 0;
|
||||
|
||||
// ---------------------------
|
||||
// exception messages
|
||||
|
||||
static const char *kUserErrorMessage = "Incorrect command line";
|
||||
static const char *kIncorrectListFile = "Incorrect wildcard in listfile";
|
||||
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";
|
||||
|
||||
// ---------------------------
|
||||
|
||||
bool CArchiveCommand::IsFromExtractGroup() const
|
||||
{
|
||||
switch(CommandType)
|
||||
{
|
||||
case NCommandType::kTest:
|
||||
case NCommandType::kExtract:
|
||||
case NCommandType::kFullExtract:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const
|
||||
{
|
||||
switch(CommandType)
|
||||
{
|
||||
case NCommandType::kTest:
|
||||
case NCommandType::kFullExtract:
|
||||
return NExtract::NPathMode::kFullPathnames;
|
||||
default:
|
||||
return NExtract::NPathMode::kNoPathnames;
|
||||
}
|
||||
}
|
||||
|
||||
bool CArchiveCommand::IsFromUpdateGroup() const
|
||||
{
|
||||
return (CommandType == NCommandType::kAdd ||
|
||||
CommandType == NCommandType::kUpdate ||
|
||||
CommandType == NCommandType::kDelete);
|
||||
}
|
||||
|
||||
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 bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)
|
||||
{
|
||||
UString commandStringUpper = commandString;
|
||||
commandStringUpper.MakeUpper();
|
||||
UString postString;
|
||||
int commandIndex = ParseCommand(kNumCommandForms, g_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)
|
||||
{
|
||||
bool isWildCard = DoesNameContainWildCard(name);
|
||||
bool recursed;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case NRecursedType::kWildCardOnlyRecursed:
|
||||
recursed = isWildCard;
|
||||
break;
|
||||
case NRecursedType::kRecursed:
|
||||
recursed = true;
|
||||
break;
|
||||
case NRecursedType::kNonRecursed:
|
||||
recursed = false;
|
||||
break;
|
||||
}
|
||||
wildcardCensor.AddItem(name, include, recursed);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline UINT GetCurrentCodePage()
|
||||
{ return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
|
||||
|
||||
static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor,
|
||||
LPCWSTR fileName, bool include, NRecursedType::EEnum type)
|
||||
{
|
||||
UStringVector names;
|
||||
if (!ReadNamesFromListFile(GetSystemString(fileName,
|
||||
GetCurrentCodePage()), names))
|
||||
throw kIncorrectListFile;
|
||||
for (int i = 0; i < names.Size(); i++)
|
||||
if (!AddNameToCensor(wildcardCensor, names[i], include, type))
|
||||
throw kIncorrectWildCardInListFile;
|
||||
}
|
||||
|
||||
static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor,
|
||||
const UString &name, bool include, NRecursedType::EEnum recursedType)
|
||||
{
|
||||
if (!AddNameToCensor(wildcardCensor, name, include, recursedType))
|
||||
throw kIncorrectWildCardInCommandLine;
|
||||
}
|
||||
|
||||
static void AddToCensorFromNonSwitchesStrings(
|
||||
int startIndex,
|
||||
NWildcard::CCensor &wildcardCensor,
|
||||
const UStringVector &nonSwitchStrings, NRecursedType::EEnum type,
|
||||
bool thereAreSwitchIncludes)
|
||||
{
|
||||
if(nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes))
|
||||
AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type);
|
||||
for(int i = startIndex; i < nonSwitchStrings.Size(); i++)
|
||||
{
|
||||
const UString &s = nonSwitchStrings[i];
|
||||
if (s[0] == kFileListID)
|
||||
AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type);
|
||||
else
|
||||
AddCommandLineWildCardToCensr(wildcardCensor, s, true, type);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor,
|
||||
const UString &switchParam, bool include,
|
||||
NRecursedType::EEnum commonRecursedType)
|
||||
{
|
||||
int splitPos = switchParam.Find(L':');
|
||||
if (splitPos < 0)
|
||||
throw kUserErrorMessage;
|
||||
UString mappingName = switchParam.Left(splitPos);
|
||||
|
||||
UString switchParam2 = switchParam.Mid(splitPos + 1);
|
||||
splitPos = switchParam2.Find(L':');
|
||||
if (splitPos < 0)
|
||||
throw kUserErrorMessage;
|
||||
|
||||
UString mappingSize = switchParam2.Left(splitPos);
|
||||
UString eventName = switchParam2.Mid(splitPos + 1);
|
||||
|
||||
UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL);
|
||||
UInt32 dataSize = (UInt32)dataSize64;
|
||||
{
|
||||
CFileMapping fileMapping;
|
||||
if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName)))
|
||||
throw L"Can not open mapping";
|
||||
LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize);
|
||||
if (data == NULL)
|
||||
throw L"MapViewOfFile error";
|
||||
try
|
||||
{
|
||||
const wchar_t *curData = (const wchar_t *)data;
|
||||
if (*curData != 0)
|
||||
throw L"Incorrect mapping data";
|
||||
UInt32 numChars = dataSize / sizeof(wchar_t);
|
||||
UString name;
|
||||
for (UInt32 i = 1; i < numChars; i++)
|
||||
{
|
||||
wchar_t c = curData[i];
|
||||
if (c == L'\0')
|
||||
{
|
||||
AddCommandLineWildCardToCensr(wildcardCensor,
|
||||
name, include, commonRecursedType);
|
||||
name.Empty();
|
||||
}
|
||||
else
|
||||
name += c;
|
||||
}
|
||||
if (!name.IsEmpty())
|
||||
throw L"data error";
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
UnmapViewOfFile(data);
|
||||
throw;
|
||||
}
|
||||
UnmapViewOfFile(data);
|
||||
}
|
||||
|
||||
{
|
||||
NSynchronization::CEvent event;
|
||||
event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName));
|
||||
event.Set();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor,
|
||||
const UStringVector &strings, bool include,
|
||||
NRecursedType::EEnum commonRecursedType)
|
||||
{
|
||||
for(int i = 0; i < strings.Size(); i++)
|
||||
{
|
||||
const UString &name = strings[i];
|
||||
NRecursedType::EEnum recursedType;
|
||||
int pos = 0;
|
||||
if (name.Length() < kSomeCludePostStringMinSize)
|
||||
throw kUserErrorMessage;
|
||||
if (::MyCharUpper(name[pos]) == kRecursedIDChar)
|
||||
{
|
||||
pos++;
|
||||
int index = UString(kRecursedPostCharSet).Find(name[pos]);
|
||||
recursedType = GetRecursedTypeFromIndex(index);
|
||||
if (index >= 0)
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
recursedType = commonRecursedType;
|
||||
if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize)
|
||||
throw kUserErrorMessage;
|
||||
UString tail = name.Mid(pos + 1);
|
||||
if (name[pos] == kImmediateNameID)
|
||||
AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType);
|
||||
else if (name[pos] == kFileListID)
|
||||
AddToCensorFromListFile(wildcardCensor, tail, include, recursedType);
|
||||
#ifdef _WIN32
|
||||
else if (name[pos] == kMapNameID)
|
||||
ParseMapWithPaths(wildcardCensor, tail, include, recursedType);
|
||||
#endif
|
||||
else
|
||||
throw kUserErrorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const UString kUpdatePairStateIDSet = L"PQRXYZW";
|
||||
const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};
|
||||
|
||||
const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti
|
||||
|
||||
const wchar_t *kUpdateIgnoreItselfPostStringID = L"-";
|
||||
const wchar_t kUpdateNewArchivePostCharID = '!';
|
||||
|
||||
|
||||
static bool ParseUpdateCommandString2(const UString &command,
|
||||
NUpdateArchive::CActionSet &actionSet, UString &postString)
|
||||
{
|
||||
for(int i = 0; i < command.Length();)
|
||||
{
|
||||
wchar_t c = MyCharUpper(command[i]);
|
||||
int statePos = kUpdatePairStateIDSet.Find(c);
|
||||
if (statePos < 0)
|
||||
{
|
||||
postString = command.Mid(i);
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
if (i >= command.Length())
|
||||
return false;
|
||||
int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i]));
|
||||
if (actionPos < 0)
|
||||
return false;
|
||||
actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos);
|
||||
if (kUpdatePairStateNotSupportedActions[statePos] == actionPos)
|
||||
return false;
|
||||
i++;
|
||||
}
|
||||
postString.Empty();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ParseUpdateCommandString(CUpdateOptions &options,
|
||||
const UStringVector &updatePostStrings,
|
||||
const NUpdateArchive::CActionSet &defaultActionSet)
|
||||
{
|
||||
for(int i = 0; i < updatePostStrings.Size(); i++)
|
||||
{
|
||||
const UString &updateString = updatePostStrings[i];
|
||||
if(updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0)
|
||||
{
|
||||
if(options.UpdateArchiveItself)
|
||||
{
|
||||
options.UpdateArchiveItself = false;
|
||||
options.Commands.Delete(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NUpdateArchive::CActionSet actionSet = defaultActionSet;
|
||||
|
||||
UString postString;
|
||||
if (!ParseUpdateCommandString2(updateString, actionSet, postString))
|
||||
throw kUserErrorMessage;
|
||||
if(postString.IsEmpty())
|
||||
{
|
||||
if(options.UpdateArchiveItself)
|
||||
options.Commands[0].ActionSet = actionSet;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID)
|
||||
throw kUserErrorMessage;
|
||||
CUpdateArchiveCommand uc;
|
||||
UString archivePath = postString.Mid(1);
|
||||
if (archivePath.IsEmpty())
|
||||
throw kUserErrorMessage;
|
||||
uc.ArchivePath.BaseExtension = options.ArchivePath.BaseExtension;
|
||||
uc.ArchivePath.VolExtension = options.ArchivePath.VolExtension;
|
||||
uc.ArchivePath.ParseFromPath(archivePath);
|
||||
uc.ActionSet = actionSet;
|
||||
options.Commands.Add(uc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char kByteSymbol = 'B';
|
||||
static const char kKiloSymbol = 'K';
|
||||
static const char kMegaSymbol = 'M';
|
||||
static const char kGigaSymbol = 'G';
|
||||
|
||||
static bool ParseComplexSize(const UString &src, UInt64 &result)
|
||||
{
|
||||
UString s = src;
|
||||
s.MakeUpper();
|
||||
|
||||
const wchar_t *start = s;
|
||||
const wchar_t *end;
|
||||
UInt64 number = ConvertStringToUInt64(start, &end);
|
||||
int numDigits = end - start;
|
||||
if (numDigits == 0 || s.Length() > numDigits + 1)
|
||||
return false;
|
||||
if (s.Length() == numDigits)
|
||||
{
|
||||
result = number;
|
||||
return true;
|
||||
}
|
||||
int numBits;
|
||||
switch (s[numDigits])
|
||||
{
|
||||
case kByteSymbol:
|
||||
result = number;
|
||||
return true;
|
||||
case kKiloSymbol:
|
||||
numBits = 10;
|
||||
break;
|
||||
case kMegaSymbol:
|
||||
numBits = 20;
|
||||
break;
|
||||
case kGigaSymbol:
|
||||
numBits = 30;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (number >= ((UInt64)1 << (64 - numBits)))
|
||||
return false;
|
||||
result = number << numBits;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SetAddCommandOptions(
|
||||
NCommandType::EEnum commandType,
|
||||
const CParser &parser,
|
||||
CUpdateOptions &options)
|
||||
{
|
||||
NUpdateArchive::CActionSet defaultActionSet;
|
||||
switch(commandType)
|
||||
{
|
||||
case NCommandType::kAdd:
|
||||
defaultActionSet = NUpdateArchive::kAddActionSet;
|
||||
break;
|
||||
case NCommandType::kDelete:
|
||||
defaultActionSet = NUpdateArchive::kDeleteActionSet;
|
||||
break;
|
||||
default:
|
||||
defaultActionSet = NUpdateArchive::kUpdateActionSet;
|
||||
}
|
||||
|
||||
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())
|
||||
NDirectory::MyGetTempPath(options.WorkingDir);
|
||||
else
|
||||
options.WorkingDir = postString;
|
||||
}
|
||||
if(options.SfxMode = parser[NKey::kSfx].ThereIs)
|
||||
options.SfxModule = parser[NKey::kSfx].PostStrings[0];
|
||||
|
||||
if (parser[NKey::kVolume].ThereIs)
|
||||
{
|
||||
const UStringVector &sv = parser[NKey::kVolume].PostStrings;
|
||||
for (int i = 0; i < sv.Size(); i++)
|
||||
{
|
||||
const UString &s = sv[i];
|
||||
UInt64 size;
|
||||
if (!ParseComplexSize(sv[i], size))
|
||||
throw "incorrect volume size";
|
||||
options.VolumesSizes.Add(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SetMethodOptions(const CParser &parser,
|
||||
CUpdateOptions &options)
|
||||
{
|
||||
if (parser[NKey::kProperty].ThereIs)
|
||||
{
|
||||
// options.MethodMode.Properties.Clear();
|
||||
for(int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)
|
||||
{
|
||||
CProperty property;
|
||||
const UString &postString = parser[NKey::kProperty].PostStrings[i];
|
||||
int index = postString.Find(L'=');
|
||||
if (index < 0)
|
||||
property.Name = postString;
|
||||
else
|
||||
{
|
||||
property.Name = postString.Left(index);
|
||||
property.Value = postString.Mid(index + 1);
|
||||
}
|
||||
options.MethodMode.Properties.Add(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void SetArchiveType(const UString &archiveType,
|
||||
#ifndef EXCLUDE_COM
|
||||
UString &filePath, CLSID &classID,
|
||||
#else
|
||||
UString &formatName,
|
||||
#endif
|
||||
UString &archiveExtension)
|
||||
{
|
||||
CObjectVector<CArchiverInfo> archiverInfoVector;
|
||||
ReadArchiverInfoList(archiverInfoVector);
|
||||
if (archiverInfoVector.Size() == 0)
|
||||
throw "There are no installed archive handlers";
|
||||
if (archiveType.IsEmpty())
|
||||
throw "Incorrect archive type was assigned";
|
||||
for (int i = 0; i < archiverInfoVector.Size(); i++)
|
||||
{
|
||||
const CArchiverInfo &archiverInfo = archiverInfoVector[i];
|
||||
if (archiverInfo.Name.CompareNoCase(archiveType) == 0)
|
||||
{
|
||||
#ifndef EXCLUDE_COM
|
||||
classID = archiverInfo.ClassID;
|
||||
filePath = archiverInfo.FilePath;
|
||||
#else
|
||||
formatName = archiverInfo.Name;
|
||||
|
||||
#endif
|
||||
|
||||
archiveExtension = archiverInfo.GetMainExtension();
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw "Incorrect archive type was assigned";
|
||||
}
|
||||
|
||||
|
||||
CArchiveCommandLineParser::CArchiveCommandLineParser(): parser(kNumSwitches) {}
|
||||
|
||||
void CArchiveCommandLineParser::Parse1(UStringVector commandStrings,
|
||||
CArchiveCommandLineOptions &options)
|
||||
{
|
||||
try
|
||||
{
|
||||
parser.ParseStrings(kSwitchForms, commandStrings);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
throw kUserErrorMessage;
|
||||
}
|
||||
|
||||
options.IsInTerminal = (isatty(fileno(stdin)) != 0);
|
||||
options.IsStdOutTerminal = (isatty(fileno(stdout)) != 0);
|
||||
options.IsStdErrTerminal = (isatty(fileno(stderr)) != 0);
|
||||
options.StdOutMode = parser[NKey::kStdOut].ThereIs;
|
||||
options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;
|
||||
options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs;
|
||||
}
|
||||
|
||||
void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
|
||||
{
|
||||
const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
|
||||
int numNonSwitchStrings = nonSwitchStrings.Size();
|
||||
if(numNonSwitchStrings < kMinNonSwitchWords)
|
||||
throw kUserErrorMessage;
|
||||
|
||||
if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))
|
||||
throw kUserErrorMessage;
|
||||
|
||||
NRecursedType::EEnum recursedType;
|
||||
if (parser[NKey::kRecursed].ThereIs)
|
||||
recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex);
|
||||
else
|
||||
recursedType = NRecursedType::kNonRecursed;
|
||||
|
||||
bool thereAreSwitchIncludes = false;
|
||||
if (parser[NKey::kInclude].ThereIs)
|
||||
{
|
||||
thereAreSwitchIncludes = true;
|
||||
AddSwitchWildCardsToCensor(options.WildcardCensor,
|
||||
parser[NKey::kInclude].PostStrings, true, recursedType);
|
||||
}
|
||||
if (parser[NKey::kExclude].ThereIs)
|
||||
AddSwitchWildCardsToCensor(options.WildcardCensor,
|
||||
parser[NKey::kExclude].PostStrings, false, recursedType);
|
||||
|
||||
int curCommandIndex = kCommandIndex + 1;
|
||||
bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs;
|
||||
if (thereIsArchiveName)
|
||||
{
|
||||
if(curCommandIndex >= numNonSwitchStrings)
|
||||
throw kUserErrorMessage;
|
||||
options.ArchiveName = nonSwitchStrings[curCommandIndex++];
|
||||
}
|
||||
|
||||
AddToCensorFromNonSwitchesStrings(
|
||||
curCommandIndex, options.WildcardCensor,
|
||||
nonSwitchStrings, recursedType, thereAreSwitchIncludes);
|
||||
|
||||
options.YesToAll = parser[NKey::kYes].ThereIs;
|
||||
|
||||
bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
|
||||
|
||||
options.PasswordEnabled = parser[NKey::kPassword].ThereIs;
|
||||
|
||||
if(options.PasswordEnabled)
|
||||
options.Password = parser[NKey::kPassword].PostStrings[0];
|
||||
|
||||
options.StdInMode = parser[NKey::kStdIn].ThereIs;
|
||||
options.ShowDialog = parser[NKey::kShowDialog].ThereIs;
|
||||
|
||||
if(isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)
|
||||
{
|
||||
if (options.StdInMode)
|
||||
throw "reading archives from stdin is not implemented";
|
||||
if (!options.WildcardCensor.AllAreRelative())
|
||||
throw "cannot use absolute pathnames for this command";
|
||||
|
||||
NWildcard::CCensor archiveWildcardCensor;
|
||||
|
||||
if (parser[NKey::kArInclude].ThereIs)
|
||||
{
|
||||
AddSwitchWildCardsToCensor(archiveWildcardCensor,
|
||||
parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed);
|
||||
}
|
||||
if (parser[NKey::kArExclude].ThereIs)
|
||||
AddSwitchWildCardsToCensor(archiveWildcardCensor,
|
||||
parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed);
|
||||
|
||||
if (thereIsArchiveName)
|
||||
AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed);
|
||||
|
||||
CObjectVector<CDirItem> dirItems;
|
||||
EnumerateItems(archiveWildcardCensor, dirItems, NULL);
|
||||
UStringVector archivePaths;
|
||||
int i;
|
||||
for (i = 0; i < dirItems.Size(); i++)
|
||||
archivePaths.Add(dirItems[i].FullPath);
|
||||
|
||||
if (archivePaths.Size() == 0)
|
||||
throw "there is no such archive";
|
||||
|
||||
UStringVector archivePathsFull;
|
||||
|
||||
for (i = 0; i < archivePaths.Size(); i++)
|
||||
{
|
||||
UString fullPath;
|
||||
NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath);
|
||||
archivePathsFull.Add(fullPath);
|
||||
}
|
||||
CIntVector indices;
|
||||
SortStringsToIndices(archivePathsFull, indices);
|
||||
options.ArchivePathsSorted.Reserve(indices.Size());
|
||||
options.ArchivePathsFullSorted.Reserve(indices.Size());
|
||||
for (i = 0; i < indices.Size(); i++)
|
||||
{
|
||||
options.ArchivePathsSorted.Add(archivePaths[indices[i]]);
|
||||
options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]);
|
||||
}
|
||||
|
||||
if(isExtractGroupCommand)
|
||||
{
|
||||
if (options.StdOutMode && options.IsStdOutTerminal)
|
||||
throw kTerminalOutError;
|
||||
if(parser[NKey::kOutputDir].ThereIs)
|
||||
{
|
||||
options.OutputDir = parser[NKey::kOutputDir].PostStrings[0];
|
||||
NFile::NName::NormalizeDirPathPrefix(options.OutputDir);
|
||||
}
|
||||
|
||||
options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
|
||||
if(parser[NKey::kOverwrite].ThereIs)
|
||||
options.OverwriteMode =
|
||||
k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];
|
||||
else if (options.YesToAll)
|
||||
options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
|
||||
}
|
||||
}
|
||||
else if(options.Command.IsFromUpdateGroup())
|
||||
{
|
||||
CUpdateOptions &updateOptions = options.UpdateOptions;
|
||||
|
||||
UString archiveType;
|
||||
if(parser[NKey::kArchiveType].ThereIs)
|
||||
archiveType = parser[NKey::kArchiveType].PostStrings[0];
|
||||
else
|
||||
archiveType = kDefaultArchiveType;
|
||||
|
||||
UString typeExtension;
|
||||
if (!archiveType.IsEmpty())
|
||||
{
|
||||
#ifndef EXCLUDE_COM
|
||||
SetArchiveType(archiveType, updateOptions.MethodMode.FilePath,
|
||||
updateOptions.MethodMode.ClassID, typeExtension);
|
||||
#else
|
||||
SetArchiveType(archiveType, updateOptions.MethodMode.Name, typeExtension);
|
||||
#endif
|
||||
}
|
||||
UString extension = typeExtension;
|
||||
if(parser[NKey::kSfx].ThereIs)
|
||||
extension = kSFXExtension;
|
||||
updateOptions.ArchivePath.BaseExtension = extension;
|
||||
updateOptions.ArchivePath.VolExtension = typeExtension;
|
||||
updateOptions.ArchivePath.ParseFromPath(options.ArchiveName);
|
||||
SetAddCommandOptions(options.Command.CommandType, parser,
|
||||
updateOptions);
|
||||
|
||||
SetMethodOptions(parser, updateOptions);
|
||||
|
||||
options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;
|
||||
|
||||
if (options.EnablePercents)
|
||||
{
|
||||
if ((options.StdOutMode && !options.IsStdErrTerminal) ||
|
||||
(!options.StdOutMode && !options.IsStdOutTerminal))
|
||||
options.EnablePercents = false;
|
||||
}
|
||||
|
||||
if (updateOptions.EMailMode = parser[NKey::kEmail].ThereIs)
|
||||
{
|
||||
updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();
|
||||
if (updateOptions.EMailAddress.Length() > 0)
|
||||
if (updateOptions.EMailAddress[0] == L'.')
|
||||
{
|
||||
updateOptions.EMailRemoveAfter = true;
|
||||
updateOptions.EMailAddress.Delete(0);
|
||||
}
|
||||
}
|
||||
|
||||
updateOptions.StdOutMode = options.StdOutMode;
|
||||
updateOptions.StdInMode = options.StdInMode;
|
||||
|
||||
if (updateOptions.StdOutMode && updateOptions.EMailMode)
|
||||
throw "stdout mode and email mode cannot be combined";
|
||||
if (updateOptions.StdOutMode && options.IsStdOutTerminal)
|
||||
throw kTerminalOutError;
|
||||
if(updateOptions.StdInMode)
|
||||
updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();
|
||||
}
|
||||
else
|
||||
throw kUserErrorMessage;
|
||||
}
|
||||
84
7zip/UI/Common/ArchiveCommandLine.h
Executable file
84
7zip/UI/Common/ArchiveCommandLine.h
Executable file
@@ -0,0 +1,84 @@
|
||||
// ArchiveCommandLine.h
|
||||
|
||||
#ifndef __ARCHIVECOMMANDLINE_H
|
||||
#define __ARCHIVECOMMANDLINE_H
|
||||
|
||||
#include "Common/Wildcard.h"
|
||||
#include "Common/CommandLineParser.h"
|
||||
|
||||
#include "Extract.h"
|
||||
#include "Update.h"
|
||||
|
||||
namespace NCommandType { enum EEnum
|
||||
{
|
||||
kAdd = 0,
|
||||
kUpdate,
|
||||
kDelete,
|
||||
kTest,
|
||||
kExtract,
|
||||
kFullExtract,
|
||||
kList
|
||||
};}
|
||||
|
||||
namespace NRecursedType { enum EEnum
|
||||
{
|
||||
kRecursed,
|
||||
kWildCardOnlyRecursed,
|
||||
kNonRecursed,
|
||||
};}
|
||||
|
||||
struct CArchiveCommand
|
||||
{
|
||||
NCommandType::EEnum CommandType;
|
||||
bool IsFromExtractGroup() const;
|
||||
bool IsFromUpdateGroup() const;
|
||||
bool IsTestMode() const { return CommandType == NCommandType::kTest; }
|
||||
NExtract::NPathMode::EEnum GetPathMode() const;
|
||||
};
|
||||
|
||||
struct CArchiveCommandLineOptions
|
||||
{
|
||||
bool HelpMode;
|
||||
|
||||
bool IsInTerminal;
|
||||
bool IsStdOutTerminal;
|
||||
bool IsStdErrTerminal;
|
||||
bool StdInMode;
|
||||
bool StdOutMode;
|
||||
bool EnableHeaders;
|
||||
|
||||
bool YesToAll;
|
||||
bool ShowDialog;
|
||||
// NWildcard::CCensor ArchiveWildcardCensor;
|
||||
NWildcard::CCensor WildcardCensor;
|
||||
|
||||
CArchiveCommand Command;
|
||||
UString ArchiveName;
|
||||
|
||||
bool PasswordEnabled;
|
||||
UString Password;
|
||||
|
||||
// Extract
|
||||
bool AppendName;
|
||||
UString OutputDir;
|
||||
NExtract::NOverwriteMode::EEnum OverwriteMode;
|
||||
UStringVector ArchivePathsSorted;
|
||||
UStringVector ArchivePathsFullSorted;
|
||||
|
||||
CUpdateOptions UpdateOptions;
|
||||
bool EnablePercents;
|
||||
|
||||
CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {};
|
||||
|
||||
};
|
||||
|
||||
class CArchiveCommandLineParser
|
||||
{
|
||||
NCommandLineParser::CParser parser;
|
||||
public:
|
||||
CArchiveCommandLineParser();
|
||||
void Parse1(const UStringVector commandStrings, CArchiveCommandLineOptions &options);
|
||||
void Parse2(CArchiveCommandLineOptions &options);
|
||||
};
|
||||
|
||||
#endif
|
||||
392
7zip/UI/Common/ArchiveExtractCallback.cpp
Executable file
392
7zip/UI/Common/ArchiveExtractCallback.cpp
Executable file
@@ -0,0 +1,392 @@
|
||||
// ArchiveExtractCallback.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ArchiveExtractCallback.h"
|
||||
|
||||
#include "Common/Wildcard.h"
|
||||
#include "Common/StringConvert.h"
|
||||
|
||||
#include "Windows/FileDir.h"
|
||||
#include "Windows/FileFind.h"
|
||||
#include "Windows/Time.h"
|
||||
#include "Windows/Defs.h"
|
||||
#include "Windows/PropVariant.h"
|
||||
|
||||
#include "Windows/PropVariantConversions.h"
|
||||
|
||||
#include "../../Common/FilePathAutoRename.h"
|
||||
|
||||
#include "../Common/ExtractingFilePath.h"
|
||||
#include "OpenArchive.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name";
|
||||
static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file ";
|
||||
static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";
|
||||
|
||||
|
||||
void CArchiveExtractCallback::Init(
|
||||
IInArchive *archiveHandler,
|
||||
IFolderArchiveExtractCallback *extractCallback2,
|
||||
bool stdOutMode,
|
||||
const UString &directoryPath,
|
||||
NExtract::NPathMode::EEnum pathMode,
|
||||
NExtract::NOverwriteMode::EEnum overwriteMode,
|
||||
const UStringVector &removePathParts,
|
||||
const UString &itemDefaultName,
|
||||
const FILETIME &utcLastWriteTimeDefault,
|
||||
UInt32 attributesDefault)
|
||||
{
|
||||
_stdOutMode = stdOutMode;
|
||||
_numErrors = 0;
|
||||
_extractCallback2 = extractCallback2;
|
||||
_itemDefaultName = itemDefaultName;
|
||||
_utcLastWriteTimeDefault = utcLastWriteTimeDefault;
|
||||
_attributesDefault = attributesDefault;
|
||||
_removePathParts = removePathParts;
|
||||
_pathMode = pathMode;
|
||||
_overwriteMode = overwriteMode;
|
||||
_archiveHandler = archiveHandler;
|
||||
_directoryPath = directoryPath;
|
||||
NFile::NName::NormalizeDirPathPrefix(_directoryPath);
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)
|
||||
{
|
||||
return _extractCallback2->SetTotal(size);
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)
|
||||
{
|
||||
return _extractCallback2->SetCompleted(completeValue);
|
||||
}
|
||||
|
||||
void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts)
|
||||
{
|
||||
UString fullPath = _directoryPath;
|
||||
for(int i = 0; i < dirPathParts.Size(); i++)
|
||||
{
|
||||
fullPath += dirPathParts[i];
|
||||
NFile::NDirectory::MyCreateDirectory(fullPath);
|
||||
fullPath += wchar_t(NFile::NName::kDirDelimiter);
|
||||
}
|
||||
}
|
||||
|
||||
static UString MakePathNameFromParts(const UStringVector &parts)
|
||||
{
|
||||
UString result;
|
||||
for(int i = 0; i < parts.Size(); i++)
|
||||
{
|
||||
if(i != 0)
|
||||
result += wchar_t(NFile::NName::kDirDelimiter);
|
||||
result += parts[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index,
|
||||
ISequentialOutStream **outStream, Int32 askExtractMode)
|
||||
{
|
||||
*outStream = 0;
|
||||
_outFileStream.Release();
|
||||
NCOM::CPropVariant propVariant;
|
||||
RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariant));
|
||||
|
||||
UString fullPath;
|
||||
if(propVariant.vt == VT_EMPTY)
|
||||
fullPath = _itemDefaultName;
|
||||
else
|
||||
{
|
||||
if(propVariant.vt != VT_BSTR)
|
||||
return E_FAIL;
|
||||
fullPath = propVariant.bstrVal;
|
||||
}
|
||||
|
||||
// UString fullPathCorrect = GetCorrectPath(fullPath);
|
||||
_filePath = fullPath;
|
||||
_isSplit = false;
|
||||
|
||||
RINOK(_archiveHandler->GetProperty(index, kpidPosition, &propVariant));
|
||||
if (propVariant.vt != VT_EMPTY)
|
||||
{
|
||||
if (propVariant.vt != VT_UI8)
|
||||
return E_FAIL;
|
||||
_position = propVariant.uhVal.QuadPart;
|
||||
_isSplit = true;
|
||||
}
|
||||
|
||||
if(askExtractMode == NArchive::NExtract::NAskMode::kExtract)
|
||||
{
|
||||
if (_stdOutMode)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream;
|
||||
*outStream = outStreamLoc.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &propVariant));
|
||||
if (propVariant.vt == VT_EMPTY)
|
||||
{
|
||||
_processedFileInfo.Attributes = _attributesDefault;
|
||||
_processedFileInfo.AttributesAreDefined = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (propVariant.vt != VT_UI4)
|
||||
throw "incorrect item";
|
||||
_processedFileInfo.Attributes = propVariant.ulVal;
|
||||
_processedFileInfo.AttributesAreDefined = true;
|
||||
}
|
||||
|
||||
RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDirectory));
|
||||
|
||||
RINOK(_archiveHandler->GetProperty(index, kpidLastWriteTime, &propVariant));
|
||||
switch(propVariant.vt)
|
||||
{
|
||||
case VT_EMPTY:
|
||||
_processedFileInfo.UTCLastWriteTime = _utcLastWriteTimeDefault;
|
||||
break;
|
||||
case VT_FILETIME:
|
||||
_processedFileInfo.UTCLastWriteTime = propVariant.filetime;
|
||||
break;
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
RINOK(_archiveHandler->GetProperty(index, kpidSize, &propVariant));
|
||||
bool newFileSizeDefined = (propVariant.vt != VT_EMPTY);
|
||||
UInt64 newFileSize;
|
||||
if (newFileSizeDefined)
|
||||
newFileSize = ConvertPropVariantToUInt64(propVariant);
|
||||
|
||||
bool isAnti = false;
|
||||
{
|
||||
NCOM::CPropVariant propVariantTemp;
|
||||
RINOK(_archiveHandler->GetProperty(index, kpidIsAnti,
|
||||
&propVariantTemp));
|
||||
if (propVariantTemp.vt == VT_BOOL)
|
||||
isAnti = VARIANT_BOOLToBool(propVariantTemp.boolVal);
|
||||
}
|
||||
|
||||
UStringVector pathParts;
|
||||
SplitPathToParts(fullPath, pathParts);
|
||||
|
||||
if(pathParts.IsEmpty())
|
||||
return E_FAIL;
|
||||
UString processedPath;
|
||||
switch(_pathMode)
|
||||
{
|
||||
case NExtract::NPathMode::kFullPathnames:
|
||||
{
|
||||
processedPath = fullPath;
|
||||
break;
|
||||
}
|
||||
case NExtract::NPathMode::kCurrentPathnames:
|
||||
{
|
||||
// for incorrect paths: "/dir1/dir2/file"
|
||||
int numRemovePathParts = _removePathParts.Size();
|
||||
if(pathParts.Size() <= numRemovePathParts)
|
||||
return E_FAIL;
|
||||
for(int i = 0; i < numRemovePathParts; i++)
|
||||
if(_removePathParts[i].CollateNoCase(pathParts[i]) != 0)
|
||||
return E_FAIL;
|
||||
pathParts.Delete(0, numRemovePathParts);
|
||||
processedPath = MakePathNameFromParts(pathParts);
|
||||
break;
|
||||
}
|
||||
case NExtract::NPathMode::kNoPathnames:
|
||||
{
|
||||
processedPath = pathParts.Back();
|
||||
pathParts.Delete(0, pathParts.Size() - 1); // Test it!!
|
||||
break;
|
||||
}
|
||||
}
|
||||
processedPath = GetCorrectPath(processedPath);
|
||||
if(!_processedFileInfo.IsDirectory)
|
||||
pathParts.DeleteBack();
|
||||
|
||||
MakeCorrectPath(pathParts);
|
||||
|
||||
if (!isAnti)
|
||||
if (!pathParts.IsEmpty())
|
||||
CreateComplexDirectory(pathParts);
|
||||
|
||||
UString fullProcessedPath = _directoryPath + processedPath;
|
||||
|
||||
if(_processedFileInfo.IsDirectory)
|
||||
{
|
||||
_diskFilePath = fullProcessedPath;
|
||||
if (isAnti)
|
||||
NFile::NDirectory::MyRemoveDirectory(_diskFilePath);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!_isSplit)
|
||||
{
|
||||
NFile::NFind::CFileInfoW fileInfo;
|
||||
if(NFile::NFind::FindFile(fullProcessedPath, fileInfo))
|
||||
{
|
||||
switch(_overwriteMode)
|
||||
{
|
||||
case NExtract::NOverwriteMode::kSkipExisting:
|
||||
return S_OK;
|
||||
case NExtract::NOverwriteMode::kAskBefore:
|
||||
{
|
||||
Int32 overwiteResult;
|
||||
RINOK(_extractCallback2->AskOverwrite(
|
||||
fullProcessedPath, &fileInfo.LastWriteTime, &fileInfo.Size,
|
||||
fullPath, &_processedFileInfo.UTCLastWriteTime, newFileSizeDefined?
|
||||
&newFileSize : NULL, &overwiteResult))
|
||||
|
||||
switch(overwiteResult)
|
||||
{
|
||||
case NOverwriteAnswer::kCancel:
|
||||
return E_ABORT;
|
||||
case NOverwriteAnswer::kNo:
|
||||
return S_OK;
|
||||
case NOverwriteAnswer::kNoToAll:
|
||||
_overwriteMode = NExtract::NOverwriteMode::kSkipExisting;
|
||||
return S_OK;
|
||||
case NOverwriteAnswer::kYesToAll:
|
||||
_overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
|
||||
break;
|
||||
case NOverwriteAnswer::kYes:
|
||||
break;
|
||||
case NOverwriteAnswer::kAutoRename:
|
||||
_overwriteMode = NExtract::NOverwriteMode::kAutoRename;
|
||||
break;
|
||||
default:
|
||||
throw 20413;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename)
|
||||
{
|
||||
if (!AutoRenamePath(fullProcessedPath))
|
||||
{
|
||||
UString message = UString(kCantAutoRename) +
|
||||
fullProcessedPath;
|
||||
RINOK(_extractCallback2->MessageError(message));
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting)
|
||||
{
|
||||
UString existPath = fullProcessedPath;
|
||||
if (!AutoRenamePath(existPath))
|
||||
{
|
||||
UString message = kCantAutoRename + fullProcessedPath;
|
||||
RINOK(_extractCallback2->MessageError(message));
|
||||
return E_ABORT;
|
||||
}
|
||||
if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath))
|
||||
{
|
||||
UString message = UString(kCantRenameFile) + fullProcessedPath;
|
||||
RINOK(_extractCallback2->MessageError(message));
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))
|
||||
{
|
||||
UString message = UString(kCantDeleteOutputFile) +
|
||||
fullProcessedPath;
|
||||
RINOK(_extractCallback2->MessageError(message));
|
||||
return E_ABORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isAnti)
|
||||
{
|
||||
_outFileStreamSpec = new COutFileStream;
|
||||
CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
|
||||
if (!_outFileStreamSpec->File.Open(fullProcessedPath,
|
||||
_isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))
|
||||
{
|
||||
// if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
|
||||
{
|
||||
UString message = L"can not open output file " + fullProcessedPath;
|
||||
RINOK(_extractCallback2->MessageError(message));
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
if (_isSplit)
|
||||
{
|
||||
RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
_outFileStream = outStreamLoc;
|
||||
*outStream = outStreamLoc.Detach();
|
||||
}
|
||||
_diskFilePath = fullProcessedPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
*outStream = NULL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
|
||||
{
|
||||
_extractMode = false;
|
||||
switch (askExtractMode)
|
||||
{
|
||||
case NArchive::NExtract::NAskMode::kExtract:
|
||||
_extractMode = true;
|
||||
};
|
||||
return _extractCallback2->PrepareOperation(_filePath, askExtractMode, _isSplit ? &_position: 0);
|
||||
}
|
||||
|
||||
void CArchiveExtractCallback::AddErrorMessage(LPCTSTR message)
|
||||
{
|
||||
_messages.Add(message);
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
|
||||
{
|
||||
switch(operationResult)
|
||||
{
|
||||
case NArchive::NExtract::NOperationResult::kOK:
|
||||
case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
|
||||
case NArchive::NExtract::NOperationResult::kCRCError:
|
||||
case NArchive::NExtract::NOperationResult::kDataError:
|
||||
break;
|
||||
default:
|
||||
_outFileStream.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
if(_outFileStream != NULL)
|
||||
_outFileStreamSpec->File.SetLastWriteTime(&_processedFileInfo.UTCLastWriteTime);
|
||||
_outFileStream.Release();
|
||||
if (_extractMode && _processedFileInfo.AttributesAreDefined)
|
||||
NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes);
|
||||
RINOK(_extractCallback2->SetOperationResult(operationResult));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
STDMETHODIMP CArchiveExtractCallback::GetInStream(
|
||||
const wchar_t *name, ISequentialInStream **inStream)
|
||||
{
|
||||
CInFileStream *inFile = new CInFileStream;
|
||||
CMyComPtr<ISequentialInStream> inStreamTemp = inFile;
|
||||
if (!inFile->Open(_srcDirectoryPrefix + name))
|
||||
return ::GetLastError();
|
||||
*inStream = inStreamTemp.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
|
||||
{
|
||||
if (!_cryptoGetTextPassword)
|
||||
{
|
||||
RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword,
|
||||
&_cryptoGetTextPassword));
|
||||
}
|
||||
return _cryptoGetTextPassword->CryptoGetTextPassword(password);
|
||||
}
|
||||
|
||||
95
7zip/UI/Common/ArchiveExtractCallback.h
Executable file
95
7zip/UI/Common/ArchiveExtractCallback.h
Executable file
@@ -0,0 +1,95 @@
|
||||
// ArchiveExtractCallback.h
|
||||
|
||||
#ifndef __ARCHIVEEXTRACTCALLBACK_H
|
||||
#define __ARCHIVEEXTRACTCALLBACK_H
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
#include "IFileExtractCallback.h"
|
||||
|
||||
#include "Common/String.h"
|
||||
#include "Common/MyCom.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
#include "../../IPassword.h"
|
||||
|
||||
#include "ExtractMode.h"
|
||||
|
||||
class CArchiveExtractCallback:
|
||||
public IArchiveExtractCallback,
|
||||
// public IArchiveVolumeExtractCallback,
|
||||
public ICryptoGetTextPassword,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
|
||||
// COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback)
|
||||
|
||||
// IProgress
|
||||
STDMETHOD(SetTotal)(UInt64 aize);
|
||||
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
|
||||
|
||||
// IExtractCallBack
|
||||
STDMETHOD(GetStream)(UInt32 anIndex, ISequentialOutStream **outStream,
|
||||
Int32 askExtractMode);
|
||||
STDMETHOD(PrepareOperation)(Int32 askExtractMode);
|
||||
STDMETHOD(SetOperationResult)(Int32 resultEOperationResult);
|
||||
|
||||
// IArchiveVolumeExtractCallback
|
||||
// STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream);
|
||||
|
||||
// ICryptoGetTextPassword
|
||||
STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword);
|
||||
|
||||
private:
|
||||
CMyComPtr<IInArchive> _archiveHandler;
|
||||
CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
|
||||
CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
|
||||
UString _directoryPath;
|
||||
NExtract::NPathMode::EEnum _pathMode;
|
||||
NExtract::NOverwriteMode::EEnum _overwriteMode;
|
||||
|
||||
UString _filePath;
|
||||
UInt64 _position;
|
||||
bool _isSplit;
|
||||
|
||||
UString _diskFilePath;
|
||||
|
||||
CSysStringVector _messages;
|
||||
|
||||
bool _extractMode;
|
||||
struct CProcessedFileInfo
|
||||
{
|
||||
FILETIME UTCLastWriteTime;
|
||||
bool IsDirectory;
|
||||
bool AttributesAreDefined;
|
||||
UInt32 Attributes;
|
||||
} _processedFileInfo;
|
||||
|
||||
COutFileStream *_outFileStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> _outFileStream;
|
||||
UStringVector _removePathParts;
|
||||
|
||||
UString _itemDefaultName;
|
||||
FILETIME _utcLastWriteTimeDefault;
|
||||
UInt32 _attributesDefault;
|
||||
bool _stdOutMode;
|
||||
|
||||
void CreateComplexDirectory(const UStringVector &dirPathParts);
|
||||
void AddErrorMessage(LPCTSTR message);
|
||||
public:
|
||||
void Init(
|
||||
IInArchive *archiveHandler,
|
||||
IFolderArchiveExtractCallback *extractCallback2,
|
||||
bool stdOutMode,
|
||||
const UString &directoryPath,
|
||||
NExtract::NPathMode::EEnum pathMode,
|
||||
NExtract::NOverwriteMode::EEnum overwriteMode,
|
||||
const UStringVector &removePathParts,
|
||||
const UString &itemDefaultName,
|
||||
const FILETIME &utcLastWriteTimeDefault,
|
||||
UInt32 attributesDefault);
|
||||
|
||||
UInt64 _numErrors;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -29,7 +29,7 @@ UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName)
|
||||
{
|
||||
NFile::NFind::CFileInfoW fileInfo;
|
||||
if (!NFile::NFind::FindFile(srcName, fileInfo))
|
||||
return ::GetLastError();
|
||||
return resultName;
|
||||
resultName = fileInfo.Name;
|
||||
if (!fileInfo.IsDirectory() && !keepName)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// ArchiveName.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __ARCHIVENAME_H
|
||||
#define __ARCHIVENAME_H
|
||||
|
||||
@@ -9,4 +7,4 @@
|
||||
|
||||
UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
117
7zip/UI/Common/ArchiveOpenCallback.cpp
Executable file
117
7zip/UI/Common/ArchiveOpenCallback.cpp
Executable file
@@ -0,0 +1,117 @@
|
||||
// ArchiveOpenCallback.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ArchiveOpenCallback.h"
|
||||
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Windows/PropVariant.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)
|
||||
{
|
||||
return Callback->SetTotal(files, bytes);
|
||||
}
|
||||
|
||||
STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)
|
||||
{
|
||||
return Callback->SetTotal(files, bytes);
|
||||
}
|
||||
|
||||
STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NCOM::CPropVariant propVariant;
|
||||
if (_subArchiveMode)
|
||||
{
|
||||
switch(propID)
|
||||
{
|
||||
case kpidName:
|
||||
propVariant = _subArchiveName;
|
||||
break;
|
||||
}
|
||||
propVariant.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
switch(propID)
|
||||
{
|
||||
case kpidName:
|
||||
propVariant = _fileInfo.Name;
|
||||
break;
|
||||
case kpidIsFolder:
|
||||
propVariant = _fileInfo.IsDirectory();
|
||||
break;
|
||||
case kpidSize:
|
||||
propVariant = _fileInfo.Size;
|
||||
break;
|
||||
case kpidAttributes:
|
||||
propVariant = (UInt32)_fileInfo.Attributes;
|
||||
break;
|
||||
case kpidLastAccessTime:
|
||||
propVariant = _fileInfo.LastAccessTime;
|
||||
break;
|
||||
case kpidCreationTime:
|
||||
propVariant = _fileInfo.CreationTime;
|
||||
break;
|
||||
case kpidLastWriteTime:
|
||||
propVariant = _fileInfo.LastWriteTime;
|
||||
break;
|
||||
}
|
||||
propVariant.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int COpenCallbackImp::FindName(const UString &name)
|
||||
{
|
||||
for (int i = 0; i < FileNames.Size(); i++)
|
||||
if (name.CompareNoCase(FileNames[i]) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct CInFileStreamVol: public CInFileStream
|
||||
{
|
||||
UString Name;
|
||||
COpenCallbackImp *OpenCallbackImp;
|
||||
CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
|
||||
~CInFileStreamVol()
|
||||
{
|
||||
int index = OpenCallbackImp->FindName(Name);
|
||||
if (index >= 0)
|
||||
OpenCallbackImp->FileNames.Delete(index);
|
||||
}
|
||||
};
|
||||
|
||||
STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name,
|
||||
IInStream **inStream)
|
||||
{
|
||||
if (_subArchiveMode)
|
||||
return S_FALSE;
|
||||
RINOK(Callback->CheckBreak());
|
||||
*inStream = NULL;
|
||||
UString fullPath = _folderPrefix + name;
|
||||
if (!NFile::NFind::FindFile(fullPath, _fileInfo))
|
||||
return S_FALSE;
|
||||
if (_fileInfo.IsDirectory())
|
||||
return S_FALSE;
|
||||
CInFileStreamVol *inFile = new CInFileStreamVol;
|
||||
CMyComPtr<IInStream> inStreamTemp = inFile;
|
||||
if (!inFile->Open(fullPath))
|
||||
return ::GetLastError();
|
||||
*inStream = inStreamTemp.Detach();
|
||||
inFile->Name = name;
|
||||
inFile->OpenCallbackImp = this;
|
||||
inFile->OpenCallbackRef = this;
|
||||
FileNames.Add(name);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
|
||||
{
|
||||
return Callback->CryptoGetTextPassword(password);
|
||||
}
|
||||
#endif
|
||||
|
||||
87
7zip/UI/Common/ArchiveOpenCallback.h
Executable file
87
7zip/UI/Common/ArchiveOpenCallback.h
Executable file
@@ -0,0 +1,87 @@
|
||||
// ArchiveOpenCallback.h
|
||||
|
||||
#ifndef __ARCHIVE_OPEN_CALLBACK_H
|
||||
#define __ARCHIVE_OPEN_CALLBACK_H
|
||||
|
||||
#include "Common/String.h"
|
||||
#include "Common/MyCom.h"
|
||||
#include "Windows/FileFind.h"
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
#include "../../IPassword.h"
|
||||
#endif
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
struct IOpenCallbackUI
|
||||
{
|
||||
virtual HRESULT CheckBreak() = 0;
|
||||
virtual HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes) = 0;
|
||||
virtual HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes) = 0;
|
||||
#ifndef _NO_CRYPTO
|
||||
virtual HRESULT CryptoGetTextPassword(BSTR *password) = 0;
|
||||
virtual HRESULT GetPasswordIfAny(UString &password) = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
class COpenCallbackImp:
|
||||
public IArchiveOpenCallback,
|
||||
public IArchiveOpenVolumeCallback,
|
||||
public IArchiveOpenSetSubArchiveName,
|
||||
#ifndef _NO_CRYPTO
|
||||
public ICryptoGetTextPassword,
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
#ifndef _NO_CRYPTO
|
||||
MY_UNKNOWN_IMP3(
|
||||
IArchiveOpenVolumeCallback,
|
||||
ICryptoGetTextPassword,
|
||||
IArchiveOpenSetSubArchiveName
|
||||
)
|
||||
#else
|
||||
MY_UNKNOWN_IMP2(
|
||||
IArchiveOpenVolumeCallback,
|
||||
IArchiveOpenSetSubArchiveName
|
||||
)
|
||||
#endif
|
||||
|
||||
STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);
|
||||
STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);
|
||||
|
||||
// IArchiveOpenVolumeCallback
|
||||
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
|
||||
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
// ICryptoGetTextPassword
|
||||
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
||||
#endif
|
||||
|
||||
STDMETHOD(SetSubArchiveName(const wchar_t *name))
|
||||
{
|
||||
_subArchiveMode = true;
|
||||
_subArchiveName = name;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
UString _folderPrefix;
|
||||
NWindows::NFile::NFind::CFileInfoW _fileInfo;
|
||||
bool _subArchiveMode;
|
||||
UString _subArchiveName;
|
||||
public:
|
||||
UStringVector FileNames;
|
||||
IOpenCallbackUI *Callback;
|
||||
void Init(const UString &folderPrefix, const UString &fileName)
|
||||
{
|
||||
_folderPrefix = folderPrefix;
|
||||
if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo))
|
||||
throw 1;
|
||||
FileNames.Clear();
|
||||
_subArchiveMode = false;
|
||||
}
|
||||
int FindName(const UString &name);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -10,7 +10,9 @@
|
||||
#include "Windows/FileFind.h"
|
||||
#include "Windows/FileName.h"
|
||||
#include "Windows/DLL.h"
|
||||
#ifdef _WIN32
|
||||
#include "Windows/Registry.h"
|
||||
#endif
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
@@ -48,7 +50,7 @@ static void SplitString(const UString &srcString, UStringVector &destStrings)
|
||||
destStrings.Add(string);
|
||||
}
|
||||
|
||||
typedef UINT32 (WINAPI * GetHandlerPropertyFunc)(
|
||||
typedef UInt32 (WINAPI * GetHandlerPropertyFunc)(
|
||||
PROPID propID, PROPVARIANT *value);
|
||||
|
||||
/*
|
||||
@@ -72,7 +74,7 @@ static wchar_t *kFormatFolderName = L"Formats";
|
||||
static LPCTSTR kRegistryPath = TEXT("Software\\7-zip");
|
||||
static LPCTSTR kProgramPathValue = TEXT("Path");
|
||||
|
||||
UString GetBaseFolderPrefix()
|
||||
static UString GetBaseFolderPrefixFromRegistry()
|
||||
{
|
||||
UString moduleFolderPrefix = GetModuleFolderPrefix();
|
||||
NFind::CFileInfoW fileInfo;
|
||||
@@ -80,6 +82,7 @@ UString GetBaseFolderPrefix()
|
||||
if (fileInfo.IsDirectory())
|
||||
return moduleFolderPrefix;
|
||||
CSysString pathSys;
|
||||
#ifdef _WIN32
|
||||
{
|
||||
NRegistry::CKey key;
|
||||
if(key.Open(HKEY_CURRENT_USER, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
|
||||
@@ -100,16 +103,25 @@ UString GetBaseFolderPrefix()
|
||||
return path;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return moduleFolderPrefix;
|
||||
}
|
||||
|
||||
typedef UINT32 (WINAPI *CreateObjectPointer)(
|
||||
typedef UInt32 (WINAPI *CreateObjectPointer)(
|
||||
const GUID *clsID,
|
||||
const GUID *interfaceID,
|
||||
void **outObject);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _SFX
|
||||
static void SetBuffer(CByteBuffer &bb, const Byte *data, int size)
|
||||
{
|
||||
bb.SetCapacity(size);
|
||||
memmove((Byte *)bb, data, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
|
||||
{
|
||||
archivers.Clear();
|
||||
@@ -123,6 +135,10 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
|
||||
item.KeepName = false;
|
||||
item.Name = L"7z";
|
||||
item.Extensions.Add(CArchiverExtInfo(L"7z"));
|
||||
#ifndef _SFX
|
||||
const unsigned char kSig[] = {'7' , 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
||||
SetBuffer(item.StartSignature, kSig, 6);
|
||||
#endif
|
||||
archivers.Add(item);
|
||||
}
|
||||
#endif
|
||||
@@ -135,6 +151,10 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
|
||||
item.Name = L"BZip2";
|
||||
item.Extensions.Add(CArchiverExtInfo(L"bz2"));
|
||||
item.Extensions.Add(CArchiverExtInfo(L"tbz2", L".tar"));
|
||||
#ifndef _SFX
|
||||
const unsigned char sig[] = {'B' , 'Z', 'h' };
|
||||
SetBuffer(item.StartSignature, sig, 3);
|
||||
#endif
|
||||
archivers.Add(item);
|
||||
}
|
||||
#endif
|
||||
@@ -147,6 +167,21 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
|
||||
item.Name = L"GZip";
|
||||
item.Extensions.Add(CArchiverExtInfo(L"gz"));
|
||||
item.Extensions.Add(CArchiverExtInfo(L"tgz", L".tar"));
|
||||
#ifndef _SFX
|
||||
const unsigned char sig[] = { 0x1F, 0x8B };
|
||||
SetBuffer(item.StartSignature, sig, 2);
|
||||
#endif
|
||||
archivers.Add(item);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_SPLIT
|
||||
{
|
||||
CArchiverInfo item;
|
||||
item.UpdateEnabled = false;
|
||||
item.KeepName = true;
|
||||
item.Name = L"Split";
|
||||
item.Extensions.Add(CArchiverExtInfo(L"001"));
|
||||
archivers.Add(item);
|
||||
}
|
||||
#endif
|
||||
@@ -169,6 +204,10 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
|
||||
item.KeepName = false;
|
||||
item.Name = L"Zip";
|
||||
item.Extensions.Add(CArchiverExtInfo(L"zip"));
|
||||
#ifndef _SFX
|
||||
const unsigned char sig[] = { 0x50, 0x4B, 0x03, 0x04 };
|
||||
SetBuffer(item.StartSignature, sig, 4);
|
||||
#endif
|
||||
archivers.Add(item);
|
||||
}
|
||||
#endif
|
||||
@@ -199,13 +238,31 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
|
||||
item.UpdateEnabled = false;
|
||||
item.Name = L"Arj";
|
||||
item.Extensions.Add(CArchiverExtInfo(L"arj"));
|
||||
#ifndef _SFX
|
||||
const unsigned char sig[] = { 0x60, 0xEA };
|
||||
SetBuffer(item.StartSignature, sig, 2);
|
||||
#endif
|
||||
archivers.Add(item);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_Z
|
||||
{
|
||||
CArchiverInfo item;
|
||||
item.UpdateEnabled = false;
|
||||
item.Name = L"Z";
|
||||
item.Extensions.Add(CArchiverExtInfo(L"Z"));
|
||||
#ifndef _SFX
|
||||
const unsigned char sig[] = { 0x1F, 0x9D };
|
||||
SetBuffer(item.StartSignature, sig, 2);
|
||||
#endif
|
||||
archivers.Add(item);
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
UString folderPath = GetBaseFolderPrefix() +
|
||||
UString folderPath = GetBaseFolderPrefixFromRegistry() +
|
||||
kFormatFolderName + L"\\";
|
||||
NFind::CEnumeratorW enumerator(folderPath + L"*");
|
||||
NFind::CFileInfoW fileInfo;
|
||||
@@ -253,6 +310,7 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
|
||||
|
||||
UString ext = prop.bstrVal;
|
||||
// item.Extension = prop.bstrVal;
|
||||
prop.Clear();
|
||||
|
||||
UString addExt;
|
||||
|
||||
@@ -282,23 +340,30 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
|
||||
item.Extensions.Add(extInfo);
|
||||
}
|
||||
|
||||
if (getHandlerProperty(NArchive::kUpdate, &prop) != S_OK)
|
||||
continue;
|
||||
if (prop.vt != VT_BOOL)
|
||||
continue;
|
||||
item.UpdateEnabled = VARIANT_BOOLToBool(prop.boolVal);
|
||||
if (getHandlerProperty(NArchive::kUpdate, &prop) == S_OK)
|
||||
if (prop.vt == VT_BOOL)
|
||||
item.UpdateEnabled = VARIANT_BOOLToBool(prop.boolVal);
|
||||
prop.Clear();
|
||||
|
||||
if (item.UpdateEnabled)
|
||||
{
|
||||
if (getHandlerProperty(NArchive::kKeepName, &prop) != S_OK)
|
||||
continue;
|
||||
if (prop.vt != VT_BOOL)
|
||||
continue;
|
||||
item.KeepName = VARIANT_BOOLToBool(prop.boolVal);
|
||||
if (getHandlerProperty(NArchive::kKeepName, &prop) == S_OK)
|
||||
if (prop.vt == VT_BOOL)
|
||||
item.KeepName = VARIANT_BOOLToBool(prop.boolVal);
|
||||
prop.Clear();
|
||||
}
|
||||
|
||||
if (getHandlerProperty(NArchive::kStartSignature, &prop) == S_OK)
|
||||
{
|
||||
if (prop.vt == VT_BSTR)
|
||||
{
|
||||
UINT len = ::SysStringByteLen(prop.bstrVal);
|
||||
item.StartSignature.SetCapacity(len);
|
||||
memmove(item.StartSignature, prop.bstrVal, len);
|
||||
}
|
||||
}
|
||||
prop.Clear();
|
||||
|
||||
archivers.Add(item);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
// ArchiverInfo.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __ARCHIVERINFO_H
|
||||
#define __ARCHIVERINFO_H
|
||||
|
||||
#include "Common/String.h"
|
||||
#include "Common/Types.h"
|
||||
#include "Common/Buffer.h"
|
||||
|
||||
struct CArchiverExtInfo
|
||||
{
|
||||
@@ -27,6 +26,10 @@ struct CArchiverInfo
|
||||
#endif
|
||||
UString Name;
|
||||
CObjectVector<CArchiverExtInfo> Extensions;
|
||||
#ifndef _SFX
|
||||
CByteBuffer StartSignature;
|
||||
CByteBuffer FinishSignature;
|
||||
#endif
|
||||
int FindExtension(const UString &ext) const
|
||||
{
|
||||
for (int i = 0; i < Extensions.Size(); i++)
|
||||
|
||||
@@ -11,14 +11,18 @@
|
||||
|
||||
#include "Windows/Synchronization.h"
|
||||
#include "Windows/FileMapping.h"
|
||||
#include "Windows/FileDir.h"
|
||||
|
||||
#include "../../FileManager/ProgramLocation.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
static LPCWSTR kShowDialogSwitch = L" -ad";
|
||||
static LPCWSTR kEmailSwitch = L" -seml";
|
||||
static LPCWSTR kEmailSwitch = L" -seml.";
|
||||
static LPCWSTR kMapSwitch = L" -i#";
|
||||
static LPCWSTR kArchiveNoNameSwitch = L" -an";
|
||||
static LPCWSTR kArchiveMapSwitch = L" -ai#";
|
||||
static LPCWSTR kStopSwitchParsing = L" --";
|
||||
|
||||
|
||||
static bool IsItWindowsNT()
|
||||
@@ -31,6 +35,7 @@ static bool IsItWindowsNT()
|
||||
}
|
||||
|
||||
HRESULT MyCreateProcess(const UString ¶ms,
|
||||
LPCTSTR curDir,
|
||||
NWindows::NSynchronization::CEvent *event)
|
||||
{
|
||||
STARTUPINFO startupInfo;
|
||||
@@ -45,7 +50,8 @@ HRESULT MyCreateProcess(const UString ¶ms,
|
||||
PROCESS_INFORMATION processInformation;
|
||||
BOOL result = ::CreateProcess(NULL, (TCHAR *)(const TCHAR *)
|
||||
GetSystemString(params),
|
||||
NULL, NULL, FALSE, 0, NULL, NULL,
|
||||
NULL, NULL, FALSE, 0, NULL,
|
||||
curDir,
|
||||
&startupInfo, &processInformation);
|
||||
if (result == 0)
|
||||
return ::GetLastError();
|
||||
@@ -70,7 +76,7 @@ static UString GetQuotedString(const UString &s)
|
||||
|
||||
static UString Get7zGuiPath()
|
||||
{
|
||||
UString path = L"\"";
|
||||
UString path;
|
||||
UString folder;
|
||||
if (GetProgramFolderPath(folder))
|
||||
path += folder;
|
||||
@@ -78,28 +84,117 @@ static UString Get7zGuiPath()
|
||||
path += L"7zgn.exe";
|
||||
else
|
||||
path += L"7zg.exe";
|
||||
path += L"\"";
|
||||
return path;
|
||||
// path += L"7z.exe";
|
||||
return GetQuotedString(path);
|
||||
}
|
||||
|
||||
static HRESULT CreateMap(const UStringVector &names,
|
||||
const UString &id,
|
||||
CFileMapping &fileMapping, NSynchronization::CEvent &event,
|
||||
UString ¶ms)
|
||||
{
|
||||
UInt32 extraSize = 2;
|
||||
UInt32 dataSize = 0;
|
||||
for (int i = 0; i < names.Size(); i++)
|
||||
dataSize += (names[i].Length() + 1) * sizeof(wchar_t);
|
||||
UInt32 totalSize = extraSize + dataSize;
|
||||
|
||||
UString mappingName;
|
||||
UString eventName;
|
||||
|
||||
CRandom random;
|
||||
random.Init(GetTickCount());
|
||||
while(true)
|
||||
{
|
||||
int number = random.Generate();
|
||||
wchar_t temp[32];
|
||||
ConvertUInt64ToString(UInt32(number), temp);
|
||||
mappingName = id;
|
||||
mappingName += L"Mapping";
|
||||
mappingName += temp;
|
||||
if (!fileMapping.Create(INVALID_HANDLE_VALUE, NULL,
|
||||
PAGE_READWRITE, totalSize, GetSystemString(mappingName)))
|
||||
return E_FAIL;
|
||||
if (::GetLastError() != ERROR_ALREADY_EXISTS)
|
||||
break;
|
||||
fileMapping.Close();
|
||||
}
|
||||
|
||||
while(true)
|
||||
{
|
||||
int number = random.Generate();
|
||||
wchar_t temp[32];
|
||||
ConvertUInt64ToString(UInt32(number), temp);
|
||||
eventName = id;
|
||||
eventName += L"MappingEndEvent";
|
||||
eventName += temp;
|
||||
if (!event.Create(true, false, GetSystemString(eventName)))
|
||||
return E_FAIL;
|
||||
if (::GetLastError() != ERROR_ALREADY_EXISTS)
|
||||
break;
|
||||
event.Close();
|
||||
}
|
||||
|
||||
params += mappingName;
|
||||
params += L":";
|
||||
wchar_t string[10];
|
||||
ConvertUInt64ToString(totalSize, string);
|
||||
params += string;
|
||||
|
||||
params += L":";
|
||||
params += eventName;
|
||||
|
||||
LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_WRITE, 0, totalSize);
|
||||
if (data == NULL)
|
||||
return E_FAIL;
|
||||
try
|
||||
{
|
||||
wchar_t *curData = (wchar_t *)data;
|
||||
*curData = 0;
|
||||
curData++;
|
||||
for (int i = 0; i < names.Size(); i++)
|
||||
{
|
||||
const UString &s = names[i];
|
||||
memcpy(curData, (const wchar_t *)s, s.Length() * sizeof(wchar_t));
|
||||
curData += s.Length();
|
||||
*curData++ = L'\0';
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
UnmapViewOfFile(data);
|
||||
throw;
|
||||
}
|
||||
// UnmapViewOfFile(data);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CompressFiles(
|
||||
const UString &curDir,
|
||||
const UString &archiveName,
|
||||
const UStringVector &names,
|
||||
// const UString &outFolder,
|
||||
bool email,
|
||||
bool showDialog)
|
||||
{
|
||||
/*
|
||||
UString curDir;
|
||||
if (names.Size() > 0)
|
||||
{
|
||||
NFile::NDirectory::GetOnlyDirPrefix(names[0], curDir);
|
||||
}
|
||||
*/
|
||||
UString params;
|
||||
params = Get7zGuiPath();
|
||||
params += L" a";
|
||||
params += kMapSwitch;
|
||||
// params += _fileNames[0];
|
||||
|
||||
UINT32 extraSize = 2;
|
||||
UINT32 dataSize = 0;
|
||||
UInt32 extraSize = 2;
|
||||
UInt32 dataSize = 0;
|
||||
for (int i = 0; i < names.Size(); i++)
|
||||
dataSize += (names[i].Length() + 1) * sizeof(wchar_t);
|
||||
UINT32 totalSize = extraSize + dataSize;
|
||||
UInt32 totalSize = extraSize + dataSize;
|
||||
|
||||
UString mappingName;
|
||||
UString eventName;
|
||||
@@ -111,7 +206,7 @@ HRESULT CompressFiles(
|
||||
{
|
||||
int number = random.Generate();
|
||||
wchar_t temp[32];
|
||||
ConvertUINT64ToString(UINT32(number), temp);
|
||||
ConvertUInt64ToString(UInt32(number), temp);
|
||||
mappingName = L"7zCompressMapping";
|
||||
mappingName += temp;
|
||||
if (!fileMapping.Create(INVALID_HANDLE_VALUE, NULL,
|
||||
@@ -130,7 +225,7 @@ HRESULT CompressFiles(
|
||||
{
|
||||
int number = random.Generate();
|
||||
wchar_t temp[32];
|
||||
ConvertUINT64ToString(UINT32(number), temp);
|
||||
ConvertUInt64ToString(UInt32(number), temp);
|
||||
eventName = L"7zCompressMappingEndEvent";
|
||||
eventName += temp;
|
||||
if (!event.Create(true, false, GetSystemString(eventName)))
|
||||
@@ -146,7 +241,7 @@ HRESULT CompressFiles(
|
||||
params += mappingName;
|
||||
params += L":";
|
||||
wchar_t string[10];
|
||||
ConvertUINT64ToString(totalSize, string);
|
||||
ConvertUInt64ToString(totalSize, string);
|
||||
params += string;
|
||||
|
||||
params += L":";
|
||||
@@ -158,7 +253,9 @@ HRESULT CompressFiles(
|
||||
if (showDialog)
|
||||
params += kShowDialogSwitch;
|
||||
|
||||
params += kStopSwitchParsing;
|
||||
params += L" ";
|
||||
|
||||
params += GetQuotedString(archiveName);
|
||||
|
||||
LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_WRITE, 0, totalSize);
|
||||
@@ -177,11 +274,14 @@ HRESULT CompressFiles(
|
||||
const UString &unicodeString = names[i];
|
||||
memcpy(curData, (const wchar_t *)unicodeString ,
|
||||
unicodeString .Length() * sizeof(wchar_t));
|
||||
curData += unicodeString .Length();
|
||||
curData += unicodeString.Length();
|
||||
*curData++ = L'\0';
|
||||
}
|
||||
// MessageBox(0, params, 0, 0);
|
||||
RINOK(MyCreateProcess(params, &event));
|
||||
CSysString sysCurDir = GetSystemString(curDir);
|
||||
RINOK(MyCreateProcess(params,
|
||||
(sysCurDir.IsEmpty()? 0: (LPCTSTR)sysCurDir),
|
||||
&event));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
@@ -190,8 +290,7 @@ HRESULT CompressFiles(
|
||||
}
|
||||
UnmapViewOfFile(data);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
CThreadCompressMain *compressor = new CThreadCompressMain();;
|
||||
compressor->FileNames = _fileNames;
|
||||
@@ -202,13 +301,24 @@ HRESULT CompressFiles(
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ExtractArchive(const UString &archiveName,
|
||||
static HRESULT ExtractGroupCommand(const UStringVector &archivePaths,
|
||||
const UString ¶ms)
|
||||
{
|
||||
UString params2 = params;
|
||||
params2 += kArchiveNoNameSwitch;
|
||||
params2 += kArchiveMapSwitch;
|
||||
CFileMapping fileMapping;
|
||||
NSynchronization::CEvent event;
|
||||
RINOK(CreateMap(archivePaths, L"7zExtract", fileMapping, event, params2));
|
||||
return MyCreateProcess(params2, 0, &event);
|
||||
}
|
||||
|
||||
HRESULT ExtractArchives(const UStringVector &archivePaths,
|
||||
const UString &outFolder, bool showDialog)
|
||||
{
|
||||
UString params;
|
||||
params = Get7zGuiPath();
|
||||
params += L" x ";
|
||||
params += GetQuotedString(archiveName);
|
||||
params += L" x";
|
||||
if (!outFolder.IsEmpty())
|
||||
{
|
||||
params += L" -o";
|
||||
@@ -216,14 +326,13 @@ HRESULT ExtractArchive(const UString &archiveName,
|
||||
}
|
||||
if (showDialog)
|
||||
params += kShowDialogSwitch;
|
||||
return MyCreateProcess(params);
|
||||
return ExtractGroupCommand(archivePaths, params);
|
||||
}
|
||||
|
||||
HRESULT TestArchive(const UString &archiveName)
|
||||
HRESULT TestArchives(const UStringVector &archivePaths)
|
||||
{
|
||||
UString params;
|
||||
params = Get7zGuiPath();
|
||||
params += L" t ";
|
||||
params += GetQuotedString(archiveName);
|
||||
return MyCreateProcess(params);
|
||||
params += L" t";
|
||||
return ExtractGroupCommand(archivePaths, params);
|
||||
}
|
||||
|
||||
@@ -6,17 +6,21 @@
|
||||
#include "Common/String.h"
|
||||
#include "Windows/Synchronization.h"
|
||||
|
||||
HRESULT MyCreateProcess(const UString ¶ms,
|
||||
NWindows::NSynchronization::CEvent *event = NULL);
|
||||
HRESULT CompressFiles(const UString &archiveName,
|
||||
HRESULT MyCreateProcess(const UString ¶ms,
|
||||
LPCTSTR lpCurrentDirectory,
|
||||
NWindows::NSynchronization::CEvent *event = NULL);
|
||||
HRESULT CompressFiles(
|
||||
const UString &curDir,
|
||||
const UString &archiveName,
|
||||
const UStringVector &names,
|
||||
// const UString &outFolder,
|
||||
bool email, bool showDialog);
|
||||
|
||||
HRESULT ExtractArchive(const UString &archiveName,
|
||||
HRESULT ExtractArchives(
|
||||
const UStringVector &archivePaths,
|
||||
const UString &outFolder, bool showDialog);
|
||||
|
||||
HRESULT TestArchive(const UString &archiveName);
|
||||
HRESULT TestArchives(const UStringVector &archivePaths);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2,32 +2,22 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Windows/FileDir.h"
|
||||
|
||||
#include "Common/StringConvert.h"
|
||||
#include "DefaultName.h"
|
||||
|
||||
const wchar_t *kEmptyFileAlias = L"[Content]";
|
||||
static const wchar_t *kEmptyFileAlias = L"[Content]";
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NDirectory;
|
||||
|
||||
UString GetDefaultName(const UString &fullFileName,
|
||||
UString GetDefaultName2(const UString &fileName,
|
||||
const UString &extension, const UString &addSubExtension)
|
||||
{
|
||||
UString fileName;
|
||||
if (!GetOnlyName(fullFileName, fileName))
|
||||
throw 5011749;
|
||||
int extLength = extension.Length();
|
||||
int fileNameLength = fileName.Length();
|
||||
if (fileNameLength <= extLength + 1)
|
||||
return kEmptyFileAlias;
|
||||
int dotPos = fileNameLength - (extLength + 1);
|
||||
if (fileName[dotPos] != '.')
|
||||
return kEmptyFileAlias;
|
||||
if (extension.CollateNoCase(fileName.Mid(dotPos + 1)) == 0)
|
||||
return fileName.Left(dotPos) + addSubExtension;
|
||||
if (fileNameLength > extLength + 1)
|
||||
{
|
||||
int dotPos = fileNameLength - (extLength + 1);
|
||||
if (fileName[dotPos] == '.')
|
||||
if (extension.CollateNoCase(fileName.Mid(dotPos + 1)) == 0)
|
||||
return fileName.Left(dotPos) + addSubExtension;
|
||||
}
|
||||
return kEmptyFileAlias;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
// DefaultName.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __DEFAULTNAME_H
|
||||
#define __DEFAULTNAME_H
|
||||
|
||||
#include "Common/String.h"
|
||||
|
||||
UString GetDefaultName(const UString &fullFileName,
|
||||
UString GetDefaultName2(const UString &fileName,
|
||||
const UString &extension, const UString &addSubExtension);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
// DirItem.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __DIR_ITEM_H
|
||||
#define __DIR_ITEM_H
|
||||
|
||||
// #include "Common/Types.h"
|
||||
#include "Common/String.h"
|
||||
// #include "Windows/PropVariant.h"
|
||||
#include "Common/Types.h"
|
||||
|
||||
struct CDirItem
|
||||
{
|
||||
UINT32 Attributes;
|
||||
UInt32 Attributes;
|
||||
FILETIME CreationTime;
|
||||
FILETIME LastAccessTime;
|
||||
FILETIME LastWriteTime;
|
||||
UINT64 Size;
|
||||
UInt64 Size;
|
||||
UString Name;
|
||||
UString FullPath;
|
||||
bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }
|
||||
@@ -28,7 +25,7 @@ struct CArchiveItem
|
||||
// NWindows::NCOM::CPropVariant LastWriteTime;
|
||||
FILETIME LastWriteTime;
|
||||
bool SizeIsDefined;
|
||||
UINT64 Size;
|
||||
UInt64 Size;
|
||||
UString Name;
|
||||
bool Censored;
|
||||
int IndexInServer;
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "EnumDirItems.h"
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/Wildcard.h"
|
||||
#include "Common/MyCom.h"
|
||||
|
||||
#include "EnumDirItems.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
@@ -28,27 +31,33 @@ void AddDirFileInfo(
|
||||
dirItems.Add(item);
|
||||
}
|
||||
|
||||
static void EnumerateDirectory(
|
||||
static HRESULT EnumerateDirectory(
|
||||
const UString &baseFolderPrefix,
|
||||
const UString &directory,
|
||||
const UString &prefix,
|
||||
CObjectVector<CDirItem> &dirItems)
|
||||
{
|
||||
NFind::CEnumeratorW enumerator(baseFolderPrefix + directory + wchar_t(kAnyStringWildcard));
|
||||
NFind::CFileInfoW fileInfo;
|
||||
while (enumerator.Next(fileInfo))
|
||||
while (true)
|
||||
{
|
||||
NFind::CFileInfoW fileInfo;
|
||||
bool found;
|
||||
if (!enumerator.Next(fileInfo, found))
|
||||
return ::GetLastError();
|
||||
if (!found)
|
||||
break;
|
||||
AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo,
|
||||
dirItems);
|
||||
if (fileInfo.IsDirectory())
|
||||
{
|
||||
EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter),
|
||||
prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems);
|
||||
RINOK(EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter),
|
||||
prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems));
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void EnumerateDirItems(
|
||||
HRESULT EnumerateDirItems(
|
||||
const UString &baseFolderPrefix,
|
||||
const UStringVector &fileNames,
|
||||
const UString &archiveNamePrefix,
|
||||
@@ -63,9 +72,88 @@ void EnumerateDirItems(
|
||||
AddDirFileInfo(archiveNamePrefix, fileName, fileInfo, dirItems);
|
||||
if (fileInfo.IsDirectory())
|
||||
{
|
||||
EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter),
|
||||
RINOK(EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter),
|
||||
archiveNamePrefix + fileInfo.Name + wchar_t(kDirDelimiter),
|
||||
dirItems);
|
||||
dirItems));
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT EnumerateDirItems(
|
||||
const NWildcard::CCensorNode &curNode,
|
||||
const UString &diskPrefix,
|
||||
const UString &archivePrefix,
|
||||
const UString &addArchivePrefix,
|
||||
CObjectVector<CDirItem> &dirItems,
|
||||
bool enterToSubFolders,
|
||||
IEnumDirItemCallback *callback)
|
||||
{
|
||||
if (!enterToSubFolders)
|
||||
if (curNode.NeedCheckSubDirs())
|
||||
enterToSubFolders = true;
|
||||
if (callback)
|
||||
RINOK(callback->CheckBreak());
|
||||
NFind::CEnumeratorW enumerator(diskPrefix + wchar_t(kAnyStringWildcard));
|
||||
while (true)
|
||||
{
|
||||
NFind::CFileInfoW fileInfo;
|
||||
bool found;
|
||||
if (!enumerator.Next(fileInfo, found))
|
||||
return ::GetLastError();
|
||||
if (!found)
|
||||
break;
|
||||
|
||||
if (callback)
|
||||
RINOK(callback->CheckBreak());
|
||||
UString name = fileInfo.Name;
|
||||
bool enterToSubFolders2 = enterToSubFolders;
|
||||
if (curNode.CheckPathToRoot(addArchivePrefix + name, !fileInfo.IsDirectory()))
|
||||
{
|
||||
AddDirFileInfo(archivePrefix, diskPrefix + fileInfo.Name, fileInfo, dirItems);
|
||||
if (fileInfo.IsDirectory())
|
||||
enterToSubFolders2 = true;;
|
||||
}
|
||||
if (!fileInfo.IsDirectory())
|
||||
continue;
|
||||
|
||||
const NWildcard::CCensorNode *nextNode = 0;
|
||||
if (addArchivePrefix.IsEmpty())
|
||||
{
|
||||
int index = curNode.FindSubNode(name);
|
||||
if (index >= 0)
|
||||
nextNode = &curNode.SubNodes[index];
|
||||
}
|
||||
if (!enterToSubFolders2 && nextNode == 0)
|
||||
continue;
|
||||
|
||||
UString archivePrefixNew = archivePrefix;
|
||||
UString addArchivePrefixNew = addArchivePrefix;
|
||||
if (nextNode == 0)
|
||||
{
|
||||
nextNode = &curNode;
|
||||
addArchivePrefixNew += name;
|
||||
addArchivePrefixNew += wchar_t(kDirDelimiter);
|
||||
}
|
||||
archivePrefixNew += name;
|
||||
archivePrefixNew += wchar_t(kDirDelimiter);
|
||||
RINOK(EnumerateDirItems(*nextNode,
|
||||
diskPrefix + fileInfo.Name + wchar_t(kDirDelimiter),
|
||||
archivePrefixNew, addArchivePrefixNew,
|
||||
dirItems, enterToSubFolders2, callback));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT EnumerateItems(const NWildcard::CCensor &censor,
|
||||
CObjectVector<CDirItem> &dirItems, IEnumDirItemCallback *callback)
|
||||
{
|
||||
for (int i = 0; i < censor.Pairs.Size(); i++)
|
||||
{
|
||||
if (callback)
|
||||
RINOK(callback->CheckBreak());
|
||||
const NWildcard::CPair &pair = censor.Pairs[i];
|
||||
RINOK(EnumerateDirItems(pair.Head, pair.Prefix, L"", L"", dirItems, false, callback));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
// EnumDirItems.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __ENUM_DIR_ITEMS_H
|
||||
#define __ENUM_DIR_ITEMS_H
|
||||
|
||||
#include "Common/String.h"
|
||||
#include "Common/Vector.h"
|
||||
#include "Common/Wildcard.h"
|
||||
#include "DirItem.h"
|
||||
// #include "UpdatePairBasic.h"
|
||||
|
||||
#include "Windows/FileFind.h"
|
||||
|
||||
@@ -18,16 +14,20 @@ void AddDirFileInfo(
|
||||
NWindows::NFile::NFind::CFileInfoW &fileInfo,
|
||||
CObjectVector<CDirItem> &dirItems);
|
||||
|
||||
void EnumerateDirItems(
|
||||
|
||||
HRESULT EnumerateDirItems(
|
||||
const UString &baseFolderPrefix,
|
||||
const UStringVector &fileNames,
|
||||
const UString &archiveNamePrefix,
|
||||
CObjectVector<CDirItem> &dirItems);
|
||||
|
||||
/*
|
||||
void EnumerateItems(const CSysStringVector &filePaths,
|
||||
const UString &archiveNamePrefix,
|
||||
CArchiveStyleDirItemInfoVector &dirFileInfoVector, UINT codePage);
|
||||
*/
|
||||
struct IEnumDirItemCallback
|
||||
{
|
||||
virtual HRESULT CheckBreak() { return S_OK; }
|
||||
};
|
||||
|
||||
|
||||
HRESULT EnumerateItems(const NWildcard::CCensor &censor,
|
||||
CObjectVector<CDirItem> &dirItems, IEnumDirItemCallback *callback);
|
||||
|
||||
#endif
|
||||
|
||||
27
7zip/UI/Common/ExitCode.h
Executable file
27
7zip/UI/Common/ExitCode.h
Executable file
@@ -0,0 +1,27 @@
|
||||
// ExitCode.h
|
||||
|
||||
#ifndef __EXIT_CODE_H
|
||||
#define __EXIT_CODE_H
|
||||
|
||||
namespace NExitCode {
|
||||
|
||||
enum EEnum {
|
||||
|
||||
kSuccess = 0, // Successful operation
|
||||
kWarning = 1, // Non fatal error(s) occurred
|
||||
kFatalError = 2, // A fatal error occurred
|
||||
// kCRCError = 3, // A CRC error occurred when unpacking
|
||||
// kLockedArchive = 4, // Attempt to modify an archive previously locked
|
||||
// kWriteError = 5, // Write to disk error
|
||||
// kOpenError = 6, // Open file error
|
||||
kUserError = 7, // Command line option error
|
||||
kMemoryError = 8, // Not enough memory for operation
|
||||
// kCreateFileError = 9, // Create file error
|
||||
|
||||
kUserBreak = 255 // User stopped the process
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
127
7zip/UI/Common/Extract.cpp
Executable file
127
7zip/UI/Common/Extract.cpp
Executable file
@@ -0,0 +1,127 @@
|
||||
// Extract.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Extract.h"
|
||||
|
||||
#include "Windows/Defs.h"
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/FileDir.h"
|
||||
|
||||
#include "OpenArchive.h"
|
||||
|
||||
#ifndef EXCLUDE_COM
|
||||
#include "Windows/DLL.h"
|
||||
#endif
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
HRESULT DecompressArchive(
|
||||
IInArchive *archive,
|
||||
const UString &defaultName,
|
||||
const NWildcard::CCensorNode &wildcardCensor,
|
||||
const CExtractOptions &options,
|
||||
IExtractCallbackUI *callback)
|
||||
{
|
||||
CRecordVector<UInt32> realIndices;
|
||||
UInt32 numItems;
|
||||
RINOK(archive->GetNumberOfItems(&numItems));
|
||||
|
||||
for(UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
UString filePath;
|
||||
RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath));
|
||||
bool isFolder;
|
||||
RINOK(IsArchiveItemFolder(archive, i, isFolder));
|
||||
if (!wildcardCensor.CheckPath(filePath, !isFolder))
|
||||
continue;
|
||||
realIndices.Add(i);
|
||||
}
|
||||
if (realIndices.Size() == 0)
|
||||
{
|
||||
callback->ThereAreNoFiles();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
|
||||
CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
|
||||
|
||||
UStringVector removePathParts;
|
||||
|
||||
UString outDir = options.OutputDir;
|
||||
outDir.Replace(L"*", defaultName);
|
||||
if(!outDir.IsEmpty())
|
||||
if(!NFile::NDirectory::CreateComplexDirectory(outDir))
|
||||
{
|
||||
throw UString(L"Can not create output directory ") + outDir;
|
||||
}
|
||||
|
||||
extractCallbackSpec->Init(
|
||||
archive,
|
||||
callback,
|
||||
options.StdOutMode,
|
||||
outDir,
|
||||
options.PathMode,
|
||||
options.OverwriteMode,
|
||||
removePathParts,
|
||||
options.DefaultItemName,
|
||||
options.ArchiveFileInfo.LastWriteTime,
|
||||
options.ArchiveFileInfo.Attributes);
|
||||
|
||||
HRESULT result = archive->Extract(&realIndices.Front(),
|
||||
realIndices.Size(), options.TestMode? 1: 0,
|
||||
extractCallback);
|
||||
|
||||
return callback->ExtractResult(result);
|
||||
}
|
||||
|
||||
HRESULT DecompressArchives(
|
||||
UStringVector &archivePaths, UStringVector &archivePathsFull,
|
||||
const NWildcard::CCensorNode &wildcardCensor,
|
||||
const CExtractOptions &optionsSpec,
|
||||
IOpenCallbackUI *openCallback,
|
||||
IExtractCallbackUI *extractCallback)
|
||||
{
|
||||
CExtractOptions options = optionsSpec;
|
||||
for (int i = 0; i < archivePaths.Size(); i++)
|
||||
{
|
||||
const UString &archivePath = archivePaths[i];
|
||||
NFile::NFind::CFileInfoW archiveFileInfo;
|
||||
if (!NFile::NFind::FindFile(archivePath, archiveFileInfo))
|
||||
throw "there is no such archive";
|
||||
|
||||
if (archiveFileInfo.IsDirectory())
|
||||
throw "there is no such archive";
|
||||
|
||||
options.ArchiveFileInfo = archiveFileInfo;
|
||||
|
||||
RINOK(extractCallback->BeforeOpen(archivePath));
|
||||
CArchiveLink archiveLink;
|
||||
HRESULT result = MyOpenArchive(archivePath, archiveLink, openCallback);
|
||||
RINOK(extractCallback->OpenResult(archivePath, result));
|
||||
if (result != S_OK)
|
||||
continue;
|
||||
|
||||
for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
|
||||
{
|
||||
int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]);
|
||||
if (index >= 0 && index > i)
|
||||
{
|
||||
archivePaths.Delete(index);
|
||||
archivePathsFull.Delete(index);
|
||||
}
|
||||
}
|
||||
UString password;
|
||||
RINOK(openCallback->GetPasswordIfAny(password));
|
||||
if (!password.IsEmpty())
|
||||
{
|
||||
RINOK(extractCallback->SetPassword(password));
|
||||
}
|
||||
|
||||
options.DefaultItemName = archiveLink.GetDefaultItemName();
|
||||
RINOK(DecompressArchive(
|
||||
archiveLink.GetArchive(), archiveLink.GetDefaultItemName(),
|
||||
wildcardCensor, options, extractCallback));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
55
7zip/UI/Common/Extract.h
Executable file
55
7zip/UI/Common/Extract.h
Executable file
@@ -0,0 +1,55 @@
|
||||
// Extract.h
|
||||
|
||||
#ifndef __EXTRACT_H
|
||||
#define __EXTRACT_H
|
||||
|
||||
#include "Common/Wildcard.h"
|
||||
#include "Windows/FileFind.h"
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
#include "../Common/ZipRegistry.h"
|
||||
|
||||
#include "ArchiveExtractCallback.h"
|
||||
#include "ArchiveOpenCallback.h"
|
||||
#include "ExtractMode.h"
|
||||
|
||||
class CExtractOptions
|
||||
{
|
||||
public:
|
||||
bool StdOutMode;
|
||||
bool TestMode;
|
||||
NExtract::NPathMode::EEnum PathMode;
|
||||
|
||||
UString OutputDir;
|
||||
bool YesToAll;
|
||||
UString DefaultItemName;
|
||||
NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo;
|
||||
|
||||
// bool ShowDialog;
|
||||
// bool PasswordEnabled;
|
||||
// UString Password;
|
||||
|
||||
NExtract::NOverwriteMode::EEnum OverwriteMode;
|
||||
|
||||
CExtractOptions():
|
||||
StdOutMode(false),
|
||||
YesToAll(false),
|
||||
TestMode(false),
|
||||
PathMode(NExtract::NPathMode::kFullPathnames),
|
||||
OverwriteMode(NExtract::NOverwriteMode::kAskBefore)
|
||||
{}
|
||||
|
||||
/*
|
||||
bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) ||
|
||||
(ExtractMode == NExtractMode::kFullPath); }
|
||||
*/
|
||||
};
|
||||
|
||||
HRESULT DecompressArchives(
|
||||
UStringVector &archivePaths, UStringVector &archivePathsFull,
|
||||
const NWildcard::CCensorNode &wildcardCensor,
|
||||
const CExtractOptions &options,
|
||||
IOpenCallbackUI *openCallback,
|
||||
IExtractCallbackUI *extractCallback);
|
||||
|
||||
#endif
|
||||
31
7zip/UI/Common/ExtractMode.h
Executable file
31
7zip/UI/Common/ExtractMode.h
Executable file
@@ -0,0 +1,31 @@
|
||||
// ExtractMode.h
|
||||
|
||||
#ifndef __EXTRACT_MODE_H
|
||||
#define __EXTRACT_MODE_H
|
||||
|
||||
namespace NExtract {
|
||||
|
||||
namespace NPathMode
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kFullPathnames,
|
||||
kCurrentPathnames,
|
||||
kNoPathnames
|
||||
};
|
||||
}
|
||||
|
||||
namespace NOverwriteMode
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kAskBefore,
|
||||
kWithoutPrompt,
|
||||
kSkipExisting,
|
||||
kAutoRename,
|
||||
kAutoRenameExisting
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -3,20 +3,32 @@
|
||||
#include "StdAfx.h"
|
||||
#include "ExtractingFilePath.h"
|
||||
|
||||
static void ReplaceDisk(UString &s)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < s.Length(); i++)
|
||||
if (s[i] != ' ')
|
||||
break;
|
||||
if (s.Length() > i + 1)
|
||||
{
|
||||
if (s[i + 1] == L':')
|
||||
{
|
||||
s.Delete(i + 1);
|
||||
// s.Insert(i + 1, L'_');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UString GetCorrectFileName(const UString &path)
|
||||
{
|
||||
UString result = path;
|
||||
result.Trim();
|
||||
result.Replace(L"..\\", L"");
|
||||
result.Replace(L"../", L"");
|
||||
if (result.Length() > 1)
|
||||
{
|
||||
if (result[1] == L':')
|
||||
{
|
||||
result.Delete(1);
|
||||
// result.Insert(first + 1, L'_');
|
||||
}
|
||||
UString test = path;
|
||||
test.Trim();
|
||||
if (test == L"..")
|
||||
result.Replace(L"..", L"");
|
||||
}
|
||||
ReplaceDisk(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -29,7 +41,6 @@ UString GetCorrectPath(const UString &path)
|
||||
break;
|
||||
while(result.Length() > first)
|
||||
{
|
||||
|
||||
if (result[first] == L'\\' || result[first] == L'/')
|
||||
{
|
||||
result.Delete(first);
|
||||
@@ -40,15 +51,19 @@ UString GetCorrectPath(const UString &path)
|
||||
result.Replace(L"..\\", L"");
|
||||
result.Replace(L"../", L"");
|
||||
|
||||
if (result.Length() > 1)
|
||||
{
|
||||
if (result[first + 1] == L':')
|
||||
{
|
||||
result.Delete(first + 1);
|
||||
// result.Insert(first + 1, L'_');
|
||||
}
|
||||
}
|
||||
ReplaceDisk(result);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
void MakeCorrectPath(UStringVector &pathParts)
|
||||
{
|
||||
for (int i = 0; i < pathParts.Size();)
|
||||
{
|
||||
UString &s = pathParts[i];
|
||||
s = GetCorrectFileName(s);
|
||||
if (s.IsEmpty())
|
||||
pathParts.Delete(i);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// ExtractingFilePath.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __EXTRACTINGFILEPATH_H
|
||||
#define __EXTRACTINGFILEPATH_H
|
||||
|
||||
@@ -9,5 +7,6 @@
|
||||
|
||||
UString GetCorrectFileName(const UString &path);
|
||||
UString GetCorrectPath(const UString &path);
|
||||
void MakeCorrectPath(UStringVector &pathParts);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
// HandlerLoader.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __HANDLERLOADER_H
|
||||
#define __HANDLERLOADER_H
|
||||
|
||||
#include "../../ICoder.h"
|
||||
#include "Windows/DLL.h"
|
||||
|
||||
typedef UINT32 (WINAPI * CreateObjectFunc)(
|
||||
typedef UInt32 (WINAPI * CreateObjectFunc)(
|
||||
const GUID *clsID,
|
||||
const GUID *interfaceID,
|
||||
void **outObject);
|
||||
@@ -37,6 +35,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
46
7zip/UI/Common/IFileExtractCallback.h
Executable file
46
7zip/UI/Common/IFileExtractCallback.h
Executable file
@@ -0,0 +1,46 @@
|
||||
// IFileExtractCallback.h
|
||||
|
||||
#ifndef __IFILEEXTRACTCALLBACK_H
|
||||
#define __IFILEEXTRACTCALLBACK_H
|
||||
|
||||
#include "Common/String.h"
|
||||
|
||||
namespace NOverwriteAnswer
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kYes,
|
||||
kYesToAll,
|
||||
kNo,
|
||||
kNoToAll,
|
||||
kAutoRename,
|
||||
kCancel,
|
||||
};
|
||||
}
|
||||
|
||||
// {23170F69-40C1-278A-0000-000100070000}
|
||||
DEFINE_GUID(IID_IFolderArchiveExtractCallback,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00);
|
||||
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100070000")
|
||||
IFolderArchiveExtractCallback: public IProgress
|
||||
{
|
||||
public:
|
||||
STDMETHOD(AskOverwrite)(
|
||||
const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
|
||||
const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
|
||||
Int32 *answer) PURE;
|
||||
STDMETHOD(PrepareOperation)(const wchar_t *name, Int32 askExtractMode, const UInt64 *position) PURE;
|
||||
STDMETHOD(MessageError)(const wchar_t *message) PURE;
|
||||
STDMETHOD(SetOperationResult)(Int32 operationResult) PURE;
|
||||
};
|
||||
|
||||
struct IExtractCallbackUI: IFolderArchiveExtractCallback
|
||||
{
|
||||
virtual HRESULT BeforeOpen(const wchar_t *name) = 0;
|
||||
virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) = 0;
|
||||
virtual HRESULT ThereAreNoFiles() = 0;
|
||||
virtual HRESULT ExtractResult(HRESULT result) = 0;
|
||||
virtual HRESULT SetPassword(const UString &password) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
#include "OpenArchive.h"
|
||||
|
||||
#include "Common/Wildcard.h"
|
||||
|
||||
#include "Windows/FileName.h"
|
||||
#include "Windows/FileDir.h"
|
||||
#include "Windows/Defs.h"
|
||||
#include "Windows/PropVariant.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
|
||||
@@ -24,6 +27,10 @@
|
||||
#include "../../Archive/GZip/GZipHandler.h"
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_SPLIT
|
||||
#include "../../Archive/Split/SplitHandler.h"
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_TAR
|
||||
#include "../../Archive/Tar/TarHandler.h"
|
||||
#endif
|
||||
@@ -32,17 +39,86 @@
|
||||
#include "../../Archive/Zip/ZipHandler.h"
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_Z
|
||||
#include "../../Archive/Z/ZHandler.h"
|
||||
#endif
|
||||
|
||||
#ifndef EXCLUDE_COM
|
||||
#include "HandlerLoader.h"
|
||||
#endif
|
||||
|
||||
#include "DefaultName.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
const UINT64 kMaxCheckStartPosition = 1 << 20;
|
||||
HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(archive->GetProperty(index, kpidPath, &prop));
|
||||
if(prop.vt == VT_BSTR)
|
||||
result = prop.bstrVal;
|
||||
else if (prop.vt == VT_EMPTY)
|
||||
result.Empty();
|
||||
else
|
||||
return E_FAIL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ReOpenArchive(IInArchive *archive,
|
||||
const UString &fileName)
|
||||
HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result)
|
||||
{
|
||||
RINOK(GetArchiveItemPath(archive, index, result));
|
||||
if (result.IsEmpty())
|
||||
result = defaultName;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index,
|
||||
const FILETIME &defaultFileTime, FILETIME &fileTime)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(archive->GetProperty(index, kpidLastWriteTime, &prop));
|
||||
if (prop.vt == VT_FILETIME)
|
||||
fileTime = prop.filetime;
|
||||
else if (prop.vt == VT_EMPTY)
|
||||
fileTime = defaultFileTime;
|
||||
else
|
||||
return E_FAIL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(archive->GetProperty(index, propID, &prop));
|
||||
if(prop.vt == VT_BOOL)
|
||||
result = VARIANT_BOOLToBool(prop.boolVal);
|
||||
else if (prop.vt == VT_EMPTY)
|
||||
result = false;
|
||||
else
|
||||
return E_FAIL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
|
||||
{
|
||||
return IsArchiveItemProp(archive, index, kpidIsFolder, result);
|
||||
}
|
||||
|
||||
HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result)
|
||||
{
|
||||
return IsArchiveItemProp(archive, index, kpidIsAnti, result);
|
||||
}
|
||||
|
||||
// Static-SFX (for Linux) can be big
|
||||
const UInt64 kMaxCheckStartPosition =
|
||||
#ifdef _WIN32
|
||||
1 << 20;
|
||||
#else
|
||||
1 << 22;
|
||||
#endif
|
||||
|
||||
|
||||
HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName)
|
||||
{
|
||||
CInFileStream *inStreamSpec = new CInFileStream;
|
||||
CMyComPtr<IInStream> inStream(inStreamSpec);
|
||||
@@ -50,49 +126,87 @@ HRESULT ReOpenArchive(IInArchive *archive,
|
||||
return archive->Open(inStream, &kMaxCheckStartPosition, NULL);
|
||||
}
|
||||
|
||||
HRESULT OpenArchive(const UString &fileName,
|
||||
#ifndef _SFX
|
||||
static inline bool TestSignature(const Byte *p1, const Byte *p2, UInt32 size)
|
||||
{
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
if (p1[i] != p2[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
HRESULT OpenArchive(
|
||||
IInStream *inStream,
|
||||
const UString &fileName,
|
||||
#ifndef EXCLUDE_COM
|
||||
HMODULE *module,
|
||||
#endif
|
||||
IInArchive **archiveResult,
|
||||
CArchiverInfo &archiverInfoResult,
|
||||
int &subExtIndex,
|
||||
UString &defaultItemName,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
{
|
||||
CInFileStream *inStreamSpec = new CInFileStream;
|
||||
CMyComPtr<IInStream> inStream(inStreamSpec);
|
||||
if (!inStreamSpec->Open(fileName))
|
||||
return GetLastError();
|
||||
|
||||
*archiveResult = NULL;
|
||||
CObjectVector<CArchiverInfo> archiverInfoList;
|
||||
ReadArchiverInfoList(archiverInfoList);
|
||||
UString extension;
|
||||
{
|
||||
UString name, pureName, dot;
|
||||
if(!NFile::NDirectory::GetOnlyName(fileName, name))
|
||||
return E_FAIL;
|
||||
NFile::NName::SplitNameToPureNameAndExtension(name, pureName, dot, extension);
|
||||
int dotPos = fileName.ReverseFind(L'.');
|
||||
if (dotPos >= 0)
|
||||
extension = fileName.Mid(dotPos + 1);
|
||||
}
|
||||
CIntVector orderIndices;
|
||||
int firstArchiverIndex;
|
||||
for(firstArchiverIndex = 0;
|
||||
firstArchiverIndex < archiverInfoList.Size(); firstArchiverIndex++)
|
||||
int i;
|
||||
bool finded = false;
|
||||
for(i = 0; i < archiverInfoList.Size(); i++)
|
||||
{
|
||||
int subIndex = archiverInfoList[firstArchiverIndex].FindExtension(extension);
|
||||
if (subIndex >= 0)
|
||||
break;
|
||||
if (archiverInfoList[i].FindExtension(extension) >= 0)
|
||||
{
|
||||
orderIndices.Insert(0, i);
|
||||
finded = true;
|
||||
}
|
||||
else
|
||||
orderIndices.Add(i);
|
||||
}
|
||||
if(firstArchiverIndex < archiverInfoList.Size())
|
||||
orderIndices.Add(firstArchiverIndex);
|
||||
for(int j = 0; j < archiverInfoList.Size(); j++)
|
||||
if(j != firstArchiverIndex)
|
||||
orderIndices.Add(j);
|
||||
|
||||
HRESULT badResult = S_OK;
|
||||
for(int i = 0; i < orderIndices.Size(); i++)
|
||||
#ifndef _SFX
|
||||
if (!finded)
|
||||
{
|
||||
inStreamSpec->Seek(0, STREAM_SEEK_SET, NULL);
|
||||
CByteBuffer byteBuffer;
|
||||
const UInt32 kBufferSize = (200 << 10);
|
||||
byteBuffer.SetCapacity(kBufferSize);
|
||||
Byte *buffer = byteBuffer;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
UInt32 processedSize;
|
||||
RINOK(inStream->Read(buffer, kBufferSize, &processedSize));
|
||||
int numFinded = 0;
|
||||
for (int pos = (int)processedSize; pos >= 0 ; pos--)
|
||||
{
|
||||
for(int i = numFinded; i < orderIndices.Size(); i++)
|
||||
{
|
||||
int index = orderIndices[i];
|
||||
const CArchiverInfo &ai = archiverInfoList[index];
|
||||
const CByteBuffer &sig = ai.StartSignature;
|
||||
if (sig.GetCapacity() == 0)
|
||||
continue;
|
||||
if (pos + sig.GetCapacity() > processedSize)
|
||||
continue;
|
||||
if (TestSignature(buffer + pos, sig, sig.GetCapacity()))
|
||||
{
|
||||
orderIndices.Delete(i);
|
||||
orderIndices.Insert(0, index);
|
||||
numFinded++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
HRESULT badResult = S_OK;
|
||||
for(i = 0; i < orderIndices.Size(); i++)
|
||||
{
|
||||
inStream->Seek(0, STREAM_SEEK_SET, NULL);
|
||||
const CArchiverInfo &archiverInfo = archiverInfoList[orderIndices[i]];
|
||||
#ifndef EXCLUDE_COM
|
||||
CHandlerLoader loader;
|
||||
@@ -114,6 +228,11 @@ HRESULT OpenArchive(const UString &fileName,
|
||||
archive = new NArchive::NGZip::CHandler;
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_SPLIT
|
||||
if (archiverInfo.Name.CompareNoCase(L"Split") == 0)
|
||||
archive = new NArchive::NSplit::CHandler;
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_TAR
|
||||
if (archiverInfo.Name.CompareNoCase(L"Tar") == 0)
|
||||
archive = new NArchive::NTar::CHandler;
|
||||
@@ -124,6 +243,11 @@ HRESULT OpenArchive(const UString &fileName,
|
||||
archive = new NArchive::NZip::CHandler;
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_Z
|
||||
if (archiverInfo.Name.CompareNoCase(L"Z") == 0)
|
||||
archive = new NArchive::NZ::CHandler;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef EXCLUDE_COM
|
||||
if (!archive)
|
||||
@@ -144,28 +268,260 @@ HRESULT OpenArchive(const UString &fileName,
|
||||
if(result != S_OK)
|
||||
{
|
||||
badResult = result;
|
||||
if(result == E_ABORT)
|
||||
break;
|
||||
continue;
|
||||
// return result;
|
||||
}
|
||||
*archiveResult = archive.Detach();
|
||||
#ifndef EXCLUDE_COM
|
||||
*module = loader.Detach();
|
||||
#endif
|
||||
archiverInfoResult = archiverInfo;
|
||||
subExtIndex = archiverInfo.FindExtension(extension);
|
||||
int subExtIndex = archiverInfo.FindExtension(extension);
|
||||
if (subExtIndex < 0)
|
||||
subExtIndex = 0;
|
||||
defaultItemName = GetDefaultName2(fileName,
|
||||
archiverInfo.Extensions[subExtIndex].Extension,
|
||||
archiverInfo.Extensions[subExtIndex].AddExtension);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
if (badResult != S_OK)
|
||||
return badResult;
|
||||
return S_FALSE;
|
||||
|
||||
/*
|
||||
#else
|
||||
return S_FALSE;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
||||
HRESULT OpenArchive(const UString &filePath,
|
||||
#ifndef EXCLUDE_COM
|
||||
HMODULE *module,
|
||||
#endif
|
||||
IInArchive **archiveResult,
|
||||
CArchiverInfo &archiverInfo,
|
||||
UString &defaultItemName,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
{
|
||||
CInFileStream *inStreamSpec = new CInFileStream;
|
||||
CMyComPtr<IInStream> inStream(inStreamSpec);
|
||||
if (!inStreamSpec->Open(filePath))
|
||||
return GetLastError();
|
||||
return OpenArchive(inStream, ExtractFileNameFromPath(filePath),
|
||||
#ifndef EXCLUDE_COM
|
||||
module,
|
||||
#endif
|
||||
archiveResult, archiverInfo,
|
||||
defaultItemName, openArchiveCallback);
|
||||
}
|
||||
|
||||
static void MakeDefaultName(UString &name)
|
||||
{
|
||||
int dotPos = name.ReverseFind(L'.');
|
||||
if (dotPos < 0)
|
||||
return;
|
||||
UString ext = name.Mid(dotPos + 1);
|
||||
if (ext.IsEmpty())
|
||||
return;
|
||||
for (int pos = 0; pos < ext.Length(); pos++)
|
||||
if (ext[pos] < L'0' || ext[pos] > L'9')
|
||||
return;
|
||||
name = name.Left(dotPos);
|
||||
}
|
||||
|
||||
HRESULT OpenArchive(const UString &fileName,
|
||||
#ifndef EXCLUDE_COM
|
||||
HMODULE *module0,
|
||||
HMODULE *module1,
|
||||
#endif
|
||||
IInArchive **archive0,
|
||||
IInArchive **archive1,
|
||||
CArchiverInfo &archiverInfo0,
|
||||
CArchiverInfo &archiverInfo1,
|
||||
UString &defaultItemName0,
|
||||
UString &defaultItemName1,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
{
|
||||
HRESULT result = OpenArchive(fileName,
|
||||
#ifndef EXCLUDE_COM
|
||||
module0,
|
||||
#endif
|
||||
archive0, archiverInfo0, defaultItemName0, openArchiveCallback);
|
||||
RINOK(result);
|
||||
CMyComPtr<IInArchiveGetStream> getStream;
|
||||
result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream);
|
||||
if (result != S_OK || getStream == 0)
|
||||
return S_OK;
|
||||
|
||||
CMyComPtr<ISequentialInStream> subSeqStream;
|
||||
result = getStream->GetStream(0, &subSeqStream);
|
||||
if (result != S_OK)
|
||||
return S_OK;
|
||||
|
||||
CMyComPtr<IInStream> subStream;
|
||||
if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK)
|
||||
return S_OK;
|
||||
if (!subStream)
|
||||
return S_OK;
|
||||
|
||||
UInt32 numItems;
|
||||
RINOK((*archive0)->GetNumberOfItems(&numItems));
|
||||
if (numItems < 1)
|
||||
return S_OK;
|
||||
|
||||
UString subPath;
|
||||
RINOK(GetArchiveItemPath(*archive0, 0, subPath))
|
||||
if (subPath.IsEmpty())
|
||||
{
|
||||
MakeDefaultName(defaultItemName0);
|
||||
subPath = defaultItemName0;
|
||||
if (archiverInfo0.Name.CompareNoCase(L"7z") == 0)
|
||||
{
|
||||
if (subPath.Right(3).CompareNoCase(L".7z") != 0)
|
||||
subPath += L".7z";
|
||||
}
|
||||
}
|
||||
else
|
||||
subPath = ExtractFileNameFromPath(subPath);
|
||||
|
||||
CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;
|
||||
openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);
|
||||
if (setSubArchiveName)
|
||||
setSubArchiveName->SetSubArchiveName(subPath);
|
||||
|
||||
result = OpenArchive(subStream, subPath,
|
||||
#ifndef EXCLUDE_COM
|
||||
module1,
|
||||
#endif
|
||||
archive1, archiverInfo1, defaultItemName1, openArchiveCallback);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT MyOpenArchive(const UString &archiveName,
|
||||
#ifndef EXCLUDE_COM
|
||||
HMODULE *module,
|
||||
#endif
|
||||
IInArchive **archive,
|
||||
UString &defaultItemName,
|
||||
IOpenCallbackUI *openCallbackUI)
|
||||
{
|
||||
COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
|
||||
CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec;
|
||||
openCallbackSpec->Callback = openCallbackUI;
|
||||
|
||||
UString fullName;
|
||||
int fileNamePartStartIndex;
|
||||
NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex);
|
||||
openCallbackSpec->Init(
|
||||
fullName.Left(fileNamePartStartIndex),
|
||||
fullName.Mid(fileNamePartStartIndex));
|
||||
|
||||
CArchiverInfo archiverInfo;
|
||||
return OpenArchive(archiveName,
|
||||
#ifndef EXCLUDE_COM
|
||||
module,
|
||||
#endif
|
||||
archive,
|
||||
archiverInfo,
|
||||
defaultItemName,
|
||||
openCallback);
|
||||
}
|
||||
|
||||
HRESULT MyOpenArchive(const UString &archiveName,
|
||||
#ifndef EXCLUDE_COM
|
||||
HMODULE *module0,
|
||||
HMODULE *module1,
|
||||
#endif
|
||||
IInArchive **archive0,
|
||||
IInArchive **archive1,
|
||||
UString &defaultItemName0,
|
||||
UString &defaultItemName1,
|
||||
UStringVector &volumePaths,
|
||||
IOpenCallbackUI *openCallbackUI)
|
||||
{
|
||||
COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
|
||||
CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec;
|
||||
openCallbackSpec->Callback = openCallbackUI;
|
||||
|
||||
UString fullName;
|
||||
int fileNamePartStartIndex;
|
||||
NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex);
|
||||
UString prefix = fullName.Left(fileNamePartStartIndex);
|
||||
UString name = fullName.Mid(fileNamePartStartIndex);
|
||||
openCallbackSpec->Init(prefix, name);
|
||||
|
||||
CArchiverInfo archiverInfo0, archiverInfo1;
|
||||
HRESULT result = OpenArchive(archiveName,
|
||||
#ifndef EXCLUDE_COM
|
||||
module0,
|
||||
module1,
|
||||
#endif
|
||||
archive0,
|
||||
archive1,
|
||||
archiverInfo0,
|
||||
archiverInfo1,
|
||||
defaultItemName0,
|
||||
defaultItemName1,
|
||||
openCallback);
|
||||
RINOK(result);
|
||||
volumePaths.Add(prefix + name);
|
||||
for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++)
|
||||
volumePaths.Add(prefix + openCallbackSpec->FileNames[i]);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CArchiveLink::Close()
|
||||
{
|
||||
if (Archive1 != 0)
|
||||
RINOK(Archive1->Close());
|
||||
if (Archive0 != 0)
|
||||
RINOK(Archive0->Close());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CArchiveLink::Release()
|
||||
{
|
||||
if (Archive1 != 0)
|
||||
Archive1.Release();
|
||||
if (Archive0 != 0)
|
||||
Archive0.Release();
|
||||
#ifndef EXCLUDE_COM
|
||||
Library1.Free();
|
||||
Library0.Free();
|
||||
#endif
|
||||
}
|
||||
|
||||
HRESULT OpenArchive(const UString &archiveName,
|
||||
CArchiveLink &archiveLink,
|
||||
IArchiveOpenCallback *openCallback)
|
||||
{
|
||||
return OpenArchive(archiveName,
|
||||
#ifndef EXCLUDE_COM
|
||||
&archiveLink.Library0, &archiveLink.Library1,
|
||||
#endif
|
||||
&archiveLink.Archive0, &archiveLink.Archive1,
|
||||
archiveLink.ArchiverInfo0, archiveLink.ArchiverInfo1,
|
||||
archiveLink.DefaultItemName0, archiveLink.DefaultItemName1,
|
||||
openCallback);
|
||||
}
|
||||
|
||||
HRESULT MyOpenArchive(const UString &archiveName,
|
||||
CArchiveLink &archiveLink,
|
||||
IOpenCallbackUI *openCallbackUI)
|
||||
{
|
||||
return MyOpenArchive(archiveName,
|
||||
#ifndef EXCLUDE_COM
|
||||
&archiveLink.Library0, &archiveLink.Library1,
|
||||
#endif
|
||||
&archiveLink.Archive0, &archiveLink.Archive1,
|
||||
archiveLink.DefaultItemName0, archiveLink.DefaultItemName1,
|
||||
archiveLink.VolumePaths,
|
||||
openCallbackUI);
|
||||
}
|
||||
|
||||
HRESULT ReOpenArchive(CArchiveLink &archiveLink,
|
||||
const UString &fileName)
|
||||
{
|
||||
if (archiveLink.GetNumLevels() > 1)
|
||||
return E_NOTIMPL;
|
||||
if (archiveLink.GetNumLevels() == 0)
|
||||
return MyOpenArchive(fileName, archiveLink, 0);
|
||||
return ReOpenArchive(archiveLink.GetArchive(), fileName);
|
||||
}
|
||||
|
||||
@@ -4,21 +4,130 @@
|
||||
#define __OPENARCHIVE_H
|
||||
|
||||
#include "Common/String.h"
|
||||
#include "Windows/FileFind.h"
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
#include "ArchiverInfo.h"
|
||||
#include "ArchiveOpenCallback.h"
|
||||
|
||||
HRESULT OpenArchive(const UString &fileName,
|
||||
#ifndef EXCLUDE_COM
|
||||
#include "Windows/DLL.h"
|
||||
#endif
|
||||
|
||||
HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result);
|
||||
HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index,
|
||||
const FILETIME &defaultFileTime, FILETIME &fileTime);
|
||||
HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result);
|
||||
HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result);
|
||||
|
||||
struct ISetSubArchiveName
|
||||
{
|
||||
virtual void SetSubArchiveName(const wchar_t *name) = 0;
|
||||
};
|
||||
|
||||
HRESULT OpenArchive(
|
||||
IInStream *inStream,
|
||||
const UString &fileName,
|
||||
#ifndef EXCLUDE_COM
|
||||
HMODULE *module,
|
||||
#endif
|
||||
IInArchive **archiveResult,
|
||||
CArchiverInfo &archiverInfoResult,
|
||||
UString &defaultItemName,
|
||||
IArchiveOpenCallback *openArchiveCallback);
|
||||
|
||||
HRESULT OpenArchive(const UString &filePath,
|
||||
#ifndef EXCLUDE_COM
|
||||
HMODULE *module,
|
||||
#endif
|
||||
IInArchive **archive,
|
||||
CArchiverInfo &archiverInfoResult,
|
||||
int &subExtIndex,
|
||||
CArchiverInfo &archiverInfo,
|
||||
UString &defaultItemName,
|
||||
IArchiveOpenCallback *openArchiveCallback);
|
||||
|
||||
HRESULT OpenArchive(const UString &filePath,
|
||||
#ifndef EXCLUDE_COM
|
||||
HMODULE *module0,
|
||||
HMODULE *module1,
|
||||
#endif
|
||||
IInArchive **archive0,
|
||||
IInArchive **archive1,
|
||||
CArchiverInfo &archiverInfo0,
|
||||
CArchiverInfo &archiverInfo1,
|
||||
UString &defaultItemName0,
|
||||
UString &defaultItemName1,
|
||||
IArchiveOpenCallback *openArchiveCallback);
|
||||
|
||||
|
||||
HRESULT ReOpenArchive(IInArchive *archive,
|
||||
const UString &fileName);
|
||||
|
||||
HRESULT MyOpenArchive(const UString &archiveName,
|
||||
#ifndef EXCLUDE_COM
|
||||
HMODULE *module,
|
||||
#endif
|
||||
IInArchive **archive,
|
||||
UString &defaultItemName,
|
||||
IOpenCallbackUI *openCallbackUI);
|
||||
|
||||
HRESULT MyOpenArchive(const UString &archiveName,
|
||||
#ifndef EXCLUDE_COM
|
||||
HMODULE *module0,
|
||||
HMODULE *module1,
|
||||
#endif
|
||||
IInArchive **archive0,
|
||||
IInArchive **archive1,
|
||||
UString &defaultItemName0,
|
||||
UString &defaultItemName1,
|
||||
UStringVector &volumePaths,
|
||||
IOpenCallbackUI *openCallbackUI);
|
||||
|
||||
struct CArchiveLink
|
||||
{
|
||||
#ifndef EXCLUDE_COM
|
||||
NWindows::NDLL::CLibrary Library0;
|
||||
NWindows::NDLL::CLibrary Library1;
|
||||
#endif
|
||||
CMyComPtr<IInArchive> Archive0;
|
||||
CMyComPtr<IInArchive> Archive1;
|
||||
UString DefaultItemName0;
|
||||
UString DefaultItemName1;
|
||||
|
||||
CArchiverInfo ArchiverInfo0;
|
||||
CArchiverInfo ArchiverInfo1;
|
||||
|
||||
UStringVector VolumePaths;
|
||||
|
||||
int GetNumLevels() const
|
||||
{
|
||||
int result = 0;
|
||||
if (Archive0)
|
||||
{
|
||||
result++;
|
||||
if (Archive1)
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; }
|
||||
UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; }
|
||||
const CArchiverInfo &GetArchiverInfo() { return Archive1 != 0 ? ArchiverInfo1: ArchiverInfo0; }
|
||||
HRESULT Close();
|
||||
void Release();
|
||||
};
|
||||
|
||||
HRESULT OpenArchive(const UString &archiveName,
|
||||
CArchiveLink &archiveLink,
|
||||
IArchiveOpenCallback *openCallback);
|
||||
|
||||
HRESULT MyOpenArchive(const UString &archiveName,
|
||||
CArchiveLink &archiveLink,
|
||||
IOpenCallbackUI *openCallbackUI);
|
||||
|
||||
HRESULT ReOpenArchive(CArchiveLink &archiveLink,
|
||||
const UString &fileName);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -14,13 +14,24 @@
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
static UString ConvertUINT32ToString(UINT32 value)
|
||||
static UString ConvertUInt32ToString(UInt32 value)
|
||||
{
|
||||
wchar_t buffer[32];
|
||||
ConvertUINT64ToString(value, buffer);
|
||||
ConvertUInt64ToString(value, buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void ConvertUInt32ToHex(UInt32 value, wchar_t *s)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
int t = value & 0xF;
|
||||
value >>= 4;
|
||||
s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10)));
|
||||
}
|
||||
s[8] = L'\0';
|
||||
}
|
||||
|
||||
UString ConvertPropertyToString(const PROPVARIANT &propVariant,
|
||||
PROPID propID, bool full)
|
||||
{
|
||||
@@ -38,22 +49,22 @@ UString ConvertPropertyToString(const PROPVARIANT &propVariant,
|
||||
return UString();
|
||||
if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime))
|
||||
return UString(); // It is error;
|
||||
return ConvertFileTimeToString2(localFileTime, true, full);
|
||||
return ConvertFileTimeToString(localFileTime, true, full);
|
||||
}
|
||||
case kpidCRC:
|
||||
{
|
||||
if(propVariant.vt != VT_UI4)
|
||||
break;
|
||||
TCHAR temp[17];
|
||||
wsprintf(temp, TEXT("%08X"), propVariant.ulVal);
|
||||
return GetUnicodeString(temp);
|
||||
wchar_t temp[12];
|
||||
ConvertUInt32ToHex(propVariant.ulVal, temp);
|
||||
return temp;
|
||||
}
|
||||
case kpidAttributes:
|
||||
{
|
||||
if(propVariant.vt != VT_UI4)
|
||||
break;
|
||||
UString result;
|
||||
UINT32 attributes = propVariant.ulVal;
|
||||
UInt32 attributes = propVariant.ulVal;
|
||||
if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R';
|
||||
if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H';
|
||||
if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S';
|
||||
@@ -67,12 +78,12 @@ UString ConvertPropertyToString(const PROPVARIANT &propVariant,
|
||||
{
|
||||
if(propVariant.vt != VT_UI4)
|
||||
break;
|
||||
UINT32 size = propVariant.ulVal;
|
||||
UInt32 size = propVariant.ulVal;
|
||||
if (size % (1 << 20) == 0)
|
||||
return ConvertUINT32ToString(size >> 20) + L"MB";
|
||||
return ConvertUInt32ToString(size >> 20) + L"MB";
|
||||
if (size % (1 << 10) == 0)
|
||||
return ConvertUINT32ToString(size >> 10) + L"KB";
|
||||
return ConvertUINT32ToString(size);
|
||||
return ConvertUInt32ToString(size >> 10) + L"KB";
|
||||
return ConvertUInt32ToString(size);
|
||||
}
|
||||
}
|
||||
return ConvertPropVariantToString(propVariant);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// PropIDUtils.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __PROPIDUTILS_H
|
||||
#define __PROPIDUTILS_H
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ static int __cdecl CompareStrings(const void *a1, const void *a2)
|
||||
return s1.CompareNoCase(s2);
|
||||
}
|
||||
|
||||
void SortStringsToIndices(UStringVector &strings, CIntVector &indices)
|
||||
void SortStringsToIndices(const UStringVector &strings, CIntVector &indices)
|
||||
{
|
||||
indices.Clear();
|
||||
if (strings.IsEmpty())
|
||||
@@ -22,9 +22,19 @@ void SortStringsToIndices(UStringVector &strings, CIntVector &indices)
|
||||
indices.Reserve(numItems);
|
||||
int i;
|
||||
for(i = 0; i < numItems; i++)
|
||||
pointers.Add(&strings.CPointerVector::operator[](i));
|
||||
pointers.Add((void *)&strings.CPointerVector::operator[](i));
|
||||
void **stringsBase = (void **)pointers[0];
|
||||
qsort(&pointers[0], numItems, sizeof(void *), CompareStrings);
|
||||
for(i = 0; i < numItems; i++)
|
||||
indices.Add((void **)pointers[i] - stringsBase);
|
||||
}
|
||||
|
||||
void SortStrings(const UStringVector &src, UStringVector &dest)
|
||||
{
|
||||
CIntVector indices;
|
||||
SortStringsToIndices(src, indices);
|
||||
dest.Clear();
|
||||
dest.Reserve(indices.Size());
|
||||
for (int i = 0; i < indices.Size(); i++)
|
||||
dest.Add(src[indices[i]]);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
// SortUtils.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __SORTUTLS_H
|
||||
#define __SORTUTLS_H
|
||||
|
||||
#include "Common/String.h"
|
||||
|
||||
void SortStringsToIndices(UStringVector &strings, CIntVector &indices);
|
||||
void SortStringsToIndices(const UStringVector &strings, CIntVector &indices);
|
||||
void SortStrings(const UStringVector &src, UStringVector &dest);
|
||||
|
||||
#endif
|
||||
|
||||
22
7zip/UI/Common/TempFiles.cpp
Executable file
22
7zip/UI/Common/TempFiles.cpp
Executable file
@@ -0,0 +1,22 @@
|
||||
// TempFiles.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "TempFiles.h"
|
||||
|
||||
#include "Windows/FileDir.h"
|
||||
#include "Windows/FileIO.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
|
||||
void CTempFiles::Clear()
|
||||
{
|
||||
while(!Paths.IsEmpty())
|
||||
{
|
||||
NDirectory::DeleteFileAlways(Paths.Back());
|
||||
Paths.DeleteBack();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
16
7zip/UI/Common/TempFiles.h
Executable file
16
7zip/UI/Common/TempFiles.h
Executable file
@@ -0,0 +1,16 @@
|
||||
// TempFiles.h
|
||||
|
||||
#ifndef __TEMPFILES_H
|
||||
#define __TEMPFILES_H
|
||||
|
||||
#include "Common/String.h"
|
||||
|
||||
class CTempFiles
|
||||
{
|
||||
void Clear();
|
||||
public:
|
||||
UStringVector Paths;
|
||||
~CTempFiles() { Clear(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
850
7zip/UI/Common/Update.cpp
Executable file
850
7zip/UI/Common/Update.cpp
Executable file
@@ -0,0 +1,850 @@
|
||||
// Update.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <mapi.h>
|
||||
#endif
|
||||
|
||||
#include "Update.h"
|
||||
|
||||
#include "Common/IntToString.h"
|
||||
#include "Common/StringToInt.h"
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/CommandLineParser.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Windows/DLL.h"
|
||||
#endif
|
||||
|
||||
#include "Windows/Defs.h"
|
||||
#include "Windows/FileDir.h"
|
||||
#include "Windows/FileFind.h"
|
||||
#include "Windows/FileName.h"
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/PropVariantConversions.h"
|
||||
// #include "Windows/Synchronization.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
#include "../../Compress/Copy/CopyCoder.h"
|
||||
|
||||
#include "../Common/DirItem.h"
|
||||
#include "../Common/EnumDirItems.h"
|
||||
#include "../Common/UpdateProduce.h"
|
||||
#include "../Common/OpenArchive.h"
|
||||
|
||||
#include "TempFiles.h"
|
||||
#include "UpdateCallback.h"
|
||||
#include "EnumDirItems.h"
|
||||
|
||||
#ifdef FORMAT_7Z
|
||||
#include "../../Archive/7z/7zHandler.h"
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_BZIP2
|
||||
#include "../../Archive/BZip2/BZip2Handler.h"
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_GZIP
|
||||
#include "../../Archive/GZip/GZipHandler.h"
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_TAR
|
||||
#include "../../Archive/Tar/TarHandler.h"
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_ZIP
|
||||
#include "../../Archive/Zip/ZipHandler.h"
|
||||
#endif
|
||||
|
||||
#ifndef EXCLUDE_COM
|
||||
#include "../Common/HandlerLoader.h"
|
||||
#endif
|
||||
|
||||
static const char *kUpdateIsNotSupoorted =
|
||||
"update operations are not supported for this archive";
|
||||
|
||||
using namespace NCommandLineParser;
|
||||
using namespace NWindows;
|
||||
using namespace NCOM;
|
||||
using namespace NFile;
|
||||
using namespace NName;
|
||||
|
||||
static const wchar_t *kTempArchiveFilePrefixString = L"7zi";
|
||||
static const wchar_t *kTempFolderPrefix = L"7zE";
|
||||
|
||||
static const char *kIllegalFileNameMessage = "Illegal file name for temp archive";
|
||||
|
||||
using namespace NUpdateArchive;
|
||||
|
||||
static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
|
||||
{
|
||||
const wchar_t *endPtr;
|
||||
UInt64 result = ConvertStringToUInt64(s, &endPtr);
|
||||
if (endPtr - (const wchar_t *)s != s.Length())
|
||||
prop = s;
|
||||
else if (result <= 0xFFFFFFFF)
|
||||
prop = (UInt32)result;
|
||||
else
|
||||
prop = result;
|
||||
}
|
||||
|
||||
static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream)
|
||||
{
|
||||
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
|
||||
return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
class COutMultiVolStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
size_t _streamIndex; // required stream
|
||||
UInt64 _offsetPos; // offset from start of _streamIndex index
|
||||
UInt64 _absPos;
|
||||
UInt64 _length;
|
||||
|
||||
struct CSubStreamInfo
|
||||
{
|
||||
CMyComPtr<IOutStream> Stream;
|
||||
UString Name;
|
||||
UInt64 Pos;
|
||||
UInt64 RealSize;
|
||||
};
|
||||
CObjectVector<CSubStreamInfo> Streams;
|
||||
public:
|
||||
// CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
|
||||
CRecordVector<UInt64> Sizes;
|
||||
UString Prefix;
|
||||
CTempFiles *TempFiles;
|
||||
|
||||
void Init()
|
||||
{
|
||||
_streamIndex = 0;
|
||||
_offsetPos = 0;
|
||||
_absPos = 0;
|
||||
_length = 0;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP1(IOutStream)
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
STDMETHOD(SetSize)(Int64 newSize);
|
||||
};
|
||||
|
||||
// static NSynchronization::CCriticalSection g_TempPathsCS;
|
||||
|
||||
STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if(processedSize != NULL)
|
||||
*processedSize = 0;
|
||||
while(size > 0)
|
||||
{
|
||||
if (_streamIndex >= (size_t)Streams.Size())
|
||||
{
|
||||
CSubStreamInfo subStream;
|
||||
|
||||
wchar_t temp[32];
|
||||
ConvertUInt64ToString(_streamIndex + 1, temp);
|
||||
UString res = temp;
|
||||
while (res.Length() < 3)
|
||||
res = UString(L'0') + res;
|
||||
UString name = Prefix + res;
|
||||
COutFileStream *streamSpec = new COutFileStream;
|
||||
subStream.Stream = streamSpec;
|
||||
if(!streamSpec->Create(name, false))
|
||||
return ::GetLastError();
|
||||
{
|
||||
// NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);
|
||||
TempFiles->Paths.Add(name);
|
||||
}
|
||||
|
||||
subStream.Pos = 0;
|
||||
subStream.RealSize = 0;
|
||||
subStream.Name = name;
|
||||
Streams.Add(subStream);
|
||||
continue;
|
||||
}
|
||||
CSubStreamInfo &subStream = Streams[_streamIndex];
|
||||
|
||||
int index = _streamIndex;
|
||||
if (index >= Sizes.Size())
|
||||
index = Sizes.Size() - 1;
|
||||
UInt64 volSize = Sizes[index];
|
||||
|
||||
if (_offsetPos >= volSize)
|
||||
{
|
||||
_offsetPos -= volSize;
|
||||
_streamIndex++;
|
||||
continue;
|
||||
}
|
||||
if (_offsetPos != subStream.Pos)
|
||||
{
|
||||
// CMyComPtr<IOutStream> outStream;
|
||||
// RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
|
||||
RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
|
||||
subStream.Pos = _offsetPos;
|
||||
}
|
||||
|
||||
UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos);
|
||||
UInt32 realProcessed;
|
||||
RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
|
||||
data = (void *)((Byte *)data + realProcessed);
|
||||
size -= realProcessed;
|
||||
subStream.Pos += realProcessed;
|
||||
_offsetPos += realProcessed;
|
||||
_absPos += realProcessed;
|
||||
if (_absPos > _length)
|
||||
_length = _absPos;
|
||||
if (_offsetPos > subStream.RealSize)
|
||||
subStream.RealSize = _offsetPos;
|
||||
if(processedSize != NULL)
|
||||
*processedSize += realProcessed;
|
||||
if (subStream.Pos == volSize)
|
||||
{
|
||||
_streamIndex++;
|
||||
_offsetPos = 0;
|
||||
}
|
||||
if (realProcessed != curSize)
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMultiVolStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Write(data, size, processedSize);
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if(seekOrigin >= 3)
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
switch(seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET:
|
||||
_absPos = offset;
|
||||
break;
|
||||
case STREAM_SEEK_CUR:
|
||||
_absPos += offset;
|
||||
break;
|
||||
case STREAM_SEEK_END:
|
||||
_absPos = _length + offset;
|
||||
break;
|
||||
}
|
||||
_offsetPos = _absPos;
|
||||
if (newPosition != NULL)
|
||||
*newPosition = _absPos;
|
||||
_streamIndex = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize)
|
||||
{
|
||||
if (newSize < 0)
|
||||
return E_INVALIDARG;
|
||||
int i = 0;
|
||||
while (i < Streams.Size())
|
||||
{
|
||||
CSubStreamInfo &subStream = Streams[i++];
|
||||
if ((UInt64)newSize < subStream.RealSize)
|
||||
{
|
||||
RINOK(subStream.Stream->SetSize(newSize));
|
||||
subStream.RealSize = newSize;
|
||||
break;
|
||||
}
|
||||
newSize -= subStream.RealSize;
|
||||
}
|
||||
while (i < Streams.Size())
|
||||
{
|
||||
{
|
||||
CSubStreamInfo &subStream = Streams.Back();
|
||||
subStream.Stream.Release();
|
||||
NDirectory::DeleteFileAlways(subStream.Name);
|
||||
}
|
||||
Streams.DeleteBack();
|
||||
}
|
||||
_offsetPos = _absPos;
|
||||
_streamIndex = 0;
|
||||
_length = newSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static HRESULT Compress(
|
||||
const CActionSet &actionSet,
|
||||
IInArchive *archive,
|
||||
const CCompressionMethodMode &compressionMethod,
|
||||
CArchivePath &archivePath,
|
||||
const CObjectVector<CArchiveItem> &archiveItems,
|
||||
bool stdInMode,
|
||||
const UString &stdInFileName,
|
||||
bool stdOutMode,
|
||||
const CObjectVector<CDirItem> &dirItems,
|
||||
bool sfxMode,
|
||||
const UString &sfxModule,
|
||||
const CRecordVector<UInt64> &volumesSizes,
|
||||
CTempFiles &tempFiles,
|
||||
CUpdateErrorInfo &errorInfo,
|
||||
IUpdateCallbackUI *callback)
|
||||
{
|
||||
#ifndef EXCLUDE_COM
|
||||
CHandlerLoader loader;
|
||||
#endif
|
||||
|
||||
CMyComPtr<IOutArchive> outArchive;
|
||||
if(archive != NULL)
|
||||
{
|
||||
CMyComPtr<IInArchive> archive2 = archive;
|
||||
HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
|
||||
if(result != S_OK)
|
||||
throw kUpdateIsNotSupoorted;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef EXCLUDE_COM
|
||||
|
||||
if (loader.CreateHandler(compressionMethod.FilePath,
|
||||
compressionMethod.ClassID, (void **)&outArchive, true) != S_OK)
|
||||
throw kUpdateIsNotSupoorted;
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_7Z
|
||||
if (compressionMethod.Name.CompareNoCase(L"7z") == 0)
|
||||
outArchive = new NArchive::N7z::CHandler;
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_BZIP2
|
||||
if (compressionMethod.Name.CompareNoCase(L"BZip2") == 0)
|
||||
outArchive = new NArchive::NBZip2::CHandler;
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_GZIP
|
||||
if (compressionMethod.Name.CompareNoCase(L"GZip") == 0)
|
||||
outArchive = new NArchive::NGZip::CHandler;
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_TAR
|
||||
if (compressionMethod.Name.CompareNoCase(L"Tar") == 0)
|
||||
outArchive = new NArchive::NTar::CHandler;
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_ZIP
|
||||
if (compressionMethod.Name.CompareNoCase(L"Zip") == 0)
|
||||
outArchive = new NArchive::NZip::CHandler;
|
||||
#endif
|
||||
|
||||
}
|
||||
if (outArchive == 0)
|
||||
throw kUpdateIsNotSupoorted;
|
||||
|
||||
NFileTimeType::EEnum fileTimeType;
|
||||
UInt32 value;
|
||||
RINOK(outArchive->GetFileTimeType(&value));
|
||||
|
||||
switch(value)
|
||||
{
|
||||
case NFileTimeType::kWindows:
|
||||
case NFileTimeType::kDOS:
|
||||
case NFileTimeType::kUnix:
|
||||
fileTimeType = NFileTimeType::EEnum(value);
|
||||
break;
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
CObjectVector<CUpdatePair> updatePairs;
|
||||
GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs); // must be done only once!!!
|
||||
|
||||
CObjectVector<CUpdatePair2> updatePairs2;
|
||||
UpdateProduce(dirItems, archiveItems, updatePairs, actionSet, updatePairs2);
|
||||
|
||||
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
|
||||
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec );
|
||||
|
||||
updateCallbackSpec->StdInMode = stdInMode;
|
||||
updateCallbackSpec->Callback = callback;
|
||||
updateCallbackSpec->DirItems = &dirItems;
|
||||
updateCallbackSpec->ArchiveItems = &archiveItems;
|
||||
updateCallbackSpec->UpdatePairs = &updatePairs2;
|
||||
|
||||
CMyComPtr<ISequentialOutStream> outStream;
|
||||
|
||||
const UString &archiveName = archivePath.GetFinalPath();
|
||||
if (!stdOutMode)
|
||||
{
|
||||
UString resultPath;
|
||||
int pos;
|
||||
if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
|
||||
throw 1417161;
|
||||
NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
|
||||
}
|
||||
if (volumesSizes.Size() == 0)
|
||||
{
|
||||
if (stdOutMode)
|
||||
outStream = new CStdOutFileStream;
|
||||
else
|
||||
{
|
||||
COutFileStream *outStreamSpec = new COutFileStream;
|
||||
outStream = outStreamSpec;
|
||||
bool isOK = false;
|
||||
UString realPath;
|
||||
for (int i = 0; i < (1 << 16); i++)
|
||||
{
|
||||
if (archivePath.Temp)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
wchar_t s[32];
|
||||
ConvertUInt64ToString(i, s);
|
||||
archivePath.TempPostfix = s;
|
||||
}
|
||||
realPath = archivePath.GetTempPath();
|
||||
}
|
||||
else
|
||||
realPath = archivePath.GetFinalPath();
|
||||
if (outStreamSpec->Create(realPath, false))
|
||||
{
|
||||
tempFiles.Paths.Add(realPath);
|
||||
isOK = true;
|
||||
break;
|
||||
}
|
||||
if (::GetLastError() != ERROR_FILE_EXISTS)
|
||||
break;
|
||||
if (!archivePath.Temp)
|
||||
break;
|
||||
}
|
||||
if (!isOK)
|
||||
{
|
||||
errorInfo.SystemError = ::GetLastError();
|
||||
errorInfo.FileName = realPath;
|
||||
errorInfo.Message = L"Can not open file";
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stdOutMode)
|
||||
return E_FAIL;
|
||||
COutMultiVolStream *volStreamSpec = new COutMultiVolStream;
|
||||
outStream = volStreamSpec;
|
||||
volStreamSpec->Sizes = volumesSizes;
|
||||
volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L".");
|
||||
volStreamSpec->TempFiles = &tempFiles;
|
||||
volStreamSpec->Init();
|
||||
|
||||
/*
|
||||
updateCallbackSpec->VolumesSizes = volumesSizes;
|
||||
updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
|
||||
if (!archivePath.VolExtension.IsEmpty())
|
||||
updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension;
|
||||
*/
|
||||
}
|
||||
|
||||
CMyComPtr<ISetProperties> setProperties;
|
||||
if (outArchive.QueryInterface(IID_ISetProperties, &setProperties) == S_OK)
|
||||
{
|
||||
UStringVector realNames;
|
||||
CPropVariant *values = new CPropVariant[compressionMethod.Properties.Size()];
|
||||
try
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < compressionMethod.Properties.Size(); i++)
|
||||
{
|
||||
const CProperty &property = compressionMethod.Properties[i];
|
||||
NCOM::CPropVariant propVariant;
|
||||
if (!property.Value.IsEmpty())
|
||||
ParseNumberString(property.Value, propVariant);
|
||||
realNames.Add(property.Name);
|
||||
values[i] = propVariant;
|
||||
}
|
||||
CRecordVector<const wchar_t *> names;
|
||||
for(i = 0; i < realNames.Size(); i++)
|
||||
names.Add((const wchar_t *)realNames[i]);
|
||||
|
||||
RINOK(setProperties->SetProperties(&names.Front(), values, names.Size()));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
delete []values;
|
||||
throw;
|
||||
}
|
||||
delete []values;
|
||||
}
|
||||
|
||||
if (sfxMode)
|
||||
{
|
||||
CInFileStream *sfxStreamSpec = new CInFileStream;
|
||||
CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
|
||||
if (!sfxStreamSpec->Open(sfxModule))
|
||||
{
|
||||
errorInfo.SystemError = ::GetLastError();
|
||||
errorInfo.Message = L"Can't open sfx module";
|
||||
errorInfo.FileName = sfxModule;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
CMyComPtr<ISequentialOutStream> sfxOutStream;
|
||||
if (volumesSizes.Size() == 0)
|
||||
sfxOutStream = outStream;
|
||||
else
|
||||
{
|
||||
COutFileStream *outStreamSpec = new COutFileStream;
|
||||
sfxOutStream = outStreamSpec;
|
||||
UString realPath = archivePath.GetFinalPath();
|
||||
if (!outStreamSpec->Create(realPath, false))
|
||||
{
|
||||
errorInfo.SystemError = ::GetLastError();
|
||||
errorInfo.FileName = realPath;
|
||||
errorInfo.Message = L"Can not open file";
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
RINOK(CopyBlock(sfxStream, sfxOutStream));
|
||||
}
|
||||
|
||||
HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(),
|
||||
updateCallback);
|
||||
callback->Finilize();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
|
||||
IInArchive *archive,
|
||||
const UString &defaultItemName,
|
||||
const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
|
||||
CObjectVector<CArchiveItem> &archiveItems)
|
||||
{
|
||||
archiveItems.Clear();
|
||||
UInt32 numItems;
|
||||
RINOK(archive->GetNumberOfItems(&numItems));
|
||||
archiveItems.Reserve(numItems);
|
||||
for(UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
CArchiveItem ai;
|
||||
|
||||
RINOK(GetArchiveItemPath(archive, i, defaultItemName, ai.Name));
|
||||
RINOK(IsArchiveItemFolder(archive, i, ai.IsDirectory));
|
||||
ai.Censored = censor.CheckPath(ai.Name, !ai.IsDirectory);
|
||||
RINOK(GetArchiveItemFileTime(archive, i,
|
||||
archiveFileInfo.LastWriteTime, ai.LastWriteTime));
|
||||
|
||||
CPropVariant propertySize;
|
||||
RINOK(archive->GetProperty(i, kpidSize, &propertySize));
|
||||
if (ai.SizeIsDefined = (propertySize.vt != VT_EMPTY))
|
||||
ai.Size = ConvertPropVariantToUInt64(propertySize);
|
||||
|
||||
ai.IndexInServer = i;
|
||||
archiveItems.Add(ai);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static HRESULT UpdateWithItemLists(
|
||||
CUpdateOptions &options,
|
||||
IInArchive *archive,
|
||||
const CObjectVector<CArchiveItem> &archiveItems,
|
||||
const CObjectVector<CDirItem> &dirItems,
|
||||
CTempFiles &tempFiles,
|
||||
CUpdateErrorInfo &errorInfo,
|
||||
IUpdateCallbackUI2 *callback)
|
||||
{
|
||||
for(int i = 0; i < options.Commands.Size(); i++)
|
||||
{
|
||||
CUpdateArchiveCommand &command = options.Commands[i];
|
||||
if (options.StdOutMode)
|
||||
{
|
||||
RINOK(callback->StartArchive(0, archive != 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(),
|
||||
i == 0 && options.UpdateArchiveItself && archive != 0));
|
||||
}
|
||||
|
||||
RINOK(Compress(command.ActionSet, archive,
|
||||
options.MethodMode,
|
||||
command.ArchivePath,
|
||||
archiveItems,
|
||||
options.StdInMode, options.StdInFileName,
|
||||
options.StdOutMode,
|
||||
dirItems,
|
||||
options.SfxMode, options.SfxModule,
|
||||
options.VolumesSizes,
|
||||
tempFiles,
|
||||
errorInfo, callback));
|
||||
|
||||
RINOK(callback->FinishArchive());
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
class CCurrentDirRestorer
|
||||
{
|
||||
CSysString m_CurrentDirectory;
|
||||
public:
|
||||
CCurrentDirRestorer()
|
||||
{ NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); }
|
||||
~CCurrentDirRestorer()
|
||||
{ RestoreDirectory();}
|
||||
bool RestoreDirectory()
|
||||
{ return BOOLToBool(::SetCurrentDirectory(m_CurrentDirectory)); }
|
||||
};
|
||||
#endif
|
||||
|
||||
struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback
|
||||
{
|
||||
IUpdateCallbackUI2 *Callback;
|
||||
HRESULT CheckBreak() { return Callback->CheckBreak(); }
|
||||
};
|
||||
|
||||
HRESULT UpdateArchive(const NWildcard::CCensor &censor,
|
||||
CUpdateOptions &options,
|
||||
CUpdateErrorInfo &errorInfo,
|
||||
IOpenCallbackUI *openCallback,
|
||||
IUpdateCallbackUI2 *callback)
|
||||
{
|
||||
if (options.StdOutMode && options.EMailMode)
|
||||
return E_FAIL;
|
||||
|
||||
if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode))
|
||||
return E_NOTIMPL;
|
||||
|
||||
if (options.SfxMode)
|
||||
{
|
||||
CProperty property;
|
||||
property.Name = L"rsfx";
|
||||
property.Value = L"on";
|
||||
options.MethodMode.Properties.Add(property);
|
||||
if (options.SfxModule.IsEmpty())
|
||||
{
|
||||
errorInfo.Message = L"sfx file is not specified";
|
||||
return E_FAIL;
|
||||
}
|
||||
UString name = options.SfxModule;
|
||||
if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule))
|
||||
{
|
||||
errorInfo.Message = L"can't find specified sfx module";
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
const UString archiveName = options.ArchivePath.GetFinalPath();
|
||||
|
||||
UString defaultItemName;
|
||||
NFind::CFileInfoW archiveFileInfo;
|
||||
|
||||
CArchiveLink archiveLink;
|
||||
IInArchive *archive = 0;
|
||||
if (NFind::FindFile(archiveName, archiveFileInfo))
|
||||
{
|
||||
if (archiveFileInfo.IsDirectory())
|
||||
throw "there is no such archive";
|
||||
if (options.VolumesSizes.Size() > 0)
|
||||
return E_NOTIMPL;
|
||||
HRESULT result = MyOpenArchive(archiveName, archiveLink, openCallback);
|
||||
RINOK(callback->OpenResult(archiveName, result));
|
||||
RINOK(result);
|
||||
if (archiveLink.VolumePaths.Size() > 1)
|
||||
{
|
||||
errorInfo.SystemError = E_NOTIMPL;
|
||||
errorInfo.Message = L"Updating for multivolume archives is not implemented";
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
archive = archiveLink.GetArchive();
|
||||
defaultItemName = archiveLink.GetDefaultItemName();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
if (archiveType.IsEmpty())
|
||||
throw "type of archive is not specified";
|
||||
*/
|
||||
}
|
||||
|
||||
CObjectVector<CDirItem> dirItems;
|
||||
if (options.StdInMode)
|
||||
{
|
||||
CDirItem item;
|
||||
item.FullPath = item.Name = options.StdInFileName;
|
||||
item.Size = (UInt64)(Int64)-1;
|
||||
item.Attributes = 0;
|
||||
SYSTEMTIME st;
|
||||
FILETIME ft;
|
||||
GetSystemTime(&st);
|
||||
SystemTimeToFileTime(&st, &ft);
|
||||
item.CreationTime = item.LastAccessTime = item.LastWriteTime = ft;
|
||||
dirItems.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool needScanning = false;
|
||||
for(int i = 0; i < options.Commands.Size(); i++)
|
||||
if (options.Commands[i].ActionSet.NeedScanning())
|
||||
needScanning = true;
|
||||
if (needScanning)
|
||||
{
|
||||
CEnumDirItemUpdateCallback enumCallback;
|
||||
enumCallback.Callback = callback;
|
||||
RINOK(callback->StartScanning());
|
||||
RINOK(EnumerateItems(censor, dirItems, &enumCallback));
|
||||
RINOK(callback->FinishScanning());
|
||||
}
|
||||
}
|
||||
|
||||
UString tempDirPrefix;
|
||||
bool usesTempDir = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
NDirectory::CTempDirectoryW tempDirectory;
|
||||
if (options.EMailMode && options.EMailRemoveAfter)
|
||||
{
|
||||
tempDirectory.Create(kTempFolderPrefix);
|
||||
tempDirPrefix = tempDirectory.GetPath();
|
||||
NormalizeDirPathPrefix(tempDirPrefix);
|
||||
usesTempDir = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
CTempFiles tempFiles;
|
||||
|
||||
bool createTempFile = false;
|
||||
if(!options.StdOutMode && options.UpdateArchiveItself)
|
||||
{
|
||||
CArchivePath &ap = options.Commands[0].ArchivePath;
|
||||
ap = options.ArchivePath;
|
||||
// if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty())
|
||||
if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0)
|
||||
{
|
||||
createTempFile = true;
|
||||
ap.Temp = true;
|
||||
if (!options.WorkingDir.IsEmpty())
|
||||
{
|
||||
ap.TempPrefix = options.WorkingDir;
|
||||
NormalizeDirPathPrefix(ap.TempPrefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < options.Commands.Size(); i++)
|
||||
{
|
||||
CArchivePath &ap = options.Commands[i].ArchivePath;
|
||||
if (usesTempDir)
|
||||
{
|
||||
// Check it
|
||||
ap.Prefix = tempDirPrefix;
|
||||
// ap.Temp = true;
|
||||
// ap.TempPrefix = tempDirPrefix;
|
||||
}
|
||||
if (i > 0 || !createTempFile)
|
||||
{
|
||||
const UString &path = ap.GetFinalPath();
|
||||
if (NFind::DoesFileExist(path))
|
||||
{
|
||||
errorInfo.SystemError = 0;
|
||||
errorInfo.Message = L"File already exists";
|
||||
errorInfo.FileName = path;
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CObjectVector<CArchiveItem> archiveItems;
|
||||
if (archive != NULL)
|
||||
{
|
||||
RINOK(EnumerateInArchiveItems(censor,
|
||||
archive, defaultItemName, archiveFileInfo, archiveItems));
|
||||
}
|
||||
|
||||
RINOK(UpdateWithItemLists(options, archive, archiveItems, dirItems,
|
||||
tempFiles, errorInfo, callback));
|
||||
|
||||
if (archive != NULL)
|
||||
{
|
||||
RINOK(archiveLink.Close());
|
||||
archiveLink.Release();
|
||||
}
|
||||
|
||||
tempFiles.Paths.Clear();
|
||||
if(createTempFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
CArchivePath &ap = options.Commands[0].ArchivePath;
|
||||
const UString &tempPath = ap.GetTempPath();
|
||||
if (archive != NULL)
|
||||
if (!NDirectory::DeleteFileAlways(archiveName))
|
||||
{
|
||||
errorInfo.SystemError = ::GetLastError();
|
||||
errorInfo.Message = L"delete file error";
|
||||
errorInfo.FileName = archiveName;
|
||||
return E_FAIL;
|
||||
}
|
||||
if (!NDirectory::MyMoveFile(tempPath, archiveName))
|
||||
{
|
||||
errorInfo.SystemError = ::GetLastError();
|
||||
errorInfo.Message = L"move file error";
|
||||
errorInfo.FileName = tempPath;
|
||||
errorInfo.FileName2 = archiveName;
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (options.EMailMode)
|
||||
{
|
||||
NDLL::CLibrary mapiLib;
|
||||
if (!mapiLib.Load(TEXT("Mapi32.dll")))
|
||||
{
|
||||
errorInfo.SystemError = ::GetLastError();
|
||||
errorInfo.Message = L"can not load Mapi32.dll";
|
||||
return E_FAIL;
|
||||
}
|
||||
LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)
|
||||
mapiLib.GetProcAddress("MAPISendDocuments");
|
||||
if (fnSend == 0)
|
||||
{
|
||||
errorInfo.SystemError = ::GetLastError();
|
||||
errorInfo.Message = L"can not find MAPISendDocuments function";
|
||||
return E_FAIL;
|
||||
}
|
||||
UStringVector fullPaths;
|
||||
int i;
|
||||
for(i = 0; i < options.Commands.Size(); i++)
|
||||
{
|
||||
CArchivePath &ap = options.Commands[i].ArchivePath;
|
||||
UString arcPath;
|
||||
if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath))
|
||||
{
|
||||
errorInfo.SystemError = ::GetLastError();
|
||||
return E_FAIL;
|
||||
}
|
||||
fullPaths.Add(arcPath);
|
||||
}
|
||||
CCurrentDirRestorer curDirRestorer;
|
||||
for(i = 0; i < fullPaths.Size(); i++)
|
||||
{
|
||||
UString arcPath = fullPaths[i];
|
||||
UString fileName = ExtractFileNameFromPath(arcPath);
|
||||
AString path = GetAnsiString(arcPath);
|
||||
AString name = GetAnsiString(fileName);
|
||||
// Warning!!! MAPISendDocuments function changes Current directory
|
||||
fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
157
7zip/UI/Common/Update.h
Executable file
157
7zip/UI/Common/Update.h
Executable file
@@ -0,0 +1,157 @@
|
||||
// Update.h
|
||||
|
||||
#ifndef __UPDATE_H
|
||||
#define __UPDATE_H
|
||||
|
||||
#include "Common/Wildcard.h"
|
||||
#include "Windows/FileFind.h"
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
#include "UpdateAction.h"
|
||||
#include "ArchiveOpenCallback.h"
|
||||
#include "UpdateCallback.h"
|
||||
|
||||
struct CArchivePath
|
||||
{
|
||||
UString Prefix; // path(folder) prefix including slash
|
||||
UString Name; // base name
|
||||
UString BaseExtension; // archive type extension or "exe" extension
|
||||
UString VolExtension; // archive type extension for volumes
|
||||
|
||||
bool Temp;
|
||||
UString TempPrefix; // path(folder) for temp location
|
||||
UString TempPostfix;
|
||||
|
||||
CArchivePath(): Temp(false) {};
|
||||
|
||||
void ParseFromPath(const UString &path)
|
||||
{
|
||||
SplitPathToParts(path, Prefix, Name);
|
||||
if (Name.IsEmpty())
|
||||
return;
|
||||
int dotPos = Name.ReverseFind(L'.');
|
||||
if (dotPos < 0)
|
||||
return;
|
||||
if (dotPos == Name.Length() - 1)
|
||||
{
|
||||
Name = Name.Left(dotPos);
|
||||
BaseExtension.Empty();
|
||||
return;
|
||||
}
|
||||
if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0)
|
||||
Name = Name.Left(dotPos);
|
||||
else
|
||||
BaseExtension.Empty();
|
||||
}
|
||||
|
||||
UString GetPathWithoutExt() const
|
||||
{
|
||||
return Prefix + Name;
|
||||
}
|
||||
|
||||
UString GetFinalPath() const
|
||||
{
|
||||
UString path = GetPathWithoutExt();
|
||||
if (!BaseExtension.IsEmpty())
|
||||
path += UString(L'.') + BaseExtension;
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
UString GetTempPath() const
|
||||
{
|
||||
UString path = TempPrefix + Name;
|
||||
if (!BaseExtension.IsEmpty())
|
||||
path += UString(L'.') + BaseExtension;
|
||||
path += L".tmp";
|
||||
path += TempPostfix;
|
||||
return path;
|
||||
}
|
||||
};
|
||||
|
||||
struct CUpdateArchiveCommand
|
||||
{
|
||||
CArchivePath ArchivePath;
|
||||
NUpdateArchive::CActionSet ActionSet;
|
||||
};
|
||||
|
||||
struct CProperty
|
||||
{
|
||||
UString Name;
|
||||
UString Value;
|
||||
};
|
||||
|
||||
struct CCompressionMethodMode
|
||||
{
|
||||
#ifndef EXCLUDE_COM
|
||||
UString FilePath;
|
||||
CLSID ClassID;
|
||||
#else
|
||||
UString Name;
|
||||
#endif
|
||||
CObjectVector<CProperty> Properties;
|
||||
};
|
||||
|
||||
struct CUpdateOptions
|
||||
{
|
||||
CCompressionMethodMode MethodMode;
|
||||
|
||||
CObjectVector<CUpdateArchiveCommand> Commands;
|
||||
bool UpdateArchiveItself;
|
||||
CArchivePath ArchivePath;
|
||||
|
||||
bool SfxMode;
|
||||
UString SfxModule;
|
||||
|
||||
bool StdInMode;
|
||||
UString StdInFileName;
|
||||
bool StdOutMode;
|
||||
|
||||
bool EMailMode;
|
||||
bool EMailRemoveAfter;
|
||||
UString EMailAddress;
|
||||
|
||||
UString WorkingDir;
|
||||
|
||||
CUpdateOptions():
|
||||
UpdateArchiveItself(true),
|
||||
SfxMode(false),
|
||||
StdInMode(false),
|
||||
StdOutMode(false),
|
||||
EMailMode(false),
|
||||
EMailRemoveAfter(false)
|
||||
{};
|
||||
CRecordVector<UInt64> VolumesSizes;
|
||||
};
|
||||
|
||||
struct CErrorInfo
|
||||
{
|
||||
DWORD SystemError;
|
||||
UString FileName;
|
||||
UString FileName2;
|
||||
UString Message;
|
||||
CErrorInfo(): SystemError(0) {};
|
||||
};
|
||||
|
||||
struct CUpdateErrorInfo: public CErrorInfo
|
||||
{
|
||||
};
|
||||
|
||||
struct IUpdateCallbackUI2: public IUpdateCallbackUI
|
||||
{
|
||||
virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) = 0;
|
||||
|
||||
virtual HRESULT StartScanning() = 0;
|
||||
virtual HRESULT FinishScanning() = 0;
|
||||
|
||||
virtual HRESULT StartArchive(const wchar_t *name, bool updating) = 0;
|
||||
virtual HRESULT FinishArchive() = 0;
|
||||
};
|
||||
|
||||
HRESULT UpdateArchive(const NWildcard::CCensor &censor,
|
||||
CUpdateOptions &options,
|
||||
CUpdateErrorInfo &errorInfo,
|
||||
IOpenCallbackUI *openCallback,
|
||||
IUpdateCallbackUI2 *callback);
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,5 @@
|
||||
// UpdateAction.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __UPDATE_ACTION_H
|
||||
#define __UPDATE_ACTION_H
|
||||
|
||||
@@ -34,6 +32,17 @@ namespace NUpdateArchive {
|
||||
struct CActionSet
|
||||
{
|
||||
NPairAction::EEnum StateActions[NPairState::kNumValues];
|
||||
bool NeedScanning() const
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NPairState::kNumValues; i++)
|
||||
if (StateActions[i] == NPairAction::kCompress)
|
||||
return true;
|
||||
for (i = 1; i < NPairState::kNumValues; i++)
|
||||
if (StateActions[i] != NPairAction::kIgnore)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
extern const CActionSet kAddActionSet;
|
||||
extern const CActionSet kUpdateActionSet;
|
||||
|
||||
242
7zip/UI/Common/UpdateCallback.cpp
Executable file
242
7zip/UI/Common/UpdateCallback.cpp
Executable file
@@ -0,0 +1,242 @@
|
||||
// UpdateCallback.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "UpdateCallback.h"
|
||||
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/IntToString.h"
|
||||
#include "Common/Defs.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
CArchiveUpdateCallback::CArchiveUpdateCallback():
|
||||
Callback(0),
|
||||
StdInMode(false),
|
||||
DirItems(0),
|
||||
ArchiveItems(0),
|
||||
UpdatePairs(0)
|
||||
{}
|
||||
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)
|
||||
{
|
||||
return Callback->SetTotal(size);
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)
|
||||
{
|
||||
return Callback->SetCompleted(completeValue);
|
||||
}
|
||||
|
||||
/*
|
||||
STATPROPSTG kProperties[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidIsFolder, VT_BOOL},
|
||||
{ NULL, kpidSize, VT_UI8},
|
||||
{ NULL, kpidLastAccessTime, VT_FILETIME},
|
||||
{ NULL, kpidCreationTime, VT_FILETIME},
|
||||
{ NULL, kpidLastWriteTime, VT_FILETIME},
|
||||
{ NULL, kpidAttributes, VT_UI4},
|
||||
{ NULL, kpidIsAnti, VT_BOOL}
|
||||
};
|
||||
*/
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **enumerator)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
/*
|
||||
return CStatPropEnumerator::CreateEnumerator(kProperties,
|
||||
sizeof(kProperties) / sizeof(kProperties[0]), enumerator);
|
||||
*/
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
|
||||
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
|
||||
{
|
||||
RINOK(Callback->CheckBreak());
|
||||
const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
|
||||
if(newData != NULL)
|
||||
*newData = BoolToInt(updatePair.NewData);
|
||||
if(newProperties != NULL)
|
||||
*newProperties = BoolToInt(updatePair.NewProperties);
|
||||
if(indexInArchive != NULL)
|
||||
{
|
||||
if (updatePair.ExistInArchive)
|
||||
{
|
||||
if (ArchiveItems == 0)
|
||||
*indexInArchive = updatePair.ArchiveItemIndex;
|
||||
else
|
||||
*indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
|
||||
}
|
||||
else
|
||||
*indexInArchive = UInt32(-1);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
|
||||
NWindows::NCOM::CPropVariant propVariant;
|
||||
|
||||
if (propID == kpidIsAnti)
|
||||
{
|
||||
propVariant = updatePair.IsAnti;
|
||||
propVariant.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (updatePair.IsAnti)
|
||||
{
|
||||
switch(propID)
|
||||
{
|
||||
case kpidIsFolder:
|
||||
case kpidPath:
|
||||
break;
|
||||
case kpidSize:
|
||||
propVariant = (UInt64)0;
|
||||
propVariant.Detach(value);
|
||||
return S_OK;
|
||||
default:
|
||||
propVariant.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if(updatePair.ExistOnDisk)
|
||||
{
|
||||
const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex];
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPath:
|
||||
propVariant = dirItem.Name;
|
||||
break;
|
||||
case kpidIsFolder:
|
||||
propVariant = dirItem.IsDirectory();
|
||||
break;
|
||||
case kpidSize:
|
||||
propVariant = dirItem.Size;
|
||||
break;
|
||||
case kpidAttributes:
|
||||
propVariant = dirItem.Attributes;
|
||||
break;
|
||||
case kpidLastAccessTime:
|
||||
propVariant = dirItem.LastAccessTime;
|
||||
break;
|
||||
case kpidCreationTime:
|
||||
propVariant = dirItem.CreationTime;
|
||||
break;
|
||||
case kpidLastWriteTime:
|
||||
propVariant = dirItem.LastWriteTime;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (propID == kpidPath)
|
||||
{
|
||||
if (updatePair.NewNameIsDefined)
|
||||
{
|
||||
propVariant = updatePair.NewName;
|
||||
propVariant.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
if (updatePair.ExistInArchive && Archive)
|
||||
{
|
||||
UInt32 indexInArchive;
|
||||
if (ArchiveItems == 0)
|
||||
indexInArchive = updatePair.ArchiveItemIndex;
|
||||
else
|
||||
indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
|
||||
return Archive->GetProperty(indexInArchive, propID, value);
|
||||
}
|
||||
}
|
||||
propVariant.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index,
|
||||
ISequentialInStream **inStream)
|
||||
{
|
||||
const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
|
||||
if(!updatePair.NewData)
|
||||
return E_FAIL;
|
||||
|
||||
RINOK(Callback->CheckBreak());
|
||||
RINOK(Callback->Finilize());
|
||||
|
||||
if(updatePair.IsAnti)
|
||||
{
|
||||
return Callback->GetStream((*ArchiveItems)[updatePair.ArchiveItemIndex].Name, true);
|
||||
}
|
||||
const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex];
|
||||
RINOK(Callback->GetStream(dirItem.Name, false));
|
||||
|
||||
if(dirItem.IsDirectory())
|
||||
return S_OK;
|
||||
|
||||
if (StdInMode)
|
||||
{
|
||||
CStdInFileStream *inStreamSpec = new CStdInFileStream;
|
||||
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
|
||||
*inStream = inStreamLoc.Detach();
|
||||
}
|
||||
else
|
||||
{
|
||||
CInFileStream *inStreamSpec = new CInFileStream;
|
||||
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
|
||||
UString path = DirPrefix + dirItem.FullPath;
|
||||
if(!inStreamSpec->Open(path))
|
||||
{
|
||||
return Callback->OpenFileError(path, ::GetLastError());
|
||||
}
|
||||
*inStream = inStreamLoc.Detach();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult)
|
||||
{
|
||||
return Callback->SetOperationResult(operationResult);
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
|
||||
{
|
||||
if (VolumesSizes.Size() == 0)
|
||||
return S_FALSE;
|
||||
if (index >= (UInt32)VolumesSizes.Size())
|
||||
index = VolumesSizes.Size() - 1;
|
||||
*size = VolumesSizes[index];
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
|
||||
{
|
||||
wchar_t temp[32];
|
||||
ConvertUInt64ToString(index + 1, temp);
|
||||
UString res = temp;
|
||||
while (res.Length() < 2)
|
||||
res = UString(L'0') + res;
|
||||
UString fileName = VolName;
|
||||
fileName += L'.';
|
||||
fileName += res;
|
||||
fileName += VolExt;
|
||||
COutFileStream *streamSpec = new COutFileStream;
|
||||
CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
|
||||
if(!streamSpec->Create(fileName, false))
|
||||
return ::GetLastError();
|
||||
*volumeStream = streamLoc.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
|
||||
{
|
||||
return Callback->CryptoGetTextPassword2(passwordIsDefined, password);
|
||||
}
|
||||
70
7zip/UI/Common/UpdateCallback.h
Executable file
70
7zip/UI/Common/UpdateCallback.h
Executable file
@@ -0,0 +1,70 @@
|
||||
// UpdateCallback.h
|
||||
|
||||
#ifndef __UPDATECALLBACK_H
|
||||
#define __UPDATECALLBACK_H
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "Common/String.h"
|
||||
|
||||
#include "../../IPassword.h"
|
||||
|
||||
#include "../Common/UpdatePair.h"
|
||||
#include "../Common/UpdateProduce.h"
|
||||
|
||||
struct IUpdateCallbackUI
|
||||
{
|
||||
virtual HRESULT SetTotal(UInt64 size) = 0;
|
||||
virtual HRESULT SetCompleted(const UInt64 *completeValue) = 0;
|
||||
virtual HRESULT CheckBreak() = 0;
|
||||
virtual HRESULT Finilize() = 0;
|
||||
virtual HRESULT GetStream(const wchar_t *name, bool isAnti) = 0;
|
||||
virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) = 0;
|
||||
virtual HRESULT SetOperationResult(Int32 operationResult) = 0;
|
||||
virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) = 0;
|
||||
virtual HRESULT CloseProgress() { return S_OK; };
|
||||
};
|
||||
|
||||
class CArchiveUpdateCallback:
|
||||
public IArchiveUpdateCallback2,
|
||||
public ICryptoGetTextPassword2,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(IArchiveUpdateCallback2,
|
||||
ICryptoGetTextPassword2)
|
||||
|
||||
// IProgress
|
||||
STDMETHOD(SetTotal)(UInt64 size);
|
||||
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
|
||||
|
||||
// IUpdateCallback
|
||||
STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);
|
||||
STDMETHOD(GetUpdateItemInfo)(UInt32 index,
|
||||
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);
|
||||
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream);
|
||||
STDMETHOD(SetOperationResult)(Int32 operationResult);
|
||||
|
||||
STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size);
|
||||
STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream);
|
||||
|
||||
STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
|
||||
|
||||
public:
|
||||
CRecordVector<UInt64> VolumesSizes;
|
||||
UString VolName;
|
||||
UString VolExt;
|
||||
|
||||
IUpdateCallbackUI *Callback;
|
||||
|
||||
UString DirPrefix;
|
||||
bool StdInMode;
|
||||
const CObjectVector<CDirItem> *DirItems;
|
||||
const CObjectVector<CArchiveItem> *ArchiveItems;
|
||||
const CObjectVector<CUpdatePair2> *UpdatePairs;
|
||||
CMyComPtr<IInArchive> Archive;
|
||||
|
||||
CArchiveUpdateCallback();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "SortUtils.h"
|
||||
|
||||
using namespace NWindows;
|
||||
// using namespace NCOM;
|
||||
using namespace NTime;
|
||||
|
||||
static int MyCompareTime(NFileTimeType::EEnum fileTimeType,
|
||||
@@ -23,7 +22,7 @@ static int MyCompareTime(NFileTimeType::EEnum fileTimeType,
|
||||
return ::CompareFileTime(&time1, &time2);
|
||||
case NFileTimeType::kUnix:
|
||||
{
|
||||
time_t unixTime1, unixTime2;
|
||||
UInt32 unixTime1, unixTime2;
|
||||
if (!FileTimeToUnixTime(time1, unixTime1))
|
||||
throw 4191614;
|
||||
if (!FileTimeToUnixTime(time2, unixTime2))
|
||||
@@ -32,7 +31,7 @@ static int MyCompareTime(NFileTimeType::EEnum fileTimeType,
|
||||
}
|
||||
case NFileTimeType::kDOS:
|
||||
{
|
||||
UINT32 dosTime1, dosTime2;
|
||||
UInt32 dosTime1, dosTime2;
|
||||
if (!FileTimeToDosTime(time1, dosTime1))
|
||||
throw 4191616;
|
||||
if (!FileTimeToDosTime(time2, dosTime2))
|
||||
@@ -51,23 +50,32 @@ static const char *kSameTimeChangedSizeCollisionMessaged =
|
||||
"Collision between files with same date/time and different sizes:\n";
|
||||
*/
|
||||
|
||||
static void TestDuplicateString(const UStringVector &strings,
|
||||
const CIntVector &indices)
|
||||
static inline int MyFileNameCompare(const UString &s1, const UString &s2)
|
||||
{
|
||||
return
|
||||
#ifdef _WIN32
|
||||
s1.CollateNoCase(s2);
|
||||
#else
|
||||
s1.Compare(s2);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices)
|
||||
{
|
||||
for(int i = 0; i + 1 < indices.Size(); i++)
|
||||
if (strings[indices[i]].CollateNoCase(strings[indices[i + 1]]) == 0)
|
||||
if (MyFileNameCompare(strings[indices[i]], strings[indices[i + 1]]) == 0)
|
||||
{
|
||||
UString message = kDuplicateFileNameMessage;
|
||||
message += L"\n";
|
||||
message += strings[indices[i]];
|
||||
message += L"\n";
|
||||
message += strings[indices[i+1]];
|
||||
message += strings[indices[i + 1]];
|
||||
throw message;
|
||||
}
|
||||
}
|
||||
|
||||
void GetUpdatePairInfoList(
|
||||
const CObjectVector<CDirItem> &dirItems,
|
||||
const CObjectVector<CDirItem> &dirItems,
|
||||
const CObjectVector<CArchiveItem> &archiveItems,
|
||||
NFileTimeType::EEnum fileTimeType,
|
||||
CObjectVector<CUpdatePair> &updatePairs)
|
||||
@@ -96,7 +104,7 @@ void GetUpdatePairInfoList(
|
||||
archiveItemIndex2 = archiveIndices[archiveItemIndex];
|
||||
const CDirItem &dirItem = dirItems[dirItemIndex2];
|
||||
const CArchiveItem &archiveItem = archiveItems[archiveItemIndex2];
|
||||
int compareResult = dirItem.Name.CollateNoCase(archiveItem.Name);
|
||||
int compareResult = MyFileNameCompare(dirItem.Name, archiveItem.Name);
|
||||
if (compareResult < 0)
|
||||
{
|
||||
pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// UpdatePair.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __UPDATEPAIR_H
|
||||
#define __UPDATEPAIR_H
|
||||
#ifndef __UPDATE_PAIR_H
|
||||
#define __UPDATE_PAIR_H
|
||||
|
||||
#include "DirItem.h"
|
||||
#include "UpdateAction.h"
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// UpdateProduce.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __UPDATEPRODUCE_H
|
||||
#define __UPDATEPRODUCE_H
|
||||
#ifndef __UPDATE_PRODUCE_H
|
||||
#define __UPDATE_PRODUCE_H
|
||||
|
||||
#include "UpdatePair.h"
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "WorkDir.h"
|
||||
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/Wildcard.h"
|
||||
|
||||
#include "Windows/FileName.h"
|
||||
#include "Windows/FileDir.h"
|
||||
@@ -16,23 +17,13 @@ using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NName;
|
||||
|
||||
static UString GetContainingDir(const UString &path)
|
||||
{
|
||||
UString resultPath;
|
||||
int pos;
|
||||
if(!NFile::NDirectory::MyGetFullPathName(path, resultPath, pos))
|
||||
throw 141716;
|
||||
return resultPath.Left(pos);
|
||||
}
|
||||
|
||||
UString GetWorkDir(const NWorkDir::CInfo &workDirInfo,
|
||||
const UString &archiveName)
|
||||
UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path)
|
||||
{
|
||||
NWorkDir::NMode::EEnum mode = workDirInfo.Mode;
|
||||
if (workDirInfo.ForRemovableOnly)
|
||||
{
|
||||
mode = NWorkDir::NMode::kCurrent;
|
||||
UString prefix = archiveName.Left(3);
|
||||
UString prefix = path.Left(3);
|
||||
if (prefix[1] == L':' && prefix[2] == L'\\')
|
||||
{
|
||||
UINT driveType = GetDriveType(GetSystemString(prefix, GetCurrentCodePage()));
|
||||
@@ -51,7 +42,7 @@ UString GetWorkDir(const NWorkDir::CInfo &workDirInfo,
|
||||
{
|
||||
case NWorkDir::NMode::kCurrent:
|
||||
{
|
||||
return GetContainingDir(archiveName);
|
||||
return ExtractDirPrefixFromPath(path);
|
||||
}
|
||||
case NWorkDir::NMode::kSpecified:
|
||||
{
|
||||
@@ -59,7 +50,7 @@ UString GetWorkDir(const NWorkDir::CInfo &workDirInfo,
|
||||
NormalizeDirPathPrefix(tempDir);
|
||||
return tempDir;
|
||||
}
|
||||
default: // NZipSettings::NWorkDir::NMode::kSystem:
|
||||
default:
|
||||
{
|
||||
UString tempDir;
|
||||
if(!NFile::NDirectory::MyGetTempPath(tempDir))
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
// WorkDir.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __WORKDIR_H
|
||||
#define __WORKDIR_H
|
||||
|
||||
#include "../Common/ZipRegistry.h"
|
||||
#include "ZipRegistry.h"
|
||||
|
||||
UString GetWorkDir(const NWorkDir::CInfo &workDirInfo,
|
||||
const UString &archiveName);
|
||||
UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ static CSysString GetKeyPath(const CSysString &path)
|
||||
return CSysString(kCUBasePath) + CSysString('\\') + CSysString(path);
|
||||
}
|
||||
|
||||
void SaveExtractionInfo(const NExtraction::CInfo &info)
|
||||
void SaveExtractionInfo(const NExtract::CInfo &info)
|
||||
{
|
||||
NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
|
||||
CKey extractionKey;
|
||||
@@ -48,20 +48,20 @@ void SaveExtractionInfo(const NExtraction::CInfo &info)
|
||||
for(int i = 0; i < info.Paths.Size(); i++)
|
||||
{
|
||||
TCHAR numberString[16];
|
||||
ConvertUINT64ToString(i, numberString);
|
||||
ConvertUInt64ToString(i, numberString);
|
||||
pathHistoryKey.SetValue(numberString, info.Paths[i]);
|
||||
}
|
||||
}
|
||||
extractionKey.SetValue(kExtractionExtractModeValueName, UINT32(info.PathMode));
|
||||
extractionKey.SetValue(kExtractionOverwriteModeValueName, UINT32(info.OverwriteMode));
|
||||
extractionKey.SetValue(kExtractionExtractModeValueName, UInt32(info.PathMode));
|
||||
extractionKey.SetValue(kExtractionOverwriteModeValueName, UInt32(info.OverwriteMode));
|
||||
extractionKey.SetValue(kExtractionShowPasswordValueName, info.ShowPassword);
|
||||
}
|
||||
|
||||
void ReadExtractionInfo(NExtraction::CInfo &info)
|
||||
void ReadExtractionInfo(NExtract::CInfo &info)
|
||||
{
|
||||
info.Paths.Clear();
|
||||
info.PathMode = NExtraction::NPathMode::kFullPathnames;
|
||||
info.OverwriteMode = NExtraction::NOverwriteMode::kAskBefore;
|
||||
info.PathMode = NExtract::NPathMode::kCurrentPathnames;
|
||||
info.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
|
||||
info.ShowPassword = false;
|
||||
|
||||
NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
|
||||
@@ -77,7 +77,7 @@ void ReadExtractionInfo(NExtraction::CInfo &info)
|
||||
while(true)
|
||||
{
|
||||
TCHAR numberString[16];
|
||||
ConvertUINT64ToString(info.Paths.Size(), numberString);
|
||||
ConvertUInt64ToString(info.Paths.Size(), numberString);
|
||||
CSysString path;
|
||||
if (pathHistoryKey.QueryValue(numberString, path) != ERROR_SUCCESS)
|
||||
break;
|
||||
@@ -85,29 +85,29 @@ void ReadExtractionInfo(NExtraction::CInfo &info)
|
||||
}
|
||||
}
|
||||
}
|
||||
UINT32 extractModeIndex;
|
||||
UInt32 extractModeIndex;
|
||||
if (extractionKey.QueryValue(kExtractionExtractModeValueName, extractModeIndex) == ERROR_SUCCESS)
|
||||
{
|
||||
switch (extractModeIndex)
|
||||
{
|
||||
case NExtraction::NPathMode::kFullPathnames:
|
||||
case NExtraction::NPathMode::kCurrentPathnames:
|
||||
case NExtraction::NPathMode::kNoPathnames:
|
||||
info.PathMode = NExtraction::NPathMode::EEnum(extractModeIndex);
|
||||
case NExtract::NPathMode::kFullPathnames:
|
||||
case NExtract::NPathMode::kCurrentPathnames:
|
||||
case NExtract::NPathMode::kNoPathnames:
|
||||
info.PathMode = NExtract::NPathMode::EEnum(extractModeIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
UINT32 overwriteModeIndex;
|
||||
UInt32 overwriteModeIndex;
|
||||
if (extractionKey.QueryValue(kExtractionOverwriteModeValueName, overwriteModeIndex) == ERROR_SUCCESS)
|
||||
{
|
||||
switch (overwriteModeIndex)
|
||||
{
|
||||
case NExtraction::NOverwriteMode::kAskBefore:
|
||||
case NExtraction::NOverwriteMode::kWithoutPrompt:
|
||||
case NExtraction::NOverwriteMode::kSkipExisting:
|
||||
case NExtraction::NOverwriteMode::kAutoRename:
|
||||
case NExtraction::NOverwriteMode::kAutoRenameExisting:
|
||||
info.OverwriteMode = NExtraction::NOverwriteMode::EEnum(overwriteModeIndex);
|
||||
case NExtract::NOverwriteMode::kAskBefore:
|
||||
case NExtract::NOverwriteMode::kWithoutPrompt:
|
||||
case NExtract::NOverwriteMode::kSkipExisting:
|
||||
case NExtract::NOverwriteMode::kAutoRename:
|
||||
case NExtract::NOverwriteMode::kAutoRenameExisting:
|
||||
info.OverwriteMode = NExtract::NOverwriteMode::EEnum(overwriteModeIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -151,7 +151,7 @@ void SaveCompressionInfo(const NCompression::CInfo &info)
|
||||
for(int i = 0; i < info.HistoryArchives.Size(); i++)
|
||||
{
|
||||
TCHAR numberString[16];
|
||||
ConvertUINT64ToString(i, numberString);
|
||||
ConvertUInt64ToString(i, numberString);
|
||||
historyArchivesKey.SetValue(numberString, info.HistoryArchives[i]);
|
||||
}
|
||||
}
|
||||
@@ -171,7 +171,7 @@ void SaveCompressionInfo(const NCompression::CInfo &info)
|
||||
formatKey.DeleteValue(kCompressionOptions);
|
||||
else
|
||||
formatKey.SetValue(kCompressionOptions, fo.Options);
|
||||
if (fo.Level == UINT32(-1))
|
||||
if (fo.Level == UInt32(-1))
|
||||
formatKey.DeleteValue(kCompressionLevel);
|
||||
else
|
||||
formatKey.SetValue(kCompressionLevel, fo.Level);
|
||||
@@ -179,18 +179,18 @@ void SaveCompressionInfo(const NCompression::CInfo &info)
|
||||
formatKey.DeleteValue(kCompressionMethod);
|
||||
else
|
||||
formatKey.SetValue(kCompressionMethod, fo.Method);
|
||||
if (fo.Dictionary == UINT32(-1))
|
||||
if (fo.Dictionary == UInt32(-1))
|
||||
formatKey.DeleteValue(kCompressionDictionary);
|
||||
else
|
||||
formatKey.SetValue(kCompressionDictionary, fo.Dictionary);
|
||||
if (fo.Order == UINT32(-1))
|
||||
if (fo.Order == UInt32(-1))
|
||||
formatKey.DeleteValue(kCompressionOrder);
|
||||
else
|
||||
formatKey.SetValue(kCompressionOrder, fo.Order);
|
||||
}
|
||||
}
|
||||
|
||||
compressionKey.SetValue(kCompressionLevelValueName, UINT32(info.Level));
|
||||
compressionKey.SetValue(kCompressionLevelValueName, UInt32(info.Level));
|
||||
compressionKey.SetValue(kCompressionLastFormatValueName,
|
||||
GetSystemString(info.ArchiveType));
|
||||
|
||||
@@ -235,7 +235,7 @@ void ReadCompressionInfo(NCompression::CInfo &info)
|
||||
while(true)
|
||||
{
|
||||
TCHAR numberString[16];
|
||||
ConvertUINT64ToString(info.HistoryArchives.Size(), numberString);
|
||||
ConvertUInt64ToString(info.HistoryArchives.Size(), numberString);
|
||||
CSysString path;
|
||||
if (historyArchivesKey.QueryValue(numberString, path) != ERROR_SUCCESS)
|
||||
break;
|
||||
@@ -269,13 +269,13 @@ void ReadCompressionInfo(NCompression::CInfo &info)
|
||||
if (formatKey.QueryValue(kCompressionOptions, fo.Options) != ERROR_SUCCESS)
|
||||
fo.Options.Empty();
|
||||
if (formatKey.QueryValue(kCompressionLevel, fo.Level) != ERROR_SUCCESS)
|
||||
fo.Level = UINT32(-1);
|
||||
fo.Level = UInt32(-1);
|
||||
if (formatKey.QueryValue(kCompressionMethod, fo.Method) != ERROR_SUCCESS)
|
||||
fo.Method.Empty();;
|
||||
if (formatKey.QueryValue(kCompressionDictionary, fo.Dictionary) != ERROR_SUCCESS)
|
||||
fo.Dictionary = UINT32(-1);
|
||||
fo.Dictionary = UInt32(-1);
|
||||
if (formatKey.QueryValue(kCompressionOrder, fo.Order) != ERROR_SUCCESS)
|
||||
fo.Order = UINT32(-1);
|
||||
fo.Order = UInt32(-1);
|
||||
info.FormatOptionsVector.Add(fo);
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ void ReadCompressionInfo(NCompression::CInfo &info)
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 level;
|
||||
UInt32 level;
|
||||
if (compressionKey.QueryValue(kCompressionLevelValueName, level) == ERROR_SUCCESS)
|
||||
info.Level = level;
|
||||
CSysString archiveType;
|
||||
@@ -318,7 +318,7 @@ void SaveWorkDirInfo(const NWorkDir::CInfo &info)
|
||||
NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
|
||||
CKey optionsKey;
|
||||
optionsKey.Create(HKEY_CURRENT_USER, GetKeyPath(kOptionsInfoKeyName));
|
||||
optionsKey.SetValue(kWorkDirTypeValueName, UINT32(info.Mode));
|
||||
optionsKey.SetValue(kWorkDirTypeValueName, UInt32(info.Mode));
|
||||
optionsKey.SetValue(kWorkDirPathValueName, GetSystemString(info.Path));
|
||||
optionsKey.SetValue(kTempRemovableOnlyValueName, info.ForRemovableOnly);
|
||||
}
|
||||
@@ -332,7 +332,7 @@ void ReadWorkDirInfo(NWorkDir::CInfo &info)
|
||||
if(optionsKey.Open(HKEY_CURRENT_USER, GetKeyPath(kOptionsInfoKeyName), KEY_READ) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
UINT32 dirType;
|
||||
UInt32 dirType;
|
||||
if (optionsKey.QueryValue(kWorkDirTypeValueName, dirType) != ERROR_SUCCESS)
|
||||
return;
|
||||
switch (dirType)
|
||||
@@ -380,7 +380,7 @@ bool ReadCascadedMenu()
|
||||
{ return ReadOption(kCascadedMenuValueName, false); }
|
||||
|
||||
|
||||
static void SaveValue(const TCHAR *value, UINT32 valueToWrite)
|
||||
static void SaveValue(const TCHAR *value, UInt32 valueToWrite)
|
||||
{
|
||||
NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
|
||||
CKey optionsKey;
|
||||
@@ -388,7 +388,7 @@ static void SaveValue(const TCHAR *value, UINT32 valueToWrite)
|
||||
optionsKey.SetValue(value, valueToWrite);
|
||||
}
|
||||
|
||||
static bool ReadValue(const TCHAR *value, UINT32 &result)
|
||||
static bool ReadValue(const TCHAR *value, UInt32 &result)
|
||||
{
|
||||
NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
|
||||
CKey optionsKey;
|
||||
@@ -397,8 +397,8 @@ static bool ReadValue(const TCHAR *value, UINT32 &result)
|
||||
return (optionsKey.QueryValue(value, result) == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
void SaveContextMenuStatus(UINT32 value)
|
||||
void SaveContextMenuStatus(UInt32 value)
|
||||
{ SaveValue(kContextMenuValueName, value); }
|
||||
|
||||
bool ReadContextMenuStatus(UINT32 &value)
|
||||
bool ReadContextMenuStatus(UInt32 &value)
|
||||
{ return ReadValue(kContextMenuValueName, value); }
|
||||
|
||||
@@ -1,36 +1,14 @@
|
||||
// ZipRegistry.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __ZIPREGISTRY_H
|
||||
#define __ZIPREGISTRY_H
|
||||
|
||||
#include "Common/String.h"
|
||||
#include "Common/Types.h"
|
||||
#include "ExtractMode.h"
|
||||
|
||||
namespace NExtraction {
|
||||
|
||||
namespace NPathMode
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kFullPathnames,
|
||||
kCurrentPathnames,
|
||||
kNoPathnames
|
||||
};
|
||||
}
|
||||
|
||||
namespace NOverwriteMode
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kAskBefore,
|
||||
kWithoutPrompt,
|
||||
kSkipExisting,
|
||||
kAutoRename,
|
||||
kAutoRenameExisting
|
||||
};
|
||||
}
|
||||
|
||||
namespace NExtract
|
||||
{
|
||||
struct CInfo
|
||||
{
|
||||
NPathMode::EEnum PathMode;
|
||||
@@ -46,13 +24,13 @@ namespace NCompression {
|
||||
{
|
||||
CSysString FormatID;
|
||||
CSysString Options;
|
||||
UINT32 Level;
|
||||
UInt32 Level;
|
||||
CSysString Method;
|
||||
UINT32 Dictionary;
|
||||
UINT32 Order;
|
||||
UInt32 Dictionary;
|
||||
UInt32 Order;
|
||||
void Init()
|
||||
{
|
||||
Level = Dictionary = Order = UINT32(-1);
|
||||
Level = Dictionary = Order = UInt32(-1);
|
||||
Method.Empty();
|
||||
// Options.Empty();
|
||||
}
|
||||
@@ -63,7 +41,7 @@ namespace NCompression {
|
||||
{
|
||||
CSysStringVector HistoryArchives;
|
||||
// bool LevelIsDefined;
|
||||
UINT32 Level;
|
||||
UInt32 Level;
|
||||
UString ArchiveType;
|
||||
|
||||
bool Solid;
|
||||
@@ -101,8 +79,8 @@ namespace NWorkDir{
|
||||
};
|
||||
}
|
||||
|
||||
void SaveExtractionInfo(const NExtraction::CInfo &info);
|
||||
void ReadExtractionInfo(NExtraction::CInfo &info);
|
||||
void SaveExtractionInfo(const NExtract::CInfo &info);
|
||||
void ReadExtractionInfo(NExtract::CInfo &info);
|
||||
|
||||
void SaveCompressionInfo(const NCompression::CInfo &info);
|
||||
void ReadCompressionInfo(NCompression::CInfo &info);
|
||||
@@ -113,7 +91,7 @@ void ReadWorkDirInfo(NWorkDir::CInfo &info);
|
||||
void SaveCascadedMenu(bool enabled);
|
||||
bool ReadCascadedMenu();
|
||||
|
||||
void SaveContextMenuStatus(UINT32 value);
|
||||
bool ReadContextMenuStatus(UINT32 &value);
|
||||
void SaveContextMenuStatus(UInt32 value);
|
||||
bool ReadContextMenuStatus(UInt32 &value);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user