mirror of
https://github.com/winscp/winscp.git
synced 2026-10-24 02:28:55 +03:00
File checksum calculation support for SCP protocol and SFTP protocol via secondary shell session using shell commands like sha256sum
Part of Bug 52 https://winscp.net/tracker/52 Source commit: 6804a5d18405a91e8d0a2e0beccf2c31d43ed3f1
This commit is contained in:
@@ -120,6 +120,7 @@ void __fastcall TConfiguration::Default()
|
||||
FParallelDurationThreshold = 10;
|
||||
FMimeTypes = UnicodeString();
|
||||
FCertificateStorage = EmptyStr;
|
||||
FChecksumCommands = EmptyStr;
|
||||
FDontReloadMoreThanSessions = 1000;
|
||||
FScriptProgressFileNameLimit = 25;
|
||||
FKeyVersion = 0;
|
||||
|
||||
@@ -81,6 +81,7 @@ private:
|
||||
int FScriptProgressFileNameLimit;
|
||||
int FKeyVersion;
|
||||
UnicodeString FCertificateStorage;
|
||||
UnicodeString FChecksumCommands;
|
||||
|
||||
bool FDisablePasswordStoring;
|
||||
bool FForceBanners;
|
||||
@@ -331,6 +332,7 @@ public:
|
||||
__property UnicodeString ExternalIpAddress = { read = FExternalIpAddress, write = SetExternalIpAddress };
|
||||
__property UnicodeString CertificateStorage = { read = FCertificateStorage, write = SetCertificateStorage };
|
||||
__property UnicodeString CertificateStorageExpanded = { read = GetCertificateStorageExpanded };
|
||||
__property UnicodeString ChecksumCommands = { read = FChecksumCommands };
|
||||
__property int LocalPortNumberMin = { read = FLocalPortNumberMin, write = SetLocalPortNumberMin };
|
||||
__property int LocalPortNumberMax = { read = FLocalPortNumberMax, write = SetLocalPortNumberMax };
|
||||
__property bool TryFtpWhenSshFails = { read = FTryFtpWhenSshFails, write = SetTryFtpWhenSshFails };
|
||||
|
||||
@@ -1213,8 +1213,9 @@ private:
|
||||
__fastcall TBackgroundTerminal::TBackgroundTerminal(TTerminal * MainTerminal,
|
||||
TSessionData * SessionData, TConfiguration * Configuration, TTerminalItem * Item,
|
||||
const UnicodeString & Name) :
|
||||
TSecondaryTerminal(MainTerminal, SessionData, Configuration, Name), FItem(Item)
|
||||
TSecondaryTerminal(MainTerminal, SessionData, Configuration, Name, NULL), FItem(Item)
|
||||
{
|
||||
ActionLog->Enabled = false;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool __fastcall TBackgroundTerminal::DoQueryReopen(Exception * /*E*/)
|
||||
|
||||
@@ -442,6 +442,7 @@ bool __fastcall TSCPFileSystem::IsCapable(int Capability) const
|
||||
case fcRemoteCopy:
|
||||
case fcRemoveCtrlZUpload:
|
||||
case fcRemoveBOMUpload:
|
||||
case fcCalculatingChecksum:
|
||||
return true;
|
||||
|
||||
case fcTextMode:
|
||||
@@ -454,7 +455,6 @@ bool __fastcall TSCPFileSystem::IsCapable(int Capability) const
|
||||
case fcLoadingAdditionalProperties:
|
||||
case fcCheckingSpaceAvailable:
|
||||
case fcIgnorePermErrors:
|
||||
case fcCalculatingChecksum:
|
||||
case fcSecondaryShell: // has fcShellAnyCommand
|
||||
case fcGroupOwnerChangingByID: // by name
|
||||
case fcMoveToQueue:
|
||||
@@ -681,6 +681,11 @@ void __fastcall TSCPFileSystem::ExecCommand(const UnicodeString & Cmd, int Param
|
||||
ReadCommandOutput(COParams, &CmdString);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void TSCPFileSystem::InvalidOutputError(const UnicodeString & Command)
|
||||
{
|
||||
FTerminal->TerminalError(FMTLOAD(INVALID_OUTPUT_ERROR, (Command, Output->Text)));
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSCPFileSystem::ExecCommand(TFSCommand Cmd, const TVarRec * args,
|
||||
int size, int Params)
|
||||
{
|
||||
@@ -695,8 +700,7 @@ void __fastcall TSCPFileSystem::ExecCommand(TFSCommand Cmd, const TVarRec * args
|
||||
if (((MinL >= 0) && (MinL > FOutput->Count)) ||
|
||||
((MaxL >= 0) && (MaxL > FOutput->Count)))
|
||||
{
|
||||
FTerminal->TerminalError(FmtLoadStr(INVALID_OUTPUT_ERROR,
|
||||
ARRAYOFCONST((FullCommand, Output->Text))));
|
||||
InvalidOutputError(FullCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1299,11 +1303,184 @@ bool __fastcall TSCPFileSystem::LoadFilesProperties(TStrings * /*FileList*/ )
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSCPFileSystem::CalculateFilesChecksum(
|
||||
const UnicodeString & DebugUsedArg(Alg), TStrings * DebugUsedArg(FileList), TCalculatedChecksumEvent,
|
||||
TFileOperationProgressType *, bool DebugUsedArg(FirstLevel))
|
||||
UnicodeString TSCPFileSystem::CalculateFilesChecksumInitialize(const UnicodeString & Alg)
|
||||
{
|
||||
DebugFail();
|
||||
std::unique_ptr<TStrings> Algs(new TStringList());
|
||||
GetSupportedChecksumAlgs(Algs.get());
|
||||
return FindIdent(Alg, Algs.get());
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
UnicodeString TSCPFileSystem::ParseFileChecksum(
|
||||
const UnicodeString & Line, const UnicodeString & FileName, const UnicodeString & Command)
|
||||
{
|
||||
int P = Line.Pos(L" ");
|
||||
if ((P < 0) ||
|
||||
(P == Line.Length()) ||
|
||||
((Line[P + 1] != L' ') && (Line[P + 1] != L'*')) ||
|
||||
(Line.SubString(P + 2, Line.Length() - P - 1) != FileName))
|
||||
{
|
||||
InvalidOutputError(Command);
|
||||
}
|
||||
return Line.SubString(1, P - 1);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void TSCPFileSystem::ProcessFileChecksum(
|
||||
TCalculatedChecksumEvent OnCalculatedChecksum, TChecksumSessionAction & Action, TFileOperationProgressType * OperationProgress,
|
||||
bool FirstLevel, const UnicodeString & FileName, const UnicodeString & Alg, const UnicodeString & Checksum)
|
||||
{
|
||||
bool Success = !Checksum.IsEmpty();
|
||||
if (Success)
|
||||
{
|
||||
if (OnCalculatedChecksum != NULL)
|
||||
{
|
||||
OnCalculatedChecksum(UnixExtractFileName(FileName), Alg, Checksum);
|
||||
}
|
||||
Action.Checksum(Alg, Checksum);
|
||||
}
|
||||
if (FirstLevel)
|
||||
{
|
||||
TOnceDoneOperation OnceDoneOperation; // not used
|
||||
OperationProgress->Finish(FileName, Success, OnceDoneOperation);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSCPFileSystem::CalculateFilesChecksum(
|
||||
const UnicodeString & Alg, TStrings * FileList, TCalculatedChecksumEvent OnCalculatedChecksum,
|
||||
TFileOperationProgressType * OperationProgress, bool FirstLevel)
|
||||
{
|
||||
FTerminal->CalculateSubFoldersChecksum(Alg, FileList, OnCalculatedChecksum, OperationProgress, FirstLevel);
|
||||
|
||||
TStrings * AlgDefs = FTerminal->GetShellChecksumAlgDefs();
|
||||
int AlgIndex = AlgDefs->IndexOfName(Alg);
|
||||
UnicodeString AlgCommand = (AlgIndex >= 0) ? AlgDefs->ValueFromIndex[AlgIndex] : Alg;
|
||||
|
||||
int Index = 0;
|
||||
while ((Index < FileList->Count) && !OperationProgress->Cancel)
|
||||
{
|
||||
std::unique_ptr<TStrings> BatchFileList(new TStringList());
|
||||
UnicodeString FileListCommandLine;
|
||||
__int64 BatchSize = 0;
|
||||
while (Index < FileList->Count)
|
||||
{
|
||||
TRemoteFile * File = DebugNotNull(dynamic_cast<TRemoteFile *>(FileList->Objects[Index]));
|
||||
if (!File->IsDirectory)
|
||||
{
|
||||
UnicodeString FileName = FileList->Strings[Index];
|
||||
UnicodeString FileListCommandLineBak = FileListCommandLine;
|
||||
AddToShellFileListCommandLine(FileListCommandLine, FileName);
|
||||
BatchSize += File->Size;
|
||||
if (!FileListCommandLineBak.IsEmpty() &&
|
||||
((FileListCommandLine.Length() > 2048) ||
|
||||
(BatchSize > 1024*1024*1024)))
|
||||
{
|
||||
FileListCommandLine = FileListCommandLineBak;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
BatchFileList->AddObject(FileName, File);
|
||||
}
|
||||
}
|
||||
Index++;
|
||||
}
|
||||
|
||||
if (!FileListCommandLine.IsEmpty())
|
||||
{
|
||||
bool IndividualCommands = false;
|
||||
std::unique_ptr<TStrings> BatchChecksums(new TStringList());
|
||||
try
|
||||
{
|
||||
UnicodeString BatchCommand = FORMAT(L"%s %s", (AlgCommand, FileListCommandLine));
|
||||
AnyCommand(BatchCommand, NULL);
|
||||
if (Output->Count != BatchFileList->Count)
|
||||
{
|
||||
InvalidOutputError(BatchCommand);
|
||||
}
|
||||
|
||||
// First do everything that can throw.
|
||||
// Only once everything is checked, distribute the results.
|
||||
for (int BatchIndex = 0; BatchIndex < BatchFileList->Count; BatchIndex++)
|
||||
{
|
||||
UnicodeString FileName = BatchFileList->Strings[BatchIndex];
|
||||
UnicodeString Line = Output->Strings[BatchIndex];
|
||||
UnicodeString Checksum = ParseFileChecksum(Line, FileName, BatchCommand);
|
||||
BatchChecksums->Add(Checksum);
|
||||
}
|
||||
}
|
||||
catch (Exception & E)
|
||||
{
|
||||
if (!FTerminal->Active)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
else
|
||||
{
|
||||
IndividualCommands = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IndividualCommands)
|
||||
{
|
||||
// None of this should throw
|
||||
for (int BatchIndex = 0; BatchIndex < BatchFileList->Count; BatchIndex++)
|
||||
{
|
||||
UnicodeString FileName = BatchFileList->Strings[BatchIndex];
|
||||
TRemoteFile * File = DebugNotNull(dynamic_cast<TRemoteFile *>(BatchFileList->Objects[BatchIndex]));
|
||||
TChecksumSessionAction Action(FTerminal->ActionLog);
|
||||
Action.FileName(File->FullFileName);
|
||||
OperationProgress->SetFile(FileName);
|
||||
UnicodeString Checksum = BatchChecksums->Strings[BatchIndex];
|
||||
ProcessFileChecksum(OnCalculatedChecksum, Action, OperationProgress, FirstLevel, FileName, Alg, Checksum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FTerminal->LogEvent(
|
||||
L"Batch checksum calculation failed, falling back to calculating checksum individually for each file...");
|
||||
|
||||
for (int BatchIndex = 0; BatchIndex < BatchFileList->Count; BatchIndex++)
|
||||
{
|
||||
TRemoteFile * File = DebugNotNull(dynamic_cast<TRemoteFile *>(BatchFileList->Objects[BatchIndex]));
|
||||
TChecksumSessionAction Action(FTerminal->ActionLog);
|
||||
try
|
||||
{
|
||||
UnicodeString FileName = BatchFileList->Strings[BatchIndex];
|
||||
OperationProgress->SetFile(FileName);
|
||||
Action.FileName(File->FullFileName);
|
||||
bool Success = false;
|
||||
|
||||
UnicodeString Checksum;
|
||||
try
|
||||
{
|
||||
UnicodeString Command = FORMAT(L"%s %s", (AlgCommand, ShellQuoteStr(FileName)));
|
||||
AnyCommand(Command, NULL);
|
||||
if (Output->Count != 1)
|
||||
{
|
||||
InvalidOutputError(Command);
|
||||
}
|
||||
UnicodeString Line = Output->Strings[0];
|
||||
Checksum = ParseFileChecksum(Line, FileName, Command);
|
||||
}
|
||||
__finally
|
||||
{
|
||||
ProcessFileChecksum(OnCalculatedChecksum, Action, OperationProgress, FirstLevel, FileName, Alg, Checksum);
|
||||
}
|
||||
}
|
||||
catch (Exception & E)
|
||||
{
|
||||
FTerminal->RollbackAction(Action, OperationProgress, &E);
|
||||
|
||||
UnicodeString Error = FMTLOAD(CHECKSUM_ERROR, (File->FullFileName));
|
||||
FTerminal->CommandError(&E, Error);
|
||||
// Abort loop.
|
||||
// TODO: retries? resume?
|
||||
BatchIndex = BatchFileList->Count;
|
||||
Index = FileList->Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSCPFileSystem::CustomCommandOnFile(const UnicodeString FileName,
|
||||
@@ -2668,9 +2845,9 @@ void __fastcall TSCPFileSystem::SCPSink(const UnicodeString TargetDir,
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSCPFileSystem::GetSupportedChecksumAlgs(TStrings * /*Algs*/)
|
||||
void __fastcall TSCPFileSystem::GetSupportedChecksumAlgs(TStrings * Algs)
|
||||
{
|
||||
// NOOP
|
||||
FTerminal->GetShellChecksumAlgs(Algs);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSCPFileSystem::LockFile(const UnicodeString & /*FileName*/, const TRemoteFile * /*File*/)
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
const TRemoteFile * File, const TRemoteProperties * Properties,
|
||||
TChmodSessionAction & Action);
|
||||
virtual bool __fastcall LoadFilesProperties(TStrings * FileList);
|
||||
virtual UnicodeString CalculateFilesChecksumInitialize(const UnicodeString & Alg);
|
||||
virtual void __fastcall CalculateFilesChecksum(
|
||||
const UnicodeString & Alg, TStrings * FileList, TCalculatedChecksumEvent OnCalculatedChecksum,
|
||||
TFileOperationProgressType * OperationProgress, bool FirstLevel);
|
||||
@@ -117,6 +118,7 @@ private:
|
||||
const UnicodeString & CmdString);
|
||||
void __fastcall ExecCommand(TFSCommand Cmd, const TVarRec * args = NULL,
|
||||
int size = 0, int Params = -1);
|
||||
void InvalidOutputError(const UnicodeString & Command);
|
||||
void __fastcall ReadCommandOutput(int Params, const UnicodeString * Cmd = NULL);
|
||||
void __fastcall SCPResponse(bool * GotLastLine = NULL);
|
||||
void __fastcall SCPDirectorySource(const UnicodeString DirectoryName,
|
||||
@@ -145,6 +147,11 @@ private:
|
||||
TOperationSide Side,
|
||||
const TOverwriteFileParams * FileParams, const TCopyParamType * CopyParam,
|
||||
int Params, TFileOperationProgressType * OperationProgress);
|
||||
UnicodeString ParseFileChecksum(
|
||||
const UnicodeString & Line, const UnicodeString & FileName, const UnicodeString & Command);
|
||||
void ProcessFileChecksum(
|
||||
TCalculatedChecksumEvent OnCalculatedChecksum, TChecksumSessionAction & Action, TFileOperationProgressType * OperationProgress,
|
||||
bool FirstLevel, const UnicodeString & FileName, const UnicodeString & Alg, const UnicodeString & Checksum);
|
||||
|
||||
static bool __fastcall RemoveLastLine(UnicodeString & Line,
|
||||
int & ReturnCode, UnicodeString LastLine = L"");
|
||||
|
||||
@@ -1214,28 +1214,37 @@ void __fastcall TScript::DoCalculatedChecksum(
|
||||
void __fastcall TScript::ChecksumProc(TScriptProcParams * Parameters)
|
||||
{
|
||||
CheckSession();
|
||||
if (!FTerminal->IsCapable[fcCalculatingChecksum])
|
||||
if (!FTerminal->IsCapable[fcCalculatingChecksum] &&
|
||||
(!FTerminal->IsCapable[fcSecondaryShell] || FTerminal->IsEncryptingFiles()))
|
||||
{
|
||||
NotSupported();
|
||||
}
|
||||
|
||||
UnicodeString Alg = Parameters->Param[1];
|
||||
TStrings * FileList = CreateFileList(Parameters, 2, 2, fltQueryServer);
|
||||
FTerminal->ExceptionOnFail = true;
|
||||
try
|
||||
// this is used only to log failures to open separate shell session,
|
||||
// the actual call logging is done in TTerminal::CalculateFilesChecksum
|
||||
TChecksumSessionAction Action(FTerminal->ActionLog);
|
||||
if (EnsureCommandSessionFallback(fcCalculatingChecksum, Action))
|
||||
{
|
||||
if ((FileList->Count != 1) ||
|
||||
DebugNotNull(dynamic_cast<TRemoteFile *>(FileList->Objects[0]))->IsDirectory)
|
||||
{
|
||||
throw Exception(FMTLOAD(NOT_FILE_ERROR, (FileList->Strings[0])));
|
||||
}
|
||||
Action.Cancel();
|
||||
|
||||
FTerminal->CalculateFilesChecksum(Alg, FileList, DoCalculatedChecksum);
|
||||
}
|
||||
__finally
|
||||
{
|
||||
FTerminal->ExceptionOnFail = false;
|
||||
FreeFileList(FileList);
|
||||
UnicodeString Alg = Parameters->Param[1];
|
||||
TStrings * FileList = CreateFileList(Parameters, 2, 2, fltQueryServer);
|
||||
FTerminal->ExceptionOnFail = true;
|
||||
try
|
||||
{
|
||||
if ((FileList->Count != 1) ||
|
||||
DebugNotNull(dynamic_cast<TRemoteFile *>(FileList->Objects[0]))->IsDirectory)
|
||||
{
|
||||
throw Exception(FMTLOAD(NOT_FILE_ERROR, (FileList->Strings[0])));
|
||||
}
|
||||
|
||||
FTerminal->CalculateFilesChecksum(Alg, FileList, DoCalculatedChecksum);
|
||||
}
|
||||
__finally
|
||||
{
|
||||
FTerminal->ExceptionOnFail = false;
|
||||
FreeFileList(FileList);
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -999,15 +999,23 @@ bool TParallelOperation::UpdateFileList(TQueueFileList * UpdateFileList)
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------
|
||||
__fastcall TTerminal::TTerminal(TSessionData * SessionData,
|
||||
TConfiguration * Configuration)
|
||||
__fastcall TTerminal::TTerminal(TSessionData * SessionData, TConfiguration * Configuration, TActionLog * ActionLog)
|
||||
{
|
||||
FConfiguration = Configuration;
|
||||
FSessionData = new TSessionData(L"");
|
||||
FSessionData->Assign(SessionData);
|
||||
TDateTime Started = Now(); // use the same time for session and XML log
|
||||
FLog = new TSessionLog(this, Started, FSessionData, Configuration);
|
||||
FActionLog = new TActionLog(this, Started, FSessionData, Configuration);
|
||||
if (ActionLog != NULL)
|
||||
{
|
||||
FActionLog = ActionLog;
|
||||
FActionLogOwned = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
FActionLog = new TActionLog(this, Started, FSessionData, Configuration);
|
||||
FActionLogOwned = true;
|
||||
}
|
||||
FFiles = new TRemoteDirectory(this);
|
||||
FExceptionOnFail = 0;
|
||||
FInTransaction = 0;
|
||||
@@ -1078,7 +1086,14 @@ __fastcall TTerminal::~TTerminal()
|
||||
|
||||
SAFE_DESTROY_EX(TCustomFileSystem, FFileSystem);
|
||||
SAFE_DESTROY_EX(TSessionLog, FLog);
|
||||
SAFE_DESTROY_EX(TActionLog, FActionLog);
|
||||
if (FActionLogOwned)
|
||||
{
|
||||
SAFE_DESTROY_EX(TActionLog, FActionLog);
|
||||
}
|
||||
else
|
||||
{
|
||||
FActionLog = NULL;
|
||||
}
|
||||
delete FFiles;
|
||||
delete FDirectoryCache;
|
||||
delete FDirectoryChangesCache;
|
||||
@@ -4512,6 +4527,7 @@ void __fastcall TTerminal::CalculateSubFoldersChecksum(
|
||||
TOnceDoneOperation OnceDoneOperation; // unused
|
||||
while ((Index < FileList->Count) && !OperationProgress->Cancel)
|
||||
{
|
||||
UnicodeString FileName = FileList->Strings[Index];
|
||||
TRemoteFile * File = DebugNotNull(dynamic_cast<TRemoteFile *>(FileList->Objects[Index]));
|
||||
|
||||
if (File->IsDirectory &&
|
||||
@@ -4532,7 +4548,8 @@ void __fastcall TTerminal::CalculateSubFoldersChecksum(
|
||||
for (int Index = 0; Index < SubFiles->Count; Index++)
|
||||
{
|
||||
TRemoteFile * SubFile = SubFiles->Files[Index];
|
||||
SubFileList->AddObject(SubFile->FullFileName, SubFile);
|
||||
UnicodeString SubFileName = UnixCombinePaths(FileName, SubFile->FileName);
|
||||
SubFileList->AddObject(SubFileName, SubFile);
|
||||
}
|
||||
|
||||
FFileSystem->CalculateFilesChecksum(Alg, SubFileList.get(), OnCalculatedChecksum, OperationProgress, false);
|
||||
@@ -4561,9 +4578,11 @@ void __fastcall TTerminal::CalculateFilesChecksum(
|
||||
|
||||
try
|
||||
{
|
||||
UnicodeString NormalizedAlg = FFileSystem->CalculateFilesChecksumInitialize(Alg);
|
||||
TCustomFileSystem * FileSystem = GetFileSystemForCapability(fcCalculatingChecksum);
|
||||
|
||||
FFileSystem->CalculateFilesChecksum(NormalizedAlg, FileList, OnCalculatedChecksum, &Progress, true);
|
||||
UnicodeString NormalizedAlg = FileSystem->CalculateFilesChecksumInitialize(Alg);
|
||||
|
||||
FileSystem->CalculateFilesChecksum(NormalizedAlg, FileList, OnCalculatedChecksum, &Progress, true);
|
||||
}
|
||||
__finally
|
||||
{
|
||||
@@ -4937,7 +4956,7 @@ bool __fastcall TTerminal::GetCommandSessionOpened()
|
||||
//---------------------------------------------------------------------------
|
||||
TTerminal * __fastcall TTerminal::CreateSecondarySession(const UnicodeString & Name, TSessionData * SessionData)
|
||||
{
|
||||
std::unique_ptr<TTerminal> Result(new TSecondaryTerminal(this, SessionData, Configuration, Name));
|
||||
std::unique_ptr<TTerminal> Result(new TSecondaryTerminal(this, SessionData, Configuration, Name, ActionLog));
|
||||
|
||||
Result->AutoReadDirectory = false;
|
||||
|
||||
@@ -6662,9 +6681,55 @@ const TFileSystemInfo & __fastcall TTerminal::GetFileSystemInfo(bool Retrieve)
|
||||
return FFileSystem->GetFileSystemInfo(Retrieve);
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
TStrings * TTerminal::GetShellChecksumAlgDefs()
|
||||
{
|
||||
if (FShellChecksumAlgDefs.get() == NULL)
|
||||
{
|
||||
UnicodeString ChecksumCommandsDef = Configuration->ChecksumCommands;
|
||||
if (ChecksumCommandsDef.IsEmpty())
|
||||
{
|
||||
UnicodeString Delimiter(L",");
|
||||
AddToList(ChecksumCommandsDef, Sha512ChecksumAlg + L"=sha512sum", Delimiter);
|
||||
AddToList(ChecksumCommandsDef, Sha384ChecksumAlg + L"=sha384sum", Delimiter);
|
||||
AddToList(ChecksumCommandsDef, Sha256ChecksumAlg + L"=sha256sum", Delimiter);
|
||||
AddToList(ChecksumCommandsDef, Sha224ChecksumAlg + L"=sha224sum", Delimiter);
|
||||
AddToList(ChecksumCommandsDef, Sha1ChecksumAlg + L"=sha1sum", Delimiter);
|
||||
AddToList(ChecksumCommandsDef, Md5ChecksumAlg + L"=md5sums", Delimiter);
|
||||
}
|
||||
|
||||
FShellChecksumAlgDefs.reset(new TStringList());
|
||||
FShellChecksumAlgDefs->CommaText = ChecksumCommandsDef;
|
||||
}
|
||||
return FShellChecksumAlgDefs.get();
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void TTerminal::GetShellChecksumAlgs(TStrings * Algs)
|
||||
{
|
||||
TStrings * AlgDefs = GetShellChecksumAlgDefs();
|
||||
for (int Index = 0; Index < AlgDefs->Count; Index++)
|
||||
{
|
||||
Algs->Add(AlgDefs->Names[Index]);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void __fastcall TTerminal::GetSupportedChecksumAlgs(TStrings * Algs)
|
||||
{
|
||||
FFileSystem->GetSupportedChecksumAlgs(Algs);
|
||||
if (!IsCapable[fcCalculatingChecksum] && IsCapable[fcSecondaryShell])
|
||||
{
|
||||
// Both return the same anyway
|
||||
if (CommandSessionOpened)
|
||||
{
|
||||
FCommandSession->GetSupportedChecksumAlgs(Algs);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetShellChecksumAlgs(Algs);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FFileSystem->GetSupportedChecksumAlgs(Algs);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
UnicodeString __fastcall TTerminal::GetPassword()
|
||||
@@ -7789,8 +7854,11 @@ void __fastcall TTerminal::ReflectSettings()
|
||||
{
|
||||
DebugAssert(FLog != NULL);
|
||||
FLog->ReflectSettings();
|
||||
DebugAssert(FActionLog != NULL);
|
||||
FActionLog->ReflectSettings();
|
||||
if (FActionLogOwned)
|
||||
{
|
||||
DebugAssert(FActionLog != NULL);
|
||||
FActionLog->ReflectSettings();
|
||||
}
|
||||
// also FTunnelLog ?
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -8371,13 +8439,13 @@ bool TTerminal::IsValidFile(TRemoteFile * File)
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------
|
||||
__fastcall TSecondaryTerminal::TSecondaryTerminal(TTerminal * MainTerminal,
|
||||
TSessionData * ASessionData, TConfiguration * Configuration, const UnicodeString & Name) :
|
||||
TTerminal(ASessionData, Configuration),
|
||||
__fastcall TSecondaryTerminal::TSecondaryTerminal(
|
||||
TTerminal * MainTerminal, TSessionData * ASessionData, TConfiguration * Configuration,
|
||||
const UnicodeString & Name, TActionLog * ActionLog) :
|
||||
TTerminal(ASessionData, Configuration, ActionLog),
|
||||
FMainTerminal(MainTerminal)
|
||||
{
|
||||
Log->SetParent(FMainTerminal->Log, Name);
|
||||
ActionLog->Enabled = false;
|
||||
SessionData->NonPersistant();
|
||||
DebugAssert(FMainTerminal != NULL);
|
||||
FMainTerminal->FSecondaryTerminals++;
|
||||
|
||||
@@ -160,6 +160,7 @@ private:
|
||||
TSessionData * FSessionData;
|
||||
TSessionLog * FLog;
|
||||
TActionLog * FActionLog;
|
||||
bool FActionLogOwned;
|
||||
TConfiguration * FConfiguration;
|
||||
UnicodeString FCurrentDirectory;
|
||||
Integer FExceptionOnFail;
|
||||
@@ -211,6 +212,7 @@ private:
|
||||
TNotifyEvent FOnClose;
|
||||
TCallbackGuard * FCallbackGuard;
|
||||
TFindingFileEvent FOnFindingFile;
|
||||
std::unique_ptr<TStrings> FShellChecksumAlgDefs;
|
||||
bool FEnableSecureShellUsage;
|
||||
bool FCollectFileSystemUsage;
|
||||
bool FRememberedPasswordTried;
|
||||
@@ -491,6 +493,8 @@ protected:
|
||||
void __fastcall CalculateSubFoldersChecksum(
|
||||
const UnicodeString & Alg, TStrings * FileList, TCalculatedChecksumEvent OnCalculatedChecksum,
|
||||
TFileOperationProgressType * OperationProgress, bool FirstLevel);
|
||||
void GetShellChecksumAlgs(TStrings * Algs);
|
||||
TStrings * GetShellChecksumAlgDefs();
|
||||
|
||||
UnicodeString __fastcall EncryptFileName(const UnicodeString & Path, bool EncryptNewFiles);
|
||||
UnicodeString __fastcall DecryptFileName(const UnicodeString & Path, bool DecryptFullPath, bool DontCache);
|
||||
@@ -500,7 +504,7 @@ protected:
|
||||
__property TFileOperationProgressType * OperationProgress = { read=FOperationProgress };
|
||||
|
||||
public:
|
||||
__fastcall TTerminal(TSessionData * SessionData, TConfiguration * Configuration);
|
||||
__fastcall TTerminal(TSessionData * SessionData, TConfiguration * Configuration, TActionLog * ActionLog = NULL);
|
||||
__fastcall ~TTerminal();
|
||||
void __fastcall Open();
|
||||
void __fastcall Close();
|
||||
@@ -673,9 +677,9 @@ public:
|
||||
class TSecondaryTerminal : public TTerminal
|
||||
{
|
||||
public:
|
||||
__fastcall TSecondaryTerminal(TTerminal * MainTerminal,
|
||||
TSessionData * SessionData, TConfiguration * Configuration,
|
||||
const UnicodeString & Name);
|
||||
__fastcall TSecondaryTerminal(
|
||||
TTerminal * MainTerminal, TSessionData * SessionData, TConfiguration * Configuration,
|
||||
const UnicodeString & Name, TActionLog * ActionLog);
|
||||
|
||||
void __fastcall UpdateFromMain();
|
||||
|
||||
|
||||
@@ -4494,8 +4494,8 @@ void __fastcall TCustomScpExplorerForm::CalculateChecksum(const UnicodeString &
|
||||
TStrings * FileList, TCalculatedChecksumEvent OnCalculatedChecksum,
|
||||
bool & Close)
|
||||
{
|
||||
// terminal can be already closed (e.g. dropped connection)
|
||||
if (Terminal != NULL)
|
||||
if ((Terminal != NULL) && // terminal can be already closed (e.g. dropped connection)
|
||||
EnsureCommandSessionFallback(fcCalculatingChecksum))
|
||||
{
|
||||
Configuration->Usage->Inc(L"ChecksumCalculated");
|
||||
|
||||
@@ -4606,7 +4606,8 @@ bool __fastcall TCustomScpExplorerForm::SetProperties(TOperationSide Side, TStri
|
||||
if (CapableGroupChanging) Flags |= cpGroup;
|
||||
|
||||
TCalculateChecksumEvent CalculateChecksumEvent = NULL;
|
||||
if (Terminal->IsCapable[fcCalculatingChecksum])
|
||||
if (Terminal->IsCapable[fcCalculatingChecksum] ||
|
||||
(Terminal->IsCapable[fcSecondaryShell] && !Terminal->IsEncryptingFiles()))
|
||||
{
|
||||
CalculateChecksumEvent = CalculateChecksum;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user