1
0
Эх сурвалжийг харах

Bug 2222: Allow disabling SFTP extension use

https://winscp.net/tracker/2222

Source commit: 46cf6d64305cfb253f6b4c099633eec468c13c7b
Martin Prikryl 2 жил өмнө
parent
commit
c034f6c808

+ 6 - 80
source/core/FtpFileSystem.cpp

@@ -2647,8 +2647,7 @@ const TFileSystemInfo & __fastcall TFTPFileSystem::GetFileSystemInfo(bool /*Retr
         FORMAT(L"%s\r\n", (LoadStr(FTP_FEATURE_INFO)));
       for (int Index = 0; Index < FFeatures->Count; Index++)
       {
-        // For TrimLeft, refer to HandleFeatReply
-        FFileSystemInfo.AdditionalInfo += FORMAT(L"  %s\r\n", (TrimLeft(FFeatures->Strings[Index])));
+        FFileSystemInfo.AdditionalInfo += FORMAT(L"  %s\r\n", (FFeatures->Strings[Index]));
       }
     }
 
@@ -3600,85 +3599,9 @@ void __fastcall TFTPFileSystem::ResetFeatures()
   FSupportsAnyChecksumFeature = false;
 }
 //---------------------------------------------------------------------------
-UnicodeString TFTPFileSystem::CutFeature(UnicodeString & Buf)
-{
-  UnicodeString Result;
-  if (Buf.SubString(1, 1) == L"\"")
-  {
-    Buf.Delete(1, 1);
-    int P = Buf.Pos(L"\",");
-    if (P == 0)
-    {
-      Result = Buf;
-      Buf = UnicodeString();
-      // there should be the ending quote, but if not, just do nothing
-      if (Result.SubString(Result.Length(), 1) == L"\"")
-      {
-        Result.SetLength(Result.Length() - 1);
-      }
-    }
-    else
-    {
-      Result = Buf.SubString(1, P - 1);
-      Buf.Delete(1, P + 1);
-    }
-    Buf = Buf.TrimLeft();
-  }
-  else
-  {
-    Result = CutToChar(Buf, L',', true);
-  }
-  return Result;
-}
-//---------------------------------------------------------------------------
 void TFTPFileSystem::ProcessFeatures()
 {
-  std::unique_ptr<TStrings> Features(new TStringList());
-  UnicodeString FeaturesOverride = FTerminal->SessionData->ProtocolFeatures.Trim();
-  if (FeaturesOverride.SubString(1, 1) == L"*")
-  {
-    FeaturesOverride.Delete(1, 1);
-    while (!FeaturesOverride.IsEmpty())
-    {
-      UnicodeString Feature = CutFeature(FeaturesOverride);
-      Features->Add(Feature);
-    }
-  }
-  else
-  {
-    std::unique_ptr<TStrings> DeleteFeatures(CreateSortedStringList());
-    std::unique_ptr<TStrings> AddFeatures(new TStringList());
-    while (!FeaturesOverride.IsEmpty())
-    {
-      UnicodeString Feature = CutFeature(FeaturesOverride);
-      if (Feature.SubString(1, 1) == L"-")
-      {
-        Feature.Delete(1, 1);
-        DeleteFeatures->Add(Feature.LowerCase());
-      }
-      else
-      {
-        if (Feature.SubString(1, 1) == L"+")
-        {
-          Feature.Delete(1, 1);
-        }
-        AddFeatures->Add(Feature);
-      }
-    }
-
-    for (int Index = 0; Index < FFeatures->Count; Index++)
-    {
-      // IIS 2003 indents response by 4 spaces, instead of one,
-      // see example in HandleReplyStatus
-      UnicodeString Feature = FFeatures->Strings[Index].Trim();
-      if (DeleteFeatures->IndexOf(Feature) < 0)
-      {
-        Features->Add(Feature);
-      }
-    }
-
-    Features->AddStrings(AddFeatures.get());
-  }
+  std::unique_ptr<TStrings> Features(FTerminal->ProcessFeatures(FFeatures));
 
   for (int Index = 0; Index < Features->Count; Index++)
   {
@@ -3739,7 +3662,10 @@ void __fastcall TFTPFileSystem::HandleFeatReply()
   {
     FLastResponse->Delete(0);
     FLastResponse->Delete(FLastResponse->Count - 1);
-    FFeatures->Assign(FLastResponse);
+    for (int Index = 0; Index < FLastResponse->Count; Index++)
+    {
+      FFeatures->Add(FLastResponse->Strings[Index].Trim());
+    }
   }
 }
 //---------------------------------------------------------------------------

+ 0 - 1
source/core/FtpFileSystem.h

@@ -205,7 +205,6 @@ protected:
   void __fastcall HandleFeatReply();
   void __fastcall ResetFeatures();
   void ProcessFeatures();
-  UnicodeString CutFeature(UnicodeString & Buf);
   bool __fastcall SupportsSiteCommand(const UnicodeString & Command) const;
   bool __fastcall SupportsCommand(const UnicodeString & Command) const;
   void __fastcall RegisterChecksumAlgCommand(const UnicodeString & Alg, const UnicodeString & Command);

+ 45 - 52
source/core/SftpFileSystem.cpp

@@ -190,8 +190,7 @@ const int asAll = 0xFFFF;
 struct TSFTPSupport
 {
   TSFTPSupport() :
-    AttribExtensions(new TStringList()),
-    Extensions(new TStringList())
+    AttribExtensions(new TStringList())
   {
     Reset();
   }
@@ -199,7 +198,6 @@ struct TSFTPSupport
   ~TSFTPSupport()
   {
     delete AttribExtensions;
-    delete Extensions;
   }
 
   void Reset()
@@ -212,7 +210,6 @@ struct TSFTPSupport
     OpenBlockVector = 0;
     BlockVector = 0;
     AttribExtensions->Clear();
-    Extensions->Clear();
     Loaded = false;
   }
 
@@ -224,7 +221,6 @@ struct TSFTPSupport
   unsigned int OpenBlockVector;
   unsigned int BlockVector;
   TStrings * AttribExtensions;
-  TStrings * Extensions;
   bool Loaded;
 };
 //---------------------------------------------------------------------------
@@ -1901,7 +1897,6 @@ __fastcall TSFTPFileSystem::TSFTPFileSystem(TTerminal * ATerminal,
   FUtfDisablingAnnounced = true;
   FSignedTS = false;
   FSupport = new TSFTPSupport();
-  FExtensions = new TStringList();
   FFixedPaths = NULL;
   FFileSystemInfoValid = false;
 
@@ -1923,7 +1918,6 @@ __fastcall TSFTPFileSystem::~TSFTPFileSystem()
   delete FSupport;
   ResetConnection();
   delete FPacketReservations;
-  delete FExtensions;
   delete FFixedPaths;
   delete FSecureShell;
 }
@@ -1995,27 +1989,11 @@ const TFileSystemInfo & __fastcall TSFTPFileSystem::GetFileSystemInfo(bool /*Ret
       FFileSystemInfo.AdditionalInfo += LoadStr(FS_RENAME_NOT_SUPPORTED) + L"\r\n\r\n";
     }
 
-    if (FExtensions->Count > 0)
+    if (!FExtensions.IsEmpty())
     {
-      UnicodeString Name;
-      UnicodeString Value;
-      UnicodeString Line;
-      FFileSystemInfo.AdditionalInfo += LoadStr(SFTP_EXTENSION_INFO) + L"\r\n";
-      for (int Index = 0; Index < FExtensions->Count; Index++)
-      {
-        UnicodeString Name = FExtensions->Names[Index];
-        UnicodeString Value = FExtensions->Values[Name];
-        UnicodeString Line;
-        if (Value.IsEmpty())
-        {
-          Line = Name;
-        }
-        else
-        {
-          Line = FORMAT(L"%s=%s", (Name, Value));
-        }
-        FFileSystemInfo.AdditionalInfo += FORMAT(L"  %s\r\n", (Line));
-      }
+      FFileSystemInfo.AdditionalInfo +=
+        LoadStr(SFTP_EXTENSION_INFO) + L"\r\n" +
+        FExtensions;
     }
     else
     {
@@ -2212,12 +2190,7 @@ bool __fastcall TSFTPFileSystem::IsCapable(int Capability) const
 //---------------------------------------------------------------------------
 bool __fastcall TSFTPFileSystem::SupportsExtension(const UnicodeString & Extension) const
 {
-  return
-    // OpenSSH announce extensions directly in the SSH_FXP_VERSION packet only.
-    // Bitvise uses "supported2" extension for some (mostly the standard ones) and SSH_FXP_VERSION for other.
-    // ProFTPD uses "supported2" extension for the standard extensions. And repeats them along with non-standard in the SSH_FXP_VERSION.
-    (FExtensions->IndexOfName(Extension) >= 0) ||
-    (FSupport->Loaded && (FSupport->Extensions->IndexOf(Extension) >= 0));
+  return (FSupportedExtensions->IndexOf(Extension) >= 0);
 }
 //---------------------------------------------------------------------------
 inline void __fastcall TSFTPFileSystem::BusyStart()
@@ -3059,13 +3032,17 @@ void __fastcall TSFTPFileSystem::DoStartup()
       (FVersion, SFTPMinVersion, SFTPMaxVersion)));
   }
 
-  FExtensions->Clear();
+  FExtensions = EmptyStr;
   FEOL = "\r\n";
   FSupport->Loaded = false;
   FSupportsStatVfsV2 = false;
   FSupportsHardlink = false;
   bool SupportsLimits = false;
   SAFE_DESTROY(FFixedPaths);
+  // OpenSSH announce extensions directly in the SSH_FXP_VERSION packet only.
+  // Bitvise uses "supported2" extension for some (mostly the standard ones) and SSH_FXP_VERSION for other.
+  // ProFTPD uses "supported2" extension for the standard extensions. And repeats them along with non-standard in the SSH_FXP_VERSION.
+  std::unique_ptr<TStrings> SupportedExtensions(new TStringList());
 
   if (FVersion >= 3)
   {
@@ -3097,11 +3074,14 @@ void __fastcall TSFTPFileSystem::DoStartup()
         FSupport->OpenFlags = SupportedStruct.GetCardinal();
         FSupport->AccessMask = SupportedStruct.GetCardinal();
         FSupport->MaxReadSize = SupportedStruct.GetCardinal();
+        std::unique_ptr<TStrings> ExtensionsLog(new TStringList());
         if (ExtensionName == SFTP_EXT_SUPPORTED)
         {
           while (SupportedStruct.GetNextData() != NULL)
           {
-            FSupport->Extensions->Add(SupportedStruct.GetAnsiString());
+            UnicodeString Extension = SupportedStruct.GetAnsiString();
+            ExtensionsLog->Add(Extension);
+            SupportedExtensions->Add(Extension);
           }
         }
         else
@@ -3120,7 +3100,9 @@ void __fastcall TSFTPFileSystem::DoStartup()
           ExtensionCount = SupportedStruct.GetCardinal();
           for (unsigned int i = 0; i < ExtensionCount; i++)
           {
-            FSupport->Extensions->Add(SupportedStruct.GetAnsiString());
+            UnicodeString Extension = SupportedStruct.GetAnsiString();
+            SupportedExtensions->Add(Extension);
+            ExtensionsLog->Add(Extension);
           }
         }
 
@@ -3144,11 +3126,11 @@ void __fastcall TSFTPFileSystem::DoStartup()
             FTerminal->LogEvent(
               FORMAT(L"    %s", (FSupport->AttribExtensions->Strings[Index])));
           }
-          FTerminal->LogEvent(FORMAT(L"  Extensions (%d)\n", (FSupport->Extensions->Count)));
-          for (int Index = 0; Index < FSupport->Extensions->Count; Index++)
+          FTerminal->LogEvent(FORMAT(L"  Extensions (%d)\n", (ExtensionsLog->Count)));
+          for (int Index = 0; Index < ExtensionsLog->Count; Index++)
           {
             FTerminal->LogEvent(
-              FORMAT(L"    %s", (FSupport->Extensions->Strings[Index])));
+              FORMAT(L"    %s", (ExtensionsLog->Strings[Index])));
           }
         }
       }
@@ -3265,20 +3247,15 @@ void __fastcall TSFTPFileSystem::DoStartup()
       {
         FTerminal->LogEvent(0, FORMAT(L"Unknown server extension %s=%s", (ExtensionName, ExtensionDisplayData)));
       }
-      FExtensions->Values[ExtensionName] = ExtensionDisplayData;
-    }
 
-    if (SupportsExtension(SFTP_EXT_VENDOR_ID))
-    {
-      TSFTPPacket Packet(SSH_FXP_EXTENDED);
-      Packet.AddString(SFTP_EXT_VENDOR_ID);
-      Packet.AddString(FTerminal->Configuration->CompanyName);
-      Packet.AddString(FTerminal->Configuration->ProductName);
-      Packet.AddString(FTerminal->Configuration->ProductVersion);
-      Packet.AddInt64(LOWORD(FTerminal->Configuration->FixedApplicationInfo->dwFileVersionLS));
-      SendPacket(&Packet);
-      // we are not interested in the response, do not wait for it
-      ReserveResponse(&Packet, NULL);
+      UnicodeString Line = ExtensionName;
+      if (!ExtensionDisplayData.IsEmpty())
+      {
+        Line += FORMAT(L"=%s", (ExtensionDisplayData));
+      }
+      FExtensions += FORMAT(L"  %s\r\n", (Line));
+
+      SupportedExtensions->Add(ExtensionName);
     }
   }
 
@@ -3364,6 +3341,22 @@ void __fastcall TSFTPFileSystem::DoStartup()
         (int(FMaxPacketSize))));
     }
   }
+
+  FSupportedExtensions.reset(FTerminal->ProcessFeatures(SupportedExtensions.get()));
+
+  if (SupportsExtension(SFTP_EXT_VENDOR_ID))
+  {
+    TSFTPPacket Packet(SSH_FXP_EXTENDED);
+    Packet.AddString(SFTP_EXT_VENDOR_ID);
+    Packet.AddString(FTerminal->Configuration->CompanyName);
+    Packet.AddString(FTerminal->Configuration->ProductName);
+    Packet.AddString(FTerminal->Configuration->ProductVersion);
+    Packet.AddInt64(LOWORD(FTerminal->Configuration->FixedApplicationInfo->dwFileVersionLS));
+    SendPacket(&Packet);
+    // we are not interested in the response, do not wait for it
+    ReserveResponse(&Packet, NULL);
+  }
+
 }
 //---------------------------------------------------------------------------
 char * __fastcall TSFTPFileSystem::GetEOL() const

+ 2 - 1
source/core/SftpFileSystem.h

@@ -118,7 +118,8 @@ protected:
   int FBusy;
   void * FBusyToken;
   bool FAvoidBusy;
-  TStrings * FExtensions;
+  UnicodeString FExtensions;
+  std::unique_ptr<TStrings> FSupportedExtensions;
   TSFTPSupport * FSupport;
   TAutoSwitch FUtfStrings;
   bool FUtfDisablingAnnounced;

+ 80 - 0
source/core/Terminal.cpp

@@ -8908,6 +8908,86 @@ bool TTerminal::IsValidFile(TRemoteFile * File)
     (IsUnixRootPath(File->FileName) || UnixExtractFileDir(File->FileName).IsEmpty());
 }
 //---------------------------------------------------------------------------
+UnicodeString TTerminal::CutFeature(UnicodeString & Buf)
+{
+  UnicodeString Result;
+  if (Buf.SubString(1, 1) == L"\"")
+  {
+    Buf.Delete(1, 1);
+    int P = Buf.Pos(L"\",");
+    if (P == 0)
+    {
+      Result = Buf;
+      Buf = UnicodeString();
+      // there should be the ending quote, but if not, just do nothing
+      if (Result.SubString(Result.Length(), 1) == L"\"")
+      {
+        Result.SetLength(Result.Length() - 1);
+      }
+    }
+    else
+    {
+      Result = Buf.SubString(1, P - 1);
+      Buf.Delete(1, P + 1);
+    }
+    Buf = Buf.TrimLeft();
+  }
+  else
+  {
+    Result = CutToChar(Buf, L',', true);
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
+TStrings * TTerminal::ProcessFeatures(TStrings * Features)
+{
+  std::unique_ptr<TStrings> Result(new TStringList());
+  UnicodeString FeaturesOverride = SessionData->ProtocolFeatures.Trim();
+  if (FeaturesOverride.SubString(1, 1) == L"*")
+  {
+    FeaturesOverride.Delete(1, 1);
+    while (!FeaturesOverride.IsEmpty())
+    {
+      UnicodeString Feature = CutFeature(FeaturesOverride);
+      Result->Add(Feature);
+    }
+  }
+  else
+  {
+    std::unique_ptr<TStrings> DeleteFeatures(CreateSortedStringList());
+    std::unique_ptr<TStrings> AddFeatures(new TStringList());
+    while (!FeaturesOverride.IsEmpty())
+    {
+      UnicodeString Feature = CutFeature(FeaturesOverride);
+      if (Feature.SubString(1, 1) == L"-")
+      {
+        Feature.Delete(1, 1);
+        DeleteFeatures->Add(Feature.LowerCase());
+      }
+      else
+      {
+        if (Feature.SubString(1, 1) == L"+")
+        {
+          Feature.Delete(1, 1);
+        }
+        AddFeatures->Add(Feature);
+      }
+    }
+
+    for (int Index = 0; Index < Features->Count; Index++)
+    {
+      UnicodeString Feature = Features->Strings[Index];
+      if (DeleteFeatures->IndexOf(Feature) < 0)
+      {
+        Result->Add(Feature);
+      }
+    }
+
+    Result->AddStrings(AddFeatures.get());
+  }
+  return Result.release();
+}
+//---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 __fastcall TSecondaryTerminal::TSecondaryTerminal(
   TTerminal * MainTerminal, TSessionData * ASessionData, TConfiguration * Configuration,

+ 2 - 0
source/core/Terminal.h

@@ -260,6 +260,7 @@ private:
   inline bool __fastcall InTransaction();
   void __fastcall SaveCapabilities(TFileSystemInfo & FileSystemInfo);
   bool __fastcall CreateTargetDirectory(const UnicodeString & DirectoryPath, int Attrs, const TCopyParamType * CopyParam);
+  UnicodeString CutFeature(UnicodeString & Buf);
   static UnicodeString __fastcall SynchronizeModeStr(TSynchronizeMode Mode);
   static UnicodeString __fastcall SynchronizeParamsStr(int Params);
 
@@ -508,6 +509,7 @@ protected:
     TFileOperationProgressType * OperationProgress, bool FirstLevel);
   void GetShellChecksumAlgs(TStrings * Algs);
   TStrings * GetShellChecksumAlgDefs();
+  TStrings * ProcessFeatures(TStrings * Features);
 
   UnicodeString __fastcall EncryptFileName(const UnicodeString & Path, bool EncryptNewFiles);
   UnicodeString __fastcall DecryptFileName(const UnicodeString & Path, bool DecryptFullPath, bool DontCache);