mirror of
https://github.com/winscp/winscp.git
synced 2026-10-24 02:28:55 +03:00
Also GetWindowLongPtr and GWLP_USERDATA https://winscp.net/tracker/618 Source commit: c85fdf15e50ce8a6f35b1c4d2a0125a0b9c4f1f0
1876 lines
62 KiB
C++
1876 lines
62 KiB
C++
//---------------------------------------------------------------------
|
|
#include <FormsPCH.h>
|
|
#pragma hdrstop
|
|
|
|
#include <ProgParams.h>
|
|
#include <PuttyTools.h>
|
|
#include <HistoryComboBox.h>
|
|
#include <System.Character.hpp>
|
|
|
|
#include "Custom.h"
|
|
//---------------------------------------------------------------------
|
|
#pragma resource "*.dfm"
|
|
//---------------------------------------------------------------------
|
|
const int GroupBoxBorderWidth = 1;
|
|
//---------------------------------------------------------------------
|
|
__fastcall TCustomDialog::TCustomDialog(UnicodeString AHelpKeyword)
|
|
: TForm(GetFormOwner())
|
|
{
|
|
UseSystemSettings(this);
|
|
|
|
FControlPadding = ScaleByTextHeight(this, 6);
|
|
FPos = ScaleByTextHeight(this, 8);
|
|
FPrePos = FPos;
|
|
FHorizontalMargin = ScaleByTextHeight(this, 8);
|
|
FIndent = FHorizontalMargin;
|
|
FGroupBox = NULL;
|
|
|
|
HelpKeyword = AHelpKeyword;
|
|
|
|
TBorderIcons BI = BorderIcons;
|
|
if (HelpKeyword.IsEmpty())
|
|
{
|
|
BI >> biHelp;
|
|
|
|
OKButton->Left = CancelButton->Left;
|
|
CancelButton->Left = HelpButton->Left;
|
|
HelpButton->Visible = false;
|
|
}
|
|
else
|
|
{
|
|
BI << biHelp;
|
|
}
|
|
BorderIcons = BI;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
bool __fastcall TCustomDialog::Execute()
|
|
{
|
|
Changed();
|
|
return (ShowModal() == DefaultResult(this));
|
|
}
|
|
//---------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::DoChange(bool & /*CanSubmit*/)
|
|
{
|
|
// noop
|
|
}
|
|
//---------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::Changed()
|
|
{
|
|
bool CanSubmit = true;
|
|
DoChange(CanSubmit);
|
|
EnableControl(OKButton, CanSubmit);
|
|
}
|
|
//---------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::Change(TObject * /*Sender*/)
|
|
{
|
|
Changed();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::DoHelp()
|
|
{
|
|
FormHelp(this);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::HelpButtonClick(TObject * /*Sender*/)
|
|
{
|
|
DoHelp();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::DoShow()
|
|
{
|
|
OKButton->TabOrder = FCount;
|
|
CancelButton->TabOrder = static_cast<short>(FCount + 1);
|
|
HelpButton->TabOrder = static_cast<short>(FCount + 2);
|
|
Changed();
|
|
TForm::DoShow();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::DoValidate()
|
|
{
|
|
// noop
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TCustomDialog::CloseQuery()
|
|
{
|
|
if (ModalResult == DefaultResult(this))
|
|
{
|
|
DoValidate();
|
|
}
|
|
return TForm::CloseQuery();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::RemoveCancelButton()
|
|
{
|
|
CancelButton->Visible = false;
|
|
OKButton->Left = CancelButton->Left;
|
|
OKButton->Cancel = true;
|
|
DebugAssert(OKButton->Width == CancelButton->Width);
|
|
DebugAssert(OKButton->Top == CancelButton->Top);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::AddDialogButton(TButton * Button)
|
|
{
|
|
Button->Parent = this;
|
|
Button->Top = OKButton->Top;
|
|
Button->Left = FHorizontalMargin;
|
|
Button->Height = OKButton->Height;
|
|
AddWinControl(Button);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::AddImage(const UnicodeString & ImageName)
|
|
{
|
|
TImage * Image = new TImage(this);
|
|
Image->Name = L"Image";
|
|
Image->Parent = GetDefaultParent();
|
|
LoadDialogImage(Image, ImageName);
|
|
Image->SetBounds(FIndent, FPos + ScaleByTextHeight(this, 3), Image->Picture->Width, Image->Picture->Height);
|
|
FIndent += Image->Width + ScaleByTextHeight(this, 12);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
int __fastcall TCustomDialog::GetMaxControlWidth(TControl * Control)
|
|
{
|
|
return GetDefaultParent()->ClientWidth - Control->Left - FHorizontalMargin - (FGroupBox != NULL ? GroupBoxBorderWidth : 0);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TWinControl * __fastcall TCustomDialog::GetDefaultParent()
|
|
{
|
|
return (FGroupBox != NULL) ? FGroupBox : static_cast<TWinControl *>(this);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::AdjustHeight(TControl * Control)
|
|
{
|
|
FPos = Control->Top + Control->Height + FControlPadding;
|
|
int Delta = (FPos - FPrePos);
|
|
ClientHeight = ClientHeight + Delta;
|
|
if (FGroupBox != NULL)
|
|
{
|
|
FGroupBox->Height = FGroupBox->Height + Delta;
|
|
}
|
|
FPrePos = FPos;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::AddWinControl(TWinControl * Control)
|
|
{
|
|
Control->TabOrder = FCount;
|
|
FCount++;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TCheckBox * __fastcall TCustomDialog::CreateAndAddCheckBox(const UnicodeString & Caption)
|
|
{
|
|
TCheckBox * CheckBox = new TCheckBox(this);
|
|
CheckBox->Caption = Caption;
|
|
AddButtonControl(CheckBox);
|
|
return CheckBox;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TLabel * __fastcall TCustomDialog::CreateLabel(UnicodeString Label)
|
|
{
|
|
TLabel * Result = ::CreateLabel(this);
|
|
Result->Caption = Label;
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::AddEditLikeControl(TWinControl * Edit, TLabel * Label, bool OneLine)
|
|
{
|
|
Edit->Parent = GetDefaultParent();
|
|
// this updates Height property to real value
|
|
Edit->HandleNeeded();
|
|
|
|
if (Label != NULL)
|
|
{
|
|
Label->Parent = GetDefaultParent();
|
|
Label->Left = FIndent;
|
|
|
|
if (OneLine)
|
|
{
|
|
DebugAssert(Edit->Height > Label->Height);
|
|
Label->Top = FPos + ((Edit->Height - Label->Height) / 2);
|
|
}
|
|
else
|
|
{
|
|
Label->Top = FPos;
|
|
|
|
FPos += Label->Height + ScaleByTextHeight(this, 3);
|
|
}
|
|
}
|
|
|
|
Edit->Top = FPos;
|
|
if (OneLine)
|
|
{
|
|
Edit->Left = GetDefaultParent()->ClientWidth - FHorizontalMargin - Edit->Width;
|
|
}
|
|
else
|
|
{
|
|
Edit->Left = FIndent;
|
|
Edit->Width = GetMaxControlWidth(Edit);
|
|
}
|
|
|
|
AdjustHeight(Edit);
|
|
|
|
if (Label != NULL)
|
|
{
|
|
if (Label->FocusControl == NULL)
|
|
{
|
|
Label->FocusControl = Edit;
|
|
}
|
|
else
|
|
{
|
|
DebugAssert(Label->FocusControl == Edit);
|
|
}
|
|
}
|
|
|
|
AddWinControl(Edit);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::AddEdit(TCustomEdit * Edit, TLabel * Label, bool OneLine)
|
|
{
|
|
AddEditLikeControl(Edit, Label, OneLine);
|
|
|
|
TEdit * PublicEdit = reinterpret_cast<TEdit *>(Edit);
|
|
if (PublicEdit->OnChange == NULL)
|
|
{
|
|
PublicEdit->OnChange = Change;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::SetUpComboBox(TCustomCombo * Combo, TStrings * Items, bool OneLine)
|
|
{
|
|
if (Items != NULL)
|
|
{
|
|
Combo->Items = Items;
|
|
}
|
|
|
|
if (OneLine)
|
|
{
|
|
int Width = 0;
|
|
for (int Index = 0; Index < Combo->Items->Count; Index++)
|
|
{
|
|
Width = Max(Width, Combo->Canvas->TextWidth(Combo->Items->Strings[Index]));
|
|
}
|
|
|
|
Width += ScaleByTextHeight(Combo, 4 + 16 + 14);
|
|
Width = Max(Width, HelpButton->Width);
|
|
|
|
Combo->Width = Width;
|
|
Combo->Left = GetDefaultParent()->ClientWidth - FHorizontalMargin - Width;
|
|
}
|
|
|
|
TComboBox * PublicCombo = reinterpret_cast<TComboBox *>(Combo);
|
|
if (PublicCombo->OnChange == NULL)
|
|
{
|
|
PublicCombo->OnChange = Change;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::AddComboBox(TCustomCombo * Combo, TLabel * Label, TStrings * Items, bool OneLine)
|
|
{
|
|
AddEditLikeControl(Combo, Label, OneLine);
|
|
|
|
SetUpComboBox(Combo, Items, OneLine);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::AddShortCutComboBox(TComboBox * Combo, TLabel * Label, const TShortCuts & ShortCuts)
|
|
{
|
|
AddEditLikeControl(Combo, Label, true);
|
|
InitializeShortCutCombo(Combo, ShortCuts);
|
|
SetUpComboBox(Combo, NULL, true);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::ScaleButtonControl(TButtonControl * Control)
|
|
{
|
|
// this updates Height property to real value
|
|
Control->HandleNeeded();
|
|
// buttons do not scale with text on their own
|
|
Control->Height = ScaleByTextHeight(Control, Control->Height);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::AddButtonControl(TButtonControl * Control)
|
|
{
|
|
Control->Parent = GetDefaultParent();
|
|
Control->Left = FIndent + ScaleByTextHeight(this, 2);
|
|
Control->Top = FPos;
|
|
Control->Width = GetMaxControlWidth(Control);
|
|
ScaleButtonControl(Control);
|
|
|
|
AdjustHeight(Control);
|
|
|
|
AddWinControl(Control);
|
|
|
|
TCheckBox * PublicControl = reinterpret_cast<TCheckBox *>(Control);
|
|
if (PublicControl->OnClick == NULL)
|
|
{
|
|
PublicControl->OnClick = Change;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TCustomDialog::AddButtonNextToEdit(TButton * Button, TWinControl * Edit)
|
|
{
|
|
Button->Parent = GetDefaultParent();
|
|
Button->Width = HelpButton->Width;
|
|
Button->Left = GetDefaultParent()->ClientWidth - Button->Width - HorizontalMargin;
|
|
Edit->Width = Button->Left - Edit->Left - ScaleByTextHeight(this, 6);
|
|
Button->Top = Edit->Top - ScaleByTextHeight(this, 1);
|
|
ScaleButtonControl(Button);
|
|
AddWinControl(Button);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::AddText(TLabel * Label)
|
|
{
|
|
Label->Parent = GetDefaultParent();
|
|
|
|
DebugAssert(Label->AutoSize);
|
|
Label->WordWrap = true;
|
|
Label->Left = FIndent;
|
|
Label->Width = GetMaxControlWidth(Label);
|
|
Label->Top = FPos;
|
|
Label->ShowAccelChar = false;
|
|
|
|
AutoSizeLabel(Label);
|
|
|
|
AdjustHeight(Label);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::AddText(TStaticText * Label)
|
|
{
|
|
Label->Parent = GetDefaultParent();
|
|
|
|
DebugAssert(Label->AutoSize);
|
|
Label->Left = FIndent;
|
|
Label->Top = FPos;
|
|
Label->ShowAccelChar = false;
|
|
|
|
AdjustHeight(Label);
|
|
AddWinControl(Label);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::AddSeparator()
|
|
{
|
|
TBevel * Bevel = new TBevel(this);
|
|
Bevel->Parent = GetDefaultParent();
|
|
|
|
Bevel->Left = FIndent;
|
|
Bevel->Top = FPos;
|
|
Bevel->Height = 2;
|
|
Bevel->Width = GetMaxControlWidth(Bevel);
|
|
|
|
AdjustHeight(Bevel);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomDialog::StartGroup(const UnicodeString & Caption)
|
|
{
|
|
if (FGroupBox != NULL)
|
|
{
|
|
FIndent = FGroupBox->Left;
|
|
FPos = FGroupBox->Top + FGroupBox->Height + FControlPadding;
|
|
FPrePos = FPos;
|
|
FGroupBox = NULL;
|
|
}
|
|
|
|
TGroupBox * GroupBox = new TGroupBox(this);
|
|
GroupBox->Parent = this;
|
|
GroupBox->Caption = Caption;
|
|
|
|
GroupBox->Left = FIndent;
|
|
GroupBox->Top = FPos;
|
|
GroupBox->Height = ScaleByTextHeight(GroupBox, 26);
|
|
GroupBox->Width = GetMaxControlWidth(GroupBox);
|
|
|
|
AdjustHeight(GroupBox);
|
|
|
|
AddWinControl(GroupBox);
|
|
|
|
// but if the first control is oneline box, then we should roll back a bit
|
|
FPos = ScaleByTextHeight(this, 22);
|
|
FPrePos = FPos;
|
|
FIndent = FHorizontalMargin + GroupBoxBorderWidth;
|
|
|
|
FGroupBox = GroupBox;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
class TSaveSessionDialog : public TCustomDialog
|
|
{
|
|
public:
|
|
__fastcall TSaveSessionDialog(TComponent* AOwner);
|
|
void __fastcall Init(bool CanSavePassword, bool NotRecommendedSavingPassword,
|
|
TStrings * AdditionalFolders);
|
|
|
|
bool __fastcall Execute(UnicodeString & SessionName, bool & SavePassword,
|
|
bool & CreateShortcut, const UnicodeString & OriginalSessionName);
|
|
|
|
protected:
|
|
virtual void __fastcall DoValidate();
|
|
virtual void __fastcall DoChange(bool & CanSubmit);
|
|
|
|
private:
|
|
UnicodeString FOriginalSessionName;
|
|
TEdit * SessionNameEdit;
|
|
TComboBox * FolderCombo;
|
|
TCheckBox * SavePasswordCheck;
|
|
TCheckBox * CreateShortcutCheck;
|
|
UnicodeString FRootFolder;
|
|
|
|
UnicodeString __fastcall GetSessionName();
|
|
};
|
|
//---------------------------------------------------------------------------
|
|
// Need to have an Owner argument for SafeFormCreate
|
|
__fastcall TSaveSessionDialog::TSaveSessionDialog(TComponent* /*AOwner*/) :
|
|
TCustomDialog(HELP_SESSION_SAVE)
|
|
{
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TSaveSessionDialog::Init(bool CanSavePassword,
|
|
bool NotRecommendedSavingPassword, TStrings * AdditionalFolders)
|
|
{
|
|
Caption = LoadStr(SAVE_SESSION_CAPTION);
|
|
|
|
SessionNameEdit = new TEdit(this);
|
|
AddEdit(SessionNameEdit, CreateLabel(LoadStr(SAVE_SESSION_PROMPT)));
|
|
|
|
FRootFolder = LoadStr(SAVE_SESSION_ROOT_FOLDER2);
|
|
std::unique_ptr<TStringList> Folders(new TStringList());
|
|
|
|
if (AdditionalFolders != NULL)
|
|
{
|
|
Folders->AddStrings(AdditionalFolders);
|
|
}
|
|
|
|
for (int Index = 0; Index < StoredSessions->Count; Index++)
|
|
{
|
|
TSessionData * Data = StoredSessions->Sessions[Index];
|
|
if (!Data->Special && !Data->IsWorkspace)
|
|
{
|
|
UnicodeString Folder = Data->FolderName;
|
|
if (!Folder.IsEmpty() && Folders->IndexOf(Folder) < 0)
|
|
{
|
|
Folders->Add(Folder);
|
|
}
|
|
}
|
|
}
|
|
|
|
DebugAssert(!Folders->CaseSensitive);
|
|
Folders->Sort();
|
|
|
|
FolderCombo = new TUIStateAwareComboBox(this);
|
|
AddComboBox(FolderCombo, CreateLabel(LoadStr(SAVE_SESSION_FOLDER)));
|
|
FolderCombo->DropDownCount = Max(FolderCombo->DropDownCount, DefaultHistoryDropDownCount);
|
|
FolderCombo->Items->Add(FRootFolder);
|
|
FolderCombo->Items->AddStrings(Folders.get());
|
|
|
|
SavePasswordCheck = CreateAndAddCheckBox(
|
|
LoadStr(NotRecommendedSavingPassword ? SAVE_SESSION_PASSWORD :
|
|
(CustomWinConfiguration->UseMasterPassword ? SAVE_SESSION_PASSWORD_MASTER : SAVE_SESSION_PASSWORD_RECOMMENDED)));
|
|
|
|
CreateShortcutCheck = CreateAndAddCheckBox(LoadStr(SAVE_SITE_WORKSPACE_SHORTCUT));
|
|
|
|
EnableControl(SavePasswordCheck, CanSavePassword);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TSaveSessionDialog::Execute(
|
|
UnicodeString & SessionName, bool & SavePassword, bool & CreateShortcut,
|
|
const UnicodeString & OriginalSessionName)
|
|
{
|
|
FOriginalSessionName = OriginalSessionName;
|
|
SessionNameEdit->Text = TSessionData::ExtractLocalName(SessionName);
|
|
UnicodeString Folder = TSessionData::ExtractFolderName(SessionName);
|
|
if (Folder.IsEmpty())
|
|
{
|
|
FolderCombo->Text = FRootFolder;
|
|
}
|
|
else
|
|
{
|
|
FolderCombo->Text = Folder;
|
|
}
|
|
SavePasswordCheck->Checked = SavePassword;
|
|
CreateShortcutCheck->Checked = CreateShortcut;
|
|
bool Result = TCustomDialog::Execute();
|
|
if (Result)
|
|
{
|
|
SessionName = GetSessionName();
|
|
SavePassword = SavePasswordCheck->Checked;
|
|
CreateShortcut = CreateShortcutCheck->Checked;
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
UnicodeString __fastcall TSaveSessionDialog::GetSessionName()
|
|
{
|
|
UnicodeString Folder;
|
|
if (FolderCombo->Text != FRootFolder)
|
|
{
|
|
Folder = FolderCombo->Text;
|
|
}
|
|
return TSessionData::ComposePath(Folder, SessionNameEdit->Text);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TSaveSessionDialog::DoValidate()
|
|
{
|
|
TSessionData::ValidateName(SessionNameEdit->Text);
|
|
SessionNameValidate(GetSessionName(), FOriginalSessionName);
|
|
|
|
UnicodeString Folder = TSessionData::ExtractFolderName(GetSessionName());
|
|
if (!Folder.IsEmpty() && StoredSessions->IsWorkspace(Folder))
|
|
{
|
|
throw Exception(FMTLOAD(WORKSPACE_NOT_FOLDER, (Folder)));
|
|
}
|
|
|
|
if (SavePasswordCheck->Enabled && SavePasswordCheck->Checked &&
|
|
CustomWinConfiguration->UseMasterPassword)
|
|
{
|
|
CustomWinConfiguration->AskForMasterPasswordIfNotSet();
|
|
}
|
|
|
|
TCustomDialog::DoValidate();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TSaveSessionDialog::DoChange(bool & CanSubmit)
|
|
{
|
|
CanSubmit = !SessionNameEdit->Text.IsEmpty();
|
|
TCustomDialog::DoChange(CanSubmit);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TSessionData * __fastcall DoSaveSession(TSessionData * SessionData,
|
|
TSessionData * OriginalSession, bool ForceDialog,
|
|
TStrings * AdditionalFolders)
|
|
{
|
|
bool SavePassword = false;
|
|
bool * PSavePassword;
|
|
bool NotRecommendedSavingPassword =
|
|
!CustomWinConfiguration->UseMasterPassword &&
|
|
!SameText(SessionData->UserName, AnonymousUserName);
|
|
|
|
if (Configuration->DisablePasswordStoring ||
|
|
!SessionData->HasAnySessionPassword())
|
|
{
|
|
PSavePassword = NULL;
|
|
}
|
|
else
|
|
{
|
|
PSavePassword = &SavePassword;
|
|
SavePassword =
|
|
((OriginalSession != NULL) && OriginalSession->HasAnySessionPassword()) ||
|
|
!NotRecommendedSavingPassword;
|
|
}
|
|
|
|
UnicodeString SessionName = SessionData->SessionName;
|
|
|
|
bool Result;
|
|
bool CreateShortcut = false;
|
|
if (!ForceDialog && ((PSavePassword == NULL) || SavePassword))
|
|
{
|
|
// This is probably here to ask before session is started saving.
|
|
// Otherwise we would ask implicitly, when saving passwords, but at that moment,
|
|
// part of the site is already saved and when the user cancel the prompt it's too late.
|
|
CustomWinConfiguration->AskForMasterPasswordIfNotSetAndNeededToPersistSessionData(SessionData);
|
|
Result = true;
|
|
}
|
|
else
|
|
{
|
|
// This can be a standalone dialog when used with save URL (from GetLoginData)
|
|
TSaveSessionDialog * Dialog = SafeFormCreate<TSaveSessionDialog>();
|
|
try
|
|
{
|
|
Dialog->Init((PSavePassword != NULL), NotRecommendedSavingPassword, AdditionalFolders);
|
|
Result = Dialog->Execute(SessionName, SavePassword, CreateShortcut, SessionData->Name);
|
|
}
|
|
__finally
|
|
{
|
|
delete Dialog;
|
|
}
|
|
}
|
|
|
|
TSessionData * NewSession = NULL;
|
|
if (Result)
|
|
{
|
|
if ((PSavePassword != NULL) && !SavePassword)
|
|
{
|
|
SessionData->ClearSessionPasswords();
|
|
}
|
|
|
|
NewSession =
|
|
StoredSessions->NewSession(SessionName, SessionData);
|
|
// modified only, explicit
|
|
StoredSessions->Save(false, true);
|
|
if (!SessionData->HostKey.IsEmpty())
|
|
{
|
|
SessionData->CacheHostKeyIfNotCached();
|
|
}
|
|
|
|
if (CreateShortcut)
|
|
{
|
|
TOperationVisualizer Visualizer;
|
|
UnicodeString AdditionalParams =
|
|
TProgramParams::FormatSwitch(DESKTOP_SWITCH) + L" " +
|
|
TProgramParams::FormatSwitch(UPLOAD_IF_ANY_SWITCH);
|
|
CreateDesktopSessionShortCut(SessionName, L"", AdditionalParams, -1, SITE_ICON);
|
|
}
|
|
}
|
|
|
|
return NewSession;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall SessionNameValidate(const UnicodeString & Text,
|
|
const UnicodeString & OriginalName)
|
|
{
|
|
TSessionData::ValidatePath(Text);
|
|
|
|
DebugAssert(StoredSessions);
|
|
TSessionData * Data = static_cast<TSessionData *>(StoredSessions->FindByName(Text));
|
|
if (Data && Data->Special)
|
|
{
|
|
MessageDialog(FMTLOAD(CANNOT_OVERWRITE_SPECIAL_SESSION, (Text)),
|
|
qtError, qaOK, HELP_NONE);
|
|
Abort();
|
|
}
|
|
else if ((Data != NULL) && !Data->IsSameName(OriginalName) &&
|
|
MessageDialog(MainInstructions(FMTLOAD(CONFIRM_OVERWRITE_SESSION, (Text))),
|
|
qtConfirmation, qaYes | qaNo, HELP_SESSION_SAVE_OVERWRITE) != qaYes)
|
|
{
|
|
Abort();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
class TSaveWorkspaceDialog : public TCustomDialog
|
|
{
|
|
public:
|
|
__fastcall TSaveWorkspaceDialog(bool CanSavePasswords,
|
|
bool NotRecommendedSavingPasswords);
|
|
|
|
bool __fastcall Execute(
|
|
UnicodeString & WorkspaceName, bool & SavePasswords, bool & CreateShortcut,
|
|
bool & EnableAutoSave);
|
|
|
|
protected:
|
|
virtual void __fastcall DoValidate();
|
|
virtual void __fastcall DoChange(bool & CanSubmit);
|
|
|
|
private:
|
|
TComboBox * WorkspaceNameCombo;
|
|
TCheckBox * SavePasswordsCheck;
|
|
TCheckBox * CreateShortcutCheck;
|
|
TCheckBox * EnableAutoSaveCheck;
|
|
};
|
|
//---------------------------------------------------------------------------
|
|
__fastcall TSaveWorkspaceDialog::TSaveWorkspaceDialog(
|
|
bool CanSavePasswords, bool NotRecommendedSavingPasswords) :
|
|
TCustomDialog(HELP_WORKSPACE_SAVE)
|
|
{
|
|
Caption = LoadStr(SAVE_WORKSPACE_CAPTION);
|
|
|
|
WorkspaceNameCombo = new TUIStateAwareComboBox(this);
|
|
WorkspaceNameCombo->AutoComplete = false;
|
|
AddComboBox(WorkspaceNameCombo, CreateLabel(LoadStr(SAVE_WORKSPACE_PROMPT)));
|
|
WorkspaceNameCombo->DropDownCount = Max(WorkspaceNameCombo->DropDownCount, DefaultHistoryDropDownCount);
|
|
|
|
std::unique_ptr<TStrings> Workspaces(StoredSessions->GetWorkspaces());
|
|
WorkspaceNameCombo->Items->AddStrings(Workspaces.get());
|
|
|
|
SavePasswordsCheck = CreateAndAddCheckBox(
|
|
LoadStr(NotRecommendedSavingPasswords ? SAVE_WORKSPACE_PASSWORDS :
|
|
(CustomWinConfiguration->UseMasterPassword ?
|
|
SAVE_WORKSPACE_PASSWORDS_MASTER : SAVE_WORKSPACE_PASSWORDS_RECOMMENDED)));
|
|
|
|
EnableControl(SavePasswordsCheck, CanSavePasswords);
|
|
|
|
CreateShortcutCheck = CreateAndAddCheckBox(LoadStr(SAVE_SITE_WORKSPACE_SHORTCUT));
|
|
|
|
EnableAutoSaveCheck = CreateAndAddCheckBox(LoadStr(SAVE_WORKSPACE_AUTO));
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TSaveWorkspaceDialog::Execute(
|
|
UnicodeString & WorkspaceName, bool & SavePasswords, bool & CreateShortcut,
|
|
bool & EnableAutoSave)
|
|
{
|
|
WorkspaceNameCombo->Text = WorkspaceName;
|
|
SavePasswordsCheck->Checked = SavePasswords;
|
|
CreateShortcutCheck->Checked = CreateShortcut;
|
|
EnableAutoSaveCheck->Checked = EnableAutoSave;
|
|
bool Result = TCustomDialog::Execute();
|
|
if (Result)
|
|
{
|
|
WorkspaceName = WorkspaceNameCombo->Text;
|
|
SavePasswords = SavePasswordsCheck->Checked;
|
|
CreateShortcut = CreateShortcutCheck->Checked;
|
|
EnableAutoSave = EnableAutoSaveCheck->Checked;
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TSaveWorkspaceDialog::DoValidate()
|
|
{
|
|
TSessionData::ValidateName(WorkspaceNameCombo->Text);
|
|
|
|
if (StoredSessions->IsFolder(WorkspaceNameCombo->Text))
|
|
{
|
|
throw Exception(FMTLOAD(FOLDER_NOT_WORKSPACE, (WorkspaceNameCombo->Text)));
|
|
}
|
|
|
|
if (SavePasswordsCheck->Enabled && SavePasswordsCheck->Checked &&
|
|
CustomWinConfiguration->UseMasterPassword)
|
|
{
|
|
CustomWinConfiguration->AskForMasterPasswordIfNotSet();
|
|
}
|
|
|
|
TCustomDialog::DoValidate();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TSaveWorkspaceDialog::DoChange(bool & CanSubmit)
|
|
{
|
|
CanSubmit = !WorkspaceNameCombo->Text.IsEmpty();
|
|
|
|
TCustomDialog::DoChange(CanSubmit);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall DoSaveWorkspaceDialog(UnicodeString & WorkspaceName,
|
|
bool * SavePasswords, bool NotRecommendedSavingPasswords,
|
|
bool & CreateShortcut, bool & EnableAutoSave)
|
|
{
|
|
std::unique_ptr<TSaveWorkspaceDialog> Dialog(
|
|
new TSaveWorkspaceDialog((SavePasswords != NULL), NotRecommendedSavingPasswords));
|
|
|
|
bool Dummy = false;
|
|
if (SavePasswords == NULL)
|
|
{
|
|
SavePasswords = &Dummy;
|
|
}
|
|
return
|
|
Dialog->Execute(
|
|
WorkspaceName, *SavePasswords, CreateShortcut, EnableAutoSave);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
class TShortCutDialog : public TCustomDialog
|
|
{
|
|
public:
|
|
__fastcall TShortCutDialog(const TShortCuts & ShortCuts, UnicodeString HelpKeyword);
|
|
|
|
bool __fastcall Execute(TShortCut & ShortCut);
|
|
|
|
private:
|
|
TComboBox * ShortCutCombo;
|
|
};
|
|
//---------------------------------------------------------------------------
|
|
__fastcall TShortCutDialog::TShortCutDialog(const TShortCuts & ShortCuts, UnicodeString HelpKeyword) :
|
|
TCustomDialog(HelpKeyword)
|
|
{
|
|
Caption = LoadStr(SHORTCUT_CAPTION);
|
|
|
|
ShortCutCombo = new TUIStateAwareComboBox(this);
|
|
AddShortCutComboBox(ShortCutCombo, CreateLabel(LoadStr(SHORTCUT_LABEL)), ShortCuts);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TShortCutDialog::Execute(TShortCut & ShortCut)
|
|
{
|
|
SetShortCutCombo(ShortCutCombo, ShortCut);
|
|
bool Result = TCustomDialog::Execute();
|
|
if (Result)
|
|
{
|
|
ShortCut = GetShortCutCombo(ShortCutCombo);
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall DoShortCutDialog(TShortCut & ShortCut,
|
|
const TShortCuts & ShortCuts, UnicodeString HelpKeyword)
|
|
{
|
|
bool Result;
|
|
TShortCutDialog * Dialog = new TShortCutDialog(ShortCuts, HelpKeyword);
|
|
try
|
|
{
|
|
Result = Dialog->Execute(ShortCut);
|
|
}
|
|
__finally
|
|
{
|
|
delete Dialog;
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
class TRemoteMoveDialog : public TCustomDialog
|
|
{
|
|
public:
|
|
__fastcall TRemoteMoveDialog(bool Multi, TDirectoryExistsEvent OnDirectoryExists);
|
|
|
|
bool __fastcall Execute(UnicodeString & Target, UnicodeString & FileMask);
|
|
|
|
protected:
|
|
DYNAMIC void __fastcall DoShow();
|
|
virtual void __fastcall DoValidate();
|
|
UnicodeString __fastcall GetFileMask();
|
|
|
|
private:
|
|
THistoryComboBox * Combo;
|
|
bool FMulti;
|
|
TDirectoryExistsEvent FOnDirectoryExists;
|
|
};
|
|
//---------------------------------------------------------------------------
|
|
__fastcall TRemoteMoveDialog::TRemoteMoveDialog(bool Multi, TDirectoryExistsEvent OnDirectoryExists) :
|
|
TCustomDialog(HELP_REMOTE_MOVE)
|
|
{
|
|
Caption = LoadStr(REMOTE_MOVE_TITLE);
|
|
// The same as TRemoteTransferDialog
|
|
ClientWidth = ScaleByTextHeight(this, 466);
|
|
|
|
FMulti = Multi;
|
|
FOnDirectoryExists = OnDirectoryExists;
|
|
|
|
AddImage(L"Move L to R");
|
|
|
|
Combo = new THistoryComboBox(this);
|
|
AddComboBox(Combo, CreateLabel(LoadStr(REMOTE_TRANSFER_PROMPT2)));
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TRemoteMoveDialog::Execute(UnicodeString & Target, UnicodeString & FileMask)
|
|
{
|
|
Combo->HistoryKey = L"RemoteTarget";
|
|
Combo->Text = UnixIncludeTrailingBackslash(Target) + FileMask;
|
|
bool Result = TCustomDialog::Execute();
|
|
if (Result)
|
|
{
|
|
Target = UnixExtractFilePath(Combo->Text);
|
|
FileMask = GetFileMask();
|
|
Combo->SaveToHistory();
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
UnicodeString __fastcall TRemoteMoveDialog::GetFileMask()
|
|
{
|
|
return UnixExtractFileName(Combo->Text);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TRemoteMoveDialog::DoShow()
|
|
{
|
|
TCustomDialog::DoShow();
|
|
InstallPathWordBreakProc(Combo);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TRemoteMoveDialog::DoValidate()
|
|
{
|
|
if (FOnDirectoryExists(NULL, Combo->Text))
|
|
{
|
|
Combo->Text = UnixCombinePaths(Combo->Text, AnyMask);
|
|
}
|
|
|
|
if (!IsFileNameMask(GetFileMask()) && FMulti)
|
|
{
|
|
UnicodeString Message =
|
|
FormatMultiFilesToOneConfirmation(Combo->Text, true);
|
|
if (MessageDialog(Message, qtConfirmation, qaOK | qaCancel, HELP_NONE) == qaCancel)
|
|
{
|
|
Abort();
|
|
}
|
|
}
|
|
|
|
TCustomDialog::DoValidate();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall DoRemoteMoveDialog(
|
|
bool Multi, UnicodeString & Target, UnicodeString & FileMask, TDirectoryExistsEvent OnDirectoryExists)
|
|
{
|
|
std::unique_ptr<TRemoteMoveDialog> Dialog(new TRemoteMoveDialog(Multi, OnDirectoryExists));
|
|
return Dialog->Execute(Target, FileMask);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
class TCustomCommandOptionsDialog : public TCustomDialog
|
|
{
|
|
public:
|
|
__fastcall TCustomCommandOptionsDialog(
|
|
const TCustomCommandType * Command, TStrings * CustomCommandOptions, unsigned int Flags,
|
|
TCustomCommand * CustomCommandForOptions, const UnicodeString & Site, const TShortCuts * ShortCuts);
|
|
|
|
bool __fastcall Execute(TShortCut * ShortCut);
|
|
|
|
protected:
|
|
virtual void __fastcall DoHelp();
|
|
DYNAMIC void __fastcall DoShow();
|
|
|
|
private:
|
|
const TCustomCommandType * FCommand;
|
|
TStrings * FCustomCommandOptions;
|
|
std::vector<TControl *> FControls;
|
|
std::vector<std::vector<UnicodeString> > FValues;
|
|
unsigned int FFlags;
|
|
UnicodeString FSite;
|
|
TComboBox * FShortCutCombo;
|
|
|
|
THistoryComboBox * __fastcall CreateHistoryComboBox(const TCustomCommandType::TOption & Option, const UnicodeString & Value);
|
|
void __fastcall BrowseButtonClick(TObject * Sender);
|
|
void __fastcall LinkLabelClick(TObject * Sender);
|
|
UnicodeString __fastcall SaveHistoryComboBoxValue(TControl * Control);
|
|
void __fastcall AddOptionComboBox(
|
|
TComboBox * ComboBox, const UnicodeString & Value, const TCustomCommandType::TOption & Option,
|
|
std::vector<UnicodeString> & Values);
|
|
UnicodeString __fastcall GetComboBoxValue(TControl * Control, const UnicodeString & Default);
|
|
int __fastcall GetOptionIndex(TControl * Control);
|
|
int __fastcall GetControlIndex(TControl * Control);
|
|
};
|
|
//---------------------------------------------------------------------------
|
|
__fastcall TCustomCommandOptionsDialog::TCustomCommandOptionsDialog(
|
|
const TCustomCommandType * Command, TStrings * CustomCommandOptions,
|
|
unsigned int Flags, TCustomCommand * CustomCommandForOptions,
|
|
const UnicodeString & Site, const TShortCuts * ShortCuts) :
|
|
TCustomDialog(HELP_EXTENSION_OPTIONS)
|
|
{
|
|
FCommand = Command;
|
|
FFlags = Flags;
|
|
FCustomCommandOptions = CustomCommandOptions;
|
|
FSite = Site;
|
|
Caption = StripEllipsis(StripHotkey(FCommand->Name));
|
|
Width = ScaleByTextHeight(this, 444);
|
|
|
|
bool HasGroups = false;
|
|
int ControlIndex = 0;
|
|
for (int OptionIndex = 0; OptionIndex < FCommand->OptionsCount; OptionIndex++)
|
|
{
|
|
const TCustomCommandType::TOption & Option = FCommand->GetOption(OptionIndex);
|
|
|
|
if ((Option.Flags & FFlags) != 0)
|
|
{
|
|
UnicodeString OptionKey = FCommand->GetOptionKey(Option, FSite);
|
|
UnicodeString Value;
|
|
if ((CustomCommandForOptions != NULL) &&
|
|
Option.HasPatterns(CustomCommandForOptions))
|
|
{
|
|
Value = CustomCommandForOptions->Complete(Option.Default, true);
|
|
}
|
|
else
|
|
{
|
|
if (FCustomCommandOptions->IndexOfName(OptionKey) >= 0)
|
|
{
|
|
Value = FCustomCommandOptions->Values[OptionKey];
|
|
}
|
|
else
|
|
{
|
|
Value = Option.Default;
|
|
}
|
|
}
|
|
|
|
int Tag = (OptionIndex << 16) + ControlIndex;
|
|
TControl * Control = NULL;
|
|
std::vector<UnicodeString> Values;
|
|
if (Option.Kind == TCustomCommandType::okUnknown)
|
|
{
|
|
Control = NULL;
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okLabel)
|
|
{
|
|
TLabel * Label = CreateLabel(Option.Caption);
|
|
AddText(Label);
|
|
Control = Label;
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okLink)
|
|
{
|
|
TStaticText * Label = new TStaticText(this);
|
|
Label->Caption = Option.Caption;
|
|
if (IsHttpOrHttpsUrl(Label->Caption))
|
|
{
|
|
Label->Caption = SecureUrl(Label->Caption);
|
|
LinkLabel(Label);
|
|
Label->TabStop = true;
|
|
}
|
|
else if (!Option.Default.IsEmpty() && IsHttpOrHttpsUrl(Option.Default))
|
|
{
|
|
Label->OnClick = LinkLabelClick;
|
|
LinkLabel(Label);
|
|
Label->TabStop = true;
|
|
}
|
|
else
|
|
{
|
|
// keep it plain text, as we have no URL
|
|
}
|
|
AddText(Label);
|
|
Control = Label;
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okGroup)
|
|
{
|
|
StartGroup(Option.Caption);
|
|
HasGroups = true;
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okSeparator)
|
|
{
|
|
AddSeparator();
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okTextBox)
|
|
{
|
|
Control = CreateHistoryComboBox(Option, Value);
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okFile)
|
|
{
|
|
THistoryComboBox * ComboBox = CreateHistoryComboBox(Option, Value);
|
|
TButton * Button = CreateButton(this);
|
|
AddButtonNextToEdit(Button, ComboBox);
|
|
Button->Tag = Tag;
|
|
Button->Caption = LoadStr(EXTENSION_OPTIONS_BROWSE);
|
|
Button->OnClick = BrowseButtonClick;
|
|
Control = ComboBox;
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okDropDownList)
|
|
{
|
|
TComboBox * ComboBox = new TUIStateAwareComboBox(this);
|
|
ComboBox->Style = csDropDownList;
|
|
|
|
AddOptionComboBox(ComboBox, Value, Option, Values);
|
|
|
|
Control = ComboBox;
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okComboBox)
|
|
{
|
|
TComboBox * ComboBox = new TUIStateAwareComboBox(this);
|
|
ComboBox->Style = csDropDown;
|
|
|
|
AddOptionComboBox(ComboBox, Value, Option, Values);
|
|
if (ComboBox->ItemIndex < 0)
|
|
{
|
|
ComboBox->Text = Value;
|
|
}
|
|
|
|
Control = ComboBox;
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okCheckBox)
|
|
{
|
|
TCheckBox * CheckBox = CreateAndAddCheckBox(Option.Caption);
|
|
|
|
CheckBox->Checked =
|
|
(Option.Params.size() >= 1) &&
|
|
(Value == Option.Params[0]);
|
|
|
|
Control = CheckBox;
|
|
}
|
|
else
|
|
{
|
|
DebugFail();
|
|
}
|
|
|
|
if (Control != NULL)
|
|
{
|
|
Control->Tag = Tag;
|
|
}
|
|
FControls.push_back(Control);
|
|
FValues.push_back(Values);
|
|
ControlIndex++;
|
|
DebugAssert(static_cast<int>(FControls.size()) == ControlIndex);
|
|
}
|
|
}
|
|
|
|
if (ShortCuts != NULL)
|
|
{
|
|
if (HasGroups)
|
|
{
|
|
StartGroup(LoadStr(EXTENSION_GENERAL_GROUP));
|
|
}
|
|
else if (ControlIndex > 0)
|
|
{
|
|
AddSeparator();
|
|
}
|
|
FShortCutCombo = new TUIStateAwareComboBox(this);
|
|
AddShortCutComboBox(FShortCutCombo, CreateLabel(LoadStr(EXTENSION_SHORTCUT)), *ShortCuts);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomCommandOptionsDialog::AddOptionComboBox(
|
|
TComboBox * ComboBox, const UnicodeString & Value, const TCustomCommandType::TOption & Option, std::vector<UnicodeString> & Values)
|
|
{
|
|
std::unique_ptr<TStringList> Items(new TStringList());
|
|
int ItemIndex = -1;
|
|
|
|
TCustomCommandType::TOption::TParams::const_iterator ParamI = Option.Params.begin();
|
|
while (ParamI != Option.Params.end())
|
|
{
|
|
UnicodeString Item = (*ParamI);
|
|
int P = Item.Pos(L"=");
|
|
UnicodeString ParamValue;
|
|
if (P > 0)
|
|
{
|
|
ParamValue = Item.SubString(1, P - 1);
|
|
Item.Delete(1, P);
|
|
}
|
|
else
|
|
{
|
|
ParamValue = Item;
|
|
}
|
|
Item = WinConfiguration->ExtensionStringTranslation(FCommand->Id, Item);
|
|
Items->Add(Item);
|
|
if (Value == ParamValue)
|
|
{
|
|
ItemIndex = Items->Count - 1;
|
|
}
|
|
Values.push_back(ParamValue);
|
|
ParamI++;
|
|
}
|
|
|
|
AddComboBox(ComboBox, CreateLabel(Option.Caption), Items.get(), true);
|
|
|
|
ComboBox->ItemIndex = ItemIndex;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
int __fastcall TCustomCommandOptionsDialog::GetOptionIndex(TControl * Control)
|
|
{
|
|
return static_cast<int>(Control->Tag >> 16);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
int __fastcall TCustomCommandOptionsDialog::GetControlIndex(TControl * Control)
|
|
{
|
|
return static_cast<int>(Control->Tag & 0xFFFF);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomCommandOptionsDialog::LinkLabelClick(TObject * Sender)
|
|
{
|
|
TStaticText * Label = DebugNotNull(dynamic_cast<TStaticText *>(Sender));
|
|
const TCustomCommandType::TOption & Option = FCommand->GetOption(GetOptionIndex(Label));
|
|
OpenBrowser(SecureUrl(Option.Default));
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomCommandOptionsDialog::BrowseButtonClick(TObject * Sender)
|
|
{
|
|
TButton * Button = DebugNotNull(dynamic_cast<TButton *>(Sender));
|
|
int OptionIndex = GetOptionIndex(Button);
|
|
const TCustomCommandType::TOption & Option = FCommand->GetOption(OptionIndex);
|
|
int ControlIndex = GetControlIndex(Button);
|
|
THistoryComboBox * ComboBox = dynamic_cast<THistoryComboBox *>(FControls[ControlIndex]);
|
|
|
|
std::unique_ptr<TOpenDialog> OpenDialog(new TOpenDialog(Application));
|
|
|
|
UnicodeString Title;
|
|
if (!Option.FileCaption.IsEmpty())
|
|
{
|
|
Title = Option.FileCaption;
|
|
}
|
|
else
|
|
{
|
|
UnicodeString Caption = Option.Caption;
|
|
Caption = StripHotkey(Caption);
|
|
if (!Caption.IsEmpty() && (Caption[Caption.Length()] == L':'))
|
|
{
|
|
Caption.SetLength(Caption.Length() - 1);
|
|
}
|
|
Title = FMTLOAD(EXTENSION_OPTIONS_BROWSE_TITLE, (Caption));
|
|
}
|
|
OpenDialog->Title = Title;
|
|
|
|
UnicodeString Value;
|
|
if (ComboBox->Text.IsEmpty())
|
|
{
|
|
Value = Option.FileInitial;
|
|
}
|
|
else
|
|
{
|
|
Value = ComboBox->Text;
|
|
}
|
|
UnicodeString ExpandedValue = ExpandEnvironmentVariables(Value);
|
|
OpenDialog->FileName = ExpandedValue;
|
|
UnicodeString InitialDir = ExtractFilePath(ExpandedValue);
|
|
if (!InitialDir.IsEmpty())
|
|
{
|
|
OpenDialog->InitialDir = InitialDir;
|
|
}
|
|
OpenDialog->Filter = Option.FileFilter;
|
|
OpenDialog->DefaultExt = Option.FileExt;
|
|
|
|
if (OpenDialog->Execute())
|
|
{
|
|
if (OpenDialog->FileName != ExpandedValue)
|
|
{
|
|
ComboBox->Text = OpenDialog->FileName;
|
|
}
|
|
// If user just confirms the initial value, persist it
|
|
else if (ComboBox->Text.IsEmpty())
|
|
{
|
|
DebugAssert(Option.FileInitial == Value);
|
|
ComboBox->Text = Value;
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
THistoryComboBox * __fastcall TCustomCommandOptionsDialog::CreateHistoryComboBox(
|
|
const TCustomCommandType::TOption & Option, const UnicodeString & Value)
|
|
{
|
|
THistoryComboBox * ComboBox = new THistoryComboBox(this);
|
|
AddComboBox(ComboBox, CreateLabel(Option.Caption));
|
|
|
|
UnicodeString HistoryKey = FCommand->GetOptionKey(Option, FSite);
|
|
HistoryKey = CustomWinConfiguration->GetValidHistoryKey(HistoryKey);
|
|
HistoryKey = L"CustomCommandOption_" + HistoryKey;
|
|
ComboBox->HistoryKey = HistoryKey;
|
|
|
|
ComboBox->Text = Value;
|
|
return ComboBox;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TCustomCommandOptionsDialog::Execute(TShortCut * ShortCut)
|
|
{
|
|
if (ShortCut != NULL)
|
|
{
|
|
SetShortCutCombo(FShortCutCombo, *ShortCut);
|
|
}
|
|
|
|
bool Result = TCustomDialog::Execute();
|
|
|
|
if (Result)
|
|
{
|
|
int ControlIndex = 0;
|
|
for (int OptionIndex = 0; OptionIndex < FCommand->OptionsCount; OptionIndex++)
|
|
{
|
|
const TCustomCommandType::TOption & Option = FCommand->GetOption(OptionIndex);
|
|
if ((Option.Flags & FFlags) != 0)
|
|
{
|
|
if ((Option.Kind != TCustomCommandType::okUnknown) &&
|
|
Option.IsControl)
|
|
{
|
|
UnicodeString OptionKey = FCommand->GetOptionKey(Option, FSite);
|
|
|
|
TControl * Control = FControls[ControlIndex];
|
|
|
|
UnicodeString Value;
|
|
if (Option.Kind == TCustomCommandType::okTextBox)
|
|
{
|
|
Value = SaveHistoryComboBoxValue(Control);
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okFile)
|
|
{
|
|
Value = SaveHistoryComboBoxValue(Control);
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okDropDownList)
|
|
{
|
|
Value = GetComboBoxValue(Control, Option.Default);
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okComboBox)
|
|
{
|
|
TComboBox * ComboBox = DebugNotNull(dynamic_cast<TComboBox *>(Control));
|
|
Value = GetComboBoxValue(Control, ComboBox->Text);
|
|
}
|
|
else if (Option.Kind == TCustomCommandType::okCheckBox)
|
|
{
|
|
TCheckBox * CheckBox = DebugNotNull(dynamic_cast<TCheckBox *>(Control));
|
|
int Index = (CheckBox->Checked ? 0 : 1);
|
|
Value = (Index < static_cast<int>(Option.Params.size())) ? Option.Params[Index] : UnicodeString();
|
|
}
|
|
else
|
|
{
|
|
DebugFail();
|
|
}
|
|
|
|
// The default value setter deletes the "name" when the value is empty.
|
|
// It would cause us to fall back to the default value, but we want to remember the empty value.
|
|
SetStringValueEvenIfEmpty(FCustomCommandOptions, OptionKey, Value);
|
|
}
|
|
|
|
ControlIndex++;
|
|
}
|
|
}
|
|
|
|
if (ShortCut != NULL)
|
|
{
|
|
*ShortCut = GetShortCutCombo(FShortCutCombo);
|
|
}
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
UnicodeString __fastcall TCustomCommandOptionsDialog::GetComboBoxValue(
|
|
TControl * Control, const UnicodeString & Default)
|
|
{
|
|
TComboBox * ComboBox = DebugNotNull(dynamic_cast<TComboBox *>(Control));
|
|
UnicodeString Result;
|
|
if (ComboBox->ItemIndex < 0)
|
|
{
|
|
Result = Default;
|
|
}
|
|
else
|
|
{
|
|
Result = FValues[GetControlIndex(Control)][ComboBox->ItemIndex];
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
UnicodeString __fastcall TCustomCommandOptionsDialog::SaveHistoryComboBoxValue(TControl * Control)
|
|
{
|
|
THistoryComboBox * ComboBox = DebugNotNull(dynamic_cast<THistoryComboBox *>(Control));
|
|
ComboBox->SaveToHistory();
|
|
return ComboBox->Text;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomCommandOptionsDialog::DoHelp()
|
|
{
|
|
UnicodeString HelpPage;
|
|
if (!FCommand->OptionsPage.IsEmpty())
|
|
{
|
|
HelpPage = FCommand->OptionsPage;
|
|
}
|
|
else
|
|
{
|
|
HelpPage = FCommand->HomePage;
|
|
}
|
|
|
|
if (!HelpPage.IsEmpty())
|
|
{
|
|
OpenBrowser(HelpPage);
|
|
}
|
|
else
|
|
{
|
|
TCustomDialog::DoHelp();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TCustomCommandOptionsDialog::DoShow()
|
|
{
|
|
TCustomDialog::DoShow();
|
|
|
|
int ControlIndex = 0;
|
|
for (int OptionIndex = 0; OptionIndex < FCommand->OptionsCount; OptionIndex++)
|
|
{
|
|
const TCustomCommandType::TOption & Option = FCommand->GetOption(OptionIndex);
|
|
|
|
if ((Option.Flags & FFlags) != 0)
|
|
{
|
|
if (Option.Kind == TCustomCommandType::okFile)
|
|
{
|
|
TControl * Control = FControls[ControlIndex];
|
|
InstallPathWordBreakProc(DebugNotNull(dynamic_cast<TWinControl *>(Control)));
|
|
}
|
|
ControlIndex++;
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall DoCustomCommandOptionsDialog(
|
|
const TCustomCommandType * Command, TStrings * CustomCommandOptions, TShortCut * ShortCut,
|
|
unsigned int Flags, TCustomCommand * CustomCommandForOptions,
|
|
const UnicodeString & Site, const TShortCuts * ShortCuts)
|
|
{
|
|
std::unique_ptr<TCustomCommandOptionsDialog> Dialog(
|
|
new TCustomCommandOptionsDialog(Command, CustomCommandOptions, Flags, CustomCommandForOptions, Site, ShortCuts));
|
|
return Dialog->Execute(ShortCut);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
class TUsageStatisticsDialog : public TCustomDialog
|
|
{
|
|
public:
|
|
__fastcall TUsageStatisticsDialog();
|
|
|
|
protected:
|
|
virtual void __fastcall DoChange(bool & CanSubmit);
|
|
|
|
private:
|
|
TEdit * FilterEdit;
|
|
TMemo * UsageMemo;
|
|
TButton * ClipboardButton;
|
|
|
|
void __fastcall ClipboardButtonClick(TObject * Sender);
|
|
};
|
|
//---------------------------------------------------------------------------
|
|
__fastcall TUsageStatisticsDialog::TUsageStatisticsDialog() :
|
|
TCustomDialog(HELP_USAGE)
|
|
{
|
|
Caption = LoadStr(USAGE_CAPTION);
|
|
Width = ScaleByTextHeight(this, 444);
|
|
|
|
// UnformatMessage is called, because previously, ** markup was used and translations may still contain that
|
|
AddText(CreateLabel(UnformatMessage(LoadStr(USAGE_DATA2))));
|
|
|
|
FilterEdit = new TEdit(this);
|
|
FilterEdit->Width = ScaleByTextHeight(this, 277);
|
|
AddEdit(FilterEdit, CreateLabel(LoadStr(USAGE_FILTER)), true);
|
|
|
|
UsageMemo = new TMemo(this);
|
|
UsageMemo->Height = ScaleByTextHeight(this, 333);
|
|
UsageMemo->ScrollBars = ssVertical;
|
|
AddEdit(UsageMemo, NULL);
|
|
ReadOnlyControl(UsageMemo);
|
|
|
|
ClipboardButton = CreateButton(this);
|
|
ClipboardButton->Caption = LoadStr(USAGE_COPY);
|
|
ClipboardButton->Width = ScaleByTextHeight(this, 179);
|
|
ClipboardButton->OnClick = ClipboardButtonClick;
|
|
AddDialogButton(ClipboardButton);
|
|
|
|
RemoveCancelButton();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TUsageStatisticsDialog::ClipboardButtonClick(TObject * /*Sender*/)
|
|
{
|
|
TInstantOperationVisualizer Visualizer;
|
|
CopyToClipboard(UsageMemo->Lines);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TUsageStatisticsDialog::DoChange(bool & CanSubmit)
|
|
{
|
|
TCustomDialog::DoChange(CanSubmit);
|
|
UnicodeString Text = Configuration->Usage->Serialize(L"\n", FilterEdit->Text);
|
|
bool NoUsage = Text.IsEmpty();
|
|
ClipboardButton->Enabled = !NoUsage;
|
|
if (NoUsage)
|
|
{
|
|
Text = LoadStr(USAGE_DATA_NONE2);
|
|
}
|
|
UsageMemo->Lines->Text = Text;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall DoUsageStatisticsDialog()
|
|
{
|
|
std::unique_ptr<TUsageStatisticsDialog> Dialog(new TUsageStatisticsDialog());
|
|
Dialog->Execute();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
class TSiteRawDialog : public TCustomDialog
|
|
{
|
|
public:
|
|
__fastcall TSiteRawDialog();
|
|
|
|
bool __fastcall Execute(TSessionData * Data);
|
|
|
|
protected:
|
|
DYNAMIC void __fastcall DoShow();
|
|
|
|
private:
|
|
TMemo * SettingsMemo;
|
|
|
|
void __fastcall AddButtonClick(TObject * Sender);
|
|
void __fastcall SettingsMemoKeyDown(TObject * Sender, WORD & Key, TShiftState Shift);
|
|
|
|
void DeleteNames(TStrings * Names, TStrings * Options);
|
|
};
|
|
//---------------------------------------------------------------------------
|
|
__fastcall TSiteRawDialog::TSiteRawDialog() :
|
|
TCustomDialog(HELP_SITE_RAW)
|
|
{
|
|
Caption = LoadStr(SITE_RAW_CAPTION);
|
|
Width = ScaleByTextHeight(this, 444);
|
|
|
|
SettingsMemo = new TMemo(this);
|
|
SettingsMemo->Height = ScaleByTextHeight(this, 333);
|
|
SettingsMemo->OnKeyDown = SettingsMemoKeyDown;
|
|
AddEdit(SettingsMemo, NULL);
|
|
|
|
TButton * AddButton = CreateButton(this);
|
|
AddButton->Caption = LoadStr(SITE_RAW_ADD);
|
|
AddButton->Width = OKButton->Width;
|
|
AddButton->OnClick = AddButtonClick;
|
|
AddDialogButton(AddButton);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TSiteRawDialog::DoShow()
|
|
{
|
|
TCustomDialog::DoShow();
|
|
InstallPathWordBreakProc(SettingsMemo);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool __fastcall TSiteRawDialog::Execute(TSessionData * Data)
|
|
{
|
|
std::unique_ptr<TSessionData> FactoryDefaults(new TSessionData(L""));
|
|
std::unique_ptr<TSessionData> RawData(new TSessionData(L""));
|
|
RawData->Assign(Data);
|
|
// SFTP-only is not reflected by the protocol prefix, we have to use rawsettings for that
|
|
if (RawData->FSProtocol != fsSFTPonly)
|
|
{
|
|
RawData->FSProtocol = FactoryDefaults->FSProtocol;
|
|
}
|
|
RawData->HostName = FactoryDefaults->HostName;
|
|
RawData->PortNumber = FactoryDefaults->PortNumber;
|
|
RawData->UserName = FactoryDefaults->UserName;
|
|
RawData->Password = FactoryDefaults->Password;
|
|
RawData->Ftps = FactoryDefaults->Ftps;
|
|
|
|
std::unique_ptr<TStrings> Options(RawData->SaveToOptions(FactoryDefaults.get(), false, false));
|
|
|
|
SettingsMemo->Lines = Options.get();
|
|
|
|
bool Result = TCustomDialog::Execute();
|
|
if (Result)
|
|
{
|
|
std::unique_ptr<TSessionData> BackupData(new TSessionData(L""));
|
|
BackupData->Assign(Data);
|
|
Data->DefaultSettings();
|
|
|
|
Data->FSProtocol = BackupData->FSProtocol;
|
|
Data->HostName = BackupData->HostName;
|
|
Data->PortNumber = BackupData->PortNumber;
|
|
Data->UserName = BackupData->UserName;
|
|
Data->Password = BackupData->Password;
|
|
Data->Ftps = BackupData->Ftps;
|
|
|
|
Data->ApplyRawSettings(SettingsMemo->Lines, false);
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TSiteRawDialog::SettingsMemoKeyDown(TObject * Sender, WORD & Key, TShiftState Shift)
|
|
{
|
|
MemoKeyDown(Sender, Key, Shift);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TSiteRawDialog::AddButtonClick(TObject *)
|
|
{
|
|
std::unique_ptr<TSessionData> FactoryDefaults(new TSessionData(L""));
|
|
std::unique_ptr<TSessionData> BasicData(new TSessionData(L""));
|
|
BasicData->FSProtocol = TFSProtocol(FactoryDefaults->FSProtocol + 1);
|
|
UnicodeString RandomAppendix(L"_");
|
|
BasicData->HostName = FactoryDefaults->HostName + RandomAppendix;
|
|
BasicData->Ftps = TFtps(FactoryDefaults->Ftps + 1);
|
|
BasicData->PortNumber = BasicData->GetDefaultPort() + 1;
|
|
BasicData->UserName = FactoryDefaults->UserName + RandomAppendix;
|
|
BasicData->Password = FactoryDefaults->Password + RandomAppendix;
|
|
|
|
std::unique_ptr<TStrings> BasicOptions(BasicData->SaveToOptions(FactoryDefaults.get(), false, false));
|
|
|
|
std::unique_ptr<TStrings> AllOptions(TSessionData::GetAllOptionNames(false));
|
|
|
|
std::unique_ptr<TStrings> Names(CreateSortedStringList());
|
|
for (int Index = 0; Index < AllOptions->Count; Index++)
|
|
{
|
|
Names->Add(AllOptions->Names[Index]);
|
|
}
|
|
DeleteNames(Names.get(), BasicOptions.get());
|
|
DeleteNames(Names.get(), SettingsMemo->Lines);
|
|
|
|
std::unique_ptr<TCustomDialog> AddDialog(new TCustomDialog(HelpKeyword));
|
|
AddDialog->Caption = LoadStr(SITE_RAW_ADD_CAPTION);
|
|
TComboBox * AddComboBox = new TUIStateAwareComboBox(AddDialog.get());
|
|
AddComboBox->Style = csDropDownList;
|
|
AddComboBox->DropDownCount = Max(AddComboBox->DropDownCount, DefaultHistoryDropDownCount);
|
|
AddDialog->AddComboBox(AddComboBox, CreateLabel(LoadStr(SITE_RAW_ADD_LABEL)), Names.get(), true);
|
|
AddComboBox->ItemIndex = 0;
|
|
if (AddDialog->Execute())
|
|
{
|
|
UnicodeString Name = AddComboBox->Items->Strings[AddComboBox->ItemIndex];
|
|
UnicodeString Value = AllOptions->Values[Name];
|
|
UnicodeString NameAndSeparator = Name + SettingsMemo->Lines->NameValueSeparator;
|
|
int Start = (SettingsMemo->Lines->Text + NameAndSeparator).Length();
|
|
SettingsMemo->Lines->Add(NameAndSeparator + Value);
|
|
SettingsMemo->SetFocus();
|
|
SettingsMemo->SelStart = Start;
|
|
SettingsMemo->SelLength = Value.Length();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TSiteRawDialog::DeleteNames(TStrings * Names, TStrings * Options)
|
|
{
|
|
for (int Index = 0; Index < Options->Count; Index++)
|
|
{
|
|
UnicodeString Name = Options->Names[Index];
|
|
if (!Name.IsEmpty())
|
|
{
|
|
int I = Names->IndexOf(Name);
|
|
if (I >= 0)
|
|
{
|
|
Names->Delete(I);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall DoSiteRawDialog(TSessionData * Data)
|
|
{
|
|
std::unique_ptr<TSiteRawDialog> Dialog(new TSiteRawDialog());
|
|
Dialog->Execute(Data);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
class TSshHostCADialog : public TCustomDialog
|
|
{
|
|
public:
|
|
TSshHostCADialog(bool Add);
|
|
bool Execute(TSshHostCA & SshHostCA);
|
|
|
|
protected:
|
|
virtual void __fastcall DoChange(bool & CanSubmit);
|
|
virtual void __fastcall DoValidate();
|
|
|
|
private:
|
|
TEdit * NameEdit;
|
|
TEdit * PublicKeyEdit;
|
|
TEdit * PublicKeyLabel;
|
|
TEdit * ValidityExpressionEdit;
|
|
TCheckBox * PermitRsaSha1Check;
|
|
TCheckBox * PermitRsaSha256Check;
|
|
TCheckBox * PermitRsaSha512Check;
|
|
|
|
void __fastcall BrowseButtonClick(TObject * Sender);
|
|
TCheckBox * AddValidityCheckBox(int CaptionStrPart);
|
|
bool ValidatePublicKey(UnicodeString & Status);
|
|
};
|
|
//---------------------------------------------------------------------------
|
|
TSshHostCADialog::TSshHostCADialog(bool Add) :
|
|
TCustomDialog(HELP_SSH_HOST_CA)
|
|
{
|
|
ClientWidth = ScaleByTextHeight(this, 577);
|
|
Caption = LoadStr(Add ? SSH_HOST_CA_ADD : SSH_HOST_CA_EDIT);
|
|
|
|
NameEdit = new TEdit(this);
|
|
AddEdit(NameEdit, CreateLabel(LoadStr(SSH_HOST_CA_NAME)));
|
|
|
|
PublicKeyEdit = new TEdit(this);
|
|
AddEdit(PublicKeyEdit, CreateLabel(LoadStr(SSH_HOST_CA_PUBLIC_KEY)));
|
|
|
|
TButton * BrowseButton = CreateButton(this);
|
|
BrowseButton->Caption = LoadStr(SSH_HOST_CA_BROWSE);
|
|
BrowseButton->OnClick = BrowseButtonClick;
|
|
AddButtonNextToEdit(BrowseButton, PublicKeyEdit);
|
|
NameEdit->Width = PublicKeyEdit->Width;
|
|
|
|
PublicKeyLabel = new TEdit(this);
|
|
ReadOnlyControl(PublicKeyLabel);
|
|
PublicKeyLabel->BorderStyle = bsNone;
|
|
PublicKeyLabel->TabStop = false;
|
|
AddEditLikeControl(PublicKeyLabel, NULL);
|
|
|
|
ValidityExpressionEdit = new TEdit(this);
|
|
AddEdit(ValidityExpressionEdit, CreateLabel(LoadStr(SSH_HOST_CA_PUBLIC_HOSTS)));
|
|
|
|
TLabel * Label = CreateLabel(LoadStr(SSH_HOST_CA_SIGNATURE_TYPES));
|
|
AddText(Label);
|
|
|
|
PermitRsaSha1Check = AddValidityCheckBox(1);
|
|
int PermitCheckBoxTop = Label->Top - (PermitRsaSha1Check->Height - Label->Height) / 2;
|
|
PermitRsaSha1Check->Left = OKButton->Left + 1;
|
|
PermitRsaSha1Check->Top = PermitCheckBoxTop;
|
|
PermitRsaSha256Check = AddValidityCheckBox(2);
|
|
PermitRsaSha256Check->Left = CancelButton->Left + 1;
|
|
PermitRsaSha256Check->Top = PermitCheckBoxTop;
|
|
PermitRsaSha512Check = AddValidityCheckBox(3);
|
|
PermitRsaSha512Check->Left = HelpButton->Left + 1;
|
|
PermitRsaSha512Check->Top = PermitCheckBoxTop;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TCheckBox * TSshHostCADialog::AddValidityCheckBox(int CaptionStrPart)
|
|
{
|
|
TCheckBox * Result = new TCheckBox(this);
|
|
Result->Parent = this;
|
|
Result->Caption = LoadStrPart(SSH_HOST_CA_SIGNATURES, CaptionStrPart);
|
|
ScaleButtonControl(Result);
|
|
Result->Left = Left;
|
|
Result->OnClick = Change;
|
|
AddWinControl(Result);
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool TSshHostCADialog::ValidatePublicKey(UnicodeString & Status)
|
|
{
|
|
bool Result = false;
|
|
UnicodeString PublicKeyText = PublicKeyEdit->Text.Trim();
|
|
if (PublicKeyText.IsEmpty())
|
|
{
|
|
Status = LoadStr(SSH_HOST_CA_NO_KEY);
|
|
}
|
|
else
|
|
{
|
|
RawByteString PublicKeyDummy;
|
|
try
|
|
{
|
|
ParseCertificatePublicKey(PublicKeyText, PublicKeyDummy, Status);
|
|
Result = true;
|
|
}
|
|
catch (Exception & E)
|
|
{
|
|
Status = E.Message;
|
|
}
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TSshHostCADialog::DoChange(bool & CanSubmit)
|
|
{
|
|
TCustomDialog::DoChange(CanSubmit);
|
|
|
|
UnicodeString PublicKeyStatus;
|
|
ValidatePublicKey(PublicKeyStatus);
|
|
// Should drop "SHA256:" prefix, the way we do in TSecureShell::VerifyHostKey
|
|
PublicKeyLabel->Text = PublicKeyStatus;
|
|
|
|
CanSubmit = !NameEdit->Text.Trim().IsEmpty() && !PublicKeyEdit->Text.Trim().IsEmpty();
|
|
}
|
|
//---------------------------------------------------------------------
|
|
void __fastcall TSshHostCADialog::DoValidate()
|
|
{
|
|
TCustomDialog::DoValidate();
|
|
|
|
UnicodeString PublicKeyStatus;
|
|
if (!ValidatePublicKey(PublicKeyStatus))
|
|
{
|
|
PublicKeyEdit->SetFocus();
|
|
throw Exception(MainInstructions(PublicKeyStatus));
|
|
}
|
|
|
|
if (ValidityExpressionEdit->Text.Trim().IsEmpty())
|
|
{
|
|
ValidityExpressionEdit->SetFocus();
|
|
throw Exception(MainInstructions(LoadStr(SSH_HOST_CA_NO_HOSTS)));
|
|
}
|
|
|
|
UnicodeString Error;
|
|
int ErrorStart, ErrorLen;
|
|
if (!IsCertificateValidityExpressionValid(ValidityExpressionEdit->Text, Error, ErrorStart, ErrorLen))
|
|
{
|
|
std::unique_ptr<TStrings> MoreMessages(TextToStringList(Error));
|
|
MoreMessageDialog(MainInstructions(LoadStr(SSH_HOST_CA_HOSTS_INVALID)), MoreMessages.get(), qtError, qaOK, HelpKeyword);
|
|
|
|
ValidityExpressionEdit->SetFocus();
|
|
ValidityExpressionEdit->SelStart = ErrorStart;
|
|
ValidityExpressionEdit->SelLength = ErrorLen;
|
|
Abort();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool TSshHostCADialog::Execute(TSshHostCA & SshHostCA)
|
|
{
|
|
NameEdit->Text = SshHostCA.Name;
|
|
RawByteString PublicKey = SshHostCA.PublicKey;
|
|
PublicKeyEdit->Text = EncodeStrToBase64(PublicKey);
|
|
ValidityExpressionEdit->Text = SshHostCA.ValidityExpression;
|
|
PermitRsaSha1Check->Checked = SshHostCA.PermitRsaSha1;
|
|
PermitRsaSha256Check->Checked = SshHostCA.PermitRsaSha256;
|
|
PermitRsaSha512Check->Checked = SshHostCA.PermitRsaSha512;
|
|
bool Result = TCustomDialog::Execute();
|
|
if (Result)
|
|
{
|
|
SshHostCA.Name = NameEdit->Text;
|
|
SshHostCA.PublicKey = DecodeBase64ToStr(PublicKeyEdit->Text);
|
|
SshHostCA.ValidityExpression = ValidityExpressionEdit->Text;
|
|
SshHostCA.PermitRsaSha1 = PermitRsaSha1Check->Checked;
|
|
SshHostCA.PermitRsaSha256 = PermitRsaSha256Check->Checked;
|
|
SshHostCA.PermitRsaSha512 = PermitRsaSha512Check->Checked;
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TSshHostCADialog::BrowseButtonClick(TObject *)
|
|
{
|
|
std::unique_ptr<TOpenDialog> OpenDialog(new TOpenDialog(Application));
|
|
OpenDialog->Title = LoadStr(SSH_HOST_CA_BROWSE_TITLE);
|
|
OpenDialog->Filter = LoadStr(SSH_HOST_CA_BROWSE_FILTER);
|
|
bool Result = OpenDialog->Execute();
|
|
if (Result)
|
|
{
|
|
UnicodeString FileName = OpenDialog->FileName;
|
|
UnicodeString Algorithm, Comment;
|
|
bool HasCertificate;
|
|
RawByteString PublicKey;
|
|
try
|
|
{
|
|
PublicKey = LoadPublicKey(FileName, Algorithm, Comment, HasCertificate);
|
|
}
|
|
catch (Exception & E)
|
|
{
|
|
throw ExtException(&E, MainInstructions(FMTLOAD(SSH_HOST_CA_LOAD_ERROR, (FileName))));
|
|
}
|
|
|
|
if (NameEdit->Text.IsEmpty())
|
|
{
|
|
NameEdit->Text = Comment;
|
|
}
|
|
PublicKeyEdit->Text = EncodeStrToBase64(PublicKey);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool DoSshHostCADialog(bool Add, TSshHostCA & SshHostCA)
|
|
{
|
|
std::unique_ptr<TSshHostCADialog> Dialog(new TSshHostCADialog(Add));
|
|
return Dialog->Execute(SshHostCA);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
class TTagDialog : public TCustomDialog
|
|
{
|
|
public:
|
|
TTagDialog(bool Add, TStrings * Tags);
|
|
bool Execute(UnicodeString & Key, UnicodeString & Value);
|
|
|
|
protected:
|
|
virtual void __fastcall DoChange(bool & CanSubmit);
|
|
virtual void __fastcall DoValidate();
|
|
|
|
private:
|
|
TEdit * KeyEdit;
|
|
TEdit * ValueEdit;
|
|
TStrings * FTags;
|
|
|
|
void ValidateTag(TEdit * Edit);
|
|
};
|
|
//---------------------------------------------------------------------------
|
|
TTagDialog::TTagDialog(bool Add, TStrings * Tags) :
|
|
TCustomDialog(HELP_TAG)
|
|
{
|
|
Caption = LoadStr(Add ? TAG_ADD : TAG_EDIT);
|
|
FTags = Tags;
|
|
|
|
KeyEdit = new TEdit(this);
|
|
KeyEdit->MaxLength = 128;
|
|
AddEdit(KeyEdit, CreateLabel(LoadStr(TAG_KEY)));
|
|
|
|
ValueEdit = new TEdit(this);
|
|
ValueEdit->MaxLength = 256;
|
|
AddEdit(ValueEdit, CreateLabel(LoadStr(TAG_VALUE)));
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool TTagDialog::Execute(UnicodeString & Key, UnicodeString & Value)
|
|
{
|
|
// if we happen to get values longer than what we believed was possible, allow them.
|
|
KeyEdit->MaxLength = std::max(KeyEdit->MaxLength, Key.Length());
|
|
KeyEdit->Text = Key;
|
|
ValueEdit->MaxLength = std::max(ValueEdit->MaxLength, Value.Length());
|
|
ValueEdit->Text = Value;
|
|
bool Result = TCustomDialog::Execute();
|
|
if (Result)
|
|
{
|
|
Key = KeyEdit->Text;
|
|
Value = ValueEdit->Text;
|
|
}
|
|
return Result;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TTagDialog::DoChange(bool & CanSubmit)
|
|
{
|
|
CanSubmit = !KeyEdit->Text.IsEmpty();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void TTagDialog::ValidateTag(TEdit * Edit)
|
|
{
|
|
// there are lot more in various scripts
|
|
UnicodeString InvalidChars = L"!\"#$%&'()*,;<>?[\\]^`{|}~¡¢£¤¥¦§¨©«¬®¯°±´¶·¸»¿×÷";
|
|
UnicodeString Text = Edit->Text;
|
|
for (int Index = 1; Index <= Text.Length(); Index++)
|
|
{
|
|
wchar_t Ch = Text[Index];
|
|
if (TCharacter::IsControl(Ch) ||
|
|
(InvalidChars.Pos(Ch) > 0))
|
|
{
|
|
UnicodeString Message = MainInstructions(FMTLOAD(TAG_INVALID_CHAR, (Ch)));
|
|
if (MoreMessageDialog(Message, NULL, qtWarning, qaIgnore | qaAbort, HelpKeyword) != qaIgnore)
|
|
{
|
|
Edit->SetFocus();
|
|
Abort();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TTagDialog::DoValidate()
|
|
{
|
|
UnicodeString Key = KeyEdit->Text;
|
|
if (FTags->IndexOf(Key) >= 0)
|
|
{
|
|
throw Exception(MainInstructions(LoadStr(TAG_NOT_UNIQUE)));
|
|
}
|
|
|
|
ValidateTag(KeyEdit);
|
|
ValidateTag(ValueEdit);
|
|
|
|
TCustomDialog::DoValidate();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
bool DoTagDialog(bool Add, TStrings * Tags, UnicodeString & Key, UnicodeString & Value)
|
|
{
|
|
std::unique_ptr<TTagDialog> Dialog(new TTagDialog(Add, Tags));
|
|
return Dialog->Execute(Key, Value);
|
|
}
|