浏览代码

Switch-like raw session settings can be configured using on/off/auto keywords

(cherry picked from commit 2dd517c88870d4e44706197fd0873370d605d5b6)

# Conflicts:
#	source/WinSCP.cbproj
#	source/core/SessionData.cpp

Source commit: f2cb13fcb45f16475536f6c98c2d4604b5f769c9
Martin Prikryl 4 年之前
父节点
当前提交
4f8013a2de
共有 3 个文件被更改,包括 98 次插入21 次删除
  1. 66 6
      source/core/HierarchicalStorage.cpp
  2. 20 3
      source/core/HierarchicalStorage.h
  3. 12 12
      source/core/SessionData.cpp

+ 66 - 6
source/core/HierarchicalStorage.cpp

@@ -106,6 +106,32 @@ UnicodeString __fastcall UnMungeIniName(const UnicodeString & Str)
     return Str;
   }
 }
+//---------------------------------------------------------------------------
+template<typename T>
+void AddIntMapping(TIntMapping & Mapping, const wchar_t * Name, const T & Value)
+{
+  if (Name != NULL)
+  {
+    Mapping.insert(std::make_pair(UnicodeString(Name), Value));
+  }
+}
+//---------------------------------------------------------------------------
+template<typename T>
+TIntMapping CreateIntMapping(
+  const wchar_t * Name1, const T & Value1,
+  const wchar_t * Name2 = NULL, const T & Value2 = T(0),
+  const wchar_t * Name3 = NULL, const T & Value3 = T(0))
+{
+  TIntMapping Result;
+  AddIntMapping(Result, Name1, Value1);
+  AddIntMapping(Result, Name2, Value2);
+  AddIntMapping(Result, Name3, Value3);
+  return Result;
+}
+//---------------------------------------------------------------------------
+TIntMapping AutoSwitchMapping = CreateIntMapping(L"on", asOn, L"off", asOff, L"auto", asAuto);
+TIntMapping AutoSwitchReversedMapping = CreateIntMapping(L"on", asOff, L"off", asOn, L"auto", asAuto);
+TIntMapping BoolMapping = CreateIntMapping(L"on", true, L"off", false);
 //===========================================================================
 UnicodeString AccessValueName(L"Access");
 UnicodeString DefaultAccessString(L"inherit");
@@ -552,10 +578,15 @@ bool __fastcall THierarchicalStorage::ReadBool(const UnicodeString & Name, bool
 }
 //---------------------------------------------------------------------------
 int __fastcall THierarchicalStorage::ReadInteger(const UnicodeString & Name, int Default)
+{
+  return ReadIntegerWithMapping(Name, Default, NULL);
+}
+//---------------------------------------------------------------------------
+int THierarchicalStorage::ReadIntegerWithMapping(const UnicodeString & Name, int Default, const TIntMapping * Mapping)
 {
   if (CanRead())
   {
-    return DoReadInteger(Name, Default);
+    return DoReadInteger(Name, Default, Mapping);
   }
   else
   {
@@ -975,7 +1006,7 @@ double __fastcall TRegistryStorage::DoReadFloat(const UnicodeString & Name, doub
   READ_REGISTRY(ReadFloat);
 }
 //---------------------------------------------------------------------------
-int __fastcall TRegistryStorage::DoReadInteger(const UnicodeString & Name, int Default)
+int __fastcall TRegistryStorage::DoReadInteger(const UnicodeString & Name, int Default, const TIntMapping *)
 {
   READ_REGISTRY(ReadInteger);
 }
@@ -1307,20 +1338,49 @@ bool __fastcall TCustomIniFileStorage::DoReadBool(const UnicodeString & Name, bo
   }
   else
   {
-    return FIniFile->ReadBool(CurrentSection, MungeIniName(Name), Default);
+    int IntDefault = int(Default);
+    int Int = DoReadIntegerWithMapping(Name, IntDefault, &BoolMapping);
+    return (Int != 0);
   }
 }
 //---------------------------------------------------------------------------
-int __fastcall TCustomIniFileStorage::DoReadInteger(const UnicodeString & Name, int Default)
+int __fastcall TCustomIniFileStorage::DoReadIntegerWithMapping(const UnicodeString & Name, int Default, const TIntMapping * Mapping)
+{
+  int Result;
+  bool ReadAsInteger = true;
+  UnicodeString MungedName = MungeIniName(Name);
+  if (Mapping != NULL) // optimization
+  {
+    UnicodeString S = FIniFile->ReadString(CurrentSection, MungedName, EmptyStr);
+    if (!S.IsEmpty())
+    {
+      S = S.LowerCase();
+      TIntMapping::const_iterator I = Mapping->find(S);
+      if (I != Mapping->end())
+      {
+        Result = I->second;
+        ReadAsInteger = false;
+      }
+    }
+  }
+
+  if (ReadAsInteger)
+  {
+    Result = FIniFile->ReadInteger(CurrentSection, MungedName, Default);
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
+int __fastcall TCustomIniFileStorage::DoReadInteger(const UnicodeString & Name, int Default, const TIntMapping * Mapping)
 {
   int Result;
   if (HandleReadByMasterStorage(Name))
   {
-    Result = FMasterStorage->ReadInteger(Name, Default);
+    Result = FMasterStorage->ReadIntegerWithMapping(Name, Default, Mapping);
   }
   else
   {
-    Result = FIniFile->ReadInteger(CurrentSection, MungeIniName(Name), Default);
+    Result = DoReadIntegerWithMapping(Name, Default, Mapping);
   }
   return Result;
 }

+ 20 - 3
source/core/HierarchicalStorage.h

@@ -4,9 +4,11 @@
 
 #include <registry.hpp>
 #include <memory>
+#include <map>
 //---------------------------------------------------------------------------
 enum TStorage { stDetect, stRegistry, stIniFile, stNul };
 enum TStorageAccessMode { smRead, smReadWrite };
+typedef std::map<UnicodeString, int> TIntMapping;
 //---------------------------------------------------------------------------
 class THierarchicalStorage
 {
@@ -35,6 +37,9 @@ public:
   bool __fastcall DeleteValue(const UnicodeString & Name);
 
   bool __fastcall ReadBool(const UnicodeString & Name, bool Default);
+  template<typename T>
+  typename T __fastcall ReadEnum(
+    const UnicodeString & Name, const T & Default, const TIntMapping & Mapping = TIntMapping());
   int __fastcall ReadInteger(const UnicodeString & Name, int Default);
   __int64 __fastcall ReadInt64(const UnicodeString & Name, __int64 Default);
   TDateTime __fastcall ReadDateTime(const UnicodeString & Name, TDateTime Default);
@@ -115,7 +120,8 @@ protected:
 
   virtual bool __fastcall DoReadBool(const UnicodeString & Name, bool Default) = 0;
   virtual UnicodeString __fastcall DoReadStringRaw(const UnicodeString & Name, const UnicodeString & Default) = 0;
-  virtual int __fastcall DoReadInteger(const UnicodeString & Name, int Default) = 0;
+  int ReadIntegerWithMapping(const UnicodeString & Name, int Default, const TIntMapping * Mapping);
+  virtual int __fastcall DoReadInteger(const UnicodeString & Name, int Default, const TIntMapping * Mapping) = 0;
   virtual __int64 __fastcall DoReadInt64(const UnicodeString & Name, __int64 Default) = 0;
   virtual TDateTime __fastcall DoReadDateTime(const UnicodeString & Name, TDateTime Default) = 0;
   virtual double __fastcall DoReadFloat(const UnicodeString & Name, double Default) = 0;
@@ -134,6 +140,16 @@ protected:
   unsigned int __fastcall GetCurrentAccess();
 };
 //---------------------------------------------------------------------------
+extern TIntMapping AutoSwitchMapping;
+extern TIntMapping AutoSwitchReversedMapping;
+//---------------------------------------------------------------------------
+template<typename T>
+T __fastcall THierarchicalStorage::ReadEnum(const UnicodeString & Name, const T & Default, const TIntMapping & Mapping)
+{
+  const TIntMapping * AMapping = (Mapping == TIntMapping()) ? NULL : &Mapping;
+  return T(ReadIntegerWithMapping(Name, int(Default), AMapping));
+}
+//---------------------------------------------------------------------------
 class TRegistryStorage : public THierarchicalStorage
 {
 public:
@@ -164,7 +180,7 @@ protected:
   virtual void __fastcall DoWriteBinaryData(const UnicodeString & Name, const void * Buffer, int Size);
 
   virtual bool __fastcall DoReadBool(const UnicodeString & Name, bool Default);
-  virtual int __fastcall DoReadInteger(const UnicodeString & Name, int Default);
+  virtual int __fastcall DoReadInteger(const UnicodeString & Name, int Default, const TIntMapping * Mapping);
   virtual __int64 __fastcall DoReadInt64(const UnicodeString & Name, __int64 Default);
   virtual TDateTime __fastcall DoReadDateTime(const UnicodeString & Name, TDateTime Default);
   virtual double __fastcall DoReadFloat(const UnicodeString & Name, double Default);
@@ -193,6 +209,7 @@ private:
   inline bool __fastcall HandleReadByMasterStorage(const UnicodeString & Name);
   inline bool __fastcall DoValueExistsInternal(const UnicodeString & Value);
   void __fastcall DoWriteStringRawInternal(const UnicodeString & Name, const UnicodeString & Value);
+  int __fastcall DoReadIntegerWithMapping(const UnicodeString & Name, int Default, const TIntMapping * Mapping);
 
 protected:
   TCustomIniFile * FIniFile;
@@ -222,7 +239,7 @@ protected:
   virtual void __fastcall DoWriteBinaryData(const UnicodeString & Name, const void * Buffer, int Size);
 
   virtual bool __fastcall DoReadBool(const UnicodeString & Name, bool Default);
-  virtual int __fastcall DoReadInteger(const UnicodeString & Name, int Default);
+  virtual int __fastcall DoReadInteger(const UnicodeString & Name, int Default, const TIntMapping * Mapping);
   virtual __int64 __fastcall DoReadInt64(const UnicodeString & Name, __int64 Default);
   virtual TDateTime __fastcall DoReadDateTime(const UnicodeString & Name, TDateTime Default);
   virtual double __fastcall DoReadFloat(const UnicodeString & Name, double Default);

+ 12 - 12
source/core/SessionData.cpp

@@ -720,7 +720,7 @@ void __fastcall TSessionData::DoLoad(THierarchicalStorage * Storage, bool PuttyI
       Storage->ReadBool(L"AliasGroupList", false) ? UnicodeString(L"ls -gla") : ListingCommand);
   }
   IgnoreLsWarnings = Storage->ReadBool(L"IgnoreLsWarnings", IgnoreLsWarnings);
-  SCPLsFullTime = TAutoSwitch(Storage->ReadInteger(L"SCPLsFullTime", SCPLsFullTime));
+  SCPLsFullTime = Storage->ReadEnum(L"SCPLsFullTime", SCPLsFullTime, AutoSwitchMapping);
   Scp1Compatibility = Storage->ReadBool(L"Scp1Compatibility", Scp1Compatibility);
   TimeDifference = Storage->ReadFloat(L"TimeDifference", TimeDifference);
   TimeDifferenceAuto = Storage->ReadBool(L"TimeDifferenceAuto", (TimeDifference == TDateTime()));
@@ -734,16 +734,16 @@ void __fastcall TSessionData::DoLoad(THierarchicalStorage * Storage, bool PuttyI
   }
 
   ExitCode1IsError = Storage->ReadBool(L"ExitCode1IsError", ExitCode1IsError);
-  LookupUserGroups = TAutoSwitch(Storage->ReadInteger(L"LookupUserGroups2", LookupUserGroups));
+  LookupUserGroups = Storage->ReadEnum(L"LookupUserGroups2", LookupUserGroups, AutoSwitchMapping);
   EOLType = (TEOLType)Storage->ReadInteger(L"EOLType", EOLType);
   TrimVMSVersions = Storage->ReadBool(L"TrimVMSVersions", TrimVMSVersions);
-  NotUtf = TAutoSwitch(Storage->ReadInteger(L"Utf", Storage->ReadInteger(L"SFTPUtfBug", NotUtf)));
+  NotUtf = Storage->ReadEnum(L"Utf", Storage->ReadEnum(L"SFTPUtfBug", NotUtf), AutoSwitchReversedMapping);
   InternalEditorEncoding = Storage->ReadInteger(L"InternalEditorEncoding", InternalEditorEncoding);
 
   S3DefaultRegion = Storage->ReadString(L"S3DefaultRegion", S3DefaultRegion);
   S3SessionToken = Storage->ReadString(L"S3SessionToken", S3SessionToken);
   S3UrlStyle = (TS3UrlStyle)Storage->ReadInteger(L"S3UrlStyle", S3UrlStyle);
-  S3MaxKeys = (TAutoSwitch)Storage->ReadInteger(L"S3MaxKeys", S3MaxKeys);
+  S3MaxKeys = Storage->ReadEnum(L"S3MaxKeys", S3MaxKeys, AutoSwitchMapping);
 
   // PuTTY defaults to TcpNoDelay, but the psftp/pscp ignores this preference, and always set this to off (what is our default too)
   if (!PuttyImport)
@@ -813,7 +813,7 @@ void __fastcall TSessionData::DoLoad(THierarchicalStorage * Storage, bool PuttyI
     SftpServer = Storage->ReadString(L"SftpServer", SftpServer);
   }
   #define READ_SFTP_BUG(BUG) \
-    SFTPBug[sb##BUG] = TAutoSwitch(Storage->ReadInteger(L"SFTP" #BUG "Bug", SFTPBug[sb##BUG]));
+    SFTPBug[sb##BUG] = Storage->ReadEnum(L"SFTP" #BUG "Bug", SFTPBug[sb##BUG], AutoSwitchMapping);
   READ_SFTP_BUG(Symlink);
   READ_SFTP_BUG(SignedTS);
   #undef READ_SFTP_BUG
@@ -823,7 +823,7 @@ void __fastcall TSessionData::DoLoad(THierarchicalStorage * Storage, bool PuttyI
   SFTPDownloadQueue = Storage->ReadInteger(L"SFTPDownloadQueue", SFTPDownloadQueue);
   SFTPUploadQueue = Storage->ReadInteger(L"SFTPUploadQueue", SFTPUploadQueue);
   SFTPListingQueue = Storage->ReadInteger(L"SFTPListingQueue", SFTPListingQueue);
-  SFTPRealPath = TAutoSwitch(Storage->ReadInteger(L"SFTPRealPath", SFTPRealPath));
+  SFTPRealPath = Storage->ReadEnum(L"SFTPRealPath", SFTPRealPath, AutoSwitchMapping);
 
   Color = Storage->ReadInteger(L"Color", Color);
 
@@ -854,16 +854,16 @@ void __fastcall TSessionData::DoLoad(THierarchicalStorage * Storage, bool PuttyI
 
   // Ftp prefix
   FtpPasvMode = Storage->ReadBool(L"FtpPasvMode", FtpPasvMode);
-  FtpForcePasvIp = TAutoSwitch(Storage->ReadInteger(L"FtpForcePasvIp2", FtpForcePasvIp));
-  FtpUseMlsd = TAutoSwitch(Storage->ReadInteger(L"FtpUseMlsd", FtpUseMlsd));
+  FtpForcePasvIp = Storage->ReadEnum(L"FtpForcePasvIp2", FtpForcePasvIp, AutoSwitchMapping);
+  FtpUseMlsd = Storage->ReadEnum(L"FtpUseMlsd", FtpUseMlsd, AutoSwitchMapping);
   FtpAccount = Storage->ReadString(L"FtpAccount", FtpAccount);
   FtpPingInterval = Storage->ReadInteger(L"FtpPingInterval", FtpPingInterval);
   FtpPingType = static_cast<TPingType>(Storage->ReadInteger(L"FtpPingType", FtpPingType));
-  FtpTransferActiveImmediately = static_cast<TAutoSwitch>(Storage->ReadInteger(L"FtpTransferActiveImmediately2", FtpTransferActiveImmediately));
+  FtpTransferActiveImmediately = Storage->ReadEnum(L"FtpTransferActiveImmediately2", FtpTransferActiveImmediately, AutoSwitchMapping);
   Ftps = static_cast<TFtps>(Storage->ReadInteger(L"Ftps", Ftps));
-  FtpListAll = TAutoSwitch(Storage->ReadInteger(L"FtpListAll", FtpListAll));
-  FtpHost = TAutoSwitch(Storage->ReadInteger(L"FtpHost", FtpHost));
-  FtpWorkFromCwd = TAutoSwitch(Storage->ReadInteger(L"FtpWorkFromCwd", Storage->ReadInteger(L"FtpDeleteFromCwd", FtpWorkFromCwd)));
+  FtpListAll = Storage->ReadEnum(L"FtpListAll", FtpListAll, AutoSwitchMapping);
+  FtpHost = Storage->ReadEnum(L"FtpHost", FtpHost, AutoSwitchMapping);
+  FtpWorkFromCwd = Storage->ReadEnum(L"FtpWorkFromCwd", Storage->ReadEnum(L"FtpDeleteFromCwd", FtpWorkFromCwd), AutoSwitchMapping);
   SslSessionReuse = Storage->ReadBool(L"SslSessionReuse", SslSessionReuse);
   TlsCertificateFile = Storage->ReadString(L"TlsCertificateFile", TlsCertificateFile);