1
0
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 by eef27ac3 (and still not fixed by 5d189553)

Source commit: 0bd13d447e6da8427be1506b7c561d74e83b1b85
This commit is contained in:
Martin Prikryl
2019-10-10 15:52:16 +00:00
parent 9e338c4b9b
commit 46a9c8fed9
18 changed files with 454 additions and 68 deletions

View File

@@ -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()

View File

@@ -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 };

View File

@@ -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);

View File

@@ -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

View File

@@ -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);
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

View File

@@ -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

View File

@@ -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

View File

@@ -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());

View File

@@ -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);

View File

@@ -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 };

View File

@@ -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();
}
//---------------------------------------------------------------------------

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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

View File

@@ -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:"

View File

@@ -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";

View File

@@ -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);