Ver código fonte

Bug 1930: Keyboard-interactive authentication challenges can be copied to the clipboard and links contained in the challenges can be opened

https://winscp.net/tracker/1930

Source commit: 705dcf35b547fee28c4b6d341f9289936529f95c
Martin Prikryl 4 anos atrás
pai
commit
ac3e58b29e

+ 94 - 3
source/forms/Authenticate.cpp

@@ -12,6 +12,8 @@
 #include <CoreMain.h>
 #include <PasTools.hpp>
 #include <CustomWinConfiguration.h>
+#include <Character.hpp>
+#include <Tools.h>
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
 #pragma link "PasswordEdit"
@@ -240,8 +242,20 @@ TCustomEdit * __fastcall TAuthenticateForm::GenerateEdit(int Current, bool Echo)
   return Result;
 }
 //---------------------------------------------------------------------------
-TList * __fastcall TAuthenticateForm::GeneratePrompt(UnicodeString Instructions,
-  TStrings * Prompts)
+void TAuthenticateForm::ExternalLabel(TLabel * Label)
+{
+  Label->OnContextPopup = LabelContextPopup;
+  Label->PopupMenu = LabelPopupMenu;
+  UnicodeString Url;
+  if (ExtractUrl(Label->Caption, Url))
+  {
+    Label->Cursor = crHandPoint;
+    Label->OnClick = LinkClick;
+  }
+}
+//---------------------------------------------------------------------------
+TList * __fastcall TAuthenticateForm::GeneratePrompt(
+  TPromptKind Kind, const UnicodeString & Instructions, TStrings * Prompts)
 {
   while (FPromptParent->ControlCount > 0)
   {
@@ -254,6 +268,7 @@ TList * __fastcall TAuthenticateForm::GeneratePrompt(UnicodeString Instructions,
   if (!Instructions.IsEmpty())
   {
     TLabel * Label = GenerateLabel(Current, Instructions);
+    ExternalLabel(Label);
     Current += Label->Height + FPromptsGap;
   }
 
@@ -265,6 +280,10 @@ TList * __fastcall TAuthenticateForm::GeneratePrompt(UnicodeString Instructions,
     }
 
     TLabel * Label = GenerateLabel(Current, Prompts->Strings[Index]);
+    if (Kind == pkKeybInteractive)
+    {
+      ExternalLabel(Label);
+    }
     Current += Label->Height + FPromptEditGap;
 
     bool Echo = FLAGSET(int(Prompts->Objects[Index]), pupEcho);
@@ -285,7 +304,7 @@ bool __fastcall TAuthenticateForm::PromptUser(TPromptKind Kind, UnicodeString Na
 {
 
   bool Result;
-  TList * Edits = GeneratePrompt(Instructions, Prompts);
+  TList * Edits = GeneratePrompt(Kind, Instructions, Prompts);
 
   try
   {
@@ -649,3 +668,75 @@ void __fastcall TAuthenticateForm::LogViewMouseMove(TObject *, TShiftState, int
   }
 }
 //---------------------------------------------------------------------------
+bool TAuthenticateForm::ExtractUrl(const UnicodeString & Text, UnicodeString & Url)
+{
+  bool Result = false;
+  UnicodeString Prefix = HttpsProtocol + ProtocolSeparator;
+  int P = Text.Pos(Prefix);
+  if (P == 0)
+  {
+    Prefix = HttpProtocol + ProtocolSeparator;
+    P = Text.Pos(Prefix);
+  }
+  if (P > 0)
+  {
+    Url = Text.SubString(P, Text.Length() - P + 1);
+    P = 1;
+    while (P <= Url.Length())
+    {
+      if (TCharacter::IsWhiteSpace(Url[P]))
+      {
+        Url.SetLength(P - 1);
+      }
+      P++;
+    }
+    // At least one letter/digit after the prefix
+    if ((Url.Length() > Prefix.Length()) &&
+        (::IsLetter(Url[Prefix.Length() + 1]) || ::IsDigit(Url[Prefix.Length() + 1])))
+    {
+      Result = true;
+    }
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
+void __fastcall TAuthenticateForm::LabelContextPopup(TObject * Sender, const TPoint & MousePos, bool & Handled)
+{
+  TLabel * Label = dynamic_cast<TLabel *>(Sender);
+  UnicodeString Url;
+  LabelOpenLinkAction->Visible = ExtractUrl(Label->Caption, Url);
+  FContextLabel = Label;
+  MenuPopup(Sender, MousePos, Handled);
+}
+//---------------------------------------------------------------------------
+void __fastcall TAuthenticateForm::LabelCopyActionExecute(TObject *)
+{
+  if (DebugAlwaysTrue(FContextLabel != NULL))
+  {
+    TInstantOperationVisualizer Visualizer;
+    CopyToClipboard(FContextLabel->Caption);
+  }
+}
+//---------------------------------------------------------------------------
+void TAuthenticateForm::LabelOpen(TLabel * Label)
+{
+  UnicodeString Url;
+  if (ExtractUrl(Label->Caption, Url))
+  {
+    OpenBrowser(Url);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TAuthenticateForm::LabelOpenLinkActionExecute(TObject *)
+{
+  if (DebugAlwaysTrue(FContextLabel != NULL))
+  {
+    LabelOpen(FContextLabel);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TAuthenticateForm::LinkClick(TObject * Sender)
+{
+  LabelOpen(DebugNotNull(dynamic_cast<TLabel *>(Sender)));
+}
+//---------------------------------------------------------------------------

+ 27 - 0
source/forms/Authenticate.dfm

@@ -280,19 +280,32 @@ object AuthenticateForm: TAuthenticateForm
     Left = 32
     Top = 304
     object EditCopyAction: TEditCopy
+      Category = 'Banner'
       Caption = '&Copy'
       ImageIndex = 0
       ShortCut = 16451
     end
     object EditSelectAllAction: TEditSelectAll
+      Category = 'Banner'
       Caption = 'Select &All'
       ImageIndex = 1
       ShortCut = 16449
     end
     object BannerMonospacedFontAction: TAction
+      Category = 'Banner'
       Caption = 'Use &Monospaced Font'
       OnExecute = BannerMonospacedFontActionExecute
     end
+    object LabelCopyAction: TAction
+      Category = 'Label'
+      Caption = '&Copy'
+      OnExecute = LabelCopyActionExecute
+    end
+    object LabelOpenLinkAction: TAction
+      Category = 'Label'
+      Caption = '&Open'
+      OnExecute = LabelOpenLinkActionExecute
+    end
   end
   object BannerPopupMenu: TPopupMenu
     Left = 144
@@ -310,4 +323,18 @@ object AuthenticateForm: TAuthenticateForm
       Action = BannerMonospacedFontAction
     end
   end
+  object LabelPopupMenu: TPopupMenu
+    Left = 56
+    Top = 72
+    object Copy1: TMenuItem
+      Action = LabelCopyAction
+    end
+    object N2: TMenuItem
+      Caption = '-'
+    end
+    object Open1: TMenuItem
+      Action = LabelOpenLinkAction
+      Default = True
+    end
+  end
 end

+ 15 - 1
source/forms/Authenticate.h

@@ -52,6 +52,12 @@ __published:
   TMenuItem *SelectAllItem;
   TMenuItem *N1;
   TMenuItem *AdjustWindowItem;
+  TPopupMenu *LabelPopupMenu;
+  TMenuItem *N2;
+  TAction *LabelCopyAction;
+  TAction *LabelOpenLinkAction;
+  TMenuItem *Open1;
+  TMenuItem *Copy1;
   void __fastcall FormShow(TObject *Sender);
   void __fastcall HelpButtonClick(TObject *Sender);
   void __fastcall LogViewMeasureItem(TWinControl *Control, int Index, int &Height);
@@ -60,6 +66,8 @@ __published:
   void __fastcall BannerMemoContextPopup(TObject *Sender, TPoint &MousePos, bool &Handled);
   void __fastcall BannerMonospacedFontActionExecute(TObject *Sender);
   void __fastcall LogViewMouseMove(TObject *Sender, TShiftState Shift, int X, int Y);
+  void __fastcall LabelCopyActionExecute(TObject *Sender);
+  void __fastcall LabelOpenLinkActionExecute(TObject *Sender);
 
 public:
   __fastcall TAuthenticateForm(TComponent * Owner);
@@ -86,7 +94,7 @@ protected:
   void __fastcall WMNCCreate(TWMNCCreate & Message);
   TLabel * __fastcall GenerateLabel(int Current, UnicodeString Caption);
   TCustomEdit * __fastcall GenerateEdit(int Current, bool Echo);
-  TList * __fastcall GeneratePrompt(UnicodeString Instructions, TStrings * Prompts);
+  TList * __fastcall GeneratePrompt(TPromptKind Kind, const UnicodeString & Instructions, TStrings * Prompts);
   void __fastcall DoCancel();
   void __fastcall AdjustLogView();
   void __fastcall MakeLogItemVisible(int Index);
@@ -96,6 +104,11 @@ protected:
   DYNAMIC void __fastcall ChangeScale(int M, int D);
   void __fastcall UpdateBannerFont();
   void __fastcall DoAdjustWindow();
+  void __fastcall LabelContextPopup(TObject* Sender, const TPoint & MousePos, bool & Handled);
+  bool ExtractUrl(const UnicodeString & Text, UnicodeString & Url);
+  void ExternalLabel(TLabel * Label);
+  void __fastcall LinkClick(TObject * Sender);
+  void LabelOpen(TLabel * Label);
 
 private:
   void * FShowAsModalStorage;
@@ -118,6 +131,7 @@ private:
   bool FShowNoActivate;
   std::vector<UnicodeString> FHints;
   int FHintIndex;
+  TLabel * FContextLabel;
 
   INTERFACE_HOOK;
 };