mirror of
https://github.com/winscp/winscp.git
synced 2026-10-24 02:28:55 +03:00
Bug 1798: Allow configuring additional PuTTY settings (e.g. terminal settings) to be used when opening a session in PuTTY
https://winscp.net/tracker/1798 Also fixes a build broken byeef27ac3(and still not fixed by5d189553) Source commit: 0bd13d447e6da8427be1506b7c561d74e83b1b85
This commit is contained in:
@@ -1225,9 +1225,14 @@ TStrings * __fastcall TConfiguration::GetOptionsStorage()
|
||||
return FOptionsStorage.get();
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
UnicodeString __fastcall TConfiguration::GetPuttySessionsSubKey()
|
||||
{
|
||||
return StoredSessionsSubKey;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
UnicodeString __fastcall TConfiguration::GetPuttySessionsKey()
|
||||
{
|
||||
return PuttyRegistryStorageKey + L"\\Sessions";
|
||||
return PuttyRegistryStorageKey + L"\\" + PuttySessionsSubKey;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
UnicodeString __fastcall TConfiguration::GetStoredSessionsSubKey()
|
||||
|
||||
@@ -93,6 +93,7 @@ private:
|
||||
UnicodeString __fastcall GetFileVersion(TVSFixedFileInfo * Info);
|
||||
UnicodeString __fastcall GetStoredSessionsSubKey();
|
||||
UnicodeString __fastcall GetPuttySessionsKey();
|
||||
UnicodeString __fastcall GetPuttySessionsSubKey();
|
||||
void __fastcall SetRandomSeedFile(UnicodeString value);
|
||||
UnicodeString __fastcall GetRandomSeedFileName();
|
||||
void __fastcall SetPuttyRegistryStorageKey(UnicodeString value);
|
||||
@@ -270,6 +271,7 @@ public:
|
||||
__property UnicodeString StoredSessionsSubKey = {read=GetStoredSessionsSubKey};
|
||||
__property UnicodeString PuttyRegistryStorageKey = { read=FPuttyRegistryStorageKey, write=SetPuttyRegistryStorageKey };
|
||||
__property UnicodeString PuttySessionsKey = { read=GetPuttySessionsKey };
|
||||
__property UnicodeString PuttySessionsSubKey = { read=GetPuttySessionsSubKey };
|
||||
__property UnicodeString RandomSeedFile = { read=FRandomSeedFile, write=SetRandomSeedFile };
|
||||
__property UnicodeString RandomSeedFileName = { read=GetRandomSeedFileName };
|
||||
__property UnicodeString SshHostKeysSubKey = { read=GetSshHostKeysSubKey };
|
||||
|
||||
@@ -26,7 +26,7 @@ UnicodeString __fastcall MungeStr(const UnicodeString & Str, bool ForceAnsi, boo
|
||||
RawByteString Source;
|
||||
if (ForceAnsi)
|
||||
{
|
||||
Source = RawByteString(AnsiString(Str));
|
||||
Source = RawByteString(PuttyStr(Str));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -69,9 +69,14 @@ UnicodeString __fastcall UnMungeStr(const UnicodeString & Str)
|
||||
return Result;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
AnsiString PuttyStr(const UnicodeString & Str)
|
||||
{
|
||||
return AnsiString(Str);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
UnicodeString __fastcall PuttyMungeStr(const UnicodeString & Str)
|
||||
{
|
||||
return MungeStr(Str, false, false);
|
||||
return MungeStr(Str, true, false);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
UnicodeString __fastcall MungeIniName(const UnicodeString & Str)
|
||||
@@ -150,6 +155,12 @@ UnicodeString __fastcall THierarchicalStorage::GetCurrentSubKey()
|
||||
return UnMungeStr(GetCurrentSubKeyMunged());
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall THierarchicalStorage::ConfigureForPutty()
|
||||
{
|
||||
MungeStringValues = false;
|
||||
ForceAnsi = true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool __fastcall THierarchicalStorage::OpenRootKey(bool CanCreate)
|
||||
{
|
||||
return OpenSubKey(UnicodeString(), CanCreate);
|
||||
|
||||
@@ -15,6 +15,7 @@ friend class TCustomIniFileStorage;
|
||||
public:
|
||||
__fastcall THierarchicalStorage(const UnicodeString & AStorage);
|
||||
virtual __fastcall ~THierarchicalStorage();
|
||||
void __fastcall ConfigureForPutty();
|
||||
virtual bool __fastcall OpenRootKey(bool CanCreate);
|
||||
virtual bool __fastcall OpenSubKey(const UnicodeString & SubKey, bool CanCreate);
|
||||
virtual void __fastcall CloseSubKey();
|
||||
@@ -259,5 +260,6 @@ protected:
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
UnicodeString __fastcall PuttyMungeStr(const UnicodeString & Str);
|
||||
AnsiString PuttyStr(const UnicodeString & Str);
|
||||
//---------------------------------------------------------------------------
|
||||
#endif
|
||||
|
||||
@@ -381,6 +381,12 @@ ScpSeat::ScpSeat(TSecureShell * ASecureShell)
|
||||
vt = &ScpSeatVtable;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
static std::unique_ptr<TCriticalSection> PuttyRegistrySection(TraceInitPtr(new TCriticalSection()));
|
||||
enum TPuttyRegistryMode { prmPass, prmRedirect, prmCollect, prmFail };
|
||||
static TPuttyRegistryMode PuttyRegistryMode = prmRedirect;
|
||||
typedef std::map<UnicodeString, unsigned long> TPuttyRegistryTypes;
|
||||
TPuttyRegistryTypes PuttyRegistryTypes;
|
||||
//---------------------------------------------------------------------------
|
||||
static long OpenWinSCPKey(HKEY Key, const char * SubKey, HKEY * Result, bool CanCreate)
|
||||
{
|
||||
long R;
|
||||
@@ -428,17 +434,53 @@ static long OpenWinSCPKey(HKEY Key, const char * SubKey, HKEY * Result, bool Can
|
||||
//---------------------------------------------------------------------------
|
||||
long reg_open_winscp_key(HKEY Key, const char * SubKey, HKEY * Result)
|
||||
{
|
||||
if (PuttyRegistryMode == prmPass)
|
||||
{
|
||||
return RegOpenKeyA(Key, SubKey, Result);
|
||||
}
|
||||
else if (PuttyRegistryMode == prmCollect)
|
||||
{
|
||||
*Result = reinterpret_cast<HKEY>(1);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
else if (PuttyRegistryMode == prmFail)
|
||||
{
|
||||
return ERROR_CANTOPEN;
|
||||
}
|
||||
|
||||
DebugAssert(PuttyRegistryMode == prmRedirect);
|
||||
return OpenWinSCPKey(Key, SubKey, Result, false);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
long reg_create_winscp_key(HKEY Key, const char * SubKey, HKEY * Result)
|
||||
{
|
||||
if (PuttyRegistryMode == prmPass)
|
||||
{
|
||||
return RegCreateKeyA(Key, SubKey, Result);
|
||||
}
|
||||
else if (PuttyRegistryMode == prmCollect)
|
||||
{
|
||||
*Result = reinterpret_cast<HKEY>(1);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
DebugAssert(PuttyRegistryMode == prmRedirect);
|
||||
return OpenWinSCPKey(Key, SubKey, Result, true);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
long reg_query_winscp_value_ex(HKEY Key, const char * ValueName, unsigned long * /*Reserved*/,
|
||||
long reg_query_winscp_value_ex(HKEY Key, const char * ValueName, unsigned long * Reserved,
|
||||
unsigned long * Type, unsigned char * Data, unsigned long * DataSize)
|
||||
{
|
||||
if (PuttyRegistryMode == prmPass)
|
||||
{
|
||||
return RegQueryValueExA(Key, ValueName, Reserved, Type, Data, DataSize);
|
||||
}
|
||||
else if (PuttyRegistryMode == prmCollect)
|
||||
{
|
||||
return ERROR_READ_FAULT;
|
||||
}
|
||||
|
||||
DebugAssert(PuttyRegistryMode == prmRedirect);
|
||||
long R;
|
||||
DebugAssert(Configuration != NULL);
|
||||
|
||||
@@ -483,9 +525,19 @@ long reg_query_winscp_value_ex(HKEY Key, const char * ValueName, unsigned long *
|
||||
return R;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
long reg_set_winscp_value_ex(HKEY Key, const char * ValueName, unsigned long /*Reserved*/,
|
||||
long reg_set_winscp_value_ex(HKEY Key, const char * ValueName, unsigned long Reserved,
|
||||
unsigned long Type, const unsigned char * Data, unsigned long DataSize)
|
||||
{
|
||||
if (PuttyRegistryMode == prmPass)
|
||||
{
|
||||
return RegSetValueExA(Key, ValueName, Reserved, Type, Data, DataSize);
|
||||
}
|
||||
else if (PuttyRegistryMode == prmCollect)
|
||||
{
|
||||
PuttyRegistryTypes[ValueName] = Type;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
DebugAssert(PuttyRegistryMode == prmRedirect);
|
||||
DebugAssert(Configuration != NULL);
|
||||
|
||||
DebugAssert(Type == REG_SZ);
|
||||
@@ -503,6 +555,15 @@ long reg_set_winscp_value_ex(HKEY Key, const char * ValueName, unsigned long /*R
|
||||
//---------------------------------------------------------------------------
|
||||
long reg_close_winscp_key(HKEY Key)
|
||||
{
|
||||
if (PuttyRegistryMode == prmPass)
|
||||
{
|
||||
return RegCloseKey(Key);
|
||||
}
|
||||
else if (PuttyRegistryMode == prmCollect)
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
DebugAssert(PuttyRegistryMode == prmRedirect);
|
||||
DebugAssert(Configuration != NULL);
|
||||
|
||||
THierarchicalStorage * Storage = reinterpret_cast<THierarchicalStorage *>(Key);
|
||||
@@ -999,4 +1060,78 @@ UnicodeString GetDecompressorName(const ssh_decompressor * Decompressor)
|
||||
return Result;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void WritePuttySettings(THierarchicalStorage * Storage, const UnicodeString & ASettings)
|
||||
{
|
||||
if (PuttyRegistryTypes.empty())
|
||||
{
|
||||
TGuard Guard(PuttyRegistrySection.get());
|
||||
TValueRestorer<TPuttyRegistryMode> PuttyRegistryModeRestorer(PuttyRegistryMode);
|
||||
PuttyRegistryMode = prmCollect;
|
||||
Conf * conf = conf_new();
|
||||
try
|
||||
{
|
||||
do_defaults(NULL, conf);
|
||||
save_settings(NULL, conf);
|
||||
}
|
||||
__finally
|
||||
{
|
||||
conf_free(conf);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<TStrings> Settings(new TStringList());
|
||||
UnicodeString Buf = ASettings;
|
||||
UnicodeString Setting;
|
||||
while (CutToken(Buf, Setting))
|
||||
{
|
||||
Settings->Add(Setting);
|
||||
}
|
||||
|
||||
for (int Index = 0; Index < Settings->Count; Index++)
|
||||
{
|
||||
UnicodeString Name = Settings->Names[Index];
|
||||
TPuttyRegistryTypes::const_iterator IType = PuttyRegistryTypes.find(Name);
|
||||
if (IType != PuttyRegistryTypes.end())
|
||||
{
|
||||
UnicodeString Value = Settings->ValueFromIndex[Index];
|
||||
int I;
|
||||
if (IType->second == REG_SZ)
|
||||
{
|
||||
Storage->WriteStringRaw(Name, Value);
|
||||
}
|
||||
else if (DebugAlwaysTrue(IType->second == REG_DWORD) &&
|
||||
TryStrToInt(Value, I))
|
||||
{
|
||||
Storage->WriteInteger(Name, I);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void PuttyDefaults(Conf * conf)
|
||||
{
|
||||
TGuard Guard(PuttyRegistrySection.get());
|
||||
TValueRestorer<TPuttyRegistryMode> PuttyRegistryModeRestorer(PuttyRegistryMode);
|
||||
PuttyRegistryMode = prmFail;
|
||||
do_defaults(NULL, conf);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void SavePuttyDefaults(const UnicodeString & Name)
|
||||
{
|
||||
TGuard Guard(PuttyRegistrySection.get());
|
||||
TValueRestorer<TPuttyRegistryMode> PuttyRegistryModeRestorer(PuttyRegistryMode);
|
||||
PuttyRegistryMode = prmPass;
|
||||
Conf * conf = conf_new();
|
||||
try
|
||||
{
|
||||
PuttyDefaults(conf);
|
||||
AnsiString PuttyName = PuttyStr(Name);
|
||||
save_settings(PuttyName.c_str(), conf);
|
||||
}
|
||||
__finally
|
||||
{
|
||||
conf_free(conf);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -30,6 +30,7 @@ extern "C"
|
||||
UnicodeString GetCipherName(const ssh_cipher * Cipher);
|
||||
UnicodeString GetCompressorName(const ssh_compressor * Compressor);
|
||||
UnicodeString GetDecompressorName(const ssh_decompressor * Decompressor);
|
||||
void PuttyDefaults(Conf * conf);
|
||||
//---------------------------------------------------------------------------
|
||||
class TSecureShell;
|
||||
struct ScpSeat : public Seat
|
||||
|
||||
@@ -45,4 +45,10 @@ TStrings * SshKexList();
|
||||
TStrings * SshHostKeyList();
|
||||
TStrings * SshMacList();
|
||||
//---------------------------------------------------------------------------
|
||||
class TSessionData;
|
||||
void SaveAsPutty(const UnicodeString & Name, TSessionData * Data);
|
||||
class THierarchicalStorage;
|
||||
void WritePuttySettings(THierarchicalStorage * Storage, const UnicodeString & Settings);
|
||||
void SavePuttyDefaults(const UnicodeString & Name);
|
||||
//---------------------------------------------------------------------------
|
||||
#endif
|
||||
|
||||
@@ -166,7 +166,7 @@ Conf * __fastcall TSecureShell::StoreToConfig(TSessionData * Data, bool Simple)
|
||||
{
|
||||
Conf * conf = conf_new();
|
||||
|
||||
do_defaults(NULL, conf);
|
||||
PuttyDefaults(conf);
|
||||
|
||||
// user-configurable settings
|
||||
conf_set_str(conf, CONF_host, AnsiString(Data->HostNameExpanded).c_str());
|
||||
|
||||
@@ -274,6 +274,8 @@ void __fastcall TSessionData::DefaultSettings()
|
||||
|
||||
FtpProxyLogonType = 0; // none
|
||||
|
||||
PuttySettings = UnicodeString();
|
||||
|
||||
CustomParam1 = L"";
|
||||
CustomParam2 = L"";
|
||||
}
|
||||
@@ -445,6 +447,8 @@ void __fastcall TSessionData::NonPersistant()
|
||||
\
|
||||
PROPERTY_HANDLER(EncryptKey, F); \
|
||||
\
|
||||
PROPERTY(PuttySettings); \
|
||||
\
|
||||
PROPERTY(CustomParam1); \
|
||||
PROPERTY(CustomParam2);
|
||||
#define META_PROPERTIES \
|
||||
@@ -846,6 +850,8 @@ void __fastcall TSessionData::DoLoad(THierarchicalStorage * Storage, bool PuttyI
|
||||
Link = Storage->ReadString(L"Link", Link);
|
||||
NameOverride = Storage->ReadString(L"NameOverride", NameOverride);
|
||||
|
||||
PuttySettings = Storage->ReadString(L"PuttySettings", PuttySettings);
|
||||
|
||||
CustomParam1 = Storage->ReadString(L"CustomParam1", CustomParam1);
|
||||
CustomParam2 = Storage->ReadString(L"CustomParam2", CustomParam2);
|
||||
|
||||
@@ -1181,6 +1187,8 @@ void __fastcall TSessionData::DoSave(THierarchicalStorage * Storage,
|
||||
WRITE_DATA(String, Link);
|
||||
WRITE_DATA(String, NameOverride);
|
||||
|
||||
WRITE_DATA(String, PuttySettings);
|
||||
|
||||
WRITE_DATA(String, CustomParam1);
|
||||
WRITE_DATA(String, CustomParam2);
|
||||
}
|
||||
@@ -1191,6 +1199,11 @@ void __fastcall TSessionData::DoSave(THierarchicalStorage * Storage,
|
||||
bool SaveAll = (Default == NULL) && DoNotEncryptPasswords && !PuttyExport;
|
||||
|
||||
SavePasswords(Storage, PuttyExport, DoNotEncryptPasswords, SaveAll);
|
||||
|
||||
if (PuttyExport)
|
||||
{
|
||||
WritePuttySettings(Storage, PuttySettings);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
TStrings * __fastcall TSessionData::SaveToOptions(const TSessionData * Default, bool SaveName)
|
||||
@@ -3743,6 +3756,11 @@ TAutoSwitch __fastcall TSessionData::GetBug(TSshBug Bug) const
|
||||
return FBugs[Bug];
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void __fastcall TSessionData::SetPuttySettings(UnicodeString value)
|
||||
{
|
||||
SET_SESSION_PROPERTY(PuttySettings);
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void __fastcall TSessionData::SetCustomParam1(UnicodeString value)
|
||||
{
|
||||
SET_SESSION_PROPERTY(CustomParam1);
|
||||
|
||||
@@ -171,6 +171,7 @@ private:
|
||||
bool FProxyLocalhost;
|
||||
int FFtpProxyLogonType;
|
||||
TAutoSwitch FBugs[BUG_COUNT];
|
||||
UnicodeString FPuttySettings;
|
||||
UnicodeString FCustomParam1;
|
||||
UnicodeString FCustomParam2;
|
||||
bool FResolveSymlinks;
|
||||
@@ -343,6 +344,7 @@ private:
|
||||
void __fastcall SetBug(TSshBug Bug, TAutoSwitch value);
|
||||
TAutoSwitch __fastcall GetBug(TSshBug Bug) const;
|
||||
UnicodeString __fastcall GetSessionKey();
|
||||
void __fastcall SetPuttySettings(UnicodeString value);
|
||||
void __fastcall SetCustomParam1(UnicodeString value);
|
||||
void __fastcall SetCustomParam2(UnicodeString value);
|
||||
void __fastcall SetResolveSymlinks(bool value);
|
||||
@@ -604,6 +606,7 @@ public:
|
||||
__property bool ProxyLocalhost = { read=FProxyLocalhost, write=SetProxyLocalhost };
|
||||
__property int FtpProxyLogonType = { read=FFtpProxyLogonType, write=SetFtpProxyLogonType };
|
||||
__property TAutoSwitch Bug[TSshBug Bug] = { read=GetBug, write=SetBug };
|
||||
__property UnicodeString PuttySettings = { read = FPuttySettings, write = SetPuttySettings };
|
||||
__property UnicodeString CustomParam1 = { read = FCustomParam1, write = SetCustomParam1 };
|
||||
__property UnicodeString CustomParam2 = { read = FCustomParam2, write = SetCustomParam2 };
|
||||
__property UnicodeString SessionKey = { read = GetSessionKey };
|
||||
|
||||
@@ -177,6 +177,8 @@ void __fastcall TSiteAdvancedDialog::LoadSession()
|
||||
|
||||
TrimVMSVersionsCheck->Checked = FSessionData->TrimVMSVersions;
|
||||
|
||||
PuttySettingsEdit->Text = FSessionData->PuttySettings;
|
||||
|
||||
// Environment/Recycle bin page
|
||||
DeleteToRecycleBinCheck->Checked = FSessionData->DeleteToRecycleBin;
|
||||
OverwrittenToRecycleBinCheck->Checked = FSessionData->OverwrittenToRecycleBin;
|
||||
@@ -418,6 +420,8 @@ void __fastcall TSiteAdvancedDialog::LoadSession()
|
||||
FColor = (TColor)FSessionData->Color;
|
||||
}
|
||||
|
||||
EnableControl(PuttyGroup, !DoesSessionExistInPutty(FSessionData));
|
||||
|
||||
UpdateControls();
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
@@ -554,6 +558,8 @@ void __fastcall TSiteAdvancedDialog::SaveSession(TSessionData * SessionData)
|
||||
|
||||
SessionData->TrimVMSVersions = TrimVMSVersionsCheck->Checked;
|
||||
|
||||
SessionData->PuttySettings = PuttySettingsEdit->Text;
|
||||
|
||||
// Environment/Recycle bin page
|
||||
SessionData->DeleteToRecycleBin = DeleteToRecycleBinCheck->Checked;
|
||||
SessionData->OverwrittenToRecycleBin = OverwrittenToRecycleBinCheck->Checked;
|
||||
@@ -677,6 +683,14 @@ void __fastcall TSiteAdvancedDialog::SaveSession(TSessionData * SessionData)
|
||||
SessionData->Color = FColor;
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
TSessionData * __fastcall TSiteAdvancedDialog::GetSessionData()
|
||||
{
|
||||
std::unique_ptr<TSessionData> SessionData(new TSessionData(UnicodeString()));
|
||||
SessionData->Assign(FSessionData);
|
||||
SaveSession(SessionData.get());
|
||||
return SessionData.release();
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void __fastcall TSiteAdvancedDialog::UpdateNavigationTree()
|
||||
{
|
||||
TTreeNode * ActiveNode = NULL;
|
||||
@@ -1122,6 +1136,7 @@ void __fastcall TSiteAdvancedDialog::ChangePage(TTabSheet * Tab)
|
||||
void __fastcall TSiteAdvancedDialog::PageChanged()
|
||||
{
|
||||
FPrivateKeyMonitors.reset(NULL);
|
||||
ClosePuttySettings();
|
||||
|
||||
bool Found = false;
|
||||
if (PageControl->ActivePage)
|
||||
@@ -1580,9 +1595,7 @@ void __fastcall TSiteAdvancedDialog::PrivateKeyGenerateItemClick(TObject * /*Sen
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSiteAdvancedDialog::PrivateKeyUploadItemClick(TObject * /*Sender*/)
|
||||
{
|
||||
std::unique_ptr<TSessionData> SessionData(new TSessionData(UnicodeString()));
|
||||
SessionData->Assign(FSessionData);
|
||||
SaveSession(SessionData.get());
|
||||
std::unique_ptr<TSessionData> SessionData(GetSessionData());
|
||||
SessionData->FSProtocol = fsSFTPonly; // no SCP fallback, as SCP does not implement GetHomeDirectory
|
||||
SessionData->RemoteDirectory = UnicodeString();
|
||||
|
||||
@@ -1670,3 +1683,123 @@ void __fastcall TSiteAdvancedDialog::EncryptKeyEditExit(TObject * /*Sender*/)
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void TSiteAdvancedDialog::SerializePuttyRegistry(const UnicodeString & Key, TStrings * Values)
|
||||
{
|
||||
std::unique_ptr<TRegistry> Registry(new TRegistry());
|
||||
if (DebugAlwaysTrue(Registry->OpenKeyReadOnly(Key)))
|
||||
{
|
||||
std::unique_ptr<TStrings> Names(new TStringList());
|
||||
Registry->GetValueNames(Names.get());
|
||||
for (int Index = 0; Index < Names->Count; Index++)
|
||||
{
|
||||
UnicodeString Name = Names->Strings[Index];
|
||||
TRegDataType Type = Registry->GetDataType(Name);
|
||||
UnicodeString Value;
|
||||
if (Type == rdString)
|
||||
{
|
||||
Value = UnicodeString(PuttyStr(Registry->ReadString(Name)));
|
||||
}
|
||||
else if (DebugAlwaysTrue(Type == rdInteger))
|
||||
{
|
||||
Value = StrToInt(Registry->ReadInteger(Name));
|
||||
}
|
||||
SetStringValueEvenIfEmpty(Values, Name, Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSiteAdvancedDialog::PuttySettingsTimer(TObject *)
|
||||
{
|
||||
if (PuttySettingsEdit->Modified)
|
||||
{
|
||||
FPuttySettingsTimer->Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::unique_ptr<TStrings> NewPuttyRegSettings(new TStringList());
|
||||
SerializePuttyRegistry(GetPuttySiteKey(), NewPuttyRegSettings.get());
|
||||
|
||||
std::unique_ptr<TStrings> PuttySettings(new TStringList());
|
||||
for (int NewIndex = 0; NewIndex < NewPuttyRegSettings->Count; NewIndex++)
|
||||
{
|
||||
UnicodeString Name = NewPuttyRegSettings->Names[NewIndex];
|
||||
UnicodeString NewValue = NewPuttyRegSettings->ValueFromIndex[NewIndex];
|
||||
int Index = -1; // shut up
|
||||
// Ignoring values we do not know (from future versions of PuTTY),
|
||||
// as we cannot tell if they are modified or not
|
||||
if (((Index = FPuttyRegSettings->IndexOfName(Name)) >= 0) &&
|
||||
(FPuttyRegSettings->ValueFromIndex[Index] != NewValue))
|
||||
{
|
||||
SetStringValueEvenIfEmpty(PuttySettings.get(), Name, NewValue);
|
||||
}
|
||||
}
|
||||
|
||||
PuttySettingsEdit->Text = StringsToParams(PuttySettings.get()).TrimLeft();
|
||||
UpdateControls();
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
UnicodeString __fastcall TSiteAdvancedDialog::GetPuttySiteName()
|
||||
{
|
||||
return FORMAT(L"(%s)", (FMTLOAD(PUTTY_SETTINGS_SITE_NAME, (FSessionData->SessionName))));
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
UnicodeString __fastcall TSiteAdvancedDialog::GetPuttySiteKey()
|
||||
{
|
||||
return OriginalPuttyRegistryStorageKey + L"\\" + Configuration->PuttySessionsSubKey + L"\\" + PuttyMungeStr(GetPuttySiteName());
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSiteAdvancedDialog::ClosePuttySettings()
|
||||
{
|
||||
if (FPuttySettingsTimer.get() != NULL)
|
||||
{
|
||||
FPuttySettingsTimer.reset(NULL);
|
||||
std::unique_ptr<TRegistry> Registry(new TRegistry());
|
||||
Registry->DeleteKey(GetPuttySiteKey());
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSiteAdvancedDialog::PuttySettingsButtonClick(TObject *)
|
||||
{
|
||||
ClosePuttySettings();
|
||||
UnicodeString SiteName = GetPuttySiteName();
|
||||
|
||||
MessageDialog(FMTLOAD(PUTTY_SETTINGS_INSTRUCTIONS, (SiteName, SiteName)), qtInformation, qaOK, HELP_PUTTY_SETTINGS);
|
||||
|
||||
PuttySettingsEdit->Modified = false;
|
||||
std::unique_ptr<TSessionData> SessionData(GetSessionData());
|
||||
UnicodeString PuttySettings = SessionData->PuttySettings;
|
||||
SessionData->PuttySettings = UnicodeString();
|
||||
SavePuttyDefaults(SiteName);
|
||||
ExportSessionToPutty(SessionData.get(), false, SiteName);
|
||||
|
||||
UnicodeString PuttySiteKey = GetPuttySiteKey();
|
||||
FPuttyRegSettings.reset(new TStringList());
|
||||
SerializePuttyRegistry(PuttySiteKey, FPuttyRegSettings.get());
|
||||
|
||||
SessionData->PuttySettings = PuttySettings;
|
||||
ExportSessionToPutty(SessionData.get(), false, SiteName);
|
||||
|
||||
UnicodeString Program, Params, Dir;
|
||||
SplitCommand(GUIConfiguration->PuttyPath, Program, Params, Dir);
|
||||
Program = ExpandEnvironmentVariables(Program);
|
||||
if (!FindFile(Program))
|
||||
{
|
||||
throw Exception(FMTLOAD(EXECUTE_APP_ERROR, (Program)));
|
||||
}
|
||||
|
||||
ExecuteShellChecked(Program, L"");
|
||||
|
||||
FPuttySettingsTimer.reset(new TTimer(this));
|
||||
FPuttySettingsTimer->OnTimer = PuttySettingsTimer;
|
||||
FPuttySettingsTimer->Interval = MSecsPerSec;
|
||||
FPuttySettingsTimer->Enabled = true;
|
||||
|
||||
UpdateControls();
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSiteAdvancedDialog::FormClose(TObject *, TCloseAction &)
|
||||
{
|
||||
ClosePuttySettings();
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -12,6 +12,7 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
|
||||
ParentFont = True
|
||||
OldCreateOrder = True
|
||||
Position = poOwnerFormCenter
|
||||
OnClose = FormClose
|
||||
OnCloseQuery = FormCloseQuery
|
||||
OnShow = FormShow
|
||||
DesignSize = (
|
||||
@@ -67,7 +68,7 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
|
||||
Top = 20
|
||||
Width = 241
|
||||
Height = 13
|
||||
Caption = '&End-of-line characters (if not indicated by server):'
|
||||
Caption = 'End-of-line &characters (if not indicated by server):'
|
||||
FocusControl = EOLTypeCombo
|
||||
end
|
||||
object UtfLabel: TLabel
|
||||
@@ -213,6 +214,47 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
|
||||
OnClick = DataChange
|
||||
end
|
||||
end
|
||||
object PuttyGroup: TGroupBox
|
||||
Left = 0
|
||||
Top = 252
|
||||
Width = 393
|
||||
Height = 98
|
||||
Anchors = [akLeft, akTop, akRight]
|
||||
Caption = 'PuTTY'
|
||||
TabOrder = 2
|
||||
DesignSize = (
|
||||
393
|
||||
98)
|
||||
object PuttySettingsLabel: TLabel
|
||||
Left = 12
|
||||
Top = 18
|
||||
Width = 116
|
||||
Height = 13
|
||||
Caption = '&PuTTY terminal settings:'
|
||||
FocusControl = EncryptKeyPasswordEdit
|
||||
end
|
||||
object PuttySettingsButton: TButton
|
||||
Left = 12
|
||||
Top = 61
|
||||
Width = 125
|
||||
Height = 25
|
||||
Anchors = [akTop, akRight]
|
||||
Caption = '&Edit in PuTTY...'
|
||||
TabOrder = 1
|
||||
OnClick = PuttySettingsButtonClick
|
||||
end
|
||||
object PuttySettingsEdit: TEdit
|
||||
Left = 12
|
||||
Top = 34
|
||||
Width = 370
|
||||
Height = 21
|
||||
MaxLength = 64
|
||||
TabOrder = 0
|
||||
Text = 'PuttySettingsEdit'
|
||||
OnChange = DataChange
|
||||
OnExit = EncryptKeyEditExit
|
||||
end
|
||||
end
|
||||
end
|
||||
object DirectoriesSheet: TTabSheet
|
||||
Tag = 2
|
||||
|
||||
@@ -276,6 +276,10 @@ __published:
|
||||
TComboBox *S3DefaultReqionCombo;
|
||||
TLabel *S3UrlStyleLabel;
|
||||
TComboBox *S3UrlStyleCombo;
|
||||
TGroupBox *PuttyGroup;
|
||||
TButton *PuttySettingsButton;
|
||||
TLabel *PuttySettingsLabel;
|
||||
TEdit *PuttySettingsEdit;
|
||||
void __fastcall DataChange(TObject *Sender);
|
||||
void __fastcall FormShow(TObject *Sender);
|
||||
void __fastcall PageControlChange(TObject *Sender);
|
||||
@@ -315,6 +319,8 @@ __published:
|
||||
void __fastcall ShowEncryptionKeyCheckClick(TObject *Sender);
|
||||
void __fastcall GenerateKeyButtonClick(TObject *Sender);
|
||||
void __fastcall EncryptKeyEditExit(TObject *Sender);
|
||||
void __fastcall PuttySettingsButtonClick(TObject *Sender);
|
||||
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
|
||||
|
||||
|
||||
public:
|
||||
@@ -340,9 +346,12 @@ private:
|
||||
TColor FColor;
|
||||
std::unique_ptr<TPopupMenu> FColorPopupMenu;
|
||||
std::unique_ptr<TObjectList> FPrivateKeyMonitors;
|
||||
std::unique_ptr<TStrings> FPuttyRegSettings;
|
||||
std::unique_ptr<TTimer> FPuttySettingsTimer;
|
||||
|
||||
void __fastcall LoadSession();
|
||||
void __fastcall UpdateControls();
|
||||
TSessionData * __fastcall GetSessionData();
|
||||
void __fastcall SaveSession(TSessionData * SessionData);
|
||||
void __fastcall CMDialogKey(TWMKeyDown & Message);
|
||||
void __fastcall WMHelp(TWMHelp & Message);
|
||||
@@ -360,6 +369,11 @@ private:
|
||||
bool __fastcall IsNeon(TFSProtocol FSProtocol);
|
||||
void __fastcall PrivateKeyCreatedOrModified(TObject * Sender, const UnicodeString FileName);
|
||||
TCustomEdit * __fastcall GetEncryptKeyEdit(bool AShow = true);
|
||||
void __fastcall PuttySettingsTimer(TObject * Sender);
|
||||
UnicodeString __fastcall GetPuttySiteName();
|
||||
UnicodeString __fastcall GetPuttySiteKey();
|
||||
void __fastcall ClosePuttySettings();
|
||||
void SerializePuttyRegistry(const UnicodeString & Key, TStrings * Values);
|
||||
|
||||
INTERFACE_HOOK;
|
||||
};
|
||||
|
||||
@@ -66,5 +66,6 @@
|
||||
#define HELP_FILE_COLORS "ui_file_color"
|
||||
#define HELP_AUTOMATIC_UPDATE "updates#automatic_upgrade"
|
||||
#define HELP_SITE_RAW "ui_login_raw"
|
||||
#define HELP_PUTTY_SETTINGS "ui_login_environment#putty"
|
||||
|
||||
#endif // TextsWin
|
||||
|
||||
@@ -294,6 +294,8 @@
|
||||
#define USAGE_PASSPHRASE 1584
|
||||
#define AUTO_WORKSPACE_ENABLE 1585
|
||||
#define USAGE_BROWSE 1586
|
||||
#define PUTTY_SETTINGS_INSTRUCTIONS 1587
|
||||
#define PUTTY_SETTINGS_SITE_NAME 1588
|
||||
|
||||
#define WIN_FORMS_STRINGS 1600
|
||||
#define COPY_FILE 1605
|
||||
|
||||
@@ -299,6 +299,8 @@ BEGIN
|
||||
USAGE_PASSPHRASE, "A passphrase for an encrypted private key or a client certificate"
|
||||
AUTO_WORKSPACE_ENABLE, "Press 'No' to enable automatic saving of the workspace."
|
||||
USAGE_BROWSE, "Selects the specified file in file panel(s)."
|
||||
PUTTY_SETTINGS_INSTRUCTIONS, "**Edit terminal settings in PuTTY.**\n\nPuTTY will be started. Edit terminal settings of a temporary site %s. WinSCP will remember these settings after you close PuTTY."
|
||||
PUTTY_SETTINGS_SITE_NAME, "Terminal settings for %s"
|
||||
|
||||
WIN_FORMS_STRINGS, "WIN_FORMS_STRINGS"
|
||||
COPY_FILE, "%s file '%s' to %s:"
|
||||
|
||||
@@ -77,9 +77,64 @@ bool __fastcall FindFile(UnicodeString & Path)
|
||||
return Result;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool DoesSessionExistInPutty(TSessionData * SessionData)
|
||||
{
|
||||
std::unique_ptr<TRegistryStorage> Storage(new TRegistryStorage(Configuration->PuttySessionsKey));
|
||||
Storage->ConfigureForPutty();
|
||||
return Storage->OpenRootKey(true) && Storage->KeyExists(SessionData->StorageKey);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool __fastcall ExportSessionToPutty(TSessionData * SessionData, bool ReuseExisting, const UnicodeString & SessionName)
|
||||
{
|
||||
bool Result = true;
|
||||
std::unique_ptr<TRegistryStorage> Storage(new TRegistryStorage(Configuration->PuttySessionsKey));
|
||||
Storage->AccessMode = smReadWrite;
|
||||
Storage->ConfigureForPutty();
|
||||
if (Storage->OpenRootKey(true))
|
||||
{
|
||||
Result = ReuseExisting && Storage->KeyExists(SessionData->StorageKey);
|
||||
if (!Result)
|
||||
{
|
||||
std::unique_ptr<TRegistryStorage> SourceStorage(new TRegistryStorage(Configuration->PuttySessionsKey));
|
||||
SourceStorage->ConfigureForPutty();
|
||||
if (SourceStorage->OpenSubKey(StoredSessions->DefaultSettings->Name, false) &&
|
||||
Storage->OpenSubKey(SessionName, true))
|
||||
{
|
||||
Storage->Copy(SourceStorage.get());
|
||||
Storage->CloseSubKey();
|
||||
}
|
||||
|
||||
std::unique_ptr<TSessionData> ExportData(new TSessionData(L""));
|
||||
ExportData->Assign(SessionData);
|
||||
ExportData->Modified = true;
|
||||
ExportData->Name = SessionName;
|
||||
ExportData->WinTitle = SessionData->SessionName;
|
||||
ExportData->Password = L"";
|
||||
|
||||
if (SessionData->FSProtocol == fsFTP)
|
||||
{
|
||||
if (GUIConfiguration->TelnetForFtpInPutty)
|
||||
{
|
||||
ExportData->PuttyProtocol = PuttyTelnetProtocol;
|
||||
ExportData->PortNumber = TelnetPortNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExportData->PuttyProtocol = PuttySshProtocol;
|
||||
ExportData->PortNumber = SshPortNumber;
|
||||
}
|
||||
}
|
||||
|
||||
ExportData->Save(Storage.get(), true);
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall OpenSessionInPutty(const UnicodeString PuttyPath,
|
||||
TSessionData * SessionData)
|
||||
{
|
||||
// See also TSiteAdvancedDialog::PuttySettingsButtonClick
|
||||
UnicodeString Program, AParams, Dir;
|
||||
SplitCommand(PuttyPath, Program, AParams, Dir);
|
||||
Program = ExpandEnvironmentVariables(Program);
|
||||
@@ -177,67 +232,19 @@ void __fastcall OpenSessionInPutty(const UnicodeString PuttyPath,
|
||||
else
|
||||
{
|
||||
UnicodeString SessionName;
|
||||
TRegistryStorage * Storage = NULL;
|
||||
TSessionData * ExportData = NULL;
|
||||
TRegistryStorage * SourceStorage = NULL;
|
||||
try
|
||||
if (ExportSessionToPutty(SessionData, true, GUIConfiguration->PuttySession))
|
||||
{
|
||||
Storage = new TRegistryStorage(Configuration->PuttySessionsKey);
|
||||
Storage->AccessMode = smReadWrite;
|
||||
// make it compatible with putty
|
||||
Storage->MungeStringValues = false;
|
||||
Storage->ForceAnsi = true;
|
||||
if (Storage->OpenRootKey(true))
|
||||
{
|
||||
if (Storage->KeyExists(SessionData->StorageKey))
|
||||
{
|
||||
SessionName = SessionData->SessionName;
|
||||
}
|
||||
else
|
||||
{
|
||||
SourceStorage = new TRegistryStorage(Configuration->PuttySessionsKey);
|
||||
SourceStorage->MungeStringValues = false;
|
||||
SourceStorage->ForceAnsi = true;
|
||||
if (SourceStorage->OpenSubKey(StoredSessions->DefaultSettings->Name, false) &&
|
||||
Storage->OpenSubKey(GUIConfiguration->PuttySession, true))
|
||||
{
|
||||
Storage->Copy(SourceStorage);
|
||||
Storage->CloseSubKey();
|
||||
}
|
||||
|
||||
ExportData = new TSessionData(L"");
|
||||
ExportData->Assign(SessionData);
|
||||
ExportData->Modified = true;
|
||||
ExportData->Name = GUIConfiguration->PuttySession;
|
||||
ExportData->WinTitle = SessionData->SessionName;
|
||||
ExportData->Password = L"";
|
||||
|
||||
if (SessionData->FSProtocol == fsFTP)
|
||||
{
|
||||
if (GUIConfiguration->TelnetForFtpInPutty)
|
||||
{
|
||||
ExportData->PuttyProtocol = PuttyTelnetProtocol;
|
||||
ExportData->PortNumber = TelnetPortNumber;
|
||||
// PuTTY does not allow -pw for telnet
|
||||
Password = L"";
|
||||
}
|
||||
else
|
||||
{
|
||||
ExportData->PuttyProtocol = PuttySshProtocol;
|
||||
ExportData->PortNumber = SshPortNumber;
|
||||
}
|
||||
}
|
||||
|
||||
ExportData->Save(Storage, true);
|
||||
SessionName = GUIConfiguration->PuttySession;
|
||||
}
|
||||
}
|
||||
SessionName = SessionData->SessionName;
|
||||
}
|
||||
__finally
|
||||
else
|
||||
{
|
||||
delete Storage;
|
||||
delete ExportData;
|
||||
delete SourceStorage;
|
||||
SessionName = GUIConfiguration->PuttySession;
|
||||
if ((SessionData->FSProtocol == fsFTP) &&
|
||||
GUIConfiguration->TelnetForFtpInPutty)
|
||||
{
|
||||
// PuTTY does not allow -pw for telnet
|
||||
Password = L"";
|
||||
}
|
||||
}
|
||||
|
||||
UnicodeString LoadSwitch = L"-load";
|
||||
|
||||
@@ -22,6 +22,8 @@ void __fastcall ExecuteShellCheckedAndWait(const UnicodeString Command, TProcess
|
||||
TObjectList * StartCreationDirectoryMonitorsOnEachDrive(unsigned int Filter, TFileChangedEvent OnChanged);
|
||||
extern bool DontCopyCommandToClipboard;
|
||||
bool __fastcall CopyCommandToClipboard(const UnicodeString & Command);
|
||||
bool DoesSessionExistInPutty(TSessionData * SessionData);
|
||||
bool __fastcall ExportSessionToPutty(TSessionData * SessionData, bool ReuseExisting, const UnicodeString & SessionName);
|
||||
void __fastcall OpenSessionInPutty(const UnicodeString PuttyPath,
|
||||
TSessionData * SessionData);
|
||||
bool __fastcall SpecialFolderLocation(int PathID, UnicodeString & Path);
|
||||
|
||||
Reference in New Issue
Block a user