Browse Source

Bug 2118: Reading password from a named pipe

https://winscp.net/tracker/2118

Source commit: 25f8a95d0ac0db13af786c8ceee5d191dee7dc92
Martin Prikryl 3 years ago
parent
commit
686c3b611f
2 changed files with 46 additions and 13 deletions
  1. 26 7
      source/core/Common.cpp
  2. 20 6
      source/core/SessionData.cpp

+ 26 - 7
source/core/Common.cpp

@@ -4101,26 +4101,45 @@ UnicodeString __fastcall AssemblyAddRawSettings(
 //---------------------------------------------------------------------------
 void __fastcall LoadScriptFromFile(UnicodeString FileName, TStrings * Lines, bool FallbackToAnsi)
 {
-  std::auto_ptr<TFileStream> Stream(new TFileStream(ApiPath(FileName), fmOpenRead | fmShareDenyWrite));
-  Lines->DefaultEncoding = TEncoding::UTF8;
+  std::unique_ptr<TFileStream> Stream(new TFileStream(ApiPath(FileName), fmOpenRead | fmShareDenyWrite));
+
+  // Simple stream reading, to make it work with named pipes too, not only with physical files
+  TBytes Buffer;
+  Buffer.Length = 10*1024;
+  int Read;
+  int Offset = 0;
+  do
+  {
+    Read = Stream->Read(Buffer, Offset, Buffer.Length - Offset);
+    Offset += Read;
+    if (Offset > Buffer.Length / 2)
+    {
+      Buffer.Length = Buffer.Length * 2;
+    }
+  }
+  while (Read > 0);
+  Buffer.Length = Offset;
+
+  TEncoding * Encoding = NULL;
+  int PreambleSize = TEncoding::GetBufferEncoding(Buffer, Encoding, TEncoding::UTF8);
+  UnicodeString S;
   try
   {
-    Lines->LoadFromStream(Stream.get());
+    S = Encoding->GetString(Buffer, PreambleSize, Buffer.Length - PreambleSize);
   }
   catch (EEncodingError & E)
   {
     if (FallbackToAnsi)
     {
-      Lines->DefaultEncoding = TEncoding::ANSI;
-      Lines->Clear();
-      Stream->Position = 0;
-      Lines->LoadFromStream(Stream.get());
+      S = TEncoding::ANSI->GetString(Buffer);
     }
     else
     {
       throw ExtException(LoadStr(TEXT_FILE_ENCODING), &E);
     }
   }
+
+  Lines->Text = S;
 }
 //---------------------------------------------------------------------------
 UnicodeString __fastcall StripEllipsis(const UnicodeString & S)

+ 20 - 6
source/core/SessionData.cpp

@@ -1811,16 +1811,30 @@ void __fastcall TSessionData::RecryptPasswords()
   EncryptKey = EncryptKey;
 }
 //---------------------------------------------------------------------
+static std::unique_ptr<TCriticalSection> PasswordFilesCacheSection(TraceInitPtr(new TCriticalSection()));
+typedef std::map<UnicodeString, UnicodeString> TPasswordFilesCache;
+static TPasswordFilesCache PasswordFilesCache;
+//---------------------------------------------------------------------
 static UnicodeString ReadPasswordFromFile(const UnicodeString & FileName)
 {
-  UnicodeString Result = FileName;
-  if (!Result.IsEmpty())
+  UnicodeString Result;
+  if (!FileName.IsEmpty())
   {
-    std::unique_ptr<TStrings> Lines(new TStringList());
-    LoadScriptFromFile(Result, Lines.get());
-    if (Lines->Count > 0)
+    TGuard Guard(PasswordFilesCacheSection.get());
+    TPasswordFilesCache::const_iterator I = PasswordFilesCache.find(FileName);
+    if (I != PasswordFilesCache.end())
     {
-      Result = Lines->Strings[0];
+      Result = I->second;
+    }
+    else
+    {
+      std::unique_ptr<TStrings> Lines(new TStringList());
+      LoadScriptFromFile(FileName, Lines.get());
+      if (Lines->Count > 0)
+      {
+        Result = Lines->Strings[0];
+      }
+      PasswordFilesCache[FileName] = Result;
     }
   }
   return Result;