| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- //---------------------------------------------------------------------------
- #include <vcl.h>
- #pragma hdrstop
- #include <stdio.h>
- #include "Common.h"
- #include "SessionInfo.h"
- #include "Exceptions.h"
- #include "TextsCore.h"
- //---------------------------------------------------------------------------
- #pragma package(smart_init)
- //---------------------------------------------------------------------------
- TSessionInfo::TSessionInfo()
- {
- LoginTime = Now();
- }
- //---------------------------------------------------------------------------
- TFileSystemInfo::TFileSystemInfo()
- {
- memset(&IsCapable, false, sizeof(IsCapable));
- }
- //---------------------------------------------------------------------------
- const char *LogLineMarks = "<>!.*";
- __fastcall TSessionLog::TSessionLog(TSessionUI* UI, TSessionData * SessionData,
- TConfiguration * Configuration):
- TStringList()
- {
- FCriticalSection = new TCriticalSection;
- FConfiguration = Configuration;
- FParent = NULL;
- FUI = UI;
- FSessionData = SessionData;
- FFile = NULL;
- FLoggedLines = 0;
- FTopIndex = -1;
- FCurrentLogFileName = "";
- FCurrentFileName = "";
- ReflectSettings();
- }
- //---------------------------------------------------------------------------
- __fastcall TSessionLog::~TSessionLog()
- {
- CloseLogFile();
- delete FCriticalSection;
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::Lock()
- {
- FCriticalSection->Enter();
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::Unlock()
- {
- FCriticalSection->Leave();
- }
- //---------------------------------------------------------------------------
- AnsiString __fastcall TSessionLog::GetSessionName()
- {
- assert(FSessionData != NULL);
- return FSessionData->SessionName;
- }
- //---------------------------------------------------------------------------
- AnsiString __fastcall TSessionLog::GetLine(Integer Index)
- {
- return Strings[Index - FTopIndex];
- }
- //---------------------------------------------------------------------------
- TLogLineType __fastcall TSessionLog::GetType(int Index)
- {
- return (TLogLineType)Objects[Index - FTopIndex];
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::DoAddToParent(TLogLineType Type, const AnsiString & Line)
- {
- assert(FParent != NULL);
- FParent->Add(Type, Line);
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::DoAddToSelf(TLogLineType Type, const AnsiString & Line)
- {
- if (FTopIndex < 0)
- {
- FTopIndex = 0;
- }
- TStringList::AddObject(Line, (TObject*)Type);
- FLoggedLines++;
- if (LogToFile())
- {
- if (FFile == NULL)
- {
- OpenLogFile();
- }
- if (FFile != NULL)
- {
- AnsiString Timestamp = FormatDateTime(" yyyy-mm-dd hh:nn:ss.zzz ", Now());
- fputc(LogLineMarks[Type], (FILE *)FFile);
- fwrite(Timestamp.c_str(), Timestamp.Length(), 1, (FILE *)FFile);
- // use fwrite instead of fprintf to make sure that even
- // non-ascii data (unicode) gets in.
- fwrite(Line.c_str(), Line.Length(), 1, (FILE *)FFile);
- fputc('\n', (FILE *)FFile);
- }
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::DoAdd(TLogLineType Type, AnsiString Line,
- void __fastcall (__closure *f)(TLogLineType Type, const AnsiString & Line))
- {
- AnsiString Prefix;
- if (!Name.IsEmpty())
- {
- Prefix = "[" + Name + "] ";
- }
- while (!Line.IsEmpty())
- {
- f(Type, Prefix + CutToChar(Line, '\n', false));
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::Add(TLogLineType Type, const AnsiString & Line)
- {
- assert(FConfiguration);
- if (Logging)
- {
- try
- {
- if (FParent != NULL)
- {
- DoAdd(Type, Line, &DoAddToParent);
- }
- else
- {
- TGuard Guard(FCriticalSection);
- BeginUpdate();
- try
- {
- DoAdd(Type, Line, DoAddToSelf);
- }
- __finally
- {
- DeleteUnnecessary();
- EndUpdate();
- }
- }
- }
- catch (Exception &E)
- {
- // We failed logging, turn it of and notify user.
- FConfiguration->Logging = false;
- try
- {
- throw ExtException(&E, LOG_GEN_ERROR);
- }
- catch (Exception &E)
- {
- AddException(&E);
- FUI->ShowExtendedException(&E);
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::AddException(Exception * E)
- {
- if (E != NULL)
- {
- Add(llException, ExceptionLogString(E));
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::ReflectSettings()
- {
- TGuard Guard(FCriticalSection);
- FLogging = (FParent != NULL) || FConfiguration->Logging;
- // if logging to file was turned off or log file was change -> close current log file
- if ((FFile != NULL) &&
- (!LogToFile() || (FCurrentLogFileName != FConfiguration->LogFileName)))
- {
- CloseLogFile();
- }
- DeleteUnnecessary();
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::SetParent(TSessionLog * value)
- {
- if (FParent != value)
- {
- FParent = value;
- ReflectSettings();
- }
- }
- //---------------------------------------------------------------------------
- bool __fastcall TSessionLog::LogToFile()
- {
- return Logging && FConfiguration->LogToFile && (FParent == NULL);
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::CloseLogFile()
- {
- if (FFile != NULL)
- {
- fclose((FILE *)FFile);
- FFile = NULL;
- }
- FCurrentLogFileName = "";
- FCurrentFileName = "";
- }
- //---------------------------------------------------------------------------
- void TSessionLog::OpenLogFile()
- {
- try
- {
- assert(FFile == NULL);
- assert(FConfiguration != NULL);
- FCurrentLogFileName = FConfiguration->LogFileName;
- AnsiString NewFileName = StripPathQuotes(ExpandEnvironmentVariables(FCurrentLogFileName));
- TDateTime N = Now();
- for (int Index = 1; Index < NewFileName.Length(); Index++)
- {
- if (NewFileName[Index] == '&')
- {
- AnsiString Replacement;
- switch (tolower(NewFileName[Index + 1]))
- {
- case 'y':
- Replacement = FormatDateTime("yyyy", N);
- break;
- case 'm':
- Replacement = FormatDateTime("mm", N);
- break;
- case 'd':
- Replacement = FormatDateTime("dd", N);
- break;
- case 't':
- Replacement = FormatDateTime("hhnnss", N);
- break;
- case 'h':
- Replacement = MakeValidFileName(FSessionData->HostName);
- break;
- case 's':
- Replacement = MakeValidFileName(FSessionData->SessionName);
- break;
- case '&':
- Replacement = "&";
- break;
- default:
- Replacement = AnsiString("&") + NewFileName[Index + 1];
- break;
- }
- NewFileName.Delete(Index, 2);
- NewFileName.Insert(Replacement, Index);
- Index += Replacement.Length() - 1;
- }
- }
- FFile = fopen(NewFileName.c_str(), (FConfiguration->LogFileAppend ? "a" : "w"));
- if (FFile)
- {
- setvbuf((FILE *)FFile, NULL, _IONBF, BUFSIZ);
- FCurrentFileName = NewFileName;
- }
- else
- {
- throw Exception(FMTLOAD(LOG_OPENERROR, (NewFileName)));
- }
- }
- catch (Exception & E)
- {
- // We failed logging to file, turn it off and notify user.
- FCurrentLogFileName = "";
- FCurrentFileName = "";
- FConfiguration->LogToFile = false;
- try
- {
- throw ExtException(&E, LOG_GEN_ERROR);
- }
- catch (Exception & E)
- {
- AddException(&E);
- FUI->ShowExtendedException(&E);
- }
- }
- }
- //---------------------------------------------------------------------------
- void TSessionLog::DeleteUnnecessary()
- {
- BeginUpdate();
- try
- {
- if (!Logging || (FParent != NULL))
- {
- Clear();
- }
- else
- {
- while (!FConfiguration->LogWindowComplete && (Count > FConfiguration->LogWindowLines))
- {
- Delete(0);
- FTopIndex++;
- }
- }
- }
- __finally
- {
- EndUpdate();
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::AddStartupInfo()
- {
- if (Logging)
- {
- if (FParent != NULL)
- {
- // do not add session info for secondary session
- // (this should better be handled in the TSecondaryTerminal)
- }
- else
- {
- DoAddStartupInfo(FSessionData);
- }
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::DoAddStartupInfo(TSessionData * Data)
- {
- assert(Logging);
- TGuard Guard(FCriticalSection);
- BeginUpdate();
- try
- {
- #define ADF(S, F) DoAdd(llMessage, FORMAT(S, F), DoAddToSelf);
- AddSeparator();
- ADF("WinSCP %s (OS %s)", (FConfiguration->VersionStr, FConfiguration->OSVersionStr));
- ADF("Login time: %s", (FormatDateTime("dddddd tt", Now())));
- AddSeparator();
- ADF("Session name: %s", (Data->SessionName));
- ADF("Host name: %s (Port: %d)", (Data->HostName, Data->PortNumber));
- ADF("User name: %s (Password: %s, Key file: %s)",
- (Data->UserName, BooleanToEngStr(!Data->Password.IsEmpty()),
- BooleanToEngStr(!Data->PublicKeyFile.IsEmpty())))
- ADF("Tunnel: %s", (BooleanToEngStr(Data->Tunnel)));
- if (Data->Tunnel)
- {
- ADF("Tunnel: Host name: %s (Port: %d)", (Data->TunnelHostName, Data->TunnelPortNumber));
- ADF("Tunnel: User name: %s (Password: %s, Key file: %s)",
- (Data->TunnelUserName, BooleanToEngStr(!Data->TunnelPassword.IsEmpty()),
- BooleanToEngStr(!Data->TunnelPublicKeyFile.IsEmpty())))
- ADF("Tunnel: Local port number: %d", (Data->TunnelLocalPortNumber));
- }
- ADF("Transfer Protocol: %s", (Data->FSProtocolStr));
- char * PingTypes = "-NC";
- TPingType PingType;
- int PingInterval;
- if (Data->FSProtocol == fsFTP)
- {
- PingType = Data->FtpPingType;
- PingInterval = Data->FtpPingInterval;
- }
- else
- {
- PingType = Data->PingType;
- PingInterval = Data->PingInterval;
- }
- ADF("Ping type: %s, Ping interval: %d sec; Timeout: %d sec",
- (AnsiString(PingTypes[PingType]), PingInterval, Data->Timeout));
- ADF("Proxy: %s", (ProxyMethodList[Data->ProxyMethod]));
- if (Data->ProxyMethod != pmNone)
- {
- ADF("HostName: %s (Port: %d); Username: %s; Passwd: %s",
- (Data->ProxyHost, Data->ProxyPort,
- Data->ProxyUsername, BooleanToEngStr(!Data->ProxyPassword.IsEmpty())));
- if (Data->ProxyMethod == pmTelnet)
- {
- ADF("Telnet command: %s", (Data->ProxyTelnetCommand));
- }
- }
- if (Data->UsesSsh)
- {
- ADF("SSH protocol version: %s; Compression: %s",
- (Data->SshProtStr, BooleanToEngStr(Data->Compression)));
- ADF("Agent forwarding: %s; TIS/CryptoCard: %s; KI: %s; GSSAPI: %s",
- (BooleanToEngStr(Data->AgentFwd), BooleanToEngStr(Data->AuthTIS),
- BooleanToEngStr(Data->AuthKI), BooleanToEngStr(Data->AuthGSSAPI)));
- if (Data->AuthGSSAPI)
- {
- ADF("GSSAPI: Forwarding: %s; Server realm: %s",
- (BooleanToEngStr(Data->GSSAPIFwdTGT), Data->GSSAPIServerRealm));
- }
- ADF("Ciphers: %s; Ssh2DES: %s",
- (Data->CipherList, BooleanToEngStr(Data->Ssh2DES)));
- AnsiString Bugs;
- char const * BugFlags = "A+-";
- for (int Index = 0; Index < BUG_COUNT; Index++)
- {
- Bugs += AnsiString(BugFlags[Data->Bug[(TSshBug)Index]])+(Index<BUG_COUNT-1?",":"");
- }
- ADF("SSH Bugs: %s", (Bugs));
- Bugs = "";
- for (int Index = 0; Index < SFTP_BUG_COUNT; Index++)
- {
- Bugs += AnsiString(BugFlags[Data->SFTPBug[(TSftpBug)Index]])+(Index<SFTP_BUG_COUNT-1?",":"");
- }
- ADF("SFTP Bugs: %s", (Bugs));
- ADF("Return code variable: %s; Lookup user groups: %s",
- ((Data->DetectReturnVar ? AnsiString("Autodetect") : Data->ReturnVar),
- BooleanToEngStr(Data->LookupUserGroups)));
- ADF("Shell: %s, EOL: %d", ((Data->Shell.IsEmpty()? AnsiString("default") : Data->Shell), Data->EOLType));
- ADF("Clear aliases: %s, Unset nat.vars: %s, Resolve symlinks: %s",
- (BooleanToEngStr(Data->ClearAliases), BooleanToEngStr(Data->UnsetNationalVars),
- BooleanToEngStr(Data->ResolveSymlinks)));
- ADF("Alias LS: %s, Ign LS warn: %s, Scp1 Comp: %s",
- (BooleanToEngStr(Data->AliasGroupList),
- BooleanToEngStr(Data->IgnoreLsWarnings),
- BooleanToEngStr(Data->Scp1Compatibility)));
- }
- if (Data->FSProtocol == fsFTP)
- {
- ADF("FTP: Passive: %s", (BooleanToEngStr(Data->FtpPasvMode)));
- }
- ADF("Local directory: %s, Remote directory: %s, Update: %s, Cache: %s",
- ((Data->LocalDirectory.IsEmpty() ? AnsiString("default") : Data->LocalDirectory),
- (Data->RemoteDirectory.IsEmpty() ? AnsiString("home") : Data->RemoteDirectory),
- BooleanToEngStr(Data->UpdateDirectories),
- BooleanToEngStr(Data->CacheDirectories)));
- ADF("Cache directory changes: %s, Permanent: %s",
- (BooleanToEngStr(Data->CacheDirectoryChanges),
- BooleanToEngStr(Data->PreserveDirectoryChanges)));
- ADF("DST mode: %d", (int(Data->DSTMode)));
- AddSeparator();
- #undef ADF
- }
- __finally
- {
- DeleteUnnecessary();
- EndUpdate();
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::AddSeparator()
- {
- Add(llMessage, "--------------------------------------------------------------------------");
- }
- //---------------------------------------------------------------------------
- int __fastcall TSessionLog::GetBottomIndex()
- {
- return (Count > 0 ? (TopIndex + Count - 1) : -1);
- }
- //---------------------------------------------------------------------------
- bool __fastcall TSessionLog::GetLoggingToFile()
- {
- assert((FFile == NULL) || LogToFile());
- return (FFile != NULL);
- }
- //---------------------------------------------------------------------------
- void __fastcall TSessionLog::Clear()
- {
- TGuard Guard(FCriticalSection);
- FTopIndex += Count;
- TStringList::Clear();
- }
|