Browse Source

Improving PR#51/Issue 2239 implementation

https://winscp.net/tracker/2239

Lines are included at the place of the Include directive + Include works even for tunnels + Include directive supports multiple arguments + IdentityFile does not support paths relative to .ssh folder

Source commit: 632f5a12334accb9888bf90aae61c5dbc7d70d07
Martin Prikryl 2 years ago
parent
commit
937c2a1df1

+ 37 - 1
source/core/Configuration.cpp

@@ -1685,7 +1685,7 @@ bool __fastcall TConfiguration::AnyFilezillaSessionForImport(TStoredSessionList
   }
 }
 //---------------------------------------------------------------------
-UnicodeString TConfiguration::GetOpensshFolder()
+UnicodeString GetOpensshFolder()
 {
   UnicodeString ProfilePath = GetShellFolderPath(CSIDL_PROFILE);
   UnicodeString Result = TPath::Combine(ProfilePath, OpensshFolderName);
@@ -1748,6 +1748,42 @@ TStoredSessionList * TConfiguration::SelectOpensshSessionsForImport(
     {
       std::unique_ptr<TStrings> Lines(new TStringList());
       LoadScriptFromFile(ConfigFile, Lines.get(), true);
+
+      const UnicodeString OpensshIncludeDirective(L"Include");
+      for (int Index = 0; Index < Lines->Count; Index++)
+      {
+        UnicodeString Line = Lines->Strings[Index];
+        UnicodeString Directive, Args;
+        if (ParseOpensshDirective(Line, Directive, Args))
+        {
+          if (SameText(Directive, OpensshIncludeDirective))
+          {
+            while (!Args.IsEmpty())
+            {
+              UnicodeString IncludePath = ConvertPathFromOpenssh(CutOpensshToken(Args));
+
+              // If path does not exist, try if it works relatively to .ssh/
+              if (!FileExists(ApiPath(IncludePath)))
+              {
+                IncludePath = TPath::Combine(GetOpensshFolder(), IncludePath);
+              }
+
+              if (FileExists(ApiPath(IncludePath)))
+              {
+                std::unique_ptr <TStrings> LinesToInclude(new TStringList());
+                LoadScriptFromFile(IncludePath, LinesToInclude.get(), true);
+                Lines->Delete(Index); // Not really needed
+                for (int Index2 = 0; Index2 < LinesToInclude->Count; Index2++)
+                {
+                  Lines->Insert(Index + Index2, LinesToInclude->Strings[Index2]);
+                }
+                Index--;
+              }
+            }
+          }
+        }
+      }
+
       ImportSessionList->ImportFromOpenssh(Lines.get());
 
       if (ImportSessionList->Count > 0)

+ 0 - 1
source/core/Configuration.h

@@ -334,7 +334,6 @@ public:
     TStrings * Lines, TStoredSessionList * Sessions, UnicodeString & Error);
   TStoredSessionList * SelectOpensshSessionsForImport(TStoredSessionList * Sessions, UnicodeString & Error);
   UnicodeString GetPuttySessionsKey(const UnicodeString & RootKey);
-  UnicodeString GetOpensshFolder();
   void RefreshPuttySshHostCAList();
 
   __property TVSFixedFileInfo *FixedApplicationInfo  = { read=GetFixedApplicationInfo };

+ 2 - 21
source/core/SessionData.cpp

@@ -80,7 +80,6 @@ const UnicodeString RawSettingsOption(L"rawsettings");
 const UnicodeString S3HostName(S3LibDefaultHostName());
 const UnicodeString S3GoogleCloudHostName(L"storage.googleapis.com");
 const UnicodeString OpensshHostDirective(L"Host");
-const UnicodeString OpensshIncludeDirective(L"Include");
 //---------------------------------------------------------------------
 TDateTime __fastcall SecToDateTime(int Sec)
 {
@@ -92,7 +91,7 @@ static bool IsValidOpensshLine(const UnicodeString & Line)
   return !Line.IsEmpty() && (Line[1] != L'#');
 }
 //---------------------------------------------------------------------
-static bool ParseOpensshDirective(const UnicodeString & ALine, UnicodeString & Directive, UnicodeString & Value)
+bool ParseOpensshDirective(const UnicodeString & ALine, UnicodeString & Directive, UnicodeString & Value)
 {
   bool Result = IsValidOpensshLine(ALine);
   if (Result)
@@ -1623,16 +1622,8 @@ UnicodeString CutOpensshToken(UnicodeString & S)
   return Result;
 }
 //---------------------------------------------------------------------
-static UnicodeString ConvertPathFromOpenssh(const UnicodeString & Path)
+UnicodeString ConvertPathFromOpenssh(const UnicodeString & Path)
 {
-  // It may be specified the filename only, so check if it exists in the .ssh folder.
-  // If true, return the combined path
-  UnicodeString FilenameOnly = TPath::Combine(Configuration->GetOpensshFolder(), Path);
-  if (FileExists(ApiPath(FilenameOnly)))
-  {
-    return FilenameOnly;
-  }
-
   // It's likely there would be forward slashes in OpenSSH config file and our load/save dialogs
   // (e.g. when converting keys) work suboptimally when working with forward slashes.
   UnicodeString Result = GetNormalizedPath(Path);
@@ -5157,16 +5148,6 @@ void TStoredSessionList::ImportFromOpenssh(TStrings * Lines)
           }
         }
       }
-      else if (SameText(Directive, OpensshIncludeDirective))
-      {
-        UnicodeString ConfigToInclude = ConvertPathFromOpenssh(CutOpensshToken(Value));
-        if (FileExists(ApiPath(ConfigToInclude)))
-        {
-          std::unique_ptr <TStrings> LinesToInclude(new TStringList());
-          LoadScriptFromFile(ConfigToInclude, LinesToInclude.get(), true);
-          Lines->AddStrings(LinesToInclude.get());
-        }
-      }
     }
   }
 }

+ 3 - 0
source/core/SessionData.h

@@ -812,5 +812,8 @@ int __fastcall DefaultPort(TFSProtocol FSProtocol, TFtps Ftps);
 bool __fastcall IsIPv6Literal(const UnicodeString & HostName);
 UnicodeString __fastcall EscapeIPv6Literal(const UnicodeString & IP);
 TFSProtocol NormalizeFSProtocol(TFSProtocol FSProtocol);
+bool ParseOpensshDirective(const UnicodeString & ALine, UnicodeString & Directive, UnicodeString & Value);
+UnicodeString CutOpensshToken(UnicodeString & S);
+UnicodeString ConvertPathFromOpenssh(const UnicodeString & Path);
 //---------------------------------------------------------------------------
 #endif