Martin Prikryl 12 年之前
父节点
当前提交
1abb25b42b
共有 100 个文件被更改,包括 3457 次插入740 次删除
  1. 7 7
      dotnet/Session.cs
  2. 15 11
      dotnet/SessionOptions.cs
  3. 8 3
      dotnet/internal/Logger.cs
  4. 3 3
      dotnet/properties/AssemblyInfo.cs
  5. 2 3
      libs/install/openssl/readme_debug
  6. 0 3
      libs/openssl/debug.txt
  7. 1 1
      source/Console.cbproj
  8. 1 1
      source/DragExt.cbproj
  9. 2 2
      source/DragExt64.rc
  10. 3 3
      source/PngComponents.cbproj
  11. 2 2
      source/WinSCP.cbproj
  12. 0 2
      source/components/UnixDriveView.h
  13. 7 9
      source/core/Common.cpp
  14. 1 1
      source/core/Common.h
  15. 9 3
      source/core/Configuration.cpp
  16. 2 1
      source/core/Configuration.h
  17. 1 2
      source/core/CoreMain.cpp
  18. 1 1
      source/core/Cryptography.cpp
  19. 22 4
      source/core/FtpFileSystem.cpp
  20. 5 0
      source/core/Queue.cpp
  21. 2 0
      source/core/Queue.h
  22. 29 23
      source/core/RemoteFiles.cpp
  23. 2 0
      source/core/RemoteFiles.h
  24. 13 6
      source/core/ScpFileSystem.cpp
  25. 115 5
      source/core/Script.cpp
  26. 6 0
      source/core/Script.h
  27. 75 14
      source/core/SessionData.cpp
  28. 14 3
      source/core/SessionData.h
  29. 21 1
      source/core/SessionInfo.cpp
  30. 1 0
      source/core/SessionInfo.h
  31. 1 0
      source/core/Terminal.cpp
  32. 1 3
      source/core/WebDAVFileSystem.cpp
  33. 30 0
      source/filezilla/AsyncSocketEx.cpp
  34. 2 0
      source/filezilla/AsyncSocketEx.h
  35. 35 13
      source/filezilla/AsyncSslSocketLayer.cpp
  36. 12 1
      source/filezilla/AsyncSslSocketLayer.h
  37. 20 15
      source/filezilla/ControlSocket.cpp
  38. 3 1
      source/filezilla/ControlSocket.h
  39. 21 1
      source/filezilla/FileZillaApi.cpp
  40. 3 1
      source/filezilla/FileZillaApi.h
  41. 11 0
      source/filezilla/FileZillaIntf.cpp
  42. 3 0
      source/filezilla/FileZillaIntf.h
  43. 2 0
      source/filezilla/FileZillaOpt.h
  44. 135 102
      source/filezilla/FtpControlSocket.cpp
  45. 3 1
      source/filezilla/FtpControlSocket.h
  46. 11 0
      source/filezilla/FtpListResult.cpp
  47. 15 1
      source/filezilla/MainThread.cpp
  48. 3 1
      source/filezilla/MainThread.h
  49. 42 31
      source/filezilla/TransferSocket.cpp
  50. 1 0
      source/forms/Custom.cpp
  51. 37 9
      source/forms/CustomScpExplorer.cpp
  52. 0 1
      source/forms/CustomScpExplorer.dfm
  53. 2 1
      source/forms/CustomScpExplorer.h
  54. 2 5
      source/forms/FileSystemInfo.cpp
  55. 164 58
      source/forms/Login.cpp
  56. 4 4
      source/forms/Login.dfm
  57. 5 2
      source/forms/Login.h
  58. 2 0
      source/forms/NonVisual.dfm
  59. 76 13
      source/forms/Preferences.cpp
  60. 2083 0
      source/forms/Preferences.cpp.LOCAL
  61. 3 3
      source/forms/Preferences.dfm
  62. 5 1
      source/forms/Preferences.h
  63. 72 1
      source/forms/SiteAdvanced.cpp
  64. 71 0
      source/forms/SiteAdvanced.dfm
  65. 10 0
      source/forms/SiteAdvanced.h
  66. 1 1
      source/forms/SynchronizeChecklist.dfm
  67. 9 24
      source/packages/dragndrop/DragDropFilesEx.pas
  68. 1 3
      source/packages/filemng/CustomDirView.pas
  69. 1 6
      source/packages/filemng/CustomDriveView.pas
  70. 3 10
      source/packages/filemng/DirView.pas
  71. 1 3
      source/packages/filemng/DriveView.pas
  72. 1 0
      source/packages/filemng/IEComboBox.pas
  73. 1 0
      source/packages/my/ComboEdit.pas
  74. 2 1
      source/packages/my/GrayedCheckBox.pas
  75. 1 0
      source/packages/my/HistoryComboBox.pas
  76. 1 3
      source/packages/my/NortonLikeListView.pas
  77. 7 0
      source/packages/my/PasTools.pas
  78. 2 1
      source/packages/my/PasswordEdit.pas
  79. 0 2
      source/packages/png/PngImageList.pas
  80. 2 20
      source/packages/tb2k/TB2Common.pas
  81. 1 3
      source/packages/tb2k/TB2Dock.pas
  82. 2 6
      source/packages/tb2k/TB2Hook.pas
  83. 1 3
      source/packages/tb2k/TB2Item.pas
  84. 4 18
      source/packages/tbx/TBX.pas
  85. 1 1
      source/packages/tbx/TBXOfficeXPTheme.pas
  86. 1 0
      source/packages/tbx/TBXStatusBars.pas
  87. 2 8
      source/packages/tbx/TBXThemes.pas
  88. 0 15
      source/packages/tbx/TBXUtils.pas
  89. 1 1
      source/resource/HelpWin.h
  90. 8 1
      source/resource/TextsCore.h
  91. 8 1
      source/resource/TextsCore1.rc
  92. 4 3
      source/resource/TextsCore2.rc
  93. 7 7
      source/resource/TextsFileZilla.rc
  94. 4 1
      source/resource/TextsWin.h
  95. 4 1
      source/resource/TextsWin1.rc
  96. 3 3
      source/resource/TextsWin2.rc
  97. 20 6
      source/windows/ConsoleRunner.cpp
  98. 29 3
      source/windows/CustomWinConfiguration.cpp
  99. 2 1
      source/windows/CustomWinConfiguration.h
  100. 62 201
      source/windows/Setup.cpp

+ 7 - 7
dotnet/Session.cs

@@ -961,20 +961,20 @@ namespace WinSCP
                     }
                     }
                 }
                 }
 
 
-                if (!string.IsNullOrEmpty(sessionOptions.SslHostCertificateFingerprint) ||
-                    sessionOptions.GiveUpSecurityAndAcceptAnySslHostCertificate)
+                if (!string.IsNullOrEmpty(sessionOptions.TlsHostCertificateFingerprint) ||
+                    sessionOptions.GiveUpSecurityAndAcceptAnyTlsHostCertificate)
                 {
                 {
                     if (sessionOptions.FtpSecure == FtpSecure.None)
                     if (sessionOptions.FtpSecure == FtpSecure.None)
                     {
                     {
-                        throw new ArgumentException("SessionOptions.SslHostCertificateFingerprint or SessionOptions.GiveUpSecurityAndAcceptAnySslHostCertificate is set, but SessionOptions.FtpSecure is FtpSecure.None.");
+                        throw new ArgumentException("SessionOptions.TlsHostCertificateFingerprint or SessionOptions.GiveUpSecurityAndAcceptAnyTlsHostCertificate is set, but SessionOptions.FtpSecure is FtpSecure.None.");
                     }
                     }
-                    string sslHostCertificateFingerprint = sessionOptions.SslHostCertificateFingerprint;
-                    if (sessionOptions.GiveUpSecurityAndAcceptAnySslHostCertificate)
+                    string tlsHostCertificateFingerprint = sessionOptions.TlsHostCertificateFingerprint;
+                    if (sessionOptions.GiveUpSecurityAndAcceptAnyTlsHostCertificate)
                     {
                     {
                         Logger.WriteLine("WARNING! Giving up security and accepting any certificate as configured");
                         Logger.WriteLine("WARNING! Giving up security and accepting any certificate as configured");
-                        sslHostCertificateFingerprint = AddStarToList(sslHostCertificateFingerprint);
+                        tlsHostCertificateFingerprint = AddStarToList(tlsHostCertificateFingerprint);
                     }
                     }
-                    switches.Add(FormatSwitch("certificate", sslHostCertificateFingerprint));
+                    switches.Add(FormatSwitch("certificate", tlsHostCertificateFingerprint));
                 }
                 }
 
 
                 if (sessionOptions.Protocol == Protocol.Ftp)
                 if (sessionOptions.Protocol == Protocol.Ftp)

+ 15 - 11
dotnet/SessionOptions.cs

@@ -29,8 +29,8 @@ namespace WinSCP
     {
     {
         None = 0,
         None = 0,
         Implicit = 1,
         Implicit = 1,
-        ExplicitSsl = 2,
         ExplicitTls = 3,
         ExplicitTls = 3,
+        ExplicitSsl = 2,
     }
     }
 
 
     [Guid("2D4EF368-EE80-4C15-AE77-D12AEAF4B00A")]
     [Guid("2D4EF368-EE80-4C15-AE77-D12AEAF4B00A")]
@@ -59,8 +59,12 @@ namespace WinSCP
         // FTP
         // FTP
         public FtpMode FtpMode { get; set; }
         public FtpMode FtpMode { get; set; }
         public FtpSecure FtpSecure { get; set; }
         public FtpSecure FtpSecure { get; set; }
-        public string SslHostCertificateFingerprint { get { return _sslHostCertificateFingerprint; } set { SetHostSslCertificateFingerprint(value); } }
-        public bool GiveUpSecurityAndAcceptAnySslHostCertificate { get; set; }
+        public string TlsHostCertificateFingerprint { get { return _tlsHostCertificateFingerprint; } set { SetHostTlsCertificateFingerprint(value); } }
+        [Obsolete("Use TlsHostCertificateFingerprint")]
+        public string SslHostCertificateFingerprint { get { return TlsHostCertificateFingerprint; } set { TlsHostCertificateFingerprint = value; } }
+        public bool GiveUpSecurityAndAcceptAnyTlsHostCertificate { get; set; }
+        [Obsolete("Use GiveUpSecurityAndAcceptAnyTlsHostCertificate")]
+        public bool GiveUpSecurityAndAcceptAnySslHostCertificate { get { return GiveUpSecurityAndAcceptAnyTlsHostCertificate; } set { GiveUpSecurityAndAcceptAnyTlsHostCertificate = value; } }
 
 
         public void AddRawSettings(string setting, string value)
         public void AddRawSettings(string setting, string value)
         {
         {
@@ -85,19 +89,19 @@ namespace WinSCP
             _sshHostKeyFingerprint = s;
             _sshHostKeyFingerprint = s;
         }
         }
 
 
-        private void SetHostSslCertificateFingerprint(string s)
+        private void SetHostTlsCertificateFingerprint(string s)
         {
         {
             if (s != null)
             if (s != null)
             {
             {
-                Match match = _sslCertificateRegex.Match(s);
+                Match match = _tlsCertificateRegex.Match(s);
 
 
                 if (!match.Success || (match.Length != s.Length))
                 if (!match.Success || (match.Length != s.Length))
                 {
                 {
-                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "SSL host certificate fingerprint \"{0}\" does not match pattern /{1}/", s, _sslCertificateRegex));
+                    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "TLS host certificate fingerprint \"{0}\" does not match pattern /{1}/", s, _tlsCertificateRegex));
                 }
                 }
             }
             }
 
 
-            _sslHostCertificateFingerprint = s;
+            _tlsHostCertificateFingerprint = s;
         }
         }
 
 
         private void SetTimeout(TimeSpan value)
         private void SetTimeout(TimeSpan value)
@@ -121,7 +125,7 @@ namespace WinSCP
         }
         }
 
 
         private string _sshHostKeyFingerprint;
         private string _sshHostKeyFingerprint;
-        private string _sslHostCertificateFingerprint;
+        private string _tlsHostCertificateFingerprint;
         private TimeSpan _timeout;
         private TimeSpan _timeout;
         private int _portNumber;
         private int _portNumber;
 
 
@@ -129,8 +133,8 @@ namespace WinSCP
         private const string _sshHostKeyPattern = @"(ssh-rsa |ssh-dss )?\d+ ([0-9a-f]{2}:){15}[0-9a-f]{2}";
         private const string _sshHostKeyPattern = @"(ssh-rsa |ssh-dss )?\d+ ([0-9a-f]{2}:){15}[0-9a-f]{2}";
         private static readonly Regex _sshHostKeyRegex =
         private static readonly Regex _sshHostKeyRegex =
             new Regex(string.Format(CultureInfo.InvariantCulture, _listPattern, _sshHostKeyPattern));
             new Regex(string.Format(CultureInfo.InvariantCulture, _listPattern, _sshHostKeyPattern));
-        private const string _sslCertificatePattern = @"([0-9a-f]{2}:){19}[0-9a-f]{2}";
-        private static readonly Regex _sslCertificateRegex =
-            new Regex(string.Format(CultureInfo.InvariantCulture, _listPattern, _sslCertificatePattern));
+        private const string _tlsCertificatePattern = @"([0-9a-f]{2}:){19}[0-9a-f]{2}";
+        private static readonly Regex _tlsCertificateRegex =
+            new Regex(string.Format(CultureInfo.InvariantCulture, _listPattern, _tlsCertificatePattern));
     }
     }
 }
 }

+ 8 - 3
dotnet/internal/Logger.cs

@@ -80,7 +80,7 @@ namespace WinSCP
         private void AddCounter(PerformanceCounter counter)
         private void AddCounter(PerformanceCounter counter)
         {
         {
             counter.NextValue();
             counter.NextValue();
-            _processorCounters.Add(counter);
+            _performanceCounters.Add(counter);
         }
         }
 
 
         public void WriteLine(string message)
         public void WriteLine(string message)
@@ -144,6 +144,11 @@ namespace WinSCP
                     _writter.Dispose();
                     _writter.Dispose();
                     _writter = null;
                     _writter = null;
                 }
                 }
+
+                foreach (PerformanceCounter counter in _performanceCounters)
+                {
+                    counter.Dispose();
+                }
             }
             }
         }
         }
 
 
@@ -153,7 +158,7 @@ namespace WinSCP
             {
             {
                 try
                 try
                 {
                 {
-                    foreach (PerformanceCounter counter in _processorCounters)
+                    foreach (PerformanceCounter counter in _performanceCounters)
                     {
                     {
                         WriteLine("{0}{1}{2} = [{3}]",
                         WriteLine("{0}{1}{2} = [{3}]",
                             counter.CounterName,
                             counter.CounterName,
@@ -282,6 +287,6 @@ namespace WinSCP
         private readonly Dictionary<int, int> _indents = new Dictionary<int, int>();
         private readonly Dictionary<int, int> _indents = new Dictionary<int, int>();
         private readonly object _logLock = new object();
         private readonly object _logLock = new object();
         private readonly Lock _lock = new Lock();
         private readonly Lock _lock = new Lock();
-        private List<PerformanceCounter> _processorCounters = new List<PerformanceCounter>();
+        private List<PerformanceCounter> _performanceCounters = new List<PerformanceCounter>();
     }
     }
 }
 }

+ 3 - 3
dotnet/properties/AssemblyInfo.cs

@@ -19,9 +19,9 @@ using System.Runtime.InteropServices;
 // The following GUID is for the ID of the typelib if this project is exposed to COM
 // The following GUID is for the ID of the typelib if this project is exposed to COM
 [assembly: Guid("a0b93468-d98a-4845-a234-8076229ad93f")]
 [assembly: Guid("a0b93468-d98a-4845-a234-8076229ad93f")]
 
 
-[assembly: AssemblyVersion("1.1.2.0")]
-[assembly: AssemblyFileVersion("1.1.2.0")]
-[assembly: AssemblyInformationalVersionAttribute("5.2.2.0")]
+[assembly: AssemblyVersion("1.1.3.0")]
+[assembly: AssemblyFileVersion("1.1.3.0")]
+[assembly: AssemblyInformationalVersionAttribute("5.2.3.0")]
 
 
 [assembly: CLSCompliant(true)]
 [assembly: CLSCompliant(true)]
 
 

+ 2 - 3
libs/install/openssl/readme_debug

@@ -1,7 +1,6 @@
 Debug build:
 Debug build:
 - do CFLAG pridat 
 - do CFLAG pridat 
-  -v -y
+  -v -y -k -r- -vi-
   pro CodeGuard pridat
   pro CodeGuard pridat
   -vG 
   -vG 
-  a ubrat
-  -O2
+  nahradit -O2 za -Od

+ 0 - 3
libs/openssl/debug.txt

@@ -1,3 +0,0 @@
-To build debug version of OpenSSL, modify CFLAGS in Makefile as follows:
-  Add -y -k -r- -v -vi-
-  Replace -O2 with -Od

+ 1 - 1
source/Console.cbproj

@@ -41,7 +41,7 @@
 			<PackageImports>rtl.bpi;$(PackageImports)</PackageImports>
 			<PackageImports>rtl.bpi;$(PackageImports)</PackageImports>
 			<ProjectType>CppConsoleApplication</ProjectType>
 			<ProjectType>CppConsoleApplication</ProjectType>
 			<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
 			<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
-			<VerInfo_Keys>CompanyName=Martin Prikryl;FileDescription=Console interface for WinSCP;FileVersion=4.0.1.0;InternalName=console;LegalCopyright=(c) 2000-2013 Martin Prikryl;LegalTrademarks=;OriginalFilename=winscp.com;ProductName=WinSCP;ProductVersion=5.2.2.0;ReleaseType=beta;WWW=http://winscp.net/</VerInfo_Keys>
+			<VerInfo_Keys>CompanyName=Martin Prikryl;FileDescription=Console interface for WinSCP;FileVersion=4.0.1.0;InternalName=console;LegalCopyright=(c) 2000-2013 Martin Prikryl;LegalTrademarks=;OriginalFilename=winscp.com;ProductName=WinSCP;ProductVersion=5.2.3.0;ReleaseType=beta;WWW=http://winscp.net/</VerInfo_Keys>
 			<VerInfo_Locale>1033</VerInfo_Locale>
 			<VerInfo_Locale>1033</VerInfo_Locale>
 			<VerInfo_MajorVer>4</VerInfo_MajorVer>
 			<VerInfo_MajorVer>4</VerInfo_MajorVer>
 			<VerInfo_Release>1</VerInfo_Release>
 			<VerInfo_Release>1</VerInfo_Release>

+ 1 - 1
source/DragExt.cbproj

@@ -42,7 +42,7 @@
 			<ProjectType>CppDynamicLibrary</ProjectType>
 			<ProjectType>CppDynamicLibrary</ProjectType>
 			<VerInfo_DLL>true</VerInfo_DLL>
 			<VerInfo_DLL>true</VerInfo_DLL>
 			<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
 			<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
-			<VerInfo_Keys>CompanyName=Martin Prikryl;FileDescription=Drag&amp;Drop shell extension for WinSCP (32-bit);FileVersion=1.2.1.0;InternalName=dragext32;LegalCopyright=(c) 2000-2013 Martin Prikryl;LegalTrademarks=;OriginalFilename=dragext.dll;ProductName=WinSCP;ProductVersion=5.2.2.0;ReleaseType=beta;WWW=http://winscp.net/</VerInfo_Keys>
+			<VerInfo_Keys>CompanyName=Martin Prikryl;FileDescription=Drag&amp;Drop shell extension for WinSCP (32-bit);FileVersion=1.2.1.0;InternalName=dragext32;LegalCopyright=(c) 2000-2013 Martin Prikryl;LegalTrademarks=;OriginalFilename=dragext.dll;ProductName=WinSCP;ProductVersion=5.2.3.0;ReleaseType=beta;WWW=http://winscp.net/</VerInfo_Keys>
 			<VerInfo_Locale>1033</VerInfo_Locale>
 			<VerInfo_Locale>1033</VerInfo_Locale>
 			<VerInfo_MinorVer>2</VerInfo_MinorVer>
 			<VerInfo_MinorVer>2</VerInfo_MinorVer>
 			<VerInfo_Release>1</VerInfo_Release>
 			<VerInfo_Release>1</VerInfo_Release>

+ 2 - 2
source/DragExt64.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
 1 VERSIONINFO
 FILEVERSION 1,2,1,0
 FILEVERSION 1,2,1,0
-PRODUCTVERSION 5,2,2,0
+PRODUCTVERSION 5,2,3,0
 FILEOS 0x4
 FILEOS 0x4
 FILETYPE 0x2
 FILETYPE 0x2
 {
 {
@@ -16,7 +16,7 @@ FILETYPE 0x2
             VALUE "LegalTrademarks", "\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "dragext64.dll\0"
             VALUE "OriginalFilename", "dragext64.dll\0"
             VALUE "ProductName", "WinSCP\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "5.2.2.0\0"
+            VALUE "ProductVersion", "5.2.3.0\0"
             VALUE "ReleaseType", "beta\0"
             VALUE "ReleaseType", "beta\0"
             VALUE "WWW", "http://winscp.net/\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
         }

+ 3 - 3
source/PngComponents.cbproj

@@ -42,14 +42,14 @@
 			<DCC_AdditionalSwitches>-LUDesignIDE</DCC_AdditionalSwitches>
 			<DCC_AdditionalSwitches>-LUDesignIDE</DCC_AdditionalSwitches>
 			<DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>
 			<DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>
 			<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)</DCC_Namespace>
 			<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)</DCC_Namespace>
-			<DCC_UnitSearchPath>packages\png;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
+			<DCC_UnitSearchPath>packages\png;packages\my;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
 			<DynamicRTL>true</DynamicRTL>
 			<DynamicRTL>true</DynamicRTL>
 			<ILINK_Description>Png Components</ILINK_Description>
 			<ILINK_Description>Png Components</ILINK_Description>
 			<ILINK_GenerateImportLibrary>true</ILINK_GenerateImportLibrary>
 			<ILINK_GenerateImportLibrary>true</ILINK_GenerateImportLibrary>
 			<ILINK_GenerateLibFile>true</ILINK_GenerateLibFile>
 			<ILINK_GenerateLibFile>true</ILINK_GenerateLibFile>
-			<ILINK_LibraryPath>packages\png\;$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;$(BDS)\source\toolsapi\;$(ILINK_LibraryPath)</ILINK_LibraryPath>
+			<ILINK_LibraryPath>packages\png\;packages\my;$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;$(BDS)\source\toolsapi\;$(ILINK_LibraryPath)</ILINK_LibraryPath>
 			<ILINK_TranslatedLibraryPath>$(BDSLIB)\$(PLATFORM)\release\$(LANGDIR);$(ILINK_TranslatedLibraryPath)</ILINK_TranslatedLibraryPath>
 			<ILINK_TranslatedLibraryPath>$(BDSLIB)\$(PLATFORM)\release\$(LANGDIR);$(ILINK_TranslatedLibraryPath)</ILINK_TranslatedLibraryPath>
-			<IncludePath>packages\png\;$(IncludePath)</IncludePath>
+			<IncludePath>packages\png\;packages\my;$(IncludePath)</IncludePath>
 			<Multithreaded>true</Multithreaded>
 			<Multithreaded>true</Multithreaded>
 			<ProjectType>CppPackage</ProjectType>
 			<ProjectType>CppPackage</ProjectType>
 			<UsePackages>true</UsePackages>
 			<UsePackages>true</UsePackages>

+ 2 - 2
source/WinSCP.cbproj

@@ -51,11 +51,11 @@
 			<ProjectType>CppVCLApplication</ProjectType>
 			<ProjectType>CppVCLApplication</ProjectType>
 			<UsingDelphiRTL>true</UsingDelphiRTL>
 			<UsingDelphiRTL>true</UsingDelphiRTL>
 			<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
 			<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
-			<VerInfo_Keys>CompanyName=Martin Prikryl;FileDescription=WinSCP: SFTP, FTP and SCP client;FileVersion=5.2.2.0;InternalName=winscp;LegalCopyright=(c) 2000-2013 Martin Prikryl;LegalTrademarks=;OriginalFilename=winscp.exe;ProductName=WinSCP;ProductVersion=5.2.2.0;ReleaseType=beta;WWW=http://winscp.net/</VerInfo_Keys>
+			<VerInfo_Keys>CompanyName=Martin Prikryl;FileDescription=WinSCP: SFTP, FTP and SCP client;FileVersion=5.2.3.0;InternalName=winscp;LegalCopyright=(c) 2000-2013 Martin Prikryl;LegalTrademarks=;OriginalFilename=winscp.exe;ProductName=WinSCP;ProductVersion=5.2.3.0;ReleaseType=beta;WWW=http://winscp.net/</VerInfo_Keys>
 			<VerInfo_Locale>1033</VerInfo_Locale>
 			<VerInfo_Locale>1033</VerInfo_Locale>
 			<VerInfo_MajorVer>5</VerInfo_MajorVer>
 			<VerInfo_MajorVer>5</VerInfo_MajorVer>
 			<VerInfo_MinorVer>2</VerInfo_MinorVer>
 			<VerInfo_MinorVer>2</VerInfo_MinorVer>
-			<VerInfo_Release>2</VerInfo_Release>
+			<VerInfo_Release>3</VerInfo_Release>
 		</PropertyGroup>
 		</PropertyGroup>
 		<PropertyGroup Condition="'$(Cfg_1)'!=''">
 		<PropertyGroup Condition="'$(Cfg_1)'!=''">
 			<BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>
 			<BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>

+ 0 - 2
source/components/UnixDriveView.h

@@ -110,8 +110,6 @@ __published:
   __property OnDDDragFileName;
   __property OnDDDragFileName;
   __property OnDDEnd;
   __property OnDDEnd;
 
 
-  __property UseDragImages;
-
   __property TargetPopUpMenu;
   __property TargetPopUpMenu;
   __property UseSystemContextMenu;
   __property UseSystemContextMenu;
 
 

+ 7 - 9
source/core/Common.cpp

@@ -1775,16 +1775,9 @@ void __fastcall AddToList(UnicodeString & List, const UnicodeString & Value, con
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
-bool __fastcall Is2000()
-{
-  return (Win32MajorVersion >= 5);
-}
-//---------------------------------------------------------------------------
 bool __fastcall IsWin7()
 bool __fastcall IsWin7()
 {
 {
-  return
-    (Win32MajorVersion > 6) ||
-    ((Win32MajorVersion == 6) && (Win32MinorVersion >= 1));
+  return CheckWin32Version(6, 1);
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 bool __fastcall IsExactly2008R2()
 bool __fastcall IsExactly2008R2()
@@ -1845,7 +1838,7 @@ bool __fastcall IsExactly2008R2()
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 LCID __fastcall GetDefaultLCID()
 LCID __fastcall GetDefaultLCID()
 {
 {
-  return Is2000() ? GetUserDefaultLCID() : GetThreadLocale();
+  return GetUserDefaultLCID();
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 static UnicodeString ADefaultEncodingName;
 static UnicodeString ADefaultEncodingName;
@@ -1908,5 +1901,10 @@ UnicodeString __fastcall FormatSize(__int64 Size)
   return FormatNumber(Size);
   return FormatNumber(Size);
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+UnicodeString __fastcall ExtractFileBaseName(const UnicodeString & Path)
+{
+  return ChangeFileExt(ExtractFileName(Path), L"");
+}
+//---------------------------------------------------------------------------
 // Suppress warning about unused constants in DateUtils.hpp
 // Suppress warning about unused constants in DateUtils.hpp
 #pragma warn -8080
 #pragma warn -8080

+ 1 - 1
source/core/Common.h

@@ -87,7 +87,6 @@ UnicodeString __fastcall EscapeHotkey(const UnicodeString & Caption);
 bool __fastcall CutToken(UnicodeString & Str, UnicodeString & Token,
 bool __fastcall CutToken(UnicodeString & Str, UnicodeString & Token,
   UnicodeString * RawToken = NULL);
   UnicodeString * RawToken = NULL);
 void __fastcall AddToList(UnicodeString & List, const UnicodeString & Value, const UnicodeString & Delimiter);
 void __fastcall AddToList(UnicodeString & List, const UnicodeString & Value, const UnicodeString & Delimiter);
-bool __fastcall Is2000();
 bool __fastcall IsWin7();
 bool __fastcall IsWin7();
 bool __fastcall IsExactly2008R2();
 bool __fastcall IsExactly2008R2();
 TLibModule * __fastcall FindModule(void * Instance);
 TLibModule * __fastcall FindModule(void * Instance);
@@ -99,6 +98,7 @@ UnicodeString __fastcall WindowsProductName();
 bool __fastcall IsDirectoryWriteable(const UnicodeString & Path);
 bool __fastcall IsDirectoryWriteable(const UnicodeString & Path);
 UnicodeString __fastcall FormatNumber(__int64 Size);
 UnicodeString __fastcall FormatNumber(__int64 Size);
 UnicodeString __fastcall FormatSize(__int64 Size);
 UnicodeString __fastcall FormatSize(__int64 Size);
+UnicodeString __fastcall ExtractFileBaseName(const UnicodeString & Path);
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 typedef void __fastcall (__closure* TProcessLocalFileEvent)
 typedef void __fastcall (__closure* TProcessLocalFileEvent)
   (const UnicodeString FileName, const TSearchRec Rec, void * Param);
   (const UnicodeString FileName, const TSearchRec Rec, void * Param);

+ 9 - 3
source/core/Configuration.cpp

@@ -178,7 +178,13 @@ void __fastcall TConfiguration::SaveData(THierarchicalStorage * Storage, bool /*
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
-void __fastcall TConfiguration::Save(bool All, bool Explicit)
+void __fastcall TConfiguration::Save()
+{
+  // only modified, implicit
+  DoSave(false, false);
+}
+//---------------------------------------------------------------------------
+void __fastcall TConfiguration::DoSave(bool All, bool Explicit)
 {
 {
   if (FDontSave) return;
   if (FDontSave) return;
 
 
@@ -272,7 +278,7 @@ void __fastcall TConfiguration::Import(const UnicodeString & FileName)
   }
   }
 
 
   // save all and explicit
   // save all and explicit
-  Save(true, true);
+  DoSave(true, true);
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 void __fastcall TConfiguration::LoadData(THierarchicalStorage * Storage)
 void __fastcall TConfiguration::LoadData(THierarchicalStorage * Storage)
@@ -977,7 +983,7 @@ void __fastcall TConfiguration::SetStorage(TStorage value)
     }
     }
 
 
     // save all and explicit
     // save all and explicit
-    Save(true, true);
+    DoSave(true, true);
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------

+ 2 - 1
source/core/Configuration.h

@@ -132,6 +132,7 @@ protected:
   void __fastcall CleanupRegistry(UnicodeString CleanupSubKey);
   void __fastcall CleanupRegistry(UnicodeString CleanupSubKey);
   UnicodeString __fastcall BannerHash(const UnicodeString & Banner);
   UnicodeString __fastcall BannerHash(const UnicodeString & Banner);
   static UnicodeString __fastcall PropertyToKey(const UnicodeString & Property);
   static UnicodeString __fastcall PropertyToKey(const UnicodeString & Property);
+  virtual void __fastcall DoSave(bool All, bool Explicit);
 
 
   virtual bool __fastcall GetConfirmOverwriting();
   virtual bool __fastcall GetConfirmOverwriting();
   virtual void __fastcall SetConfirmOverwriting(bool value);
   virtual void __fastcall SetConfirmOverwriting(bool value);
@@ -160,7 +161,7 @@ public:
   virtual __fastcall ~TConfiguration();
   virtual __fastcall ~TConfiguration();
   virtual void __fastcall Default();
   virtual void __fastcall Default();
   virtual void __fastcall Load();
   virtual void __fastcall Load();
-  virtual void __fastcall Save(bool All, bool Explicit);
+  virtual void __fastcall Save();
   void __fastcall SetNulStorage();
   void __fastcall SetNulStorage();
   void __fastcall SetDefaultStorage();
   void __fastcall SetDefaultStorage();
   void __fastcall Export(const UnicodeString & FileName);
   void __fastcall Export(const UnicodeString & FileName);

+ 1 - 2
source/core/CoreMain.cpp

@@ -96,8 +96,7 @@ void CoreFinalize()
 {
 {
   try
   try
   {
   {
-    // only modified, implicit
-    Configuration->Save(false, false);
+    Configuration->Save();
   }
   }
   catch(Exception & E)
   catch(Exception & E)
   {
   {

+ 1 - 1
source/core/Cryptography.cpp

@@ -508,7 +508,7 @@ RawByteString __fastcall ScramblePassword(UnicodeString Password)
   for (int Index = 0; Index < Padding; Index++)
   for (int Index = 0; Index < Padding; Index++)
   {
   {
     int P = 0;
     int P = 0;
-    while ((P <= 0) || (P > 255) || IsDigit(P >= '0'))
+    while ((P <= 0) || (P > 255) || IsDigit(static_cast<wchar_t>(P)))
     {
     {
       P = (int)((double)rand() / ((double)RAND_MAX / 256.0));
       P = (int)((double)rand() / ((double)RAND_MAX / 256.0));
     }
     }

+ 22 - 4
source/core/FtpFileSystem.cpp

@@ -298,11 +298,13 @@ void __fastcall TFTPFileSystem::Open()
   TSessionData * Data = FTerminal->SessionData;
   TSessionData * Data = FTerminal->SessionData;
 
 
   FSessionInfo.LoginTime = Now();
   FSessionInfo.LoginTime = Now();
-  FSessionInfo.ProtocolBaseName = L"FTP";
-  FSessionInfo.ProtocolName = FSessionInfo.ProtocolBaseName;
 
 
   switch (Data->Ftps)
   switch (Data->Ftps)
   {
   {
+    case ftpsNone:
+      // noop;
+      break;
+
     case ftpsImplicit:
     case ftpsImplicit:
       FSessionInfo.SecurityProtocolName = LoadStr(FTPS_IMPLICIT);
       FSessionInfo.SecurityProtocolName = LoadStr(FTPS_IMPLICIT);
       break;
       break;
@@ -314,6 +316,10 @@ void __fastcall TFTPFileSystem::Open()
     case ftpsExplicitTls:
     case ftpsExplicitTls:
       FSessionInfo.SecurityProtocolName = LoadStr(FTPS_EXPLICIT_TLS);
       FSessionInfo.SecurityProtocolName = LoadStr(FTPS_EXPLICIT_TLS);
       break;
       break;
+
+    default:
+      FAIL;
+      break;
   }
   }
 
 
   FLastDataSent = Now();
   FLastDataSent = Now();
@@ -484,6 +490,11 @@ void __fastcall TFTPFileSystem::Open()
     }
     }
   }
   }
   while (FPasswordFailed);
   while (FPasswordFailed);
+
+  FSessionInfo.CSCipher = FFileZillaIntf->GetCipherName().c_str();
+  FSessionInfo.SCCipher = FSessionInfo.CSCipher;
+  UnicodeString TlsVersionStr = FFileZillaIntf->GetTlsVersionStr().c_str();
+  AddToList(FSessionInfo.SecurityProtocolName, TlsVersionStr, L", ");
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 void __fastcall TFTPFileSystem::Close()
 void __fastcall TFTPFileSystem::Close()
@@ -935,8 +946,7 @@ void __fastcall TFTPFileSystem::DoFileTransferProgress(__int64 TransferSize,
   }
   }
 
 
   __int64 Diff = Bytes - OperationProgress->TransferedSize;
   __int64 Diff = Bytes - OperationProgress->TransferedSize;
-  assert(Diff >= 0);
-  if (Diff >= 0)
+  if (ALWAYS_TRUE(Diff >= 0))
   {
   {
     OperationProgress->AddTransfered(Diff);
     OperationProgress->AddTransfered(Diff);
   }
   }
@@ -2274,6 +2284,14 @@ int __fastcall TFTPFileSystem::GetOptionVal(int OptionID) const
       Result = (Data->SslSessionReuse ? TRUE : FALSE);
       Result = (Data->SslSessionReuse ? TRUE : FALSE);
       break;
       break;
 
 
+    case OPTION_MPEXT_MIN_TLS_VERSION:
+      Result = Data->MinTlsVersion;
+      break;
+
+    case OPTION_MPEXT_MAX_TLS_VERSION:
+      Result = Data->MaxTlsVersion;
+      break;
+
     case OPTION_MPEXT_SNDBUF:
     case OPTION_MPEXT_SNDBUF:
       Result = Data->SendBuf;
       Result = Data->SendBuf;
       break;
       break;

+ 5 - 0
source/core/Queue.cpp

@@ -1819,6 +1819,11 @@ int __fastcall TTerminalQueueStatus::GetDoneAndActiveCount()
   return DoneCount + ActiveCount;
   return DoneCount + ActiveCount;
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+int __fastcall TTerminalQueueStatus::GetActiveAndPendingCount()
+{
+  return Count - DoneCount;
+}
+//---------------------------------------------------------------------------
 void __fastcall TTerminalQueueStatus::Add(TQueueItemProxy * ItemProxy)
 void __fastcall TTerminalQueueStatus::Add(TQueueItemProxy * ItemProxy)
 {
 {
   ItemProxy->FQueueStatus = this;
   ItemProxy->FQueueStatus = this;

+ 2 - 0
source/core/Queue.h

@@ -254,6 +254,7 @@ public:
   __property int DoneCount = { read = FDoneCount };
   __property int DoneCount = { read = FDoneCount };
   __property int ActiveCount = { read = GetActiveCount };
   __property int ActiveCount = { read = GetActiveCount };
   __property int DoneAndActiveCount = { read = GetDoneAndActiveCount };
   __property int DoneAndActiveCount = { read = GetDoneAndActiveCount };
+  __property int ActiveAndPendingCount = { read = GetActiveAndPendingCount };
   __property TQueueItemProxy * Items[int Index] = { read = GetItem };
   __property TQueueItemProxy * Items[int Index] = { read = GetItem };
 
 
 protected:
 protected:
@@ -271,6 +272,7 @@ private:
   int __fastcall GetCount();
   int __fastcall GetCount();
   int __fastcall GetActiveCount();
   int __fastcall GetActiveCount();
   int __fastcall GetDoneAndActiveCount();
   int __fastcall GetDoneAndActiveCount();
+  int __fastcall GetActiveAndPendingCount();
   void __fastcall SetDoneCount(int Value);
   void __fastcall SetDoneCount(int Value);
   TQueueItemProxy * __fastcall GetItem(int Index);
   TQueueItemProxy * __fastcall GetItem(int Index);
 };
 };

+ 29 - 23
source/core/RemoteFiles.cpp

@@ -391,6 +391,34 @@ UnicodeString __fastcall UserModificationStr(TDateTime DateTime,
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+UnicodeString __fastcall ModificationStr(TDateTime DateTime,
+  TModificationFmt Precision)
+{
+  Word Year, Month, Day, Hour, Min, Sec, MSec;
+  DateTime.DecodeDate(&Year, &Month, &Day);
+  DateTime.DecodeTime(&Hour, &Min, &Sec, &MSec);
+  switch (Precision)
+  {
+    case mfNone:
+      return L"";
+
+    case mfMDY:
+      return FORMAT(L"%3s %2d %2d", (EngShortMonthNames[Month-1], Day, Year));
+
+    case mfMDHM:
+      return FORMAT(L"%3s %2d %2d:%2.2d",
+        (EngShortMonthNames[Month-1], Day, Hour, Min));
+
+    default:
+      assert(false);
+      // fall thru
+
+    case mfFull:
+      return FORMAT(L"%3s %2d %2d:%2.2d:%2.2d %4d",
+        (EngShortMonthNames[Month-1], Day, Hour, Min, Sec, Year));
+  }
+}
+//---------------------------------------------------------------------------
 int __fastcall FakeFileImageIndex(UnicodeString FileName, unsigned long Attrs,
 int __fastcall FakeFileImageIndex(UnicodeString FileName, unsigned long Attrs,
   UnicodeString * TypeName)
   UnicodeString * TypeName)
 {
 {
@@ -920,29 +948,7 @@ UnicodeString __fastcall TRemoteFile::GetUserModificationStr()
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 UnicodeString __fastcall TRemoteFile::GetModificationStr()
 UnicodeString __fastcall TRemoteFile::GetModificationStr()
 {
 {
-  Word Year, Month, Day, Hour, Min, Sec, MSec;
-  Modification.DecodeDate(&Year, &Month, &Day);
-  Modification.DecodeTime(&Hour, &Min, &Sec, &MSec);
-  switch (FModificationFmt)
-  {
-    case mfNone:
-      return L"";
-
-    case mfMDY:
-      return FORMAT(L"%3s %2d %2d", (EngShortMonthNames[Month-1], Day, Year));
-
-    case mfMDHM:
-      return FORMAT(L"%3s %2d %2d:%2.2d",
-        (EngShortMonthNames[Month-1], Day, Hour, Min));
-
-    default:
-      assert(false);
-      // fall thru
-
-    case mfFull:
-      return FORMAT(L"%3s %2d %2d:%2.2d:%2.2d %4d",
-        (EngShortMonthNames[Month-1], Day, Hour, Min, Sec, Year));
-  }
+  return ::ModificationStr(Modification, FModificationFmt);
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 UnicodeString __fastcall TRemoteFile::GetExtension()
 UnicodeString __fastcall TRemoteFile::GetExtension()

+ 2 - 0
source/core/RemoteFiles.h

@@ -449,6 +449,8 @@ TModificationFmt __fastcall LessDateTimePrecision(
   TModificationFmt Precision1, TModificationFmt Precision2);
   TModificationFmt Precision1, TModificationFmt Precision2);
 UnicodeString __fastcall UserModificationStr(TDateTime DateTime,
 UnicodeString __fastcall UserModificationStr(TDateTime DateTime,
   TModificationFmt Precision);
   TModificationFmt Precision);
+UnicodeString __fastcall ModificationStr(TDateTime DateTime,
+  TModificationFmt Precision);
 int __fastcall FakeFileImageIndex(UnicodeString FileName, unsigned long Attrs = 0,
 int __fastcall FakeFileImageIndex(UnicodeString FileName, unsigned long Attrs = 0,
   UnicodeString * TypeName = NULL);
   UnicodeString * TypeName = NULL);
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------

+ 13 - 6
source/core/ScpFileSystem.cpp

@@ -691,10 +691,17 @@ void __fastcall TSCPFileSystem::DoStartup()
 {
 {
   // SkipStartupMessage and DetectReturnVar must succeed,
   // SkipStartupMessage and DetectReturnVar must succeed,
   // otherwise session is to be closed.
   // otherwise session is to be closed.
-  FTerminal->ExceptionOnFail = true;
-  SkipStartupMessage();
-  if (FTerminal->SessionData->DetectReturnVar) DetectReturnVar();
-  FTerminal->ExceptionOnFail = false;
+  try
+  {
+    FTerminal->ExceptionOnFail = true;
+    SkipStartupMessage();
+    if (FTerminal->SessionData->DetectReturnVar) DetectReturnVar();
+    FTerminal->ExceptionOnFail = false;
+  }
+  catch (Exception & E)
+  {
+    FTerminal->FatalError(&E, L"");
+  }
 
 
   #define COND_OPER(OPER) if (FTerminal->SessionData->OPER) OPER()
   #define COND_OPER(OPER) if (FTerminal->SessionData->OPER) OPER()
   COND_OPER(ClearAliases);
   COND_OPER(ClearAliases);
@@ -754,7 +761,7 @@ void __fastcall TSCPFileSystem::DetectReturnVar()
         if ((Output->Count != 1) || (StrToIntDef(Output->Strings[0], 256) > 255))
         if ((Output->Count != 1) || (StrToIntDef(Output->Strings[0], 256) > 255))
         {
         {
           FTerminal->LogEvent(L"The response is not numerical exit code");
           FTerminal->LogEvent(L"The response is not numerical exit code");
-          Abort();
+          EXCEPTION;
         }
         }
       }
       }
       catch (EFatal &E)
       catch (EFatal &E)
@@ -777,7 +784,7 @@ void __fastcall TSCPFileSystem::DetectReturnVar()
 
 
     if (NewReturnVar.IsEmpty())
     if (NewReturnVar.IsEmpty())
     {
     {
-      Abort();
+      EXCEPTION;
     }
     }
     else
     else
     {
     {

+ 115 - 5
source/core/Script.cpp

@@ -366,7 +366,7 @@ void __fastcall TScript::Init()
   FCommands->Register(L"option", SCRIPT_OPTION_DESC, SCRIPT_OPTION_HELP6, &OptionProc, -1, 2, false);
   FCommands->Register(L"option", SCRIPT_OPTION_DESC, SCRIPT_OPTION_HELP6, &OptionProc, -1, 2, false);
   FCommands->Register(L"ascii", 0, SCRIPT_OPTION_HELP6, &AsciiProc, 0, 0, false);
   FCommands->Register(L"ascii", 0, SCRIPT_OPTION_HELP6, &AsciiProc, 0, 0, false);
   FCommands->Register(L"binary", 0, SCRIPT_OPTION_HELP6, &BinaryProc, 0, 0, false);
   FCommands->Register(L"binary", 0, SCRIPT_OPTION_HELP6, &BinaryProc, 0, 0, false);
-  FCommands->Register(L"synchronize", SCRIPT_SYNCHRONIZE_DESC, SCRIPT_SYNCHRONIZE_HELP6, &SynchronizeProc, 1, 3, true);
+  FCommands->Register(L"synchronize", SCRIPT_SYNCHRONIZE_DESC, SCRIPT_SYNCHRONIZE_HELP7, &SynchronizeProc, 1, 3, true);
   FCommands->Register(L"keepuptodate", SCRIPT_KEEPUPTODATE_DESC, SCRIPT_KEEPUPTODATE_HELP4, &KeepUpToDateProc, 0, 2, true);
   FCommands->Register(L"keepuptodate", SCRIPT_KEEPUPTODATE_DESC, SCRIPT_KEEPUPTODATE_HELP4, &KeepUpToDateProc, 0, 2, true);
   // the echo command does not have switches actually, but it must handle dashes in its arguments
   // the echo command does not have switches actually, but it must handle dashes in its arguments
   FCommands->Register(L"echo", SCRIPT_ECHO_DESC, SCRIPT_ECHO_HELP, &EchoProc, -1, -1, true);
   FCommands->Register(L"echo", SCRIPT_ECHO_DESC, SCRIPT_ECHO_HELP, &EchoProc, -1, -1, true);
@@ -1412,6 +1412,108 @@ void __fastcall TScript::SynchronizeDirectories(TScriptProcParams * Parameters,
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+UnicodeString __fastcall TScript::SynchronizeFileRecord(
+  const UnicodeString & RootDirectory, const TSynchronizeChecklist::TItem * Item, bool Local)
+{
+  const TSynchronizeChecklist::TItem::TFileInfo & FileInfo =
+    Local ? Item->Local : Item->Remote;
+  UnicodeString Path;
+  if (Local)
+  {
+    Path = IncludeTrailingBackslash(FileInfo.Directory) + FileInfo.FileName;
+  }
+  else
+  {
+    Path = UnixIncludeTrailingBackslash(FileInfo.Directory) + FileInfo.FileName;
+  }
+
+  if (SameText(RootDirectory, Path.SubString(1, RootDirectory.Length())))
+  {
+    Path[1] = L'.';
+    Path.Delete(2, RootDirectory.Length() - 2);
+  }
+
+  UnicodeString Result;
+  if (Item->IsDirectory)
+  {
+    if (Local)
+    {
+      Result = IncludeTrailingBackslash(Path);
+    }
+    else
+    {
+      Result = UnixIncludeTrailingBackslash(Path);
+    }
+  }
+  else
+  {
+    UnicodeString SizeStr = IntToStr(FileInfo.Size);
+    UnicodeString ModificationStr =
+      ::ModificationStr(FileInfo.Modification, FileInfo.ModificationFmt);
+    Result = FORMAT("%s [%s, %s]", (Path, SizeStr, ModificationStr));
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
+void __fastcall TScript::SynchronizePreview(
+  UnicodeString LocalDirectory, UnicodeString RemoteDirectory,
+  TSynchronizeChecklist * Checklist)
+{
+
+  LocalDirectory = IncludeTrailingBackslash(LocalDirectory);
+  RemoteDirectory = UnixIncludeTrailingBackslash(RemoteDirectory);
+
+  for (int Index = 0; (Index < Checklist->Count); Index++)
+  {
+    const TSynchronizeChecklist::TItem * Item = Checklist->Item[Index];
+    if (Item->Checked)
+    {
+      UnicodeString Message;
+      UnicodeString LocalRecord = SynchronizeFileRecord(LocalDirectory, Item, true);
+      UnicodeString RemoteRecord = SynchronizeFileRecord(RemoteDirectory, Item, false);
+
+      switch (Item->Action)
+      {
+        case TSynchronizeChecklist::saUploadNew:
+          Message =
+            FMTLOAD(SCRIPT_SYNC_UPLOAD_NEW, (LocalRecord));
+          break;
+
+        case TSynchronizeChecklist::saDownloadNew:
+          Message =
+            FMTLOAD(SCRIPT_SYNC_DOWNLOAD_NEW, (RemoteRecord));
+          break;
+
+        case TSynchronizeChecklist::saUploadUpdate:
+          Message =
+            FMTLOAD(SCRIPT_SYNC_UPLOAD_UPDATE,
+              (LocalRecord, RemoteRecord));
+          break;
+
+        case TSynchronizeChecklist::saDownloadUpdate:
+          Message =
+            FMTLOAD(SCRIPT_SYNC_DOWNLOAD_UPDATE,
+              (RemoteRecord, LocalRecord));
+          break;
+
+        case TSynchronizeChecklist::saDeleteRemote:
+          Message =
+            FMTLOAD(SCRIPT_SYNC_DELETE_REMOTE, (RemoteRecord));
+          break;
+
+        case TSynchronizeChecklist::saDeleteLocal:
+          Message =
+            FMTLOAD(SCRIPT_SYNC_DELETE_LOCAL, (LocalRecord));
+          break;
+
+      default:
+        FAIL;
+      }
+      PrintLine(Message);
+    }
+  }
+}
+//---------------------------------------------------------------------------
 void __fastcall TScript::SynchronizeProc(TScriptProcParams * Parameters)
 void __fastcall TScript::SynchronizeProc(TScriptProcParams * Parameters)
 {
 {
   CheckSession();
   CheckSession();
@@ -1477,6 +1579,7 @@ void __fastcall TScript::SynchronizeProc(TScriptProcParams * Parameters)
           break;
           break;
       }
       }
     }
     }
+    bool Preview = Parameters->FindSwitch(L"preview");
 
 
     // enforce rules
     // enforce rules
     if (FSynchronizeMode  == TTerminal::smBoth)
     if (FSynchronizeMode  == TTerminal::smBoth)
@@ -1502,9 +1605,17 @@ void __fastcall TScript::SynchronizeProc(TScriptProcParams * Parameters)
 
 
       if (AnyChecked)
       if (AnyChecked)
       {
       {
-        PrintLine(LoadStr(SCRIPT_SYNCHRONIZE_SYNCHRONIZING));
-        FTerminal->SynchronizeApply(Checklist, LocalDirectory, RemoteDirectory,
-          &CopyParam, SynchronizeParams, OnTerminalSynchronizeDirectory);
+        if (Preview)
+        {
+          PrintLine(LoadStr(SCRIPT_SYNCHRONIZE_CHECKLIST));
+          SynchronizePreview(LocalDirectory, RemoteDirectory, Checklist);
+        }
+        else
+        {
+          PrintLine(LoadStr(SCRIPT_SYNCHRONIZE_SYNCHRONIZING));
+          FTerminal->SynchronizeApply(Checklist, LocalDirectory, RemoteDirectory,
+            &CopyParam, SynchronizeParams, OnTerminalSynchronizeDirectory);
+        }
       }
       }
       else
       else
       {
       {
@@ -1515,7 +1626,6 @@ void __fastcall TScript::SynchronizeProc(TScriptProcParams * Parameters)
     {
     {
       delete Checklist;
       delete Checklist;
     }
     }
-
   }
   }
   __finally
   __finally
   {
   {

+ 6 - 0
source/core/Script.h

@@ -147,6 +147,12 @@ protected:
   void __fastcall TerminalCaptureLog(const UnicodeString & AddedLine, bool StdError);
   void __fastcall TerminalCaptureLog(const UnicodeString & AddedLine, bool StdError);
   virtual UnicodeString __fastcall GetLogCmd(const UnicodeString & FullCommand,
   virtual UnicodeString __fastcall GetLogCmd(const UnicodeString & FullCommand,
     const UnicodeString & Command, const UnicodeString & Params);
     const UnicodeString & Command, const UnicodeString & Params);
+  void __fastcall SynchronizePreview(
+    UnicodeString LocalDirectory, UnicodeString RemoteDirectory,
+    TSynchronizeChecklist * Checklist);
+  UnicodeString __fastcall SynchronizeFileRecord(
+    const UnicodeString & RootDirectory, const TSynchronizeChecklist::TItem * Item,
+    bool Local);
 
 
 private:
 private:
   void __fastcall Init();
   void __fastcall Init();

+ 75 - 14
source/core/SessionData.cpp

@@ -178,6 +178,8 @@ void __fastcall TSessionData::Default()
   FtpPingInterval = 30;
   FtpPingInterval = 30;
   FtpPingType = ptDummyCommand;
   FtpPingType = ptDummyCommand;
   Ftps = ftpsNone;
   Ftps = ftpsNone;
+  MinTlsVersion = ssl2;
+  MaxTlsVersion = tls12;
   FtpListAll = asAuto;
   FtpListAll = asAuto;
   SslSessionReuse = true;
   SslSessionReuse = true;
 
 
@@ -319,6 +321,9 @@ void __fastcall TSessionData::NonPersistant()
   \
   \
   PROPERTY(FtpProxyLogonType); \
   PROPERTY(FtpProxyLogonType); \
   \
   \
+  PROPERTY(MinTlsVersion); \
+  PROPERTY(MaxTlsVersion); \
+  \
   PROPERTY(IsWorkspace); \
   PROPERTY(IsWorkspace); \
   PROPERTY(Link); \
   PROPERTY(Link); \
   \
   \
@@ -586,6 +591,9 @@ void __fastcall TSessionData::DoLoad(THierarchicalStorage * Storage, bool & Rewr
 
 
   FtpProxyLogonType = Storage->ReadInteger(L"FtpProxyLogonType", FtpProxyLogonType);
   FtpProxyLogonType = Storage->ReadInteger(L"FtpProxyLogonType", FtpProxyLogonType);
 
 
+  MinTlsVersion = static_cast<TTlsVersion>(Storage->ReadInteger(L"MinTlsVersion", MinTlsVersion));
+  MaxTlsVersion = static_cast<TTlsVersion>(Storage->ReadInteger(L"MaxTlsVersion", MaxTlsVersion));
+
   IsWorkspace = Storage->ReadBool(L"IsWorkspace", IsWorkspace);
   IsWorkspace = Storage->ReadBool(L"IsWorkspace", IsWorkspace);
   Link = Storage->ReadString(L"Link", Link);
   Link = Storage->ReadString(L"Link", Link);
 
 
@@ -860,6 +868,9 @@ void __fastcall TSessionData::Save(THierarchicalStorage * Storage,
 
 
       WRITE_DATA(Integer, FtpProxyLogonType);
       WRITE_DATA(Integer, FtpProxyLogonType);
 
 
+      WRITE_DATA(Integer, MinTlsVersion);
+      WRITE_DATA(Integer, MaxTlsVersion);
+
       WRITE_DATA(Bool, IsWorkspace);
       WRITE_DATA(Bool, IsWorkspace);
       WRITE_DATA(String, Link);
       WRITE_DATA(String, Link);
 
 
@@ -1049,9 +1060,14 @@ void __fastcall TSessionData::RecryptPasswords()
   TunnelPassword = TunnelPassword;
   TunnelPassword = TunnelPassword;
 }
 }
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
+bool __fastcall TSessionData::HasPassword()
+{
+  return !FPassword.IsEmpty();
+}
+//---------------------------------------------------------------------
 bool __fastcall TSessionData::HasAnyPassword()
 bool __fastcall TSessionData::HasAnyPassword()
 {
 {
-  return !FPassword.IsEmpty() || !FProxyPassword.IsEmpty() || !FTunnelPassword.IsEmpty();
+  return HasPassword() || !FProxyPassword.IsEmpty() || !FTunnelPassword.IsEmpty();
 }
 }
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 void __fastcall TSessionData::Modify()
 void __fastcall TSessionData::Modify()
@@ -1086,11 +1102,16 @@ void __fastcall TSessionData::SaveRecryptedPasswords(THierarchicalStorage * Stor
 {
 {
   if (Storage->OpenSubKey(InternalStorageKey, true))
   if (Storage->OpenSubKey(InternalStorageKey, true))
   {
   {
-    RecryptPasswords();
-
-    SavePasswords(Storage, false);
+    try
+    {
+      RecryptPasswords();
 
 
-    Storage->CloseSubKey();
+      SavePasswords(Storage, false);
+    }
+    __finally
+    {
+      Storage->CloseSubKey();
+    }
   }
   }
 }
 }
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
@@ -2306,6 +2327,16 @@ void __fastcall TSessionData::SetFtps(TFtps value)
 {
 {
   SET_SESSION_PROPERTY(Ftps);
   SET_SESSION_PROPERTY(Ftps);
 }
 }
+//---------------------------------------------------------------------------
+void __fastcall TSessionData::SetMinTlsVersion(TTlsVersion value)
+{
+  SET_SESSION_PROPERTY(MinTlsVersion);
+}
+//---------------------------------------------------------------------------
+void __fastcall TSessionData::SetMaxTlsVersion(TTlsVersion value)
+{
+  SET_SESSION_PROPERTY(MaxTlsVersion);
+}
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 void __fastcall TSessionData::SetFtpListAll(TAutoSwitch value)
 void __fastcall TSessionData::SetFtpListAll(TAutoSwitch value)
 {
 {
@@ -2517,7 +2548,7 @@ void __fastcall TStoredSessionList::DoSave(THierarchicalStorage * Storage,
 }
 }
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 void __fastcall TStoredSessionList::DoSave(THierarchicalStorage * Storage,
 void __fastcall TStoredSessionList::DoSave(THierarchicalStorage * Storage,
-  bool All, bool RecryptPasswordOnly)
+  bool All, bool RecryptPasswordOnly, TStrings * RecryptPasswordErrors)
 {
 {
   TSessionData * FactoryDefaults = new TSessionData(L"");
   TSessionData * FactoryDefaults = new TSessionData(L"");
   try
   try
@@ -2526,7 +2557,23 @@ void __fastcall TStoredSessionList::DoSave(THierarchicalStorage * Storage,
     for (int Index = 0; Index < Count+HiddenCount; Index++)
     for (int Index = 0; Index < Count+HiddenCount; Index++)
     {
     {
       TSessionData * SessionData = (TSessionData *)Items[Index];
       TSessionData * SessionData = (TSessionData *)Items[Index];
-      DoSave(Storage, SessionData, All, RecryptPasswordOnly, FactoryDefaults);
+      try
+      {
+        DoSave(Storage, SessionData, All, RecryptPasswordOnly, FactoryDefaults);
+      }
+      catch (Exception & E)
+      {
+        UnicodeString Message;
+        if (RecryptPasswordOnly && ALWAYS_TRUE(RecryptPasswordErrors != NULL) &&
+            ExceptionMessage(&E, Message))
+        {
+          RecryptPasswordErrors->Add(FORMAT("%s: %s", (SessionData->SessionName, Message)));
+        }
+        else
+        {
+          throw;
+        }
+      }
     }
     }
   }
   }
   __finally
   __finally
@@ -2537,10 +2584,11 @@ void __fastcall TStoredSessionList::DoSave(THierarchicalStorage * Storage,
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 void __fastcall TStoredSessionList::Save(THierarchicalStorage * Storage, bool All)
 void __fastcall TStoredSessionList::Save(THierarchicalStorage * Storage, bool All)
 {
 {
-  DoSave(Storage, All, false);
+  DoSave(Storage, All, false, NULL);
 }
 }
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
-void __fastcall TStoredSessionList::DoSave(bool All, bool Explicit, bool RecryptPasswordOnly)
+void __fastcall TStoredSessionList::DoSave(bool All, bool Explicit,
+  bool RecryptPasswordOnly, TStrings * RecryptPasswordErrors)
 {
 {
   THierarchicalStorage * Storage = Configuration->CreateScpStorage(true);
   THierarchicalStorage * Storage = Configuration->CreateScpStorage(true);
   try
   try
@@ -2549,7 +2597,7 @@ void __fastcall TStoredSessionList::DoSave(bool All, bool Explicit, bool Recrypt
     Storage->Explicit = Explicit;
     Storage->Explicit = Explicit;
     if (Storage->OpenSubKey(Configuration->StoredSessionsSubKey, true))
     if (Storage->OpenSubKey(Configuration->StoredSessionsSubKey, true))
     {
     {
-      DoSave(Storage, All, RecryptPasswordOnly);
+      DoSave(Storage, All, RecryptPasswordOnly, RecryptPasswordErrors);
     }
     }
   }
   }
   __finally
   __finally
@@ -2562,12 +2610,12 @@ void __fastcall TStoredSessionList::DoSave(bool All, bool Explicit, bool Recrypt
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 void __fastcall TStoredSessionList::Save(bool All, bool Explicit)
 void __fastcall TStoredSessionList::Save(bool All, bool Explicit)
 {
 {
-  DoSave(All, Explicit, false);
+  DoSave(All, Explicit, false, NULL);
 }
 }
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
-void __fastcall TStoredSessionList::RecryptPasswords()
+void __fastcall TStoredSessionList::RecryptPasswords(TStrings * RecryptPasswordErrors)
 {
 {
-  DoSave(true, true, true);
+  DoSave(true, true, true, RecryptPasswordErrors);
 }
 }
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 void __fastcall TStoredSessionList::Saved()
 void __fastcall TStoredSessionList::Saved()
@@ -2786,8 +2834,21 @@ void __fastcall TStoredSessionList::UpdateStaticUsage()
   Configuration->Usage->Set(L"StoredSessionsCountColor", Color);
   Configuration->Usage->Set(L"StoredSessionsCountColor", Color);
   Configuration->Usage->Set(L"StoredSessionsCountAdvanced", Advanced);
   Configuration->Usage->Set(L"StoredSessionsCountAdvanced", Advanced);
 
 
-  bool CustomDefaultStoredSession = !FDefaultSettings->IsSame(FactoryDefaults.get(), false);
+  // actually default might be true, see below for when the default is actually used
+  bool CustomDefaultStoredSession = false;
+  try
+  {
+    // this can throw, when the default session settings have password set
+    // (and no other basic property, like hostname/username),
+    // and master password is enabled as we are called before master password
+    // handler is set
+    CustomDefaultStoredSession = !FDefaultSettings->IsSame(FactoryDefaults.get(), false);
+  }
+  catch (...)
+  {
+  }
   Configuration->Usage->Set(L"UsingDefaultStoredSession", CustomDefaultStoredSession);
   Configuration->Usage->Set(L"UsingDefaultStoredSession", CustomDefaultStoredSession);
+
   Configuration->Usage->Set(L"UsingStoredSessionsFolders", Folders);
   Configuration->Usage->Set(L"UsingStoredSessionsFolders", Folders);
   Configuration->Usage->Set(L"UsingWorkspaces", Workspaces);
   Configuration->Usage->Set(L"UsingWorkspaces", Workspaces);
 }
 }

+ 14 - 3
source/core/SessionData.h

@@ -30,6 +30,8 @@ enum TSftpBug { sbSymlink, sbSignedTS };
 enum TPingType { ptOff, ptNullPacket, ptDummyCommand };
 enum TPingType { ptOff, ptNullPacket, ptDummyCommand };
 enum TAddressFamily { afAuto, afIPv4, afIPv6 };
 enum TAddressFamily { afAuto, afIPv4, afIPv6 };
 enum TFtps { ftpsNone, ftpsImplicit, ftpsExplicitSsl, ftpsExplicitTls };
 enum TFtps { ftpsNone, ftpsImplicit, ftpsExplicitSsl, ftpsExplicitTls };
+// has to match SSL_VERSION_XXX constants in AsyncSslSocketLayer.h
+enum TTlsVersion { ssl2 = 2, ssl3 = 3, tls10 = 10, tls11 = 11, tls12 = 12 };
 enum TSessionSource { ssNone, ssStored, ssStoredModified };
 enum TSessionSource { ssNone, ssStored, ssStoredModified };
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 extern const wchar_t CipherNames[CIPHER_COUNT][10];
 extern const wchar_t CipherNames[CIPHER_COUNT][10];
@@ -156,6 +158,8 @@ private:
   int FFtpPingInterval;
   int FFtpPingInterval;
   TPingType FFtpPingType;
   TPingType FFtpPingType;
   TFtps FFtps;
   TFtps FFtps;
+  TTlsVersion FMinTlsVersion;
+  TTlsVersion FMaxTlsVersion;
   TAutoSwitch FNotUtf;
   TAutoSwitch FNotUtf;
   bool FIsWorkspace;
   bool FIsWorkspace;
   UnicodeString FLink;
   UnicodeString FLink;
@@ -297,6 +301,8 @@ private:
   void __fastcall SetFtpPingInterval(int value);
   void __fastcall SetFtpPingInterval(int value);
   void __fastcall SetFtpPingType(TPingType value);
   void __fastcall SetFtpPingType(TPingType value);
   void __fastcall SetFtps(TFtps value);
   void __fastcall SetFtps(TFtps value);
+  void __fastcall SetMinTlsVersion(TTlsVersion value);
+  void __fastcall SetMaxTlsVersion(TTlsVersion value);
   void __fastcall SetNotUtf(TAutoSwitch value);
   void __fastcall SetNotUtf(TAutoSwitch value);
   void __fastcall SetIsWorkspace(bool value);
   void __fastcall SetIsWorkspace(bool value);
   void __fastcall SetLink(UnicodeString value);
   void __fastcall SetLink(UnicodeString value);
@@ -327,6 +333,7 @@ public:
     const TSessionData * Default = NULL);
     const TSessionData * Default = NULL);
   void __fastcall SaveRecryptedPasswords(THierarchicalStorage * Storage);
   void __fastcall SaveRecryptedPasswords(THierarchicalStorage * Storage);
   void __fastcall RecryptPasswords();
   void __fastcall RecryptPasswords();
+  bool __fastcall HasPassword();
   bool __fastcall HasAnyPassword();
   bool __fastcall HasAnyPassword();
   void __fastcall Remove();
   void __fastcall Remove();
   virtual void __fastcall Assign(TPersistent * Source);
   virtual void __fastcall Assign(TPersistent * Source);
@@ -462,6 +469,8 @@ public:
   __property TDateTime FtpPingIntervalDT  = { read=GetFtpPingIntervalDT };
   __property TDateTime FtpPingIntervalDT  = { read=GetFtpPingIntervalDT };
   __property TPingType FtpPingType = { read = FFtpPingType, write = SetFtpPingType };
   __property TPingType FtpPingType = { read = FFtpPingType, write = SetFtpPingType };
   __property TFtps Ftps = { read = FFtps, write = SetFtps };
   __property TFtps Ftps = { read = FFtps, write = SetFtps };
+  __property TTlsVersion MinTlsVersion = { read = FMinTlsVersion, write = SetMinTlsVersion };
+  __property TTlsVersion MaxTlsVersion = { read = FMaxTlsVersion, write = SetMaxTlsVersion };
   __property TAutoSwitch NotUtf = { read = FNotUtf, write = SetNotUtf };
   __property TAutoSwitch NotUtf = { read = FNotUtf, write = SetNotUtf };
   __property bool IsWorkspace = { read = FIsWorkspace, write = SetIsWorkspace };
   __property bool IsWorkspace = { read = FIsWorkspace, write = SetIsWorkspace };
   __property UnicodeString Link = { read = FLink, write = SetLink };
   __property UnicodeString Link = { read = FLink, write = SetLink };
@@ -488,7 +497,7 @@ public:
   void __fastcall Save(THierarchicalStorage * Storage, bool All = false);
   void __fastcall Save(THierarchicalStorage * Storage, bool All = false);
   void __fastcall SelectAll(bool Select);
   void __fastcall SelectAll(bool Select);
   void __fastcall Import(TStoredSessionList * From, bool OnlySelected);
   void __fastcall Import(TStoredSessionList * From, bool OnlySelected);
-  void __fastcall RecryptPasswords();
+  void __fastcall RecryptPasswords(TStrings * RecryptPasswordErrors);
   TSessionData * __fastcall AtSession(int Index)
   TSessionData * __fastcall AtSession(int Index)
     { return (TSessionData*)AtObject(Index); }
     { return (TSessionData*)AtObject(Index); }
   void __fastcall SelectSessionsToImport(TStoredSessionList * Dest, bool SSHOnly);
   void __fastcall SelectSessionsToImport(TStoredSessionList * Dest, bool SSHOnly);
@@ -519,8 +528,10 @@ private:
   TSessionData * FDefaultSettings;
   TSessionData * FDefaultSettings;
   bool FReadOnly;
   bool FReadOnly;
   void __fastcall SetDefaultSettings(TSessionData * value);
   void __fastcall SetDefaultSettings(TSessionData * value);
-  void __fastcall DoSave(THierarchicalStorage * Storage, bool All, bool RecryptPasswordOnly);
-  void __fastcall DoSave(bool All, bool Explicit, bool RecryptPasswordOnly);
+  void __fastcall DoSave(THierarchicalStorage * Storage, bool All,
+    bool RecryptPasswordOnly, TStrings * RecryptPasswordErrors);
+  void __fastcall DoSave(bool All, bool Explicit, bool RecryptPasswordOnly,
+    TStrings * RecryptPasswordErrors);
   void __fastcall DoSave(THierarchicalStorage * Storage,
   void __fastcall DoSave(THierarchicalStorage * Storage,
     TSessionData * Data, bool All, bool RecryptPasswordOnly,
     TSessionData * Data, bool All, bool RecryptPasswordOnly,
     TSessionData * FactoryDefaults);
     TSessionData * FactoryDefaults);

+ 21 - 1
source/core/SessionInfo.cpp

@@ -867,6 +867,25 @@ void __fastcall TSessionLog::AddStartupInfo(bool System)
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+UnicodeString __fastcall TSessionLog::GetTlsVersionName(TTlsVersion TlsVersion)
+{
+  switch (TlsVersion)
+  {
+    default:
+      FAIL;
+    case ssl2:
+      return "SSLv2";
+    case ssl3:
+      return "SSLv3";
+    case tls10:
+      return "TLSv1.0";
+    case tls11:
+      return "TLSv1.1";
+    case tls12:
+      return "TLSv1.2";
+  }
+}
+//---------------------------------------------------------------------------
 void __fastcall TSessionLog::DoAddStartupInfo(TSessionData * Data)
 void __fastcall TSessionLog::DoAddStartupInfo(TSessionData * Data)
 {
 {
   TGuard Guard(FCriticalSection);
   TGuard Guard(FCriticalSection);
@@ -1006,7 +1025,7 @@ void __fastcall TSessionLog::DoAddStartupInfo(TSessionData * Data)
         switch (Data->Ftps)
         switch (Data->Ftps)
         {
         {
           case ftpsImplicit:
           case ftpsImplicit:
-            Ftps = L"Implicit SSL/TLS";
+            Ftps = L"Implicit TLS/SSL";
             break;
             break;
 
 
           case ftpsExplicitSsl:
           case ftpsExplicitSsl:
@@ -1030,6 +1049,7 @@ void __fastcall TSessionLog::DoAddStartupInfo(TSessionData * Data)
         if (Data->Ftps != ftpsNone)
         if (Data->Ftps != ftpsNone)
         {
         {
           ADF(L"Session reuse: %s", (BooleanToEngStr(Data->SslSessionReuse)));
           ADF(L"Session reuse: %s", (BooleanToEngStr(Data->SslSessionReuse)));
+          ADF(L"TLS/SSL versions: %s-%s", (GetTlsVersionName(Data->MinTlsVersion), GetTlsVersionName(Data->MaxTlsVersion)));
         }
         }
       }
       }
       ADF(L"Local directory: %s, Remote directory: %s, Update: %s, Cache: %s",
       ADF(L"Local directory: %s, Remote directory: %s, Update: %s, Cache: %s",

+ 1 - 0
source/core/SessionInfo.h

@@ -258,6 +258,7 @@ private:
   void __fastcall DoAddToSelf(TLogLineType aType, const UnicodeString & aLine);
   void __fastcall DoAddToSelf(TLogLineType aType, const UnicodeString & aLine);
   void __fastcall AddStartupInfo(bool System);
   void __fastcall AddStartupInfo(bool System);
   void __fastcall DoAddStartupInfo(TSessionData * Data);
   void __fastcall DoAddStartupInfo(TSessionData * Data);
+  UnicodeString __fastcall GetTlsVersionName(TTlsVersion TlsVersion);
 };
 };
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 class TActionLog
 class TActionLog

+ 1 - 0
source/core/Terminal.cpp

@@ -4144,6 +4144,7 @@ UnicodeString __fastcall TTerminal::SynchronizeParamsStr(int Params)
   AddFlagName(ParamsStr, Params, spUseCache, L"UseCache");
   AddFlagName(ParamsStr, Params, spUseCache, L"UseCache");
   AddFlagName(ParamsStr, Params, spDelayProgress, L"DelayProgress");
   AddFlagName(ParamsStr, Params, spDelayProgress, L"DelayProgress");
   AddFlagName(ParamsStr, Params, spPreviewChanges, L"*PreviewChanges"); // GUI only
   AddFlagName(ParamsStr, Params, spPreviewChanges, L"*PreviewChanges"); // GUI only
+  AddFlagName(ParamsStr, Params, spSubDirs, L"SubDirs");
   AddFlagName(ParamsStr, Params, spTimestamp, L"Timestamp");
   AddFlagName(ParamsStr, Params, spTimestamp, L"Timestamp");
   AddFlagName(ParamsStr, Params, spNotByTime, L"NotByTime");
   AddFlagName(ParamsStr, Params, spNotByTime, L"NotByTime");
   AddFlagName(ParamsStr, Params, spBySize, L"BySize");
   AddFlagName(ParamsStr, Params, spBySize, L"BySize");

+ 1 - 3
source/core/WebDAVFileSystem.cpp

@@ -11545,7 +11545,7 @@ neon_open(
   {
   {
     if (ne_has_support(NE_FEATURE_SSL) == 0)
     if (ne_has_support(NE_FEATURE_SSL) == 0)
       return error_create(WEBDAV_ERR_DAV_SOCK_INIT, NULL,
       return error_create(WEBDAV_ERR_DAV_SOCK_INIT, NULL,
-        "SSL is not supported");
+        "TLS is not supported");
   }
   }
 
 
   ne_session * sess = ne_session_create(uri->scheme, uri->host, uri->port);
   ne_session * sess = ne_session_create(uri->scheme, uri->host, uri->port);
@@ -12195,8 +12195,6 @@ void __fastcall TWebDAVFileSystem::Open()
   TSessionData * Data = FTerminal->SessionData;
   TSessionData * Data = FTerminal->SessionData;
 
 
   FSessionInfo.LoginTime = Now();
   FSessionInfo.LoginTime = Now();
-  FSessionInfo.ProtocolBaseName = CONST_WEBDAV_PROTOCOL_BASE_NAME;
-  FSessionInfo.ProtocolName = FSessionInfo.ProtocolBaseName;
 
 
   bool Ssl = (FTerminal->SessionData->Ftps != ftpsNone);
   bool Ssl = (FTerminal->SessionData->Ftps != ftpsNone);
   if (Ssl)
   if (Ssl)

+ 30 - 0
source/filezilla/AsyncSocketEx.cpp

@@ -1783,6 +1783,36 @@ void CAsyncSocketEx::SetState(int nState)
 	m_nState = nState;
 	m_nState = nState;
 }
 }
 
 
+const TCHAR * CAsyncSocketEx::GetStateDesc(int nState)
+{
+  switch (nState)
+  {
+    case notsock:
+      return _T("none");
+    case unconnected:
+      return _T("unconnected");
+    case connecting:
+      return _T("connecting");
+    case listening:
+      return _T("listening");
+    case connected:
+      return _T("connected");
+    case closed:
+      return _T("closed");
+    case aborted:
+      return _T("aborted");
+    case attached:
+      return _T("attached");
+    default:
+      return _T("unknown");
+  }
+}
+
+bool CAsyncSocketEx::LogStateChange(int nState1, int nState2)
+{
+    return (nState2 != notsock) || (nState1 != unconnected);
+}
+
 #endif //NOSOCKETSTATES
 #endif //NOSOCKETSTATES
 
 
 int CAsyncSocketEx::GetFamily() const
 int CAsyncSocketEx::GetFamily() const

+ 2 - 0
source/filezilla/AsyncSocketEx.h

@@ -296,6 +296,8 @@ protected:
 
 
 	int GetState() const;
 	int GetState() const;
 	void SetState(int nState);
 	void SetState(int nState);
+	static const TCHAR * GetStateDesc(int nState);
+	static bool LogStateChange(int nState1, int nState2);
 
 
 	int m_nState;
 	int m_nState;
 #endif //NOSOCKETSTATES
 #endif //NOSOCKETSTATES

+ 35 - 13
source/filezilla/AsyncSslSocketLayer.cpp

@@ -1025,6 +1025,7 @@ BOOL CAsyncSslSocketLayer::Connect(LPCTSTR lpszHostAddress, UINT nHostPort)
 
 
 int CAsyncSslSocketLayer::InitSSLConnection(bool clientMode,
 int CAsyncSslSocketLayer::InitSSLConnection(bool clientMode,
 	CAsyncSslSocketLayer* main, bool sessionreuse,
 	CAsyncSslSocketLayer* main, bool sessionreuse,
+	int minTlsVersion, int maxTlsVersion,
 	void* pSslContext /*=0*/)
 	void* pSslContext /*=0*/)
 {
 {
 	if (m_bUseSSL)
 	if (m_bUseSSL)
@@ -1104,7 +1105,14 @@ int CAsyncSslSocketLayer::InitSSLConnection(bool clientMode,
 	}
 	}
 
 
 	long options = pSSL_ctrl(m_ssl, SSL_CTRL_OPTIONS, 0, NULL);
 	long options = pSSL_ctrl(m_ssl, SSL_CTRL_OPTIONS, 0, NULL);
-	options |= SSL_OP_ALL;
+	#define MASK_TLS_VERSION(VERSION, FLAG) ((minTlsVersion > VERSION) || (maxTlsVersion < VERSION) ? FLAG : 0)
+	options |=
+		SSL_OP_ALL |
+		MASK_TLS_VERSION(SSL_VERSION_SSL2, SSL_OP_NO_SSLv2) |
+		MASK_TLS_VERSION(SSL_VERSION_SSL3, SSL_OP_NO_SSLv3) |
+		MASK_TLS_VERSION(SSL_VERSION_TLS10, SSL_OP_NO_TLSv1) |
+		MASK_TLS_VERSION(SSL_VERSION_TLS11, SSL_OP_NO_TLSv1_1) |
+		MASK_TLS_VERSION(SSL_VERSION_TLS12, SSL_OP_NO_TLSv1_2);
 	pSSL_ctrl(m_ssl, SSL_CTRL_OPTIONS, options, NULL);
 	pSSL_ctrl(m_ssl, SSL_CTRL_OPTIONS, options, NULL);
 
 
 	//Init SSL connection
 	//Init SSL connection
@@ -1123,11 +1131,11 @@ int CAsyncSslSocketLayer::InitSSLConnection(bool clientMode,
 				LogSocketMessage(FZ_LOG_INFO, _T("SSL_set_session failed"));
 				LogSocketMessage(FZ_LOG_INFO, _T("SSL_set_session failed"));
 				return SSL_FAILURE_INITSSL;
 				return SSL_FAILURE_INITSSL;
 			}
 			}
-			LogSocketMessage(FZ_LOG_INFO, _T("Trying reuse main SSL session ID"));
+			LogSocketMessage(FZ_LOG_INFO, _T("Trying reuse main TLS session ID"));
 		}
 		}
 		else
 		else
 		{
 		{
-			LogSocketMessage(FZ_LOG_INFO, _T("Main SSL session ID was not reused previously, not trying again"));
+			LogSocketMessage(FZ_LOG_INFO, _T("Main TLS session ID was not reused previously, not trying again"));
 			pSSL_set_session(m_ssl, NULL);
 			pSSL_set_session(m_ssl, NULL);
 		}
 		}
 	}
 	}
@@ -1398,7 +1406,7 @@ void CAsyncSslSocketLayer::apps_ssl_info_callback(const SSL *s, int where, int r
 	if (!cur)
 	if (!cur)
 	{
 	{
 		m_sCriticalSection.Unlock();
 		m_sCriticalSection.Unlock();
-		MessageBox(0, _T("Can't lookup SSL session!"), _T("Critical error"), MB_ICONEXCLAMATION);
+		MessageBox(0, _T("Can't lookup TLS session!"), _T("Critical error"), MB_ICONEXCLAMATION);
 		return;
 		return;
 	}
 	}
 	else
 	else
@@ -1416,7 +1424,7 @@ void CAsyncSslSocketLayer::apps_ssl_info_callback(const SSL *s, int where, int r
 
 
 	if (w & SSL_ST_CONNECT)
 	if (w & SSL_ST_CONNECT)
 	{
 	{
-		str = "SSL_connect";
+		str = "TLS connect";
 		if (pLayer->m_sessionreuse)
 		if (pLayer->m_sessionreuse)
 		{
 		{
 			SSL_SESSION * sessionid = SSL_get1_session(pLayer->m_ssl);
 			SSL_SESSION * sessionid = SSL_get1_session(pLayer->m_ssl);
@@ -1432,7 +1440,7 @@ void CAsyncSslSocketLayer::apps_ssl_info_callback(const SSL *s, int where, int r
 					{
 					{
 						if ((pLayer->m_Main != NULL) && (pLayer->m_Main->m_sessionid != NULL))
 						if ((pLayer->m_Main != NULL) && (pLayer->m_Main->m_sessionid != NULL))
 						{
 						{
-							pLayer->LogSocketMessage(FZ_LOG_INFO, _T("Main SSL session ID not reused, will not try again"));
+							pLayer->LogSocketMessage(FZ_LOG_INFO, _T("Main TLS session ID not reused, will not try again"));
 							SSL_SESSION_free(pLayer->m_Main->m_sessionid);
 							SSL_SESSION_free(pLayer->m_Main->m_sessionid);
 							pLayer->m_Main->m_sessionid = NULL;
 							pLayer->m_Main->m_sessionid = NULL;
 						}
 						}
@@ -1453,9 +1461,9 @@ void CAsyncSslSocketLayer::apps_ssl_info_callback(const SSL *s, int where, int r
 		}
 		}
 	}
 	}
 	else if (w & SSL_ST_ACCEPT)
 	else if (w & SSL_ST_ACCEPT)
-		str = "SSL_accept";
+		str = "TLS accept";
 	else
 	else
-		str = "undefined";
+		str = "Undefined";
 
 
 	if (where & SSL_CB_LOOP)
 	if (where & SSL_CB_LOOP)
 	{
 	{
@@ -1919,6 +1927,16 @@ BOOL CAsyncSslSocketLayer::GetPeerCertificateData(t_SslCertData &SslCertData)
 	return TRUE;
 	return TRUE;
 }
 }
 
 
+std::string CAsyncSslSocketLayer::GetTlsVersionStr()
+{
+	return m_TlsVersionStr;
+}
+
+std::string CAsyncSslSocketLayer::GetCipherName()
+{
+	return m_CipherName;
+}
+
 void CAsyncSslSocketLayer::SetNotifyReply(int nID, int nCode, int result)
 void CAsyncSslSocketLayer::SetNotifyReply(int nID, int nCode, int result)
 {
 {
 	if (!m_bBlocking)
 	if (!m_bBlocking)
@@ -1986,12 +2004,16 @@ void CAsyncSslSocketLayer::PrintSessionInfo()
 	}
 	}
 
 
 	char *buffer = new char[4096];
 	char *buffer = new char[4096];
-	sprintf(buffer, "Using %s, cipher %s: %s, %s",
-			pSSL_get_version(m_ssl),
+	m_TlsVersionStr = pSSL_get_version(m_ssl);
+	sprintf(buffer, "%s: %s, %s",
 			pSSL_CIPHER_get_version(ciph),
 			pSSL_CIPHER_get_version(ciph),
 			pSSL_CIPHER_get_name(ciph),
 			pSSL_CIPHER_get_name(ciph),
 			enc);
 			enc);
-	DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_VERBOSE_INFO, 0, buffer);
+	m_CipherName = buffer;
+	sprintf(buffer, "Using %s, cipher %s",
+			m_TlsVersionStr.c_str(),
+			m_CipherName.c_str());
+	DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_VERBOSE_WARNING, 0, buffer);
 }
 }
 
 
 void CAsyncSslSocketLayer::OnConnect(int nErrorCode)
 void CAsyncSslSocketLayer::OnConnect(int nErrorCode)
@@ -2030,7 +2052,7 @@ int CAsyncSslSocketLayer::verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
 	if (!cur)
 	if (!cur)
 	{
 	{
 		m_sCriticalSection.Unlock();
 		m_sCriticalSection.Unlock();
-		MessageBox(0, _T("Can't lookup SSL session!"), _T("Critical error"), MB_ICONEXCLAMATION);
+		MessageBox(0, _T("Can't lookup TLS session!"), _T("Critical error"), MB_ICONEXCLAMATION);
 		return 1;
 		return 1;
 	}
 	}
 	else
 	else
@@ -2106,7 +2128,7 @@ bool CAsyncSslSocketLayer::CreateSslCertificate(LPCTSTR filename, int bits, unsi
 	CAsyncSslSocketLayer layer;
 	CAsyncSslSocketLayer layer;
 	if (layer.InitSSL())
 	if (layer.InitSSL())
 	{
 	{
-		err = _T("Failed to initialize SSL library");
+		err = _T("Failed to initialize TLS library");
 		return false;
 		return false;
 	}
 	}
 
 

+ 12 - 1
source/filezilla/AsyncSslSocketLayer.h

@@ -144,11 +144,13 @@ public:
 
 
 	void SetNotifyReply(int nID, int nCode, int result);
 	void SetNotifyReply(int nID, int nCode, int result);
 	BOOL GetPeerCertificateData(t_SslCertData &SslCertData);
 	BOOL GetPeerCertificateData(t_SslCertData &SslCertData);
+	std::string GetTlsVersionStr();
+	std::string GetCipherName();
 
 
 	bool IsUsingSSL();
 	bool IsUsingSSL();
 	int InitSSLConnection(bool clientMode, 
 	int InitSSLConnection(bool clientMode, 
 		CAsyncSslSocketLayer* main,
 		CAsyncSslSocketLayer* main,
-		bool sessionreuse,
+		bool sessionreuse, int minTlsVersion, int maxTlsVersion,
 		void* pContext = 0);
 		void* pContext = 0);
 
 
 	static bool CreateSslCertificate(LPCTSTR filename, int bits, unsigned char* country, unsigned char* state,
 	static bool CreateSslCertificate(LPCTSTR filename, int bits, unsigned char* country, unsigned char* state,
@@ -248,6 +250,9 @@ private:
 	bool m_onCloseCalled;
 	bool m_onCloseCalled;
 
 
 	char* m_pKeyPassword;
 	char* m_pKeyPassword;
+
+	std::string m_TlsVersionStr;
+	std::string m_CipherName;
 };
 };
 
 
 #define SSL_INFO 0
 #define SSL_INFO 0
@@ -268,4 +273,10 @@ private:
 #define SSL_FAILURE_VERIFYCERT 8
 #define SSL_FAILURE_VERIFYCERT 8
 #define SSL_FAILURE_CERTREJECTED 0x10
 #define SSL_FAILURE_CERTREJECTED 0x10
 
 
+#define SSL_VERSION_SSL2 2
+#define SSL_VERSION_SSL3 3
+#define SSL_VERSION_TLS10 10
+#define SSL_VERSION_TLS11 11
+#define SSL_VERSION_TLS12 12
+
 #endif // ASYNCSSLSOCKETLEAYER_INCLUDED
 #endif // ASYNCSSLSOCKETLEAYER_INCLUDED

+ 20 - 15
source/filezilla/ControlSocket.cpp

@@ -211,14 +211,19 @@ int CControlSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
 	{
 	{
 		if (iter->nType == LAYERCALLBACK_STATECHANGE)
 		if (iter->nType == LAYERCALLBACK_STATECHANGE)
 		{
 		{
-			if (iter->pLayer == m_pProxyLayer)
-				LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("m_pProxyLayer changed state from %d to %d"), iter->nParam2, iter->nParam1);
+		    if (CAsyncSocketEx::LogStateChange(iter->nParam1, iter->nParam2))
+		    {
+			    const TCHAR * state2Desc = CAsyncSocketEx::GetStateDesc(iter->nParam2);
+			    const TCHAR * state1Desc = CAsyncSocketEx::GetStateDesc(iter->nParam1);
+				if (iter->pLayer == m_pProxyLayer)
+					LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("Proxy layer changed state from %s to %s"), state2Desc, state1Desc);
 #ifndef MPEXT_NO_GSS
 #ifndef MPEXT_NO_GSS
-			else if (iter->pLayer == m_pGssLayer)
-				LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("m_pGssLayer changed state from %d to %d"), iter->nParam2, iter->nParam1);
+				else if (iter->pLayer == m_pGssLayer)
+					LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("m_pGssLayer changed state from %s to %s"), state2Desc, state1Desc);
 #endif
 #endif
-			else
-				LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("Layer @ %d changed state from %d to %d"), iter->pLayer, iter->nParam2, iter->nParam1);
+				else
+					LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("Layer @ %d changed state from %s to %s"), iter->pLayer, state2Desc, state1Desc);
+			}
 		}
 		}
 		else if (iter->nType == LAYERCALLBACK_LAYERSPECIFIC)
 		else if (iter->nType == LAYERCALLBACK_LAYERSPECIFIC)
 		{
 		{
@@ -227,24 +232,24 @@ int CControlSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
 				switch (iter->nParam1)
 				switch (iter->nParam1)
 				{
 				{
 				case PROXYERROR_NOCONN:
 				case PROXYERROR_NOCONN:
-					ShowStatus(IDS_ERRORMSG_PROXY_NOCONN, 1);
+					ShowStatus(IDS_ERRORMSG_PROXY_NOCONN, FZ_LOG_ERROR);
 					break;
 					break;
 				case PROXYERROR_REQUESTFAILED:
 				case PROXYERROR_REQUESTFAILED:
-					ShowStatus(IDS_ERRORMSG_PROXY_REQUESTFAILED, 1);
+					ShowStatus(IDS_ERRORMSG_PROXY_REQUESTFAILED, FZ_LOG_ERROR);
 					if (iter->str)
 					if (iter->str)
-						ShowStatus(A2T(iter->str), 1);
+						ShowStatus(A2T(iter->str), FZ_LOG_ERROR);
 					break;
 					break;
 				case PROXYERROR_AUTHTYPEUNKNOWN:
 				case PROXYERROR_AUTHTYPEUNKNOWN:
-					ShowStatus(IDS_ERRORMSG_PROXY_AUTHTYPEUNKNOWN, 1);
+					ShowStatus(IDS_ERRORMSG_PROXY_AUTHTYPEUNKNOWN, FZ_LOG_ERROR);
 					break;
 					break;
 				case PROXYERROR_AUTHFAILED:
 				case PROXYERROR_AUTHFAILED:
-					ShowStatus(IDS_ERRORMSG_PROXY_AUTHFAILED, 1);
+					ShowStatus(IDS_ERRORMSG_PROXY_AUTHFAILED, FZ_LOG_ERROR);
 					break;
 					break;
 				case PROXYERROR_AUTHNOLOGON:
 				case PROXYERROR_AUTHNOLOGON:
-					ShowStatus(IDS_ERRORMSG_PROXY_AUTHNOLOGON, 1);
+					ShowStatus(IDS_ERRORMSG_PROXY_AUTHNOLOGON, FZ_LOG_ERROR);
 					break;
 					break;
 				case PROXYERROR_CANTRESOLVEHOST:
 				case PROXYERROR_CANTRESOLVEHOST:
-					ShowStatus(IDS_ERRORMSG_PROXY_CANTRESOLVEHOST, 1);
+					ShowStatus(IDS_ERRORMSG_PROXY_CANTRESOLVEHOST, FZ_LOG_ERROR);
 					break;
 					break;
 				default:
 				default:
 					LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Unknown proxy error") );
 					LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Unknown proxy error") );
@@ -262,10 +267,10 @@ int CControlSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
 					LogMessageRaw(FZ_LOG_APIERROR, A2CT(iter->str));
 					LogMessageRaw(FZ_LOG_APIERROR, A2CT(iter->str));
 					break;
 					break;
 				case GSS_COMMAND:
 				case GSS_COMMAND:
-					ShowStatus(A2CT(iter->str), 2);
+					ShowStatus(A2CT(iter->str), FZ_LOG_COMMAND);
 					break;
 					break;
 				case GSS_REPLY:
 				case GSS_REPLY:
-					ShowStatus(A2CT(iter->str), 3);
+					ShowStatus(A2CT(iter->str), FZ_LOG_REPLY);
 					break;
 					break;
 				}
 				}
 			}
 			}

+ 3 - 1
source/filezilla/ControlSocket.h

@@ -114,7 +114,9 @@ public:
 	void ShowStatus(CString status,int type) const;
 	void ShowStatus(CString status,int type) const;
 
 
 #ifdef MPEXT
 #ifdef MPEXT
-	virtual bool __fastcall UsingMlsd() = 0;
+	virtual bool UsingMlsd() = 0;
+	virtual std::string GetTlsVersionStr() = 0;
+	virtual std::string GetCipherName() = 0;
 #endif
 #endif
 
 
 	virtual int OnLayerCallback(std::list<t_callbackMsg>& callbacks);
 	virtual int OnLayerCallback(std::list<t_callbackMsg>& callbacks);

+ 21 - 1
source/filezilla/FileZillaApi.cpp

@@ -555,7 +555,7 @@ int CFileZillaApi::GetCurrentPath(CServerPath & path)
 	return (m_pMainThread->GetCurrentPath(path) ? FZ_REPLY_OK : FZ_REPLY_NOTCONNECTED);
 	return (m_pMainThread->GetCurrentPath(path) ? FZ_REPLY_OK : FZ_REPLY_NOTCONNECTED);
 }
 }
 
 
-bool __fastcall CFileZillaApi::UsingMlsd()
+bool CFileZillaApi::UsingMlsd()
 {
 {
 	//Check if call allowed
 	//Check if call allowed
 	if (!m_bInitialized)
 	if (!m_bInitialized)
@@ -564,6 +564,26 @@ bool __fastcall CFileZillaApi::UsingMlsd()
 		return false;
 		return false;
 	return m_pMainThread->UsingMlsd();
 	return m_pMainThread->UsingMlsd();
 }
 }
+
+std::string CFileZillaApi::GetTlsVersionStr()
+{
+	//Check if call allowed
+	if (!m_bInitialized)
+		return std::string();
+	if (IsConnected()==FZ_REPLY_NOTCONNECTED)
+		return std::string();
+	return m_pMainThread->GetTlsVersionStr();
+}
+
+std::string CFileZillaApi::GetCipherName()
+{
+	//Check if call allowed
+	if (!m_bInitialized)
+		return std::string();
+	if (IsConnected()==FZ_REPLY_NOTCONNECTED)
+		return std::string();
+	return m_pMainThread->GetCipherName();
+}
 #endif
 #endif
 
 
 int CFileZillaApi::CustomCommand(CString CustomCommand)
 int CFileZillaApi::CustomCommand(CString CustomCommand)

+ 3 - 1
source/filezilla/FileZillaApi.h

@@ -350,7 +350,9 @@ public:
 #ifdef MPEXT
 #ifdef MPEXT
 	int SetCurrentPath(CServerPath path);
 	int SetCurrentPath(CServerPath path);
 	int GetCurrentPath(CServerPath & path);
 	int GetCurrentPath(CServerPath & path);
-    bool __fastcall UsingMlsd();
+	bool UsingMlsd();
+	std::string GetTlsVersionStr();
+	std::string GetCipherName();
 #endif
 #endif
 
 
 #ifndef MPEXT_NO_CACHE
 #ifndef MPEXT_NO_CACHE

+ 11 - 0
source/filezilla/FileZillaIntf.cpp

@@ -523,3 +523,14 @@ bool __fastcall TFileZillaIntf::UsingMlsd()
 {
 {
   return FFileZillaApi->UsingMlsd();
   return FFileZillaApi->UsingMlsd();
 }
 }
+//---------------------------------------------------------------------------
+std::string __fastcall TFileZillaIntf::GetTlsVersionStr()
+{
+  return FFileZillaApi->GetTlsVersionStr();
+}
+//---------------------------------------------------------------------------
+std::string __fastcall TFileZillaIntf::GetCipherName()
+{
+  return FFileZillaApi->GetCipherName();
+}
+

+ 3 - 0
source/filezilla/FileZillaIntf.h

@@ -157,7 +157,10 @@ public:
 
 
   bool __fastcall SetCurrentPath(const wchar_t * Path);
   bool __fastcall SetCurrentPath(const wchar_t * Path);
   bool __fastcall GetCurrentPath(wchar_t * Path, size_t MaxLen);
   bool __fastcall GetCurrentPath(wchar_t * Path, size_t MaxLen);
+
   bool __fastcall UsingMlsd();
   bool __fastcall UsingMlsd();
+  std::string __fastcall GetTlsVersionStr();
+  std::string __fastcall GetCipherName();
 
 
   bool __fastcall Cancel();
   bool __fastcall Cancel();
 
 

+ 2 - 0
source/filezilla/FileZillaOpt.h

@@ -162,5 +162,7 @@
 #define OPTION_MPEXT_PRESERVEUPLOADFILETIME 1001
 #define OPTION_MPEXT_PRESERVEUPLOADFILETIME 1001
 #define OPTION_MPEXT_SSLSESSIONREUSE 1002
 #define OPTION_MPEXT_SSLSESSIONREUSE 1002
 #define OPTION_MPEXT_SNDBUF 1003
 #define OPTION_MPEXT_SNDBUF 1003
+#define OPTION_MPEXT_MIN_TLS_VERSION 1004
+#define OPTION_MPEXT_MAX_TLS_VERSION 1005
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 #endif // FileZillaOptH
 #endif // FileZillaOptH

+ 135 - 102
source/filezilla/FtpControlSocket.cpp

@@ -263,7 +263,7 @@ bool CFtpControlSocket::InitConnect()
 	// Some sanity checks
 	// Some sanity checks
 	if (m_pOwner->IsConnected())
 	if (m_pOwner->IsConnected())
 	{
 	{
-		ShowStatus(_T("Internal error: Connect called while still connected"), 1);
+		ShowStatus(_T("Internal error: Connect called while still connected"), FZ_LOG_ERROR);
 		if (!m_Operation.nOpMode)
 		if (!m_Operation.nOpMode)
 			m_Operation.nOpMode = CSMODE_CONNECT;
 			m_Operation.nOpMode = CSMODE_CONNECT;
 		DoClose(FZ_REPLY_CRITICALERROR);
 		DoClose(FZ_REPLY_CRITICALERROR);
@@ -273,14 +273,14 @@ bool CFtpControlSocket::InitConnect()
 #ifndef MPEXT_NO_SSL
 #ifndef MPEXT_NO_SSL
 	if (m_pSslLayer)
 	if (m_pSslLayer)
 	{
 	{
-		ShowStatus(_T("Internal error: m_pSslLayer not zero in Connect"), 1);
+		ShowStatus(_T("Internal error: m_pSslLayer not zero in Connect"), FZ_LOG_ERROR);
 		DoClose(FZ_REPLY_CRITICALERROR);
 		DoClose(FZ_REPLY_CRITICALERROR);
 		return false;
 		return false;
 	}
 	}
 #endif
 #endif
 	if (m_pProxyLayer)
 	if (m_pProxyLayer)
 	{
 	{
-		ShowStatus(_T("Internal error: m_pProxyLayer not zero in Connect"), 1);
+		ShowStatus(_T("Internal error: m_pProxyLayer not zero in Connect"), FZ_LOG_ERROR);
 		DoClose(FZ_REPLY_CRITICALERROR);
 		DoClose(FZ_REPLY_CRITICALERROR);
 		return false;
 		return false;
 	}
 	}
@@ -374,7 +374,7 @@ bool CFtpControlSocket::InitConnect()
 		AddLayer(m_pGssLayer);
 		AddLayer(m_pGssLayer);
 		if (!m_pGssLayer->InitGSS())
 		if (!m_pGssLayer->InitGSS())
 		{
 		{
-			ShowStatus(_T("Unable to initialize GSS api"), 1);
+			ShowStatus(_T("Unable to initialize GSS api"), FZ_LOG_ERROR);
 			DoClose(FZ_REPLY_CRITICALERROR);
 			DoClose(FZ_REPLY_CRITICALERROR);
 			return false;
 			return false;
 		}
 		}
@@ -390,7 +390,7 @@ void CFtpControlSocket::Connect(t_server &server)
 
 
 	if (m_Operation.nOpMode)
 	if (m_Operation.nOpMode)
 	{
 	{
-		ShowStatus(_T("Internal error: m_Operation.nOpMode not zero in Connect"), 1);
+		ShowStatus(_T("Internal error: m_Operation.nOpMode not zero in Connect"), FZ_LOG_ERROR);
 		m_Operation.nOpMode = CSMODE_CONNECT;
 		m_Operation.nOpMode = CSMODE_CONNECT;
 		DoClose(FZ_REPLY_CRITICALERROR);
 		DoClose(FZ_REPLY_CRITICALERROR);
 		return;
 		return;
@@ -420,18 +420,21 @@ void CFtpControlSocket::Connect(t_server &server)
 	{
 	{
 		if (!m_pSslLayer)
 		if (!m_pSslLayer)
 		{
 		{
-			ShowStatus(_T("Internal error: m_pSslLayer not initialized"), 1);
+			ShowStatus(_T("Internal error: m_pSslLayer not initialized"), FZ_LOG_ERROR);
 			DoClose(FZ_REPLY_CRITICALERROR);
 			DoClose(FZ_REPLY_CRITICALERROR);
 			return;
 			return;
 		}
 		}
-		int res = m_pSslLayer->InitSSLConnection(true, NULL, COptions::GetOptionVal(OPTION_MPEXT_SSLSESSIONREUSE));
+		int res = m_pSslLayer->InitSSLConnection(true, NULL,
+			COptions::GetOptionVal(OPTION_MPEXT_SSLSESSIONREUSE),
+			COptions::GetOptionVal(OPTION_MPEXT_MIN_TLS_VERSION),
+			COptions::GetOptionVal(OPTION_MPEXT_MAX_TLS_VERSION));
 #ifndef MPEXT_NO_SSLDLL
 #ifndef MPEXT_NO_SSLDLL
 		if (res == SSL_FAILURE_LOADDLLS)
 		if (res == SSL_FAILURE_LOADDLLS)
-			ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, 1);
+			ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, FZ_LOG_ERROR);
 		else
 		else
 #endif
 #endif
 		if (res == SSL_FAILURE_INITSSL)
 		if (res == SSL_FAILURE_INITSSL)
-			ShowStatus(IDS_ERRORMSG_CANTINITSSL, 1);
+			ShowStatus(IDS_ERRORMSG_CANTINITSSL, FZ_LOG_ERROR);
 		if (!res)
 		if (!res)
 			PostMessage(m_pOwner->m_hOwnerWnd, m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_SECURESERVER, 1), 0);
 			PostMessage(m_pOwner->m_hOwnerWnd, m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_SECURESERVER, 1), 0);
 		else
 		else
@@ -471,7 +474,7 @@ void CFtpControlSocket::Connect(t_server &server)
 		hostname.Format( _T("%s:%d"), hostname, server.port); // add port to hostname (only if port is not 21)
 		hostname.Format( _T("%s:%d"), hostname, server.port); // add port to hostname (only if port is not 21)
 	CString str;
 	CString str;
 	str.Format(IDS_STATUSMSG_CONNECTING, hostname);
 	str.Format(IDS_STATUSMSG_CONNECTING, hostname);
-	ShowStatus(str, 0);
+	ShowStatus(str, FZ_LOG_STATUS);
 
 
 #ifndef MPEXT_NO_SSL
 #ifndef MPEXT_NO_SSL
 	if ((server.nServerType & FZ_SERVERTYPE_LAYERMASK) & (FZ_SERVERTYPE_LAYER_SSL_EXPLICIT | FZ_SERVERTYPE_LAYER_TLS_EXPLICIT))
 	if ((server.nServerType & FZ_SERVERTYPE_LAYERMASK) & (FZ_SERVERTYPE_LAYER_SSL_EXPLICIT | FZ_SERVERTYPE_LAYER_TLS_EXPLICIT))
@@ -548,18 +551,21 @@ void CFtpControlSocket::LogOnToServer(BOOL bSkipReply /*=FALSE*/)
 		{
 		{
 			if (!m_pSslLayer)
 			if (!m_pSslLayer)
 			{
 			{
-				ShowStatus(_T("Internal error: m_pSslLayer not initialized"), 1);
+				ShowStatus(_T("Internal error: m_pSslLayer not initialized"), FZ_LOG_ERROR);
 				DoClose(FZ_REPLY_CRITICALERROR);
 				DoClose(FZ_REPLY_CRITICALERROR);
 				return;
 				return;
 			}
 			}
-			int res = m_pSslLayer->InitSSLConnection(true, NULL, COptions::GetOptionVal(OPTION_MPEXT_SSLSESSIONREUSE));
+			int res = m_pSslLayer->InitSSLConnection(true, NULL,
+				COptions::GetOptionVal(OPTION_MPEXT_SSLSESSIONREUSE),
+				COptions::GetOptionVal(OPTION_MPEXT_MIN_TLS_VERSION),
+				COptions::GetOptionVal(OPTION_MPEXT_MAX_TLS_VERSION));
 #ifndef MPEXT_NO_SSLDLL
 #ifndef MPEXT_NO_SSLDLL
 			if (res == SSL_FAILURE_LOADDLLS)
 			if (res == SSL_FAILURE_LOADDLLS)
-				ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, 1);
+				ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, FZ_LOG_ERROR);
 			else
 			else
 #endif
 #endif
 			if (res == SSL_FAILURE_INITSSL)
 			if (res == SSL_FAILURE_INITSSL)
-				ShowStatus(IDS_ERRORMSG_CANTINITSSL, 1);
+				ShowStatus(IDS_ERRORMSG_CANTINITSSL, FZ_LOG_ERROR);
 			if (res)
 			if (res)
 			{
 			{
 				DoClose();
 				DoClose();
@@ -586,7 +592,7 @@ void CFtpControlSocket::LogOnToServer(BOOL bSkipReply /*=FALSE*/)
 		if (code == 2 || code == 3)
 		if (code == 2 || code == 3)
 			m_bProtP = true;
 			m_bProtP = true;
 
 
-		ShowStatus(IDS_STATUSMSG_CONNECTED, 0);
+		ShowStatus(IDS_STATUSMSG_CONNECTED, FZ_LOG_STATUS);
 		m_pOwner->SetConnected(TRUE);
 		m_pOwner->SetConnected(TRUE);
 		ResetOperation(FZ_REPLY_OK);
 		ResetOperation(FZ_REPLY_OK);
 		return;
 		return;
@@ -613,7 +619,7 @@ void CFtpControlSocket::LogOnToServer(BOOL bSkipReply /*=FALSE*/)
 		int code = GetReplyCode();
 		int code = GetReplyCode();
 		if (code != 2 && code != 3)
 		if (code != 2 && code != 3)
 			m_serverCapabilities.SetCapability(mlsd_command, no);
 			m_serverCapabilities.SetCapability(mlsd_command, no);
-		ShowStatus(IDS_STATUSMSG_CONNECTED, 0);
+		ShowStatus(IDS_STATUSMSG_CONNECTED, FZ_LOG_STATUS);
 		m_pOwner->SetConnected(TRUE);
 		m_pOwner->SetConnected(TRUE);
 		ResetOperation(FZ_REPLY_OK);
 		ResetOperation(FZ_REPLY_OK);
 		return;
 		return;
@@ -740,7 +746,7 @@ void CFtpControlSocket::LogOnToServer(BOOL bSkipReply /*=FALSE*/)
 			}
 			}
 		}
 		}
 
 
-		ShowStatus(IDS_STATUSMSG_CONNECTED, 0);
+		ShowStatus(IDS_STATUSMSG_CONNECTED, FZ_LOG_STATUS);
 		m_pOwner->SetConnected(TRUE);
 		m_pOwner->SetConnected(TRUE);
 		ResetOperation(FZ_REPLY_OK);
 		ResetOperation(FZ_REPLY_OK);
 		return;
 		return;
@@ -763,7 +769,7 @@ void CFtpControlSocket::LogOnToServer(BOOL bSkipReply /*=FALSE*/)
 		}
 		}
 #endif
 #endif
 
 
-		ShowStatus(IDS_STATUSMSG_CONNECTED, 0);
+		ShowStatus(IDS_STATUSMSG_CONNECTED, FZ_LOG_STATUS);
 		m_pOwner->SetConnected(TRUE);
 		m_pOwner->SetConnected(TRUE);
 		ResetOperation(FZ_REPLY_OK);
 		ResetOperation(FZ_REPLY_OK);
 		return;
 		return;
@@ -808,7 +814,7 @@ void CFtpControlSocket::LogOnToServer(BOOL bSkipReply /*=FALSE*/)
 						asciiOnly = false;
 						asciiOnly = false;
 				if (!asciiOnly)
 				if (!asciiOnly)
 				{
 				{
-					ShowStatus(_T("Login data contains non-ascii characters and server might not be UTF-8 aware. Trying local charset."), 0);
+					ShowStatus(_T("Login data contains non-ascii characters and server might not be UTF-8 aware. Trying local charset."), FZ_LOG_STATUS);
 					m_bUTF8 = false;
 					m_bUTF8 = false;
 					m_Operation.nOpState = CONNECT_INIT;
 					m_Operation.nOpState = CONNECT_INIT;
 				}
 				}
@@ -858,7 +864,7 @@ void CFtpControlSocket::LogOnToServer(BOOL bSkipReply /*=FALSE*/)
 		else
 		else
 		{
 		{
 			// we got authentication, we need to check whether we have forwardable tickets
 			// we got authentication, we need to check whether we have forwardable tickets
-			//ShowStatus(IDS_STATUSMSG_GSSAUTH, 0);
+			//ShowStatus(IDS_STATUSMSG_GSSAUTH, FZ_LOG_STATUS);
 			PostMessage(m_pOwner->m_hOwnerWnd,m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_SECURESERVER, TRUE), 0);
 			PostMessage(m_pOwner->m_hOwnerWnd,m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_SECURESERVER, TRUE), 0);
 			if (Send(_MPT("CWD .")))
 			if (Send(_MPT("CWD .")))
 				m_Operation.nOpState = CONNECT_GSS_CWD;
 				m_Operation.nOpState = CONNECT_GSS_CWD;
@@ -886,7 +892,7 @@ void CFtpControlSocket::LogOnToServer(BOOL bSkipReply /*=FALSE*/)
 		else
 		else
 		{
 		{
 			// we got authentication, we need to check whether we have forwardable tickets
 			// we got authentication, we need to check whether we have forwardable tickets
-			//ShowStatus(IDS_STATUSMSG_GSSAUTH, 0);
+			//ShowStatus(IDS_STATUSMSG_GSSAUTH, FZ_LOG_STATUS);
 			PostMessage(m_pOwner->m_hOwnerWnd,m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_SECURESERVER, TRUE), 0);
 			PostMessage(m_pOwner->m_hOwnerWnd,m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_SECURESERVER, TRUE), 0);
 			if (Send(_MPT("CWD .")))
 			if (Send(_MPT("CWD .")))
 				m_Operation.nOpState = CONNECT_GSS_CWD;
 				m_Operation.nOpState = CONNECT_GSS_CWD;
@@ -914,7 +920,7 @@ void CFtpControlSocket::LogOnToServer(BOOL bSkipReply /*=FALSE*/)
 
 
 			CString str;
 			CString str;
 			str.Format(IDS_STATUSMSG_FWCONNECT,hostname);
 			str.Format(IDS_STATUSMSG_FWCONNECT,hostname);
-			ShowStatus(str,0);
+			ShowStatus(str,FZ_LOG_STATUS);
 		}
 		}
 		m_Operation.nOpState++;
 		m_Operation.nOpState++;
 	}
 	}
@@ -1100,7 +1106,7 @@ void CFtpControlSocket::OnReceive(int nErrorCode)
 		m_MultiLine = "";
 		m_MultiLine = "";
 		CString str;
 		CString str;
 		str.Format(IDS_STATUSMSG_CONNECTEDWITH, m_ServerName);
 		str.Format(IDS_STATUSMSG_CONNECTEDWITH, m_ServerName);
-		ShowStatus(str, 0);
+		ShowStatus(str, FZ_LOG_STATUS);
 		m_pOwner->SetConnected(TRUE);
 		m_pOwner->SetConnected(TRUE);
 	}
 	}
 	char *buffer = new char[BUFFERSIZE];
 	char *buffer = new char[BUFFERSIZE];
@@ -1112,7 +1118,7 @@ void CFtpControlSocket::OnReceive(int nErrorCode)
 		buffer = NULL;
 		buffer = NULL;
 		if (GetLastError() != WSAEWOULDBLOCK)
 		if (GetLastError() != WSAEWOULDBLOCK)
 		{
 		{
-			ShowStatus(IDS_STATUSMSG_DISCONNECTED, 1);
+			ShowStatus(IDS_STATUSMSG_DISCONNECTED, FZ_LOG_ERROR);
 			DoClose();
 			DoClose();
 		}
 		}
 		return;
 		return;
@@ -1121,7 +1127,7 @@ void CFtpControlSocket::OnReceive(int nErrorCode)
 	{
 	{
 		delete [] buffer;
 		delete [] buffer;
 		buffer = NULL;
 		buffer = NULL;
-		ShowStatus(IDS_STATUSMSG_DISCONNECTED, 1);
+		ShowStatus(IDS_STATUSMSG_DISCONNECTED, FZ_LOG_ERROR);
 		DoClose();
 		DoClose();
 	}
 	}
 
 
@@ -1143,7 +1149,7 @@ void CFtpControlSocket::OnReceive(int nErrorCode)
 							LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Server does not send proper UTF-8, falling back to local charset"));
 							LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Server does not send proper UTF-8, falling back to local charset"));
 							m_bUTF8 = false;
 							m_bUTF8 = false;
 						}
 						}
-						ShowStatus(A2CT(utf8), 3);
+						ShowStatus(A2CT(utf8), FZ_LOG_REPLY);
 					}
 					}
 					else
 					else
 					{
 					{
@@ -1154,13 +1160,13 @@ void CFtpControlSocket::OnReceive(int nErrorCode)
 						{
 						{
 							LPWSTR p1 = new WCHAR[len + 1];
 							LPWSTR p1 = new WCHAR[len + 1];
 							MultiByteToWideChar(CP_UTF8, 0, utf8, -1 , (LPWSTR)p1, len + 1);
 							MultiByteToWideChar(CP_UTF8, 0, utf8, -1 , (LPWSTR)p1, len + 1);
-							ShowStatus(W2CT(p1), 3);
+							ShowStatus(W2CT(p1), FZ_LOG_REPLY);
 							delete [] p1;
 							delete [] p1;
 						}
 						}
 					}
 					}
 				}
 				}
 				else
 				else
-					ShowStatus(A2CT(m_RecvBuffer.back()), 3);
+					ShowStatus(A2CT(m_RecvBuffer.back()), FZ_LOG_REPLY);
 				//Check for multi-line responses
 				//Check for multi-line responses
 				if (m_RecvBuffer.back().GetLength() > 3)
 				if (m_RecvBuffer.back().GetLength() > 3)
 				{
 				{
@@ -1287,13 +1293,13 @@ void CFtpControlSocket::OnConnect(int nErrorCode)
 				m_pSslLayer ? IDS_STATUSMSG_CONNECTEDWITHSSL :
 				m_pSslLayer ? IDS_STATUSMSG_CONNECTEDWITHSSL :
 #endif
 #endif
 				IDS_STATUSMSG_CONNECTEDWITH, m_ServerName);
 				IDS_STATUSMSG_CONNECTEDWITH, m_ServerName);
-			ShowStatus(str,0);
+			ShowStatus(str,FZ_LOG_STATUS);
 		}
 		}
 	}
 	}
 	else
 	else
 	{
 	{
 		if (nErrorCode == WSAHOST_NOT_FOUND)
 		if (nErrorCode == WSAHOST_NOT_FOUND)
-			ShowStatus(IDS_ERRORMSG_CANTRESOLVEHOST, 1);
+			ShowStatus(IDS_ERRORMSG_CANTRESOLVEHOST, FZ_LOG_ERROR);
 #ifdef MPEXT
 #ifdef MPEXT
 		else
 		else
 		{
 		{
@@ -1305,7 +1311,7 @@ void CFtpControlSocket::OnConnect(int nErrorCode)
 			{
 			{
 				--Len;
 				--Len;
 			}
 			}
-			ShowStatus(CString(Buffer, Len), 1);
+			ShowStatus(CString(Buffer, Len), FZ_LOG_ERROR);
 		}
 		}
 #endif
 #endif
 		DoClose();
 		DoClose();
@@ -1316,7 +1322,7 @@ BOOL CFtpControlSocket::Send(CString str)
 {
 {
 	USES_CONVERSION;
 	USES_CONVERSION;
 
 
-	ShowStatus(str, 2);
+	ShowStatus(str, FZ_LOG_COMMAND);
 	str += _MPT("\r\n");
 	str += _MPT("\r\n");
 	int res = 0;
 	int res = 0;
 	if (m_bUTF8)
 	if (m_bUTF8)
@@ -1325,7 +1331,7 @@ BOOL CFtpControlSocket::Send(CString str)
 		int len = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, 0, 0, 0, 0);
 		int len = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, 0, 0, 0, 0);
 		if (!len)
 		if (!len)
 		{
 		{
-			ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, 1);
+			ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, FZ_LOG_ERROR);
 			DoClose();
 			DoClose();
 			return FALSE;
 			return FALSE;
 		}
 		}
@@ -1340,7 +1346,7 @@ BOOL CFtpControlSocket::Send(CString str)
 		if ((res == SOCKET_ERROR && GetLastError() != WSAEWOULDBLOCK) || !res)
 		if ((res == SOCKET_ERROR && GetLastError() != WSAEWOULDBLOCK) || !res)
 		{
 		{
 			delete [] utf8;
 			delete [] utf8;
-			ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, 1);
+			ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, FZ_LOG_ERROR);
 			DoClose();
 			DoClose();
 			return FALSE;
 			return FALSE;
 		}
 		}
@@ -1377,7 +1383,7 @@ BOOL CFtpControlSocket::Send(CString str)
 			res = -2;
 			res = -2;
 		if ((res == SOCKET_ERROR && GetLastError() != WSAEWOULDBLOCK) || !res)
 		if ((res == SOCKET_ERROR && GetLastError() != WSAEWOULDBLOCK) || !res)
 		{
 		{
-			ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, 1);
+			ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, FZ_LOG_ERROR);
 			DoClose();
 			DoClose();
 			return FALSE;
 			return FALSE;
 		}
 		}
@@ -1476,7 +1482,7 @@ void CFtpControlSocket::Disconnect()
 	ASSERT(!m_Operation.nOpMode);
 	ASSERT(!m_Operation.nOpMode);
 	m_Operation.nOpMode=CSMODE_DISCONNECT;
 	m_Operation.nOpMode=CSMODE_DISCONNECT;
 	DoClose();
 	DoClose();
-	ShowStatus(IDS_STATUSMSG_DISCONNECTED,0); //Send the disconnected message to the message log
+	ShowStatus(IDS_STATUSMSG_DISCONNECTED,FZ_LOG_STATUS); //Send the disconnected message to the message log
 }
 }
 
 
 void CFtpControlSocket::CheckForTimeout()
 void CFtpControlSocket::CheckForTimeout()
@@ -1495,7 +1501,7 @@ void CFtpControlSocket::CheckForTimeout()
 	CTimeSpan span=CTime::GetCurrentTime()-m_LastRecvTime;
 	CTimeSpan span=CTime::GetCurrentTime()-m_LastRecvTime;
 	if (span.GetTotalSeconds()>=delay)
 	if (span.GetTotalSeconds()>=delay)
 	{
 	{
-		ShowStatus(IDS_ERRORMSG_TIMEOUT, 1);
+		ShowStatus(IDS_ERRORMSG_TIMEOUT, FZ_LOG_ERROR);
 		DoClose();
 		DoClose();
 	}
 	}
 }
 }
@@ -1508,7 +1514,7 @@ void CFtpControlSocket::FtpCommand(LPCTSTR pCommand)
 }
 }
 
 
 #ifdef MPEXT
 #ifdef MPEXT
-bool __fastcall CFtpControlSocket::UsingMlsd()
+bool CFtpControlSocket::UsingMlsd()
 {
 {
 	return
 	return
 		// 0 = on, 1 = off, 2 = auto
 		// 0 = on, 1 = off, 2 = auto
@@ -1516,6 +1522,30 @@ bool __fastcall CFtpControlSocket::UsingMlsd()
 		((m_CurrentServer.iUseMlsd != 1) &&
 		((m_CurrentServer.iUseMlsd != 1) &&
 		 (m_serverCapabilities.GetCapability(mlsd_command) == yes));
 		 (m_serverCapabilities.GetCapability(mlsd_command) == yes));
 }
 }
+
+std::string CFtpControlSocket::GetTlsVersionStr()
+{
+	if (m_pSslLayer != NULL)
+	{
+		return m_pSslLayer->GetTlsVersionStr();
+	}
+	else
+	{
+		return std::string();
+	}
+}
+
+std::string CFtpControlSocket::GetCipherName()
+{
+	if (m_pSslLayer != NULL)
+	{
+		return m_pSslLayer->GetCipherName();
+	}
+	else
+	{
+		return std::string();
+	}
+}
 #endif
 #endif
 
 
 CString CFtpControlSocket::GetListingCmd()
 CString CFtpControlSocket::GetListingCmd()
@@ -1659,7 +1689,7 @@ void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath pa
 		}
 		}
 		else if (pData->pDirectoryListing && pData->nFinish==1)
 		else if (pData->pDirectoryListing && pData->nFinish==1)
 		{
 		{
-			ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL,0);
+			ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL,FZ_LOG_STATUS);
 #ifndef MPEXT_NO_CACHE
 #ifndef MPEXT_NO_CACHE
 			CDirectoryCache cache;
 			CDirectoryCache cache;
 			cache.Lock();
 			cache.Lock();
@@ -1734,7 +1764,7 @@ void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath pa
 								}
 								}
 						if (bExact)
 						if (bExact)
 						{
 						{
-							ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, 0);
+							ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, FZ_LOG_STATUS);
 							SetDirectoryListing(&dir);
 							SetDirectoryListing(&dir);
 							ResetOperation(FZ_REPLY_OK);
 							ResetOperation(FZ_REPLY_OK);
 							return;
 							return;
@@ -1790,7 +1820,7 @@ void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath pa
 								}
 								}
 						if (bExact)
 						if (bExact)
 						{
 						{
-							ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, 0);
+							ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, FZ_LOG_STATUS);
 							SetDirectoryListing(&dir);
 							SetDirectoryListing(&dir);
 							ResetOperation(FZ_REPLY_OK);
 							ResetOperation(FZ_REPLY_OK);
 							return;
 							return;
@@ -1840,7 +1870,7 @@ void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath pa
 								}
 								}
 						if (bExact)
 						if (bExact)
 						{
 						{
-							ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, 0);
+							ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, FZ_LOG_STATUS);
 							SetDirectoryListing(&dir);
 							SetDirectoryListing(&dir);
 							ResetOperation(FZ_REPLY_OK);
 							ResetOperation(FZ_REPLY_OK);
 							return;
 							return;
@@ -1961,7 +1991,7 @@ void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath pa
 		case LIST_LIST:
 		case LIST_LIST:
 			if (IsMisleadingListResponse())
 			if (IsMisleadingListResponse())
 			{
 			{
-				ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, 0);
+				ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, FZ_LOG_STATUS);
 
 
 				t_directory listing;
 				t_directory listing;
 				listing.server = m_CurrentServer;
 				listing.server = m_CurrentServer;
@@ -2011,7 +2041,7 @@ void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath pa
 		pData->path=path;
 		pData->path=path;
 		pData->subdir=subdir;
 		pData->subdir=subdir;
 		m_Operation.pData=pData;
 		m_Operation.pData=pData;
-		ShowStatus(IDS_STATUSMSG_RETRIEVINGDIRLIST, 0);
+		ShowStatus(IDS_STATUSMSG_RETRIEVINGDIRLIST, FZ_LOG_STATUS);
 		pData->nFinish=-1;
 		pData->nFinish=-1;
 		if (m_pDirectoryListing)
 		if (m_pDirectoryListing)
 		{
 		{
@@ -2065,7 +2095,7 @@ void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath pa
 									}
 									}
 							if (bExact)
 							if (bExact)
 							{
 							{
-								ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL,0);
+								ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL,FZ_LOG_STATUS);
 								SetDirectoryListing(&dir);
 								SetDirectoryListing(&dir);
 								ResetOperation(FZ_REPLY_OK);
 								ResetOperation(FZ_REPLY_OK);
 								return;
 								return;
@@ -2151,7 +2181,7 @@ void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath pa
 		{
 		{
 			if (!m_pTransferSocket->InitZlib(m_zlibLevel))
 			if (!m_pTransferSocket->InitZlib(m_zlibLevel))
 			{
 			{
-				ShowStatus(_T("Failed to initialize zlib"), 1);
+				ShowStatus(_T("Failed to initialize zlib"), FZ_LOG_ERROR);
 				ResetOperation(FZ_REPLY_ERROR);
 				ResetOperation(FZ_REPLY_ERROR);
 				return;
 				return;
 			}
 			}
@@ -2170,7 +2200,7 @@ void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath pa
 		) ||
 		) ||
 			!m_pTransferSocket->AsyncSelect())
 			!m_pTransferSocket->AsyncSelect())
 		{
 		{
-			ShowStatus(_T("Failed to create socket"), 1);
+			ShowStatus(_T("Failed to create socket"), FZ_LOG_ERROR);
 			ResetOperation(FZ_REPLY_ERROR);
 			ResetOperation(FZ_REPLY_ERROR);
 			return;
 			return;
 		}
 		}
@@ -2216,7 +2246,7 @@ void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath pa
 					!m_pTransferSocket->Listen() ||
 					!m_pTransferSocket->Listen() ||
 					!m_pTransferSocket->GetSockName(tempHostname, nPort))
 					!m_pTransferSocket->GetSockName(tempHostname, nPort))
 				{
 				{
-					ShowStatus(_T("Failed to create listen socket"), 1);
+					ShowStatus(_T("Failed to create listen socket"), FZ_LOG_ERROR);
 					ResetOperation(FZ_REPLY_ERROR);
 					ResetOperation(FZ_REPLY_ERROR);
 					return;
 					return;
 				}
 				}
@@ -2253,7 +2283,7 @@ void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath pa
 
 
 						if (!GetSockName(host, temp))
 						if (!GetSockName(host, temp))
 						{
 						{
-							ShowStatus(_T("Failed to get socket address "), 1);
+							ShowStatus(_T("Failed to get socket address "), FZ_LOG_ERROR);
 							bError = true;
 							bError = true;
 						}
 						}
 
 
@@ -2384,7 +2414,7 @@ void CFtpControlSocket::ListFile(CServerPath path /*=CServerPath()*/, CString fi
 		pData->path=path;
 		pData->path=path;
 		pData->fileName=fileName;
 		pData->fileName=fileName;
 		m_Operation.pData=pData;
 		m_Operation.pData=pData;
-		ShowStatus(IDS_STATUSMSG_RETRIEVINGLISTFILE, 0);
+		ShowStatus(IDS_STATUSMSG_RETRIEVINGLISTFILE, FZ_LOG_STATUS);
 		pData->nFinish=-1;
 		pData->nFinish=-1;
 		if (m_pDirectoryListing)
 		if (m_pDirectoryListing)
 		{
 		{
@@ -2402,7 +2432,7 @@ void CFtpControlSocket::ListFile(CServerPath path /*=CServerPath()*/, CString fi
 		code = GetReplyCode();
 		code = GetReplyCode();
 		if (IsMisleadingListResponse())
 		if (IsMisleadingListResponse())
 		{
 		{
-			ShowStatus(IDS_STATUSMSG_LISTFILESUCCESSFUL, 0);
+			ShowStatus(IDS_STATUSMSG_LISTFILESUCCESSFUL, FZ_LOG_STATUS);
 
 
 			t_directory listing;
 			t_directory listing;
 			listing.server = m_CurrentServer;
 			listing.server = m_CurrentServer;
@@ -2436,7 +2466,7 @@ void CFtpControlSocket::ListFile(CServerPath path /*=CServerPath()*/, CString fi
 			pData->pDirectoryListing->path = m_pOwner->GetCurrentPath();
 			pData->pDirectoryListing->path = m_pOwner->GetCurrentPath();
 			delete pListResult;
 			delete pListResult;
 
 
-			ShowStatus(IDS_STATUSMSG_LISTFILESUCCESSFUL,0);
+			ShowStatus(IDS_STATUSMSG_LISTFILESUCCESSFUL,FZ_LOG_STATUS);
 			SetDirectoryListing(pData->pDirectoryListing);
 			SetDirectoryListing(pData->pDirectoryListing);
 			ResetOperation(FZ_REPLY_OK);
 			ResetOperation(FZ_REPLY_OK);
 			return;
 			return;
@@ -2473,7 +2503,7 @@ void CFtpControlSocket::TransferEnd(int nMode)
 void CFtpControlSocket::OnClose(int nErrorCode)
 void CFtpControlSocket::OnClose(int nErrorCode)
 {
 {
 	LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("OnClose(%d)  OpMode=%d OpState=%d"), nErrorCode, m_Operation.nOpMode, m_Operation.nOpState);
 	LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("OnClose(%d)  OpMode=%d OpState=%d"), nErrorCode, m_Operation.nOpMode, m_Operation.nOpState);
-	ShowStatus(IDS_STATUSMSG_DISCONNECTED, 1);
+	ShowStatus(IDS_STATUSMSG_DISCONNECTED, FZ_LOG_ERROR);
 	if (m_pTransferSocket)
 	if (m_pTransferSocket)
 	{
 	{
 		m_pTransferSocket->OnClose(0);
 		m_pTransferSocket->OnClose(0);
@@ -2481,7 +2511,7 @@ void CFtpControlSocket::OnClose(int nErrorCode)
 		delete m_pTransferSocket;
 		delete m_pTransferSocket;
 		m_pTransferSocket=0;
 		m_pTransferSocket=0;
 		DoClose();
 		DoClose();
-		ShowStatus(IDS_ERRORMSG_TIMEOUT,1);
+		ShowStatus(IDS_ERRORMSG_TIMEOUT,FZ_LOG_ERROR);
 		return;
 		return;
 	}
 	}
 #ifndef MPEXT_NO_SSL
 #ifndef MPEXT_NO_SSL
@@ -2739,7 +2769,7 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 		CString str;
 		CString str;
 		str.Format(transferfile->get?IDS_STATUSMSG_DOWNLOADSTART:IDS_STATUSMSG_UPLOADSTART,
 		str.Format(transferfile->get?IDS_STATUSMSG_DOWNLOADSTART:IDS_STATUSMSG_UPLOADSTART,
 					transferfile->get ? transferfile->remotepath.FormatFilename(transferfile->remotefile) : transferfile->localfile);
 					transferfile->get ? transferfile->remotepath.FormatFilename(transferfile->remotefile) : transferfile->localfile);
-		ShowStatus(str,0);
+		ShowStatus(str,FZ_LOG_STATUS);
 
 
 		m_Operation.nOpMode=CSMODE_TRANSFER|(transferfile->get?CSMODE_DOWNLOAD:CSMODE_UPLOAD);
 		m_Operation.nOpMode=CSMODE_TRANSFER|(transferfile->get?CSMODE_DOWNLOAD:CSMODE_UPLOAD);
 
 
@@ -3355,7 +3385,7 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 				{
 				{
 					if (!m_pTransferSocket->InitZlib(m_zlibLevel))
 					if (!m_pTransferSocket->InitZlib(m_zlibLevel))
 					{
 					{
-						ShowStatus(_MPT("Failed to initialize zlib"), 1);
+						ShowStatus(_MPT("Failed to initialize zlib"), FZ_LOG_ERROR);
 						ResetOperation(FZ_REPLY_ERROR);
 						ResetOperation(FZ_REPLY_ERROR);
 						return;
 						return;
 					}
 					}
@@ -3384,7 +3414,7 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 		case FILETRANSFER_LIST_LIST:
 		case FILETRANSFER_LIST_LIST:
 			if (IsMisleadingListResponse())
 			if (IsMisleadingListResponse())
 			{
 			{
-				ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, 0);
+				ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, FZ_LOG_STATUS);
 
 
 				t_directory listing;
 				t_directory listing;
 				listing.server = m_CurrentServer;
 				listing.server = m_CurrentServer;
@@ -3703,7 +3733,7 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 					{
 					{
 						if (!m_pTransferSocket->InitZlib(m_zlibLevel))
 						if (!m_pTransferSocket->InitZlib(m_zlibLevel))
 						{
 						{
-							ShowStatus(_MPT("Failed to initialize zlib"), 1);
+							ShowStatus(_MPT("Failed to initialize zlib"), FZ_LOG_ERROR);
 							ResetOperation(FZ_REPLY_ERROR);
 							ResetOperation(FZ_REPLY_ERROR);
 							return;
 							return;
 						}
 						}
@@ -3753,7 +3783,7 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 					//Error opening the file
 					//Error opening the file
 					CString str;
 					CString str;
 					str.Format(IDS_ERRORMSG_FILEOPENFAILED,pData->transferfile.localfile);
 					str.Format(IDS_ERRORMSG_FILEOPENFAILED,pData->transferfile.localfile);
-					ShowStatus(str,1);
+					ShowStatus(str,FZ_LOG_ERROR);
 					nReplyError = FZ_REPLY_ERROR;
 					nReplyError = FZ_REPLY_ERROR;
 					break;
 					break;
 				}
 				}
@@ -3786,7 +3816,7 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 						LONG high = static_cast<LONG>(size>>32);
 						LONG high = static_cast<LONG>(size>>32);
 						if (SetFilePointer((HANDLE)m_pDataFile->m_hFile, low, &high, FILE_BEGIN)==0xFFFFFFFF && GetLastError()!=NO_ERROR)
 						if (SetFilePointer((HANDLE)m_pDataFile->m_hFile, low, &high, FILE_BEGIN)==0xFFFFFFFF && GetLastError()!=NO_ERROR)
 						{
 						{
-							ShowStatus(IDS_ERRORMSG_SETFILEPOINTER, 1);
+							ShowStatus(IDS_ERRORMSG_SETFILEPOINTER, FZ_LOG_ERROR);
 							nReplyError = FZ_REPLY_ERROR;
 							nReplyError = FZ_REPLY_ERROR;
 						}
 						}
 					}
 					}
@@ -3827,7 +3857,7 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 					pData->transferdata.transferleft = pData->transferdata.transfersize - GetLength64(*m_pDataFile);
 					pData->transferdata.transferleft = pData->transferdata.transfersize - GetLength64(*m_pDataFile);
 					if (SetFilePointer((HANDLE)m_pDataFile->m_hFile, 0, &high, FILE_END)==0xFFFFFFFF && GetLastError()!=NO_ERROR)
 					if (SetFilePointer((HANDLE)m_pDataFile->m_hFile, 0, &high, FILE_END)==0xFFFFFFFF && GetLastError()!=NO_ERROR)
 					{
 					{
-						ShowStatus(IDS_ERRORMSG_SETFILEPOINTER, 1);
+						ShowStatus(IDS_ERRORMSG_SETFILEPOINTER, FZ_LOG_ERROR);
 						nReplyError = FZ_REPLY_ERROR;
 						nReplyError = FZ_REPLY_ERROR;
 					}
 					}
 					else
 					else
@@ -3842,13 +3872,13 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 							ASSERT(m_pDataFile);
 							ASSERT(m_pDataFile);
 							if (GetLength64(*m_pDataFile) == pData->transferdata.transfersize)
 							if (GetLength64(*m_pDataFile) == pData->transferdata.transfersize)
 							{
 							{
-								ShowStatus(IDS_ERRORMSG_CANTRESUME_FINISH, 0);
+								ShowStatus(IDS_ERRORMSG_CANTRESUME_FINISH, FZ_LOG_STATUS);
 								ResetOperation(FZ_REPLY_OK);
 								ResetOperation(FZ_REPLY_OK);
 								return;
 								return;
 							}
 							}
 						}
 						}
 
 
-						ShowStatus(IDS_ERRORMSG_CANTRESUME, 1);
+						ShowStatus(IDS_ERRORMSG_CANTRESUME, FZ_LOG_ERROR);
 						pData->transferdata.transferleft=pData->transferdata.transfersize;
 						pData->transferdata.transferleft=pData->transferdata.transfersize;
 						pData->transferdata.bResume=FALSE;
 						pData->transferdata.bResume=FALSE;
 						m_Operation.nOpState=FILETRANSFER_RETRSTOR;
 						m_Operation.nOpState=FILETRANSFER_RETRSTOR;
@@ -3921,7 +3951,7 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 						{
 						{
 							if (SetFilePointer((HANDLE)m_pDataFile->m_hFile, 0, &high, FILE_END)==0xFFFFFFFF && GetLastError()!=NO_ERROR)
 							if (SetFilePointer((HANDLE)m_pDataFile->m_hFile, 0, &high, FILE_END)==0xFFFFFFFF && GetLastError()!=NO_ERROR)
 							{
 							{
-								ShowStatus(IDS_ERRORMSG_SETFILEPOINTER, 1);
+								ShowStatus(IDS_ERRORMSG_SETFILEPOINTER, FZ_LOG_ERROR);
 								nReplyError = FZ_REPLY_ERROR;
 								nReplyError = FZ_REPLY_ERROR;
 							}
 							}
 						}
 						}
@@ -3931,7 +3961,7 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 							high=static_cast<LONG>(nOffset>>32);
 							high=static_cast<LONG>(nOffset>>32);
 							if (SetFilePointer((HANDLE)m_pDataFile->m_hFile, low, &high, FILE_BEGIN)==0xFFFFFFFF && GetLastError()!=NO_ERROR)
 							if (SetFilePointer((HANDLE)m_pDataFile->m_hFile, low, &high, FILE_BEGIN)==0xFFFFFFFF && GetLastError()!=NO_ERROR)
 							{
 							{
-								ShowStatus(IDS_ERRORMSG_SETFILEPOINTER, 1);
+								ShowStatus(IDS_ERRORMSG_SETFILEPOINTER, FZ_LOG_ERROR);
 								nReplyError = FZ_REPLY_ERROR;
 								nReplyError = FZ_REPLY_ERROR;
 							}
 							}
 						}
 						}
@@ -4068,7 +4098,7 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 			{
 			{
 				if (!m_pTransferSocket->InitZlib(m_zlibLevel))
 				if (!m_pTransferSocket->InitZlib(m_zlibLevel))
 				{
 				{
-					ShowStatus(_MPT("Failed to initialize zlib"), 1);
+					ShowStatus(_MPT("Failed to initialize zlib"), FZ_LOG_ERROR);
 					ResetOperation(FZ_REPLY_ERROR);
 					ResetOperation(FZ_REPLY_ERROR);
 					return;
 					return;
 				}
 				}
@@ -4093,12 +4123,12 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 				int len=sizeof(addr);
 				int len=sizeof(addr);
 				if (!m_pProxyLayer->GetPeerName((SOCKADDR *)&addr,&len))
 				if (!m_pProxyLayer->GetPeerName((SOCKADDR *)&addr,&len))
 				{
 				{
-					ShowStatus(IDS_ERRORMSG_CANTGETLIST,1);
+					ShowStatus(IDS_ERRORMSG_CANTGETLIST,FZ_LOG_ERROR);
 					bError=TRUE;
 					bError=TRUE;
 				}
 				}
 				else if (!m_pTransferSocket->Listen(addr.sin_addr.S_un.S_addr))
 				else if (!m_pTransferSocket->Listen(addr.sin_addr.S_un.S_addr))
 				{
 				{
-					ShowStatus(IDS_ERRORMSG_CANTGETLIST,1);
+					ShowStatus(IDS_ERRORMSG_CANTGETLIST,FZ_LOG_ERROR);
 					bError=TRUE;
 					bError=TRUE;
 				}
 				}
 				//Don't send PORT command yet, params are unknown.
 				//Don't send PORT command yet, params are unknown.
@@ -4231,7 +4261,7 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 					if (GetLastError()!=WSAEWOULDBLOCK)
 					if (GetLastError()!=WSAEWOULDBLOCK)
 					{
 					{
 						bError=TRUE;
 						bError=TRUE;
-						ShowStatus(IDS_ERRORMSG_CANTGETLIST,1);
+						ShowStatus(IDS_ERRORMSG_CANTGETLIST,FZ_LOG_ERROR);
 					}
 					}
 				}
 				}
 			}
 			}
@@ -4311,7 +4341,7 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 			{
 			{
 				if (!m_pTransferSocket->InitZlib(m_zlibLevel))
 				if (!m_pTransferSocket->InitZlib(m_zlibLevel))
 				{
 				{
-					ShowStatus(_MPT("Failed to initialize zlib"), 1);
+					ShowStatus(_MPT("Failed to initialize zlib"), FZ_LOG_ERROR);
 					ResetOperation(FZ_REPLY_ERROR);
 					ResetOperation(FZ_REPLY_ERROR);
 					return;
 					return;
 				}
 				}
@@ -4336,12 +4366,12 @@ void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFi
 				int len=sizeof(addr);
 				int len=sizeof(addr);
 				if (!m_pProxyLayer->GetPeerName((SOCKADDR *)&addr,&len))
 				if (!m_pProxyLayer->GetPeerName((SOCKADDR *)&addr,&len))
 				{
 				{
-					ShowStatus(IDS_ERRORMSG_CANTGETLIST,1);
+					ShowStatus(IDS_ERRORMSG_CANTGETLIST,FZ_LOG_ERROR);
 					bError=TRUE;
 					bError=TRUE;
 				}
 				}
 				else if (!m_pTransferSocket->Listen(addr.sin_addr.S_un.S_addr))
 				else if (!m_pTransferSocket->Listen(addr.sin_addr.S_un.S_addr))
 				{
 				{
-					ShowStatus(IDS_ERRORMSG_CANTGETLIST,1);
+					ShowStatus(IDS_ERRORMSG_CANTGETLIST,FZ_LOG_ERROR);
 					bError=TRUE;
 					bError=TRUE;
 				}
 				}
 				//Don't send PORT command yet, params are unknown.
 				//Don't send PORT command yet, params are unknown.
@@ -4566,7 +4596,7 @@ void CFtpControlSocket::Cancel(BOOL bQuit/*=FALSE*/)
 		ResetOperation(FZ_REPLY_ERROR | FZ_REPLY_CANCEL);
 		ResetOperation(FZ_REPLY_ERROR | FZ_REPLY_CANCEL);
 
 
 	if (nOpMode != CSMODE_NONE && !bQuit)
 	if (nOpMode != CSMODE_NONE && !bQuit)
-		ShowStatus(IDS_ERRORMSG_INTERRUPTED, 1);
+		ShowStatus(IDS_ERRORMSG_INTERRUPTED, FZ_LOG_ERROR);
 
 
 	if (m_awaitsReply)
 	if (m_awaitsReply)
 		m_skipReply = true;
 		m_skipReply = true;
@@ -4601,7 +4631,7 @@ BOOL CFtpControlSocket::Create()
 		int max=COptions::GetOptionVal(OPTION_PORTRANGEHIGH);
 		int max=COptions::GetOptionVal(OPTION_PORTRANGEHIGH);
 		if (min>=max)
 		if (min>=max)
 		{
 		{
-			ShowStatus(IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE,1);
+			ShowStatus(IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE,FZ_LOG_ERROR);
 			return FALSE;
 			return FALSE;
 		}
 		}
 		int startport = static_cast<int>(min+((double)rand()*(max-min))/(RAND_MAX+1));
 		int startport = static_cast<int>(min+((double)rand()*(max-min))/(RAND_MAX+1));
@@ -4614,7 +4644,7 @@ BOOL CFtpControlSocket::Create()
 				port=min;
 				port=min;
 			if (port==startport)
 			if (port==startport)
 			{
 			{
-				ShowStatus(IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE,1);
+				ShowStatus(IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE,FZ_LOG_ERROR);
 				return FALSE;
 				return FALSE;
 			}
 			}
 
 
@@ -4658,7 +4688,7 @@ void CFtpControlSocket::ResetOperation(int nSuccessful /*=FALSE*/)
 		if (m_Operation.nOpMode&CSMODE_CONNECT && nSuccessful&FZ_REPLY_ERROR)
 		if (m_Operation.nOpMode&CSMODE_CONNECT && nSuccessful&FZ_REPLY_ERROR)
 		{
 		{
 			nSuccessful|=FZ_REPLY_DISCONNECTED;
 			nSuccessful|=FZ_REPLY_DISCONNECTED;
-			ShowStatus(IDS_ERRORMSG_CANTCONNECT, 1);
+			ShowStatus(IDS_ERRORMSG_CANTCONNECT, FZ_LOG_ERROR);
 		}
 		}
 
 
 		if (m_Operation.nOpMode & (CSMODE_LIST|CSMODE_LISTFILE|CSMODE_TRANSFER) && nSuccessful==FZ_REPLY_OK)
 		if (m_Operation.nOpMode & (CSMODE_LIST|CSMODE_LISTFILE|CSMODE_TRANSFER) && nSuccessful==FZ_REPLY_OK)
@@ -4766,16 +4796,16 @@ void CFtpControlSocket::ResetOperation(int nSuccessful /*=FALSE*/)
 			if (m_Operation.nOpMode&CSMODE_TRANSFER)
 			if (m_Operation.nOpMode&CSMODE_TRANSFER)
 				if (nSuccessful&FZ_REPLY_ABORTED)
 				if (nSuccessful&FZ_REPLY_ABORTED)
 					//Transfer aborted by user
 					//Transfer aborted by user
-					ShowStatus((m_Operation.nOpMode&CSMODE_DOWNLOAD)?IDS_ERRORMSG_DOWNLOADABORTED:IDS_ERRORMSG_UPLOADABORTED,1);
+					ShowStatus((m_Operation.nOpMode&CSMODE_DOWNLOAD)?IDS_ERRORMSG_DOWNLOADABORTED:IDS_ERRORMSG_UPLOADABORTED,FZ_LOG_ERROR);
 				else
 				else
-					ShowStatus(((CFileTransferData*)m_Operation.pData)->transferfile.get?IDS_ERRORMSG_DOWNLOADFAILED:IDS_ERRORMSG_UPLOADFAILED,1);
+					ShowStatus(((CFileTransferData*)m_Operation.pData)->transferfile.get?IDS_ERRORMSG_DOWNLOADFAILED:IDS_ERRORMSG_UPLOADFAILED,FZ_LOG_ERROR);
 			else if (m_Operation.nOpMode&CSMODE_LIST)
 			else if (m_Operation.nOpMode&CSMODE_LIST)
-				ShowStatus(IDS_ERRORMSG_CANTGETLIST,1);
+				ShowStatus(IDS_ERRORMSG_CANTGETLIST,FZ_LOG_ERROR);
 			else if (m_Operation.nOpMode&CSMODE_LISTFILE)
 			else if (m_Operation.nOpMode&CSMODE_LISTFILE)
-				ShowStatus(IDS_ERRORMSG_CANTGETLISTFILE,1);
+				ShowStatus(IDS_ERRORMSG_CANTGETLISTFILE,FZ_LOG_ERROR);
 		}
 		}
 		else if (m_Operation.pData && m_Operation.nOpMode&CSMODE_TRANSFER && nSuccessful==FZ_REPLY_OK)
 		else if (m_Operation.pData && m_Operation.nOpMode&CSMODE_TRANSFER && nSuccessful==FZ_REPLY_OK)
-			ShowStatus(((CFileTransferData*)m_Operation.pData)->transferfile.get?IDS_STATUSMSG_DOWNLOADSUCCESSFUL:IDS_STATUSMSG_UPLOADSUCCESSFUL,0);
+			ShowStatus(((CFileTransferData*)m_Operation.pData)->transferfile.get?IDS_STATUSMSG_DOWNLOADSUCCESSFUL:IDS_STATUSMSG_UPLOADSUCCESSFUL,FZ_LOG_STATUS);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -4951,7 +4981,7 @@ public:
 		CServerPath newPath = path;
 		CServerPath newPath = path;
 		if (!newPath.AddSubdir(dirname))
 		if (!newPath.AddSubdir(dirname))
 		{
 		{
-			ShowStatus(_T("Unable to concatenate path"), 1);
+			ShowStatus(_T("Unable to concatenate path"), FZ_LOG_ERROR);
 			return;
 			return;
 		}
 		}
 		if (!Send(_MPT("RMD ")+ newPath.GetPath()))
 		if (!Send(_MPT("RMD ")+ newPath.GetPath()))
@@ -5219,7 +5249,7 @@ void CFtpControlSocket::SetFileExistsAction(int nAction, COverwriteRequestData *
 			CFileStatus64 status;
 			CFileStatus64 status;
 			if (GetStatus64(pData->FileName1, status))
 			if (GetStatus64(pData->FileName1, status))
 			{
 			{
-				ShowStatus(IDS_ERRORMSG_NAMEINUSE, 1);
+				ShowStatus(IDS_ERRORMSG_NAMEINUSE, FZ_LOG_ERROR);
 				nReplyError=  FZ_REPLY_CRITICALERROR;
 				nReplyError=  FZ_REPLY_CRITICALERROR;
 			}
 			}
 			else
 			else
@@ -5242,7 +5272,7 @@ void CFtpControlSocket::SetFileExistsAction(int nAction, COverwriteRequestData *
 			{
 			{
 				if (m_pDirectoryListing->direntry[i].name == pData->FileName1)
 				if (m_pDirectoryListing->direntry[i].name == pData->FileName1)
 				{
 				{
-					ShowStatus(IDS_ERRORMSG_NAMEINUSE, 1);
+					ShowStatus(IDS_ERRORMSG_NAMEINUSE, FZ_LOG_ERROR);
 					nReplyError = FZ_REPLY_CRITICALERROR;
 					nReplyError = FZ_REPLY_CRITICALERROR;
 					break;
 					break;
 				}
 				}
@@ -5781,7 +5811,7 @@ void CFtpControlSocket::SetAsyncRequestResult(int nAction, CAsyncRequestData *pD
 		if (!nAction)
 		if (!nAction)
 		{
 		{
 			DoClose(FZ_REPLY_CRITICALERROR|FZ_REPLY_CANCEL);
 			DoClose(FZ_REPLY_CRITICALERROR|FZ_REPLY_CANCEL);
-			ShowStatus(IDS_ERRORMSG_INTERRUPTED,1);
+			ShowStatus(IDS_ERRORMSG_INTERRUPTED,FZ_LOG_ERROR);
 			break;
 			break;
 		}
 		}
 		else
 		else
@@ -5807,7 +5837,7 @@ void CFtpControlSocket::SetAsyncRequestResult(int nAction, CAsyncRequestData *pD
 		if (!nAction)
 		if (!nAction)
 		{
 		{
 			DoClose(FZ_REPLY_CRITICALERROR|FZ_REPLY_CANCEL);
 			DoClose(FZ_REPLY_CRITICALERROR|FZ_REPLY_CANCEL);
-			ShowStatus(IDS_ERRORMSG_INTERRUPTED,1);
+			ShowStatus(IDS_ERRORMSG_INTERRUPTED,FZ_LOG_ERROR);
 			break;
 			break;
 		}
 		}
 		m_bCheckForTimeout = TRUE;
 		m_bCheckForTimeout = TRUE;
@@ -5826,7 +5856,7 @@ void CFtpControlSocket::SetAsyncRequestResult(int nAction, CAsyncRequestData *pD
 		if (!nAction)
 		if (!nAction)
 		{
 		{
 			DoClose(FZ_REPLY_CRITICALERROR|FZ_REPLY_CANCEL);
 			DoClose(FZ_REPLY_CRITICALERROR|FZ_REPLY_CANCEL);
-			ShowStatus(IDS_ERRORMSG_INTERRUPTED,1);
+			ShowStatus(IDS_ERRORMSG_INTERRUPTED,FZ_LOG_ERROR);
 			break;
 			break;
 		}
 		}
 		else
 		else
@@ -5849,7 +5879,7 @@ void CFtpControlSocket::SetAsyncRequestResult(int nAction, CAsyncRequestData *pD
 		if (!nAction)
 		if (!nAction)
 		{
 		{
 			DoClose(FZ_REPLY_CRITICALERROR | FZ_REPLY_CANCEL);
 			DoClose(FZ_REPLY_CRITICALERROR | FZ_REPLY_CANCEL);
-			ShowStatus(IDS_ERRORMSG_INTERRUPTED, 1);
+			ShowStatus(IDS_ERRORMSG_INTERRUPTED, FZ_LOG_ERROR);
 			break;
 			break;
 		}
 		}
 		else
 		else
@@ -5873,12 +5903,15 @@ int CFtpControlSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
 	{
 	{
 		if (iter->nType == LAYERCALLBACK_STATECHANGE)
 		if (iter->nType == LAYERCALLBACK_STATECHANGE)
 		{
 		{
+		    if (CAsyncSocketEx::LogStateChange(iter->nParam1, iter->nParam2))
+		    {
 #ifndef MPEXT_NO_SSL
 #ifndef MPEXT_NO_SSL
-			if (iter->pLayer == m_pSslLayer)
-			{
-				LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("m_pSslLayer changed state from %d to %d"), iter->nParam2, iter->nParam1);
-				delete [] iter->str;
-				continue;
+				if (iter->pLayer == m_pSslLayer)
+				{
+					LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("TLS layer changed state from %s to %s"), CAsyncSocketEx::GetStateDesc(iter->nParam2), CAsyncSocketEx::GetStateDesc(iter->nParam1));
+					delete [] iter->str;
+					continue;
+				}
 			}
 			}
 #endif
 #endif
 		}
 		}
@@ -5895,7 +5928,7 @@ int CFtpControlSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
 					switch (iter->nParam2)
 					switch (iter->nParam2)
 					{
 					{
 					case SSL_INFO_ESTABLISHED:
 					case SSL_INFO_ESTABLISHED:
-						ShowStatus(IDS_STATUSMSG_SSLESTABLISHED, 0);
+						ShowStatus(IDS_STATUSMSG_SSLESTABLISHED, FZ_LOG_STATUS);
 						PostMessage(m_pOwner->m_hOwnerWnd, m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_SECURESERVER, 1), 0);
 						PostMessage(m_pOwner->m_hOwnerWnd, m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_SECURESERVER, 1), 0);
 						if (m_Operation.nOpState == CONNECT_SSL_WAITDONE)
 						if (m_Operation.nOpState == CONNECT_SSL_WAITDONE)
 						{
 						{
@@ -5908,24 +5941,24 @@ int CFtpControlSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
 					switch (iter->nParam2)
 					switch (iter->nParam2)
 					{
 					{
 					case SSL_FAILURE_UNKNOWN:
 					case SSL_FAILURE_UNKNOWN:
-						ShowStatus(IDS_ERRORMSG_UNKNOWNSSLERROR, 1);
+						ShowStatus(IDS_ERRORMSG_UNKNOWNSSLERROR, FZ_LOG_ERROR);
 						break;
 						break;
 					case SSL_FAILURE_ESTABLISH:
 					case SSL_FAILURE_ESTABLISH:
-						ShowStatus(IDS_ERRORMSG_CANTESTABLISHSSLCONNECTION, 1);
+						ShowStatus(IDS_ERRORMSG_CANTESTABLISHSSLCONNECTION, FZ_LOG_ERROR);
 						break;
 						break;
 #ifndef MPEXT_NO_SSLDLL
 #ifndef MPEXT_NO_SSLDLL
 					case SSL_FAILURE_LOADDLLS:
 					case SSL_FAILURE_LOADDLLS:
-						ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, 1);
+						ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, FZ_LOG_ERROR);
 						break;
 						break;
 #endif
 #endif
 					case SSL_FAILURE_INITSSL:
 					case SSL_FAILURE_INITSSL:
-						ShowStatus(IDS_ERRORMSG_CANTINITSSL, 1);
+						ShowStatus(IDS_ERRORMSG_CANTINITSSL, FZ_LOG_ERROR);
 						break;
 						break;
 					case SSL_FAILURE_VERIFYCERT:
 					case SSL_FAILURE_VERIFYCERT:
-						ShowStatus(IDS_ERRORMSG_SSLCERTIFICATEERROR, 1);
+						ShowStatus(IDS_ERRORMSG_SSLCERTIFICATEERROR, FZ_LOG_ERROR);
 						break;
 						break;
 					case SSL_FAILURE_CERTREJECTED:
 					case SSL_FAILURE_CERTREJECTED:
-						ShowStatus(IDS_ERRORMSG_CERTREJECTED, 1);
+						ShowStatus(IDS_ERRORMSG_CERTREJECTED, FZ_LOG_ERROR);
 						m_bDidRejectCertificate = TRUE;
 						m_bDidRejectCertificate = TRUE;
 						break;
 						break;
 					}
 					}
@@ -6162,14 +6195,14 @@ void CFtpControlSocket::OnSend(int nErrorCode)
 	{
 	{
 		if (GetLastError() != WSAEWOULDBLOCK)
 		if (GetLastError() != WSAEWOULDBLOCK)
 		{
 		{
-			ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, 1);
+			ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, FZ_LOG_ERROR);
 			DoClose();
 			DoClose();
 		}
 		}
 		return;
 		return;
 	}
 	}
 	if (!res)
 	if (!res)
 	{
 	{
-		ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, 1);
+		ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, FZ_LOG_ERROR);
 		DoClose();
 		DoClose();
 	}
 	}
 
 

+ 3 - 1
source/filezilla/FtpControlSocket.h

@@ -87,7 +87,9 @@ public:
 	bool IsMisleadingListResponse();
 	bool IsMisleadingListResponse();
 
 
 #ifdef MPEXT
 #ifdef MPEXT
-	virtual bool __fastcall UsingMlsd();
+	virtual bool UsingMlsd();
+	virtual std::string GetTlsVersionStr();
+	virtual std::string GetCipherName();
 #endif
 #endif
 
 
 	// Vom Klassen-Assistenten generierte virtuelle Funktionsüberschreibungen
 	// Vom Klassen-Assistenten generierte virtuelle Funktionsüberschreibungen

+ 11 - 0
source/filezilla/FtpListResult.cpp

@@ -1028,6 +1028,8 @@ BOOL CFtpListResult::parseAsVMS(const char *line, const int linelen, t_directory
 	std::map<CString, int>::const_iterator iter;
 	std::map<CString, int>::const_iterator iter;
 	t_directory::t_direntry dir;
 	t_directory::t_direntry dir;
 	
 	
+	dir.bUnsure = FALSE;
+	
 	const char *str = GetNextToken(line, linelen, tokenlen, pos, 0);
 	const char *str = GetNextToken(line, linelen, tokenlen, pos, 0);
 	if (!str)
 	if (!str)
 		return FALSE;
 		return FALSE;
@@ -1301,6 +1303,7 @@ BOOL CFtpListResult::parseAsMlsd(const char *line, const int linelen, t_director
 	CString facts(str, tokenlen);
 	CString facts(str, tokenlen);
 	if (facts.IsEmpty())
 	if (facts.IsEmpty())
 		return FALSE;
 		return FALSE;
+	direntry.bUnsure = FALSE;
 	direntry.dir = FALSE;
 	direntry.dir = FALSE;
 	direntry.bLink = FALSE;
 	direntry.bLink = FALSE;
 	direntry.size = -1;
 	direntry.size = -1;
@@ -2556,6 +2559,8 @@ BOOL CFtpListResult::parseAsIBM(const char *line, const int linelen, t_directory
 
 
 	copyStr(direntry.name, 0, str, tokenlen, true);
 	copyStr(direntry.name, 0, str, tokenlen, true);
 
 
+	direntry.bUnsure = FALSE;
+
 	return true;
 	return true;
 }
 }
 
 
@@ -2660,6 +2665,9 @@ BOOL CFtpListResult::parseAsIBMMVS(const char *line, const int linelen, t_direct
 	if (!str)
 	if (!str)
 		return FALSE;
 		return FALSE;
 	copyStr(direntry.name, 0, str, tokenlen, true);
 	copyStr(direntry.name, 0, str, tokenlen, true);
+
+	direntry.bUnsure = FALSE;
+
 	return true;
 	return true;
 }
 }
 
 
@@ -2726,6 +2734,7 @@ BOOL CFtpListResult::parseAsIBMMVSPDS(const char *line, const int linelen, t_dir
 		return FALSE;
 		return FALSE;
 	
 	
 	direntry.dir = FALSE;
 	direntry.dir = FALSE;
+	direntry.bUnsure = FALSE;
 	
 	
 	return true;
 	return true;
 }
 }
@@ -2742,6 +2751,7 @@ BOOL CFtpListResult::parseAsIBMMVSPDS2(const char *line, const int linelen, t_di
 	int pos = 0;
 	int pos = 0;
 	int tokenlen = 0;
 	int tokenlen = 0;
 
 
+	direntry.bUnsure = FALSE;
 	direntry.dir = FALSE;
 	direntry.dir = FALSE;
 	direntry.bLink = FALSE;
 	direntry.bLink = FALSE;
 	direntry.ownergroup = _MPT("");
 	direntry.ownergroup = _MPT("");
@@ -2969,6 +2979,7 @@ BOOL CFtpListResult::parseAsWfFtp(const char *line, const int linelen, t_directo
 	if (!parseTime(str, tokenlen, direntry.date))
 	if (!parseTime(str, tokenlen, direntry.date))
 		return FALSE;
 		return FALSE;
 
 
+	direntry.bUnsure = FALSE;
 	direntry.dir = false;
 	direntry.dir = false;
 	direntry.bLink = false;
 	direntry.bLink = false;
 	direntry.permissionstr = _T("");
 	direntry.permissionstr = _T("");

+ 15 - 1
source/filezilla/MainThread.cpp

@@ -411,12 +411,26 @@ void CMainThread::SetOption(int nOption, int nValue)
 	LCS;
 	LCS;
 }
 }
 #else
 #else
-bool __fastcall CMainThread::UsingMlsd()
+bool CMainThread::UsingMlsd()
 {
 {
 	if (!IsConnected())
 	if (!IsConnected())
 		return false;
 		return false;
 	return m_pControlSocket->UsingMlsd();
 	return m_pControlSocket->UsingMlsd();
 }
 }
+
+std::string CMainThread::GetTlsVersionStr()
+{
+	if (!IsConnected())
+		return std::string();
+	return m_pControlSocket->GetTlsVersionStr();
+}
+
+std::string CMainThread::GetCipherName()
+{
+	if (!IsConnected())
+		return std::string();
+	return m_pControlSocket->GetCipherName();
+}
 #endif
 #endif
 
 
 BOOL CMainThread::GetWorkingDir(t_directory *pWorkingDir)
 BOOL CMainThread::GetWorkingDir(t_directory *pWorkingDir)

+ 3 - 1
source/filezilla/MainThread.h

@@ -68,7 +68,9 @@ public:
 	void SetOption(int nOption, int nValue);
 	void SetOption(int nOption, int nValue);
 	int GetOption(int nOption);
 	int GetOption(int nOption);
 #else
 #else
-    bool __fastcall UsingMlsd();
+	bool UsingMlsd();
+	std::string GetTlsVersionStr();
+	std::string GetCipherName();
 #endif
 #endif
 	t_command m_LastCommand;
 	t_command m_LastCommand;
 #ifndef MPEXT_NO_CACHE
 #ifndef MPEXT_NO_CACHE

+ 42 - 31
source/filezilla/TransferSocket.cpp

@@ -386,7 +386,7 @@ void CTransferSocket::OnReceive(int nErrorCode)
 		{
 		{
 			LPTSTR msg = new TCHAR[BUFSIZE];
 			LPTSTR msg = new TCHAR[BUFSIZE];
 			if (e->GetErrorMessage(msg, BUFSIZE))
 			if (e->GetErrorMessage(msg, BUFSIZE))
-				m_pOwner->ShowStatus(msg, 1);
+				m_pOwner->ShowStatus(msg, FZ_LOG_ERROR);
 			delete [] msg;
 			delete [] msg;
 			Close();
 			Close();
 			if (!m_bSentClose)
 			if (!m_bSentClose)
@@ -437,14 +437,17 @@ void CTransferSocket::OnAccept(int nErrorCode)
 		if (m_pSslLayer)
 		if (m_pSslLayer)
 		{
 		{
 			AddLayer(m_pSslLayer);
 			AddLayer(m_pSslLayer);
-			int res = m_pSslLayer->InitSSLConnection(true, m_pOwner->m_pSslLayer, COptions::GetOptionVal(OPTION_MPEXT_SSLSESSIONREUSE));
+			int res = m_pSslLayer->InitSSLConnection(true, m_pOwner->m_pSslLayer,
+				COptions::GetOptionVal(OPTION_MPEXT_SSLSESSIONREUSE),
+				COptions::GetOptionVal(OPTION_MPEXT_MIN_TLS_VERSION),
+				COptions::GetOptionVal(OPTION_MPEXT_MAX_TLS_VERSION));
 #ifndef MPEXT_NO_SSLDLL
 #ifndef MPEXT_NO_SSLDLL
 			if (res == SSL_FAILURE_LOADDLLS)
 			if (res == SSL_FAILURE_LOADDLLS)
-				m_pOwner->ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, 1);
+				m_pOwner->ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, FZ_LOG_ERROR);
 			else
 			else
 #endif
 #endif
 			if (res == SSL_FAILURE_INITSSL)
 			if (res == SSL_FAILURE_INITSSL)
-				m_pOwner->ShowStatus(IDS_ERRORMSG_CANTINITSSL, 1);
+				m_pOwner->ShowStatus(IDS_ERRORMSG_CANTINITSSL, FZ_LOG_ERROR);
 
 
 			if (res)
 			if (res)
 			{
 			{
@@ -484,7 +487,7 @@ void CTransferSocket::OnConnect(int nErrorCode)
 		str.Format(IDS_ERRORMSG_CANTOPENTRANSFERCHANNEL,buffer);
 		str.Format(IDS_ERRORMSG_CANTOPENTRANSFERCHANNEL,buffer);
 		str.Replace( _T("\n"), _T("\0") );
 		str.Replace( _T("\n"), _T("\0") );
 		str.Replace( _T("\r"), _T("\0") );
 		str.Replace( _T("\r"), _T("\0") );
-		m_pOwner->ShowStatus(str, 1);
+		m_pOwner->ShowStatus(str, FZ_LOG_ERROR);
 		Close();
 		Close();
 		if (!m_bSentClose)
 		if (!m_bSentClose)
 		{
 		{
@@ -520,14 +523,17 @@ void CTransferSocket::OnConnect(int nErrorCode)
 		if (m_pSslLayer)
 		if (m_pSslLayer)
 		{
 		{
 			AddLayer(m_pSslLayer);
 			AddLayer(m_pSslLayer);
-			int res = m_pSslLayer->InitSSLConnection(true, m_pOwner->m_pSslLayer, COptions::GetOptionVal(OPTION_MPEXT_SSLSESSIONREUSE));
+			int res = m_pSslLayer->InitSSLConnection(true, m_pOwner->m_pSslLayer,
+				COptions::GetOptionVal(OPTION_MPEXT_SSLSESSIONREUSE),
+				COptions::GetOptionVal(OPTION_MPEXT_MIN_TLS_VERSION),
+				COptions::GetOptionVal(OPTION_MPEXT_MAX_TLS_VERSION));
 #ifndef MPEXT_NO_SSLDLL
 #ifndef MPEXT_NO_SSLDLL
 			if (res == SSL_FAILURE_LOADDLLS)
 			if (res == SSL_FAILURE_LOADDLLS)
-				m_pOwner->ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, 1);
+				m_pOwner->ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, FZ_LOG_ERROR);
 			else
 			else
 #endif
 #endif
 			if (res == SSL_FAILURE_INITSSL)
 			if (res == SSL_FAILURE_INITSSL)
-				m_pOwner->ShowStatus(IDS_ERRORMSG_CANTINITSSL, 1);
+				m_pOwner->ShowStatus(IDS_ERRORMSG_CANTINITSSL, FZ_LOG_ERROR);
 					
 					
 			if (res)
 			if (res)
 			{
 			{
@@ -584,7 +590,7 @@ int CTransferSocket::CheckForTimeout(int delay)
 	CTimeSpan span = CTime::GetCurrentTime()-m_LastActiveTime;
 	CTimeSpan span = CTime::GetCurrentTime()-m_LastActiveTime;
 	if (span.GetTotalSeconds()>=delay)
 	if (span.GetTotalSeconds()>=delay)
 	{
 	{
-		m_pOwner->ShowStatus(IDS_ERRORMSG_TIMEOUT, 1);
+		m_pOwner->ShowStatus(IDS_ERRORMSG_TIMEOUT, FZ_LOG_ERROR);
 		Close();
 		Close();
 		if (!m_bSentClose)
 		if (!m_bSentClose)
 		{
 		{
@@ -698,7 +704,7 @@ void CTransferSocket::OnSend(int nErrorCode)
 				res = deflate(&m_zlibStream, m_pFile ? 0 : Z_FINISH);
 				res = deflate(&m_zlibStream, m_pFile ? 0 : Z_FINISH);
 				if (res != Z_OK && (!m_pFile && res != Z_STREAM_END))
 				if (res != Z_OK && (!m_pFile && res != Z_STREAM_END))
 				{
 				{
-					m_pOwner->ShowStatus("ZLib error", 1);
+					m_pOwner->ShowStatus("ZLib error", FZ_LOG_ERROR);
 					Close();
 					Close();
 					if (!m_bSentClose)
 					if (!m_bSentClose)
 					{
 					{
@@ -1176,7 +1182,7 @@ BOOL CTransferSocket::Create(
 		int max=COptions::GetOptionVal(OPTION_PORTRANGEHIGH);
 		int max=COptions::GetOptionVal(OPTION_PORTRANGEHIGH);
 		if (min>=max)
 		if (min>=max)
 		{
 		{
-			m_pOwner->ShowStatus(IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE,1);
+			m_pOwner->ShowStatus(IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE,FZ_LOG_ERROR);
 			return FALSE;
 			return FALSE;
 		}
 		}
 		int startport=static_cast<int>(min+((double)rand()*(max-min))/(RAND_MAX+1));
 		int startport=static_cast<int>(min+((double)rand()*(max-min))/(RAND_MAX+1));
@@ -1188,7 +1194,7 @@ BOOL CTransferSocket::Create(
 				port=min;
 				port=min;
 			if (port==startport)
 			if (port==startport)
 			{
 			{
-				m_pOwner->ShowStatus(IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE,1);
+				m_pOwner->ShowStatus(IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE,FZ_LOG_ERROR);
 				return FALSE;
 				return FALSE;
 			}
 			}
 		}
 		}
@@ -1210,18 +1216,23 @@ int CTransferSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
 	{
 	{
 		if (iter->nType == LAYERCALLBACK_STATECHANGE)
 		if (iter->nType == LAYERCALLBACK_STATECHANGE)
 		{
 		{
-			if (iter->pLayer == m_pProxyLayer)
-				LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("m_pProxyLayer changed state from %d to %d"), iter->nParam2, iter->nParam1);
+		    if (CAsyncSocketEx::LogStateChange(iter->nParam1, iter->nParam2))
+		    {
+			    const TCHAR * state2Desc = CAsyncSocketEx::GetStateDesc(iter->nParam2);
+			    const TCHAR * state1Desc = CAsyncSocketEx::GetStateDesc(iter->nParam1);
+				if (iter->pLayer == m_pProxyLayer)
+					LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("Proxy layer changed state from %s to %s"), state2Desc, state1Desc);
 #ifndef MPEXT_NO_SSL
 #ifndef MPEXT_NO_SSL
-			else if (iter->pLayer == m_pSslLayer)
-				LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("m_pSslLayer changed state from %d to %d"), iter->nParam2, iter->nParam1);
+				else if (iter->pLayer == m_pSslLayer)
+					LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("TLS layer changed state from %s to %s"), state2Desc, state1Desc);
 #endif
 #endif
 #ifndef MPEXT_NO_GSS
 #ifndef MPEXT_NO_GSS
-			else if (iter->pLayer == m_pGssLayer)
-				LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("m_pGssLayer changed state from %d to %d"), iter->nParam2, iter->nParam1);
+				else if (iter->pLayer == m_pGssLayer)
+					LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("GSS layer changed state from %s to %s"), state2Desc, state1Desc);
 #endif
 #endif
-			else
-				LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("Layer @ %d changed state from %d to %d"), iter->pLayer, iter->nParam2, iter->nParam1);
+				else
+					LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("Layer @ %d changed state from %s to %s"), iter->pLayer, state2Desc, state1Desc);
+			}
 		}
 		}
 		else if (iter->nType == LAYERCALLBACK_LAYERSPECIFIC)
 		else if (iter->nType == LAYERCALLBACK_LAYERSPECIFIC)
 		{
 		{
@@ -1230,22 +1241,22 @@ int CTransferSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
 				switch (iter->nParam1)
 				switch (iter->nParam1)
 				{
 				{
 				case PROXYERROR_NOCONN:
 				case PROXYERROR_NOCONN:
-					m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_NOCONN, 1);
+					m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_NOCONN, FZ_LOG_ERROR);
 					break;
 					break;
 				case PROXYERROR_REQUESTFAILED:
 				case PROXYERROR_REQUESTFAILED:
-					m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_REQUESTFAILED, 1);
+					m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_REQUESTFAILED, FZ_LOG_ERROR);
 					break;
 					break;
 				case PROXYERROR_AUTHTYPEUNKNOWN:
 				case PROXYERROR_AUTHTYPEUNKNOWN:
-					m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_AUTHTYPEUNKNOWN, 1);
+					m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_AUTHTYPEUNKNOWN, FZ_LOG_ERROR);
 					break;
 					break;
 				case PROXYERROR_AUTHFAILED:
 				case PROXYERROR_AUTHFAILED:
-					m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_AUTHFAILED, 1);
+					m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_AUTHFAILED, FZ_LOG_ERROR);
 					break;
 					break;
 				case PROXYERROR_AUTHNOLOGON:
 				case PROXYERROR_AUTHNOLOGON:
-					m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_AUTHNOLOGON, 1);
+					m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_AUTHNOLOGON, FZ_LOG_ERROR);
 					break;
 					break;
 				case PROXYERROR_CANTRESOLVEHOST:
 				case PROXYERROR_CANTRESOLVEHOST:
-					m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_CANTRESOLVEHOST, 1);
+					m_pOwner->ShowStatus(IDS_ERRORMSG_PROXY_CANTRESOLVEHOST, FZ_LOG_ERROR);
 					break;
 					break;
 				default:
 				default:
 					LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Unknown proxy error"));
 					LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Unknown proxy error"));
@@ -1268,7 +1279,7 @@ int CTransferSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
 						}
 						}
 						break;
 						break;
 					case SSL_INFO_ESTABLISHED:
 					case SSL_INFO_ESTABLISHED:
-						m_pOwner->ShowStatus(IDS_STATUSMSG_SSLESTABLISHEDTRANSFER, 0);
+						m_pOwner->ShowStatus(IDS_STATUSMSG_SSLESTABLISHEDTRANSFER, FZ_LOG_STATUS);
 						TriggerEvent(FD_FORCEREAD);
 						TriggerEvent(FD_FORCEREAD);
 						break;
 						break;
 					}
 					}
@@ -1277,15 +1288,15 @@ int CTransferSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
 					switch (iter->nParam2)
 					switch (iter->nParam2)
 					{
 					{
 					case SSL_FAILURE_ESTABLISH:
 					case SSL_FAILURE_ESTABLISH:
-						m_pOwner->ShowStatus(IDS_ERRORMSG_CANTESTABLISHSSLCONNECTION, 1);
+						m_pOwner->ShowStatus(IDS_ERRORMSG_CANTESTABLISHSSLCONNECTION, FZ_LOG_ERROR);
 						break;
 						break;
 #ifndef MPEXT_NO_SSLDLL
 #ifndef MPEXT_NO_SSLDLL
 					case SSL_FAILURE_LOADDLLS:
 					case SSL_FAILURE_LOADDLLS:
-						m_pOwner->ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, 1);
+						m_pOwner->ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, FZ_LOG_ERROR);
 						break;
 						break;
 #endif
 #endif
 					case SSL_FAILURE_INITSSL:
 					case SSL_FAILURE_INITSSL:
-						m_pOwner->ShowStatus(IDS_ERRORMSG_CANTINITSSL, 1);
+						m_pOwner->ShowStatus(IDS_ERRORMSG_CANTINITSSL, FZ_LOG_ERROR);
 						break;
 						break;
 					}
 					}
 					if (!m_bSentClose)
 					if (!m_bSentClose)
@@ -1438,7 +1449,7 @@ int CTransferSocket::ReadDataFromFile(char *buffer, int len)
 	{
 	{
 		TCHAR error[BUFSIZE];
 		TCHAR error[BUFSIZE];
 		if (e->GetErrorMessage(error, BUFSIZE))
 		if (e->GetErrorMessage(error, BUFSIZE))
-			m_pOwner->ShowStatus(error, 1);
+			m_pOwner->ShowStatus(error, FZ_LOG_ERROR);
 		if (ShutDown() || GetLastError() != WSAEWOULDBLOCK)
 		if (ShutDown() || GetLastError() != WSAEWOULDBLOCK)
 		{
 		{
 			Close();
 			Close();

+ 1 - 0
source/forms/Custom.cpp

@@ -335,6 +335,7 @@ TSessionData * __fastcall DoSaveSession(TSessionData * SessionData,
   bool Result;
   bool Result;
   if (!ForceDialog && ((PSavePassword == NULL) || SavePassword))
   if (!ForceDialog && ((PSavePassword == NULL) || SavePassword))
   {
   {
+    CustomWinConfiguration->AskForMasterPasswordIfNotSetAndNeededToPersistSessionData(SessionData);
     Result = true;
     Result = true;
   }
   }
   else
   else

+ 37 - 9
source/forms/CustomScpExplorer.cpp

@@ -260,7 +260,7 @@ __fastcall TCustomScpExplorerForm::TCustomScpExplorerForm(TComponent* Owner):
   AddNewSessionImage();
   AddNewSessionImage();
   SessionsPageControl->Images = FSessionColors;
   SessionsPageControl->Images = FSessionColors;
   QueueLabel->FocusControl = QueueView3;
   QueueLabel->FocusControl = QueueView3;
-  QueueLabel->Caption = LoadStr(QUEUE_CAPTION);
+  UpdateQueueLabel();
 
 
   CreateHiddenWindow();
   CreateHiddenWindow();
   StartUpdates();
   StartUpdates();
@@ -550,8 +550,8 @@ void __fastcall TCustomScpExplorerForm::UpdateQueueStatus(bool QueueChanging)
     Configuration->Usage->SetMax(L"MaxQueueLength", FMaxQueueLength);
     Configuration->Usage->SetMax(L"MaxQueueLength", FMaxQueueLength);
   }
   }
 
 
-  SetQueueTaskbarProgress();
   FQueueController->UpdateQueueStatus(FQueueStatus);
   FQueueController->UpdateQueueStatus(FQueueStatus);
+  SetQueueProgress();
 
 
   UpdateQueueView();
   UpdateQueueView();
 
 
@@ -580,8 +580,8 @@ UnicodeString __fastcall TCustomScpExplorerForm::GetQueueProgressTitle()
   UnicodeString Result;
   UnicodeString Result;
   if (FQueueStatus != NULL)
   if (FQueueStatus != NULL)
   {
   {
-    int ActiveCount = FQueueStatus->ActiveCount;
-    if (ActiveCount == 1)
+    int ActiveAndPendingCount = FQueueStatus->ActiveAndPendingCount;
+    if ((ActiveAndPendingCount == 1) && (FQueueStatus->ActiveCount == 1))
     {
     {
       TFileOperationProgressType * ProgressData =
       TFileOperationProgressType * ProgressData =
         FQueueStatus->Items[FQueueStatus->DoneCount]->ProgressData;
         FQueueStatus->Items[FQueueStatus->DoneCount]->ProgressData;
@@ -590,9 +590,9 @@ UnicodeString __fastcall TCustomScpExplorerForm::GetQueueProgressTitle()
         Result = TTerminalManager::ProgressTitle(ProgressData);
         Result = TTerminalManager::ProgressTitle(ProgressData);
       }
       }
     }
     }
-    else if (ActiveCount > 1)
+    else if (ActiveAndPendingCount > 1)
     {
     {
-      Result = FMTLOAD(PROGRESS_IN_QUEUE, (ActiveCount));
+      Result = FMTLOAD(PROGRESS_IN_QUEUE, (ActiveAndPendingCount));
     }
     }
   }
   }
   return Result;
   return Result;
@@ -699,12 +699,12 @@ void __fastcall TCustomScpExplorerForm::RefreshQueueItems()
     if (Updated)
     if (Updated)
     {
     {
       NonVisualDataModule->UpdateNonVisibleActions();
       NonVisualDataModule->UpdateNonVisibleActions();
-      SetQueueTaskbarProgress();
+      SetQueueProgress();
     }
     }
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
-void __fastcall TCustomScpExplorerForm::SetQueueTaskbarProgress()
+void __fastcall TCustomScpExplorerForm::SetQueueProgress()
 {
 {
   TTerminalManager::Instance()->QueueStatusUpdated();
   TTerminalManager::Instance()->QueueStatusUpdated();
 
 
@@ -744,6 +744,22 @@ void __fastcall TCustomScpExplorerForm::SetQueueTaskbarProgress()
       FTaskbarList->SetProgressState(Handle, TBPF_NOPROGRESS);
       FTaskbarList->SetProgressState(Handle, TBPF_NOPROGRESS);
     }
     }
   }
   }
+
+  UpdateQueueLabel();
+}
+//---------------------------------------------------------------------------
+void __fastcall TCustomScpExplorerForm::UpdateQueueLabel()
+{
+  UnicodeString Caption = LoadStr(QUEUE_CAPTION);
+  if (FQueueStatus != NULL)
+  {
+    int ActiveAndPendingCount = FQueueStatus->ActiveAndPendingCount;
+    if (ActiveAndPendingCount > 0)
+    {
+      Caption = FORMAT("%s (%d)", (Caption, ActiveAndPendingCount));
+    }
+  }
+  QueueLabel->Caption = Caption;
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::UpdateTransferList()
 void __fastcall TCustomScpExplorerForm::UpdateTransferList()
@@ -1139,7 +1155,7 @@ void __fastcall TCustomScpExplorerForm::FileOperationProgress(
   {
   {
     SAFE_DESTROY(FProgressForm);
     SAFE_DESTROY(FProgressForm);
 
 
-    SetQueueTaskbarProgress();
+    SetQueueProgress();
 
 
     if ((ProgressData.Operation != foCalculateSize) &&
     if ((ProgressData.Operation != foCalculateSize) &&
         (ProgressData.Cancel == csContinue) &&
         (ProgressData.Cancel == csContinue) &&
@@ -7419,6 +7435,18 @@ void __fastcall TCustomScpExplorerForm::SessionsPageControlMouseDown(
     {
     {
       SessionsPageControl->ActivePageIndex = Index;
       SessionsPageControl->ActivePageIndex = Index;
       SessionsPageControlChange(NULL);
       SessionsPageControlChange(NULL);
+
+      // copied from TControl.WMContextMenu
+      SendCancelMode(SessionsPageControl);
+
+      // explicit popup instead of using PopupMenu property
+      // to avoid menu to popup somewhere within SessionsPageControlChange above,
+      // while connecting yet not-connected session and hence
+      // allowing an access to commands over not-completelly connected session
+      TPoint Point = SessionsPageControl->ClientToScreen(TPoint(X, Y));
+      TPopupMenu * PopupMenu = NonVisualDataModule->SessionsPopup;
+      PopupMenu->PopupComponent = SessionsPageControl;
+      PopupMenu->Popup(Point.x, Point.y);
     }
     }
     else if (Button == mbLeft)
     else if (Button == mbLeft)
     {
     {

+ 0 - 1
source/forms/CustomScpExplorer.dfm

@@ -296,7 +296,6 @@ object CustomScpExplorerForm: TCustomScpExplorerForm
     Align = alTop
     Align = alTop
     DoubleBuffered = True
     DoubleBuffered = True
     ParentDoubleBuffered = False
     ParentDoubleBuffered = False
-    PopupMenu = NonVisualDataModule.SessionsPopup
     TabOrder = 3
     TabOrder = 3
     TabStop = False
     TabStop = False
     OnChange = SessionsPageControlChange
     OnChange = SessionsPageControlChange

+ 2 - 1
source/forms/CustomScpExplorer.h

@@ -493,7 +493,8 @@ protected:
   void __fastcall DirViewContextPopup(
   void __fastcall DirViewContextPopup(
     TOperationSide Side, Byte PopupComponent, const TPoint & MousePos);
     TOperationSide Side, Byte PopupComponent, const TPoint & MousePos);
   bool __fastcall CommandLineFromAnotherInstance(const UnicodeString & CommandLine);
   bool __fastcall CommandLineFromAnotherInstance(const UnicodeString & CommandLine);
-  void __fastcall SetQueueTaskbarProgress();
+  void __fastcall SetQueueProgress();
+  void __fastcall UpdateQueueLabel();
 
 
 public:
 public:
   virtual __fastcall ~TCustomScpExplorerForm();
   virtual __fastcall ~TCustomScpExplorerForm();

+ 2 - 5
source/forms/FileSystemInfo.cpp

@@ -92,7 +92,8 @@ UnicodeString __fastcall TFileSystemInfoDialog::SpaceStr(__int64 Bytes)
 void __fastcall TFileSystemInfoDialog::Feed(TFeedFileSystemData AddItem)
 void __fastcall TFileSystemInfoDialog::Feed(TFeedFileSystemData AddItem)
 {
 {
   AddItem(ServerView, FSINFO_REMOTE_SYSTEM, FFileSystemInfo.RemoteSystem);
   AddItem(ServerView, FSINFO_REMOTE_SYSTEM, FFileSystemInfo.RemoteSystem);
-  AddItem(ServerView, FSINFO_SESSION_PROTOCOL, FSessionInfo.ProtocolName);
+  AddItem(ServerView, FSINFO_FS_PROTOCOL, FFileSystemInfo.ProtocolName);
+  AddItem(ServerView, FSINFO_CRYPTOGRAPHIC_PROTOCOL, FSessionInfo.SecurityProtocolName);
   AddItem(ServerView, FSINFO_SSH_IMPLEMENTATION, FSessionInfo.SshImplementation);
   AddItem(ServerView, FSINFO_SSH_IMPLEMENTATION, FSessionInfo.SshImplementation);
 
 
   UnicodeString Str = FSessionInfo.CSCipher;
   UnicodeString Str = FSessionInfo.CSCipher;
@@ -108,10 +109,6 @@ void __fastcall TFileSystemInfoDialog::Feed(TFeedFileSystemData AddItem)
     Str += FORMAT(L"/%s", (DefaultStr(FSessionInfo.SCCompression, LoadStr(NO_STR))));
     Str += FORMAT(L"/%s", (DefaultStr(FSessionInfo.SCCompression, LoadStr(NO_STR))));
   }
   }
   AddItem(ServerView, FSINFO_COMPRESSION, Str);
   AddItem(ServerView, FSINFO_COMPRESSION, Str);
-  if (FSessionInfo.ProtocolName != FFileSystemInfo.ProtocolName)
-  {
-    AddItem(ServerView, FSINFO_FS_PROTOCOL, FFileSystemInfo.ProtocolName);
-  }
 
 
   AddItem(HostKeyFingerprintEdit, 0, FSessionInfo.HostKeyFingerprint);
   AddItem(HostKeyFingerprintEdit, 0, FSessionInfo.HostKeyFingerprint);
   AddItem(CertificateFingerprintEdit, 0, FSessionInfo.CertificateFingerprint);
   AddItem(CertificateFingerprintEdit, 0, FSessionInfo.CertificateFingerprint);

+ 164 - 58
source/forms/Login.cpp

@@ -54,9 +54,7 @@ __fastcall TLoginDialog::TLoginDialog(TComponent* AOwner)
         : TForm(AOwner)
         : TForm(AOwner)
 {
 {
   FNewSiteData = new TSessionData(L"");
   FNewSiteData = new TSessionData(L"");
-  FSessionData = new TSessionData(L"");
   FInitialized = false;
   FInitialized = false;
-  FSavedSession = -1;
   FOptions = loStartup;
   FOptions = loStartup;
   FLocaleChanging = false;
   FLocaleChanging = false;
   FHintNode = NULL;
   FHintNode = NULL;
@@ -71,6 +69,9 @@ __fastcall TLoginDialog::TLoginDialog(TComponent* AOwner)
   // we need to make sure that window procedure is set asap
   // we need to make sure that window procedure is set asap
   // (so that CM_SHOWINGCHANGED handling is applied)
   // (so that CM_SHOWINGCHANGED handling is applied)
   UseSystemSettingsPre(this, &FSystemSettings);
   UseSystemSettingsPre(this, &FSystemSettings);
+
+  FOriginalSize = BoundsRect.GetSize();
+  FBasicGroupBaseHeight = BasicGroup->Height - BasicSshPanel->Height - BasicFtpPanel->Height;
   InitControls();
   InitControls();
 }
 }
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
@@ -81,7 +82,13 @@ __fastcall TLoginDialog::~TLoginDialog()
   DeleteSystemSettings(this, FSystemSettings);
   DeleteSystemSettings(this, FSystemSettings);
   FSystemSettings = NULL;
   FSystemSettings = NULL;
   delete FNewSiteData;
   delete FNewSiteData;
+  InvalidateSessionData();
+}
+//---------------------------------------------------------------------
+void __fastcall TLoginDialog::InvalidateSessionData()
+{
   delete FSessionData;
   delete FSessionData;
+  FSessionData = NULL;
 }
 }
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 void __fastcall TLoginDialog::Init(TStoredSessionList *SessionList,
 void __fastcall TLoginDialog::Init(TStoredSessionList *SessionList,
@@ -104,14 +111,15 @@ void __fastcall TLoginDialog::InitControls()
     SessionTree->WindowProc = SessionTreeProc;
     SessionTree->WindowProc = SessionTreeProc;
   }
   }
 
 
-  FtpsCombo->Items->Strings[1] = LoadStr(FTPS_IMPLICIT);
-  FtpsCombo->Items->Strings[2] = LoadStr(FTPS_EXPLICIT_SSL);
-  FtpsCombo->Items->Strings[3] = LoadStr(FTPS_EXPLICIT_TLS);
-  WebDavsCombo->Items->Strings[0] = FtpsCombo->Items->Strings[0];
-  WebDavsCombo->Items->Strings[1] = FtpsCombo->Items->Strings[1];
+  int FtpsNoneIndex = FtpsToIndex(ftpsNone);
+  int FtpsImplicitIndex = FtpsToIndex(ftpsImplicit);
+  FtpsCombo->Items->Strings[FtpsImplicitIndex] = LoadStr(FTPS_IMPLICIT);
+  FtpsCombo->Items->Strings[FtpsToIndex(ftpsExplicitTls)] = LoadStr(FTPS_EXPLICIT_TLS);
+  FtpsCombo->Items->Strings[FtpsToIndex(ftpsExplicitSsl)] = LoadStr(FTPS_EXPLICIT_SSL);
+  WebDavsCombo->Items->Strings[FtpsNoneIndex] = FtpsCombo->Items->Strings[FtpsNoneIndex];
+  WebDavsCombo->Items->Strings[FtpsImplicitIndex] = FtpsCombo->Items->Strings[FtpsImplicitIndex];
 
 
   BasicSshPanel->Top = BasicFtpPanel->Top;
   BasicSshPanel->Top = BasicFtpPanel->Top;
-  FBasicGroupBaseHeight = BasicGroup->Height - BasicSshPanel->Height - BasicFtpPanel->Height;
 
 
   SitesIncrementalSearchLabel->AutoSize = false;
   SitesIncrementalSearchLabel->AutoSize = false;
   SitesIncrementalSearchLabel->Left = SessionTree->Left;
   SitesIncrementalSearchLabel->Left = SessionTree->Left;
@@ -353,25 +361,53 @@ void __fastcall TLoginDialog::LoadContents()
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 void __fastcall TLoginDialog::LoadSession(TSessionData * SessionData)
 void __fastcall TLoginDialog::LoadSession(TSessionData * SessionData)
 {
 {
-  UserNameEdit->Text = SessionData->UserName;
-  PortNumberEdit->AsInteger = SessionData->PortNumber;
-  HostNameEdit->Text = SessionData->HostName;
-  PasswordEdit->Text = SessionData->Password;
-  FtpsCombo->ItemIndex = SessionData->Ftps;
-  WebDavsCombo->ItemIndex = SessionData->Ftps;
-  EncryptionView->Text =
-    ALWAYS_TRUE(FtpsCombo->ItemIndex >= WebDavsCombo->ItemIndex) ? FtpsCombo->Text : WebDavsCombo->Text;
-
-  bool AllowScpFallback;
-  TransferProtocolCombo->ItemIndex = FSProtocolToIndex(SessionData->FSProtocol, AllowScpFallback);
-  TransferProtocolView->Text = TransferProtocolCombo->Text;
-
-  // just in case TransferProtocolComboChange is not triggered
-  FDefaultPort = DefaultPort();
-  FUpdatePortWithProtocol = true;
+  WinConfiguration->BeginMasterPasswordSession();
+  try
+  {
+    UserNameEdit->Text = SessionData->UserName;
+    PortNumberEdit->AsInteger = SessionData->PortNumber;
+    HostNameEdit->Text = SessionData->HostName;
 
 
-  // advanced
-  FSessionData->Assign(SessionData);
+    bool Editable = FEditing || (SessionData == FNewSiteData);
+    if (Editable)
+    {
+      PasswordEdit->Text = SessionData->Password;
+    }
+    else
+    {
+      PasswordEdit->Text =
+        SessionData->HasPassword() ?
+          UnicodeString::StringOfChar(L'?', 16) : UnicodeString();
+    }
+
+    int FtpsIndex = FtpsToIndex(SessionData->Ftps);
+    FtpsCombo->ItemIndex = FtpsIndex;
+    WebDavsCombo->ItemIndex = FtpsIndex;
+    EncryptionView->Text =
+      ALWAYS_TRUE(FtpsCombo->ItemIndex >= WebDavsCombo->ItemIndex) ? FtpsCombo->Text : WebDavsCombo->Text;
+
+    bool AllowScpFallback;
+    TransferProtocolCombo->ItemIndex = FSProtocolToIndex(SessionData->FSProtocol, AllowScpFallback);
+    TransferProtocolView->Text = TransferProtocolCombo->Text;
+
+    // just in case TransferProtocolComboChange is not triggered
+    FDefaultPort = DefaultPort();
+    FUpdatePortWithProtocol = true;
+
+    // advanced
+    InvalidateSessionData();
+    // close advanced settings only when really needed,
+    // see also note in SessionAdvancedActionExecute
+    if (Editable)
+    {
+      FSessionData = new TSessionData(L"");
+      FSessionData->Assign(SessionData);
+    }
+  }
+  __finally
+  {
+    WinConfiguration->EndMasterPasswordSession();
+  }
 
 
   UpdateControls();
   UpdateControls();
 }
 }
@@ -379,7 +415,10 @@ void __fastcall TLoginDialog::LoadSession(TSessionData * SessionData)
 void __fastcall TLoginDialog::SaveSession(TSessionData * SessionData)
 void __fastcall TLoginDialog::SaveSession(TSessionData * SessionData)
 {
 {
   // advanced
   // advanced
-  SessionData->Assign(FSessionData);
+  if (ALWAYS_TRUE(FSessionData != NULL))
+  {
+    SessionData->Assign(FSessionData);
+  }
 
 
   // Basic page
   // Basic page
   SessionData->UserName = UserNameEdit->Text.Trim();
   SessionData->UserName = UserNameEdit->Text.Trim();
@@ -389,7 +428,9 @@ void __fastcall TLoginDialog::SaveSession(TSessionData * SessionData)
   SessionData->Password = PasswordEdit->Text;
   SessionData->Password = PasswordEdit->Text;
   SessionData->Ftps = GetFtps();
   SessionData->Ftps = GetFtps();
 
 
-  SessionData->FSProtocol = GetFSProtocol();
+  SessionData->FSProtocol =
+    // requiring SCP fallback distinction
+    GetFSProtocol(true);
 
 
   TSessionData * EditingSessionData = GetEditingSessionData();
   TSessionData * EditingSessionData = GetEditingSessionData();
   SessionData->Name =
   SessionData->Name =
@@ -398,13 +439,14 @@ void __fastcall TLoginDialog::SaveSession(TSessionData * SessionData)
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 void __fastcall TLoginDialog::UpdateControls()
 void __fastcall TLoginDialog::UpdateControls()
 {
 {
-  if (Visible && FInitialized)
+  // without FLocaleChanging test, some button controls get lost, when changing language
+  if (Visible && FInitialized && !FLocaleChanging)
   {
   {
     bool NewSiteSelected = IsNewSiteNode(SessionTree->Selected);
     bool NewSiteSelected = IsNewSiteNode(SessionTree->Selected);
 
 
     bool Editable = NewSiteSelected || FEditing;
     bool Editable = NewSiteSelected || FEditing;
 
 
-    TFSProtocol FSProtocol = GetFSProtocol();
+    TFSProtocol FSProtocol = GetFSProtocol(false);
     bool SshProtocol = IsSshProtocol(FSProtocol);
     bool SshProtocol = IsSshProtocol(FSProtocol);
     bool FtpProtocol = (FSProtocol == fsFTP);
     bool FtpProtocol = (FSProtocol == fsFTP);
     bool WebDavProtocol = (FSProtocol == fsWebDAV);
     bool WebDavProtocol = (FSProtocol == fsWebDAV);
@@ -517,14 +559,6 @@ void __fastcall TLoginDialog::FormShow(TObject * /*Sender*/)
     LoadContents();
     LoadContents();
   }
   }
 
 
-  if (FLocaleChanging)
-  {
-    if (FSavedSession >= 0)
-    {
-      SessionTree->Selected = SessionTree->Items->Item[FSavedSession];
-      SessionTree->Selected->MakeVisible();
-    }
-  }
   // among other this makes the expanded nodes look like expanded,
   // among other this makes the expanded nodes look like expanded,
   // because the LoadState call in Execute is too early,
   // because the LoadState call in Execute is too early,
   // and some stray call to collapsed event during showing process,
   // and some stray call to collapsed event during showing process,
@@ -668,6 +702,8 @@ void __fastcall TLoginDialog::EditSessionActionExecute(TObject * /*Sender*/)
   {
   {
     FEditing = true;
     FEditing = true;
     EditSession();
     EditSession();
+    // reload session, to make sure we load decrypted password
+    LoadContents();
     UpdateControls();
     UpdateControls();
   }
   }
 }
 }
@@ -718,6 +754,7 @@ void __fastcall TLoginDialog::SaveAsSession(bool ForceDialog)
     // this
     // this
     // - updates TransferProtocolView and EncryptionView
     // - updates TransferProtocolView and EncryptionView
     // - clears the password box, if user has not opted to save password
     // - clears the password box, if user has not opted to save password
+    // - reloads fake password
     LoadContents();
     LoadContents();
 
 
     UpdateControls();
     UpdateControls();
@@ -1086,6 +1123,9 @@ void __fastcall TLoginDialog::SaveState()
 
 
   WinConfiguration->LastStoredSession = SessionNodePath(SessionTree->Selected);
   WinConfiguration->LastStoredSession = SessionNodePath(SessionTree->Selected);
 
 
+  // used only when changing locale
+  FSavedBounds = BoundsRect;
+
   TLoginDialogConfiguration DialogConfiguration = CustomWinConfiguration->LoginDialog;
   TLoginDialogConfiguration DialogConfiguration = CustomWinConfiguration->LoginDialog;
   DialogConfiguration.WindowSize = StoreFormSize(this);
   DialogConfiguration.WindowSize = StoreFormSize(this);
   CustomWinConfiguration->LoginDialog = DialogConfiguration;
   CustomWinConfiguration->LoginDialog = DialogConfiguration;
@@ -1168,7 +1208,14 @@ void __fastcall TLoginDialog::LoadState()
     }
     }
   }
   }
 
 
-  RestoreFormSize(CustomWinConfiguration->LoginDialog.WindowSize, this);
+  if (FLocaleChanging)
+  {
+    BoundsRect = FSavedBounds;
+  }
+  else
+  {
+    RestoreFormSize(CustomWinConfiguration->LoginDialog.WindowSize, this);
+  }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 void __fastcall TLoginDialog::SaveConfiguration()
 void __fastcall TLoginDialog::SaveConfiguration()
@@ -1261,8 +1308,11 @@ void __fastcall TLoginDialog::Dispatch(void * Message)
       SaveConfiguration();
       SaveConfiguration();
       SaveState();
       SaveState();
       PersistNewSiteIfNeeded();
       PersistNewSiteIfNeeded();
-      FSavedSession = ((SessionTree->Selected != NULL) ?
-        SessionTree->Selected->AbsoluteIndex : -1);
+
+      // restore sizes to design-time state,
+      // otherwise layout is lost while reloading the form
+      BasicGroup->Height = FBasicGroupBaseHeight + BasicSshPanel->Height + BasicFtpPanel->Height;
+      SetBounds(Left, Top, FOriginalSize.cx, FOriginalSize.cy);
 
 
       assert(FSystemSettings);
       assert(FSystemSettings);
       RevokeSystemSettings(this, FSystemSettings);
       RevokeSystemSettings(this, FSystemSettings);
@@ -1297,12 +1347,7 @@ void __fastcall TLoginDialog::SetDefaultSessionActionExecute(
   {
   {
     std::auto_ptr<TSessionData> SessionData(new TSessionData(L""));
     std::auto_ptr<TSessionData> SessionData(new TSessionData(L""));
     SaveSession(SessionData.get());
     SaveSession(SessionData.get());
-    if (!Configuration->DisablePasswordStoring &&
-        SessionData->HasAnyPassword() &&
-        CustomWinConfiguration->UseMasterPassword)
-    {
-      CustomWinConfiguration->AskForMasterPasswordIfNotSet();
-    }
+    CustomWinConfiguration->AskForMasterPasswordIfNotSetAndNeededToPersistSessionData(SessionData.get());
     StoredSessions->DefaultSettings = SessionData.get();
     StoredSessions->DefaultSettings = SessionData.get();
 
 
     Default();
     Default();
@@ -1632,21 +1677,66 @@ TFSProtocol __fastcall TLoginDialog::IndexToFSProtocol(int Index, bool AllowScpF
   return Result;
   return Result;
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+int __fastcall TLoginDialog::FtpsToIndex(TFtps Ftps)
+{
+  switch (Ftps)
+  {
+    default:
+      FAIL;
+    case ftpsNone:
+      return 0;
+
+    case ftpsImplicit:
+      return 1;
+
+    case ftpsExplicitSsl:
+      return 3;
+
+    case ftpsExplicitTls:
+      return 2;
+  }
+}
+//---------------------------------------------------------------------------
 TFtps __fastcall TLoginDialog::GetFtps()
 TFtps __fastcall TLoginDialog::GetFtps()
 {
 {
-  return (TFtps)((GetFSProtocol() == fsWebDAV) ? WebDavsCombo->ItemIndex : FtpsCombo->ItemIndex);
+  int Index = ((GetFSProtocol(false) == fsWebDAV) ? WebDavsCombo->ItemIndex : FtpsCombo->ItemIndex);
+  TFtps Ftps;
+  switch (Index)
+  {
+    default:
+      FAIL;
+    case 0:
+      Ftps = ftpsNone;
+      break;
+
+    case 1:
+      Ftps = ftpsImplicit;
+      break;
+
+    case 2:
+      Ftps = ftpsExplicitTls;
+      break;
+
+    case 3:
+      Ftps = ftpsExplicitSsl;
+      break;
+  }
+  return Ftps;
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
-TFSProtocol __fastcall TLoginDialog::GetFSProtocol()
+TFSProtocol __fastcall TLoginDialog::GetFSProtocol(bool RequireScpFallbackDistinction)
 {
 {
   bool AllowScpFallback = false;
   bool AllowScpFallback = false;
-  FSProtocolToIndex(FSessionData->FSProtocol, AllowScpFallback);
+  if (RequireScpFallbackDistinction && ALWAYS_TRUE(FSessionData != NULL))
+  {
+    FSProtocolToIndex(FSessionData->FSProtocol, AllowScpFallback);
+  }
   return IndexToFSProtocol(TransferProtocolCombo->ItemIndex, AllowScpFallback);
   return IndexToFSProtocol(TransferProtocolCombo->ItemIndex, AllowScpFallback);
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 int __fastcall TLoginDialog::DefaultPort()
 int __fastcall TLoginDialog::DefaultPort()
 {
 {
-  TFSProtocol FSProtocol = GetFSProtocol();
+  TFSProtocol FSProtocol = GetFSProtocol(false);
   TFtps Ftps = GetFtps();
   TFtps Ftps = GetFtps();
   int Result;
   int Result;
   switch (FSProtocol)
   switch (FSProtocol)
@@ -2130,8 +2220,9 @@ void __fastcall TLoginDialog::PortNumberEditChange(TObject * Sender)
         {
         {
           TransferProtocolCombo->ItemIndex = ProtocolIndex;
           TransferProtocolCombo->ItemIndex = ProtocolIndex;
 
 
-          FtpsCombo->ItemIndex = Ftps;
-          WebDavsCombo->ItemIndex = Ftps;
+          int FtpsIndex = FtpsToIndex(Ftps);
+          FtpsCombo->ItemIndex = FtpsIndex;
+          WebDavsCombo->ItemIndex = FtpsIndex;
         }
         }
         __finally
         __finally
         {
         {
@@ -2358,8 +2449,17 @@ void __fastcall TLoginDialog::PersistNewSiteIfNeeded()
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 void __fastcall TLoginDialog::SessionAdvancedActionExecute(TObject * /*Sender*/)
 void __fastcall TLoginDialog::SessionAdvancedActionExecute(TObject * /*Sender*/)
 {
 {
-  SaveSession(FSessionData);
-  DoSiteAdvancedDialog(FSessionData, FOptions);
+  // If we ever allow showing advanced settings, while read-only,
+  // we must make sure that FSessionData actually holds the advanced settings,
+  // what is currently does not, in order to avoid master password prompt,
+  // while cloning the session data in LoadSession.
+  // To implement this, we may delegate the cloning to TWinConfiguration and
+  // make use of FDontDecryptPasswords
+  if (ALWAYS_TRUE(FSessionData != NULL))
+  {
+    SaveSession(FSessionData);
+    DoSiteAdvancedDialog(FSessionData, FOptions);
+  }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 TPopupMenu * __fastcall TLoginDialog::GetSelectedNodePopupMenu()
 TPopupMenu * __fastcall TLoginDialog::GetSelectedNodePopupMenu()
@@ -2396,7 +2496,7 @@ void __fastcall TLoginDialog::SessionTreeMouseDown(TObject * /*Sender*/,
   TMouseButton Button, TShiftState /*Shift*/, int X, int Y)
   TMouseButton Button, TShiftState /*Shift*/, int X, int Y)
 {
 {
   TTreeNode * Node = SessionTree->GetNodeAt(X, Y);
   TTreeNode * Node = SessionTree->GetNodeAt(X, Y);
-  if (Button == mbRight)
+  if ((Button == mbRight) && (Node != NULL))
   {
   {
     SessionTree->Selected = Node;
     SessionTree->Selected = Node;
   }
   }
@@ -2415,8 +2515,14 @@ void __fastcall TLoginDialog::SessionTreeContextPopup(TObject * /*Sender*/,
   }
   }
   else
   else
   {
   {
-    SessionTree->PopupMenu = GetSelectedNodePopupMenu();
-    MenuPopup(SessionTree, MousePos, Handled);
+    if (SessionTree->Selected != NULL)
+    {
+      SessionTree->PopupMenu = GetSelectedNodePopupMenu();
+      if (NOT_NULL(SessionTree->PopupMenu))
+      {
+        MenuPopup(SessionTree, MousePos, Handled);
+      }
+    }
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------

+ 4 - 4
source/forms/Login.dfm

@@ -241,9 +241,9 @@ object LoginDialog: TLoginDialog
           OnChange = TransferProtocolComboChange
           OnChange = TransferProtocolComboChange
           Items.Strings = (
           Items.Strings = (
             'No encryption'
             'No encryption'
-            'SSL/TLS Implicit encryptionX'
-            'SSL Explicit encryptionX'
-            'TLS Explicit encryptionX')
+            'TLS/SSL Implicit encryptionX'
+            'TLS Explicit encryptionX'
+            'SSL Explicit encryptionX')
         end
         end
         object WebDavsCombo: TComboBox
         object WebDavsCombo: TComboBox
           Left = 163
           Left = 163
@@ -255,7 +255,7 @@ object LoginDialog: TLoginDialog
           OnChange = TransferProtocolComboChange
           OnChange = TransferProtocolComboChange
           Items.Strings = (
           Items.Strings = (
             'No encryptionX'
             'No encryptionX'
-            'SSL/TLS Implicit encryptionX')
+            'TLS/SSL Implicit encryptionX')
         end
         end
         object BasicFtpPanel: TPanel
         object BasicFtpPanel: TPanel
           Left = 12
           Left = 12

+ 5 - 2
source/forms/Login.h

@@ -221,7 +221,6 @@ private:
   TStoredSessionList * FStoredSessions;
   TStoredSessionList * FStoredSessions;
   int FOptions;
   int FOptions;
   bool FInitialized;
   bool FInitialized;
-  int FSavedSession;
   bool FLocaleChanging;
   bool FLocaleChanging;
   void * FSystemSettings;
   void * FSystemSettings;
   TWndMethod FOldSessionTreeProc;
   TWndMethod FOldSessionTreeProc;
@@ -234,8 +233,10 @@ private:
   int FIncrementalSearching;
   int FIncrementalSearching;
   bool FSitesIncrementalSearchHaveNext;
   bool FSitesIncrementalSearchHaveNext;
   int FBasicGroupBaseHeight;
   int FBasicGroupBaseHeight;
+  TRect FSavedBounds;
   bool FEditing;
   bool FEditing;
   bool FRenaming;
   bool FRenaming;
+  TSize FOriginalSize;
 
 
   void __fastcall LoadSession(TSessionData * SessionData);
   void __fastcall LoadSession(TSessionData * SessionData);
   void __fastcall LoadContents();
   void __fastcall LoadContents();
@@ -248,8 +249,9 @@ private:
   void __fastcall CMDialogKey(TWMKeyDown & Message);
   void __fastcall CMDialogKey(TWMKeyDown & Message);
   int __fastcall FSProtocolToIndex(TFSProtocol FSProtocol, bool & AllowScpFallback);
   int __fastcall FSProtocolToIndex(TFSProtocol FSProtocol, bool & AllowScpFallback);
   TFSProtocol __fastcall IndexToFSProtocol(int Index, bool AllowScpFallback);
   TFSProtocol __fastcall IndexToFSProtocol(int Index, bool AllowScpFallback);
+  int __fastcall FtpsToIndex(TFtps Ftps);
   TFtps __fastcall GetFtps();
   TFtps __fastcall GetFtps();
-  TFSProtocol __fastcall GetFSProtocol();
+  TFSProtocol __fastcall GetFSProtocol(bool RequireScpFallbackDistinction);
   void __fastcall UpdateFolderNode(TTreeNode * Node);
   void __fastcall UpdateFolderNode(TTreeNode * Node);
   TTreeNode * __fastcall AddSession(TSessionData * Data);
   TTreeNode * __fastcall AddSession(TSessionData * Data);
   TTreeNode * __fastcall AddSessionPath(UnicodeString Path,
   TTreeNode * __fastcall AddSessionPath(UnicodeString Path,
@@ -299,6 +301,7 @@ private:
   void __fastcall DefaultButton(TButton * Button, bool Default);
   void __fastcall DefaultButton(TButton * Button, bool Default);
   TSessionData * __fastcall GetEditingSessionData();
   TSessionData * __fastcall GetEditingSessionData();
   void __fastcall SaveAsSession(bool ForceDialog);
   void __fastcall SaveAsSession(bool ForceDialog);
+  void __fastcall InvalidateSessionData();
 
 
 protected:
 protected:
   void __fastcall Default();
   void __fastcall Default();

+ 2 - 0
source/forms/NonVisual.dfm

@@ -604,6 +604,8 @@ object NonVisualDataModule: TNonVisualDataModule
       Hint = 'Close session|Terminate current session'
       Hint = 'Close session|Terminate current session'
       ImageIndex = 26
       ImageIndex = 26
       ShortCut = 24644
       ShortCut = 24644
+      SecondaryShortCuts.Strings = (
+        'Ctrl+W')
     end
     end
     object SavedSessionsAction2: TAction
     object SavedSessionsAction2: TAction
       Tag = 15
       Tag = 15

+ 76 - 13
source/forms/Preferences.cpp

@@ -78,7 +78,7 @@ __fastcall TPreferencesDialog::TPreferencesDialog(
   HintLabel(LogFileNameHintText, LoadStr(LOG_FILE_HINT3));
   HintLabel(LogFileNameHintText, LoadStr(LOG_FILE_HINT3));
   HintLabel(ActionsLogFileNameHintText, LoadStr(LOG_FILE_HINT3));
   HintLabel(ActionsLogFileNameHintText, LoadStr(LOG_FILE_HINT3));
 
 
-  HintLabel(ShellIconsText);
+  HintLabel(ShellIconsText2);
   HotTrackLabel(CopyParamLabel);
   HotTrackLabel(CopyParamLabel);
   HintLabel(PuttyPathHintText, LoadStr(PUTTY_PATTERNS_HINT));
   HintLabel(PuttyPathHintText, LoadStr(PUTTY_PATTERNS_HINT));
 
 
@@ -1053,7 +1053,7 @@ void __fastcall TPreferencesDialog::UpdateControls()
 
 
     // integration
     // integration
     // There's no quick launch in Windows 7
     // There's no quick launch in Windows 7
-    EnableControl(QuickLaunchIconButton, !IsWin7());
+    EnableControl(QuickLaunchIconButton, !::IsWin7());
 
 
     // languages
     // languages
     LanguageChangeLabel->Visible =
     LanguageChangeLabel->Visible =
@@ -1859,6 +1859,68 @@ void __fastcall TPreferencesDialog::SessionReopenTimeoutEditGetValue(
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+bool __fastcall TPreferencesDialog::CanSetMasterPassword()
+{
+  bool Result;
+  bool Retry;
+  do
+  {
+    Retry = false;
+    Result = !AnyOtherInstanceOfSelf();
+
+    if (!Result)
+    {
+      unsigned int Answer =
+        MessageDialog(
+          LoadStr(MASTER_PASSWORD_OTHER_INSTANCE),
+          qtConfirmation, qaRetry | qaIgnore | qaCancel,
+          HELP_MASTER_PASSWORD);
+
+      switch (Answer)
+      {
+        case qaRetry:
+          Retry = true;
+          break;
+
+        case qaIgnore:
+          Result = true;
+          break;
+
+        case qaCancel:
+        default:
+          // noop
+          break;
+      }
+    }
+  }
+  while (Retry && !Result);
+
+  return Result;
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::MasterPasswordChanged(
+  UnicodeString Message, TStrings * RecryptPasswordErrors)
+{
+  Configuration->Save();
+  if (RecryptPasswordErrors->Count > 0)
+  {
+    Message = FMTLOAD(MASTER_PASSWORD_RECRYPT_ERRORS, (Message));
+  }
+  MoreMessageDialog(
+    Message, RecryptPasswordErrors, qtInformation, qaOK, HELP_MASTER_PASSWORD);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::ChangeMasterPassword(UnicodeString Message)
+{
+  UnicodeString NewPassword;
+  if (DoChangeMasterPasswordDialog(NewPassword))
+  {
+    std::auto_ptr<TStrings> RecryptPasswordErrors(new TStringList());
+    WinConfiguration->ChangeMasterPassword(NewPassword, RecryptPasswordErrors.get());
+    MasterPasswordChanged(Message, RecryptPasswordErrors.get());
+  }
+}
+//---------------------------------------------------------------------------
 void __fastcall TPreferencesDialog::UseMasterPasswordCheckClick(
 void __fastcall TPreferencesDialog::UseMasterPasswordCheckClick(
   TObject * /*Sender*/)
   TObject * /*Sender*/)
 {
 {
@@ -1866,19 +1928,20 @@ void __fastcall TPreferencesDialog::UseMasterPasswordCheckClick(
   {
   {
     try
     try
     {
     {
-      if (UseMasterPasswordCheck->Checked)
+      if (CanSetMasterPassword())
       {
       {
-        if (DoChangeMasterPasswordDialog())
+        if (UseMasterPasswordCheck->Checked)
         {
         {
-          MessageDialog(LoadStr(MASTER_PASSWORD_SET), qtInformation, qaOK, HELP_MASTER_PASSWORD);
+          ChangeMasterPassword(LoadStr(MASTER_PASSWORD_SET));
         }
         }
-      }
-      else
-      {
-        if (DoMasterPasswordDialog())
+        else
         {
         {
-          WinConfiguration->ClearMasterPassword();
-          MessageDialog(LoadStr(MASTER_PASSWORD_CLEARED), qtInformation, qaOK, HELP_MASTER_PASSWORD);
+          if (DoMasterPasswordDialog())
+          {
+            std::auto_ptr<TStrings> RecryptPasswordErrors(new TStringList());
+            WinConfiguration->ClearMasterPassword(RecryptPasswordErrors.get());
+            MasterPasswordChanged(LoadStr(MASTER_PASSWORD_CLEARED), RecryptPasswordErrors.get());
+          }
         }
         }
       }
       }
     }
     }
@@ -1893,9 +1956,9 @@ void __fastcall TPreferencesDialog::UseMasterPasswordCheckClick(
 void __fastcall TPreferencesDialog::SetMasterPasswordButtonClick(
 void __fastcall TPreferencesDialog::SetMasterPasswordButtonClick(
   TObject * /*Sender*/)
   TObject * /*Sender*/)
 {
 {
-  if (DoChangeMasterPasswordDialog())
+  if (CanSetMasterPassword())
   {
   {
-    MessageDialog(LoadStr(MASTER_PASSWORD_CHANGED), qtInformation, qaOK, HELP_MASTER_PASSWORD);
+    ChangeMasterPassword(LoadStr(MASTER_PASSWORD_CHANGED));
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------

+ 2083 - 0
source/forms/Preferences.cpp.LOCAL

@@ -0,0 +1,2083 @@
+//---------------------------------------------------------------------
+#include <vcl.h>
+#pragma hdrstop
+
+#include <StrUtils.hpp>
+#include <Common.h>
+#include <math.h>
+
+#include "Preferences.h"
+
+#include <CoreMain.h>
+#include <Terminal.h>
+#include <Bookmarks.h>
+
+#include "VCLCommon.h"
+#include "GUITools.h"
+#include "Tools.h"
+#include "TextsWin.h"
+#include "HelpWin.h"
+#include "WinInterface.h"
+#include "WinConfiguration.h"
+#include "Setup.h"
+//---------------------------------------------------------------------
+#pragma link "CopyParams"
+#pragma link "UpDownEdit"
+#pragma link "ComboEdit"
+#ifndef NO_RESOURCES
+#pragma link "HistoryComboBox"
+#pragma resource "*.dfm"
+#endif
+//---------------------------------------------------------------------
+bool __fastcall DoPreferencesDialog(TPreferencesMode APreferencesMode,
+  TPreferencesDialogData * DialogData)
+{
+  CALLSTACK;
+  bool Result;
+  TPreferencesDialog * PreferencesDialog =
+    new TPreferencesDialog(GetFormOwner(), APreferencesMode);
+  try
+  {
+    Result = PreferencesDialog->Execute(DialogData);
+  }
+  __finally
+  {
+    delete PreferencesDialog;
+  }
+  return Result;
+}
+//---------------------------------------------------------------------
+__fastcall TPreferencesDialog::TPreferencesDialog(
+  TComponent* AOwner, TPreferencesMode PreferencesMode)
+  : TForm(AOwner)
+{
+  SetCorrectFormParent(this);
+
+  FNoUpdate = 0;
+  FPreferencesMode = PreferencesMode;
+  FEditorFont = new TFont();
+  FEditorFont->Color = clWindowText;
+  // color tends to reset in object inspector
+  EditorFontLabel->Color = clWindow;
+  // currently useless
+  FAfterFilenameEditDialog = false;
+  FCustomCommandList = new TCustomCommandList();
+  FCustomCommandChanging = false;
+  FListViewDragDest = -1;
+  FCopyParamList = new TCopyParamList();
+  FEditorList = new TEditorList();
+  UseSystemSettings(this);
+
+  FCustomCommandsScrollOnDragOver = new TListViewScrollOnDragOver(CustomCommandsView, true);
+  FCopyParamScrollOnDragOver = new TListViewScrollOnDragOver(CopyParamListView, true);
+  FEditorScrollOnDragOver = new TListViewScrollOnDragOver(EditorListView3, true);
+
+  ComboAutoSwitchInitialize(UpdatesBetaVersionsCombo);
+  EnableControl(UpdatesBetaVersionsCombo, !WinConfiguration->IsBeta);
+  EnableControl(UpdatesBetaVersionsLabel, UpdatesBetaVersionsCombo->Enabled);
+
+  HintLabel(LogFileNameHintText, LoadStr(LOG_FILE_HINT3));
+  HintLabel(ActionsLogFileNameHintText, LoadStr(LOG_FILE_HINT3));
+
+  HintLabel(ShellIconsText2);
+  HotTrackLabel(CopyParamLabel);
+  HintLabel(PuttyPathHintText, LoadStr(PUTTY_PATTERNS_HINT));
+
+  EditorEncodingCombo->Items->Add(DefaultEncodingName());
+  EditorEncodingCombo->Items->Add(LoadStr(UTF8_NAME));
+
+  std::auto_ptr<TStrings> Workspaces(StoredSessions->GetWorkspaces());
+  AutoWorkspaceCombo->Items->AddStrings(Workspaces.get());
+  AutoSaveWorkspacePasswordsCheck->Caption = LoadStr(SAVE_WORKSPACE_PASSWORDS);
+
+  PuttyRegistryStorageKeyEdit->Items->Add(OriginalPuttyRegistryStorageKey);
+  PuttyRegistryStorageKeyEdit->Items->Add(KittyRegistryStorageKey);
+}
+//---------------------------------------------------------------------------
+__fastcall TPreferencesDialog::~TPreferencesDialog()
+{
+  SAFE_DESTROY(FEditorScrollOnDragOver);
+  SAFE_DESTROY(FCopyParamScrollOnDragOver);
+  SAFE_DESTROY(FCustomCommandsScrollOnDragOver);
+  delete FEditorFont;
+  delete FCustomCommandList;
+  delete FCopyParamList;
+  delete FEditorList;
+}
+//---------------------------------------------------------------------
+bool __fastcall TPreferencesDialog::Execute(TPreferencesDialogData * DialogData)
+{
+  PuttyPathEdit->Items = CustomWinConfiguration->History[L"PuttyPath"];
+  FDialogData = DialogData;
+  LoadConfiguration();
+  bool Result = (ShowModal() == mrOk);
+  if (Result)
+  {
+    SaveConfiguration();
+    CustomWinConfiguration->History[L"PuttyPath"] = PuttyPathEdit->Items;
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::LoadLanguages()
+{
+  CALLSTACK;
+  if (!FLanguagesLoaded)
+  {
+    LanguagesView->Items->Clear();
+
+    TStrings * Locales = GUIConfiguration->Locales;
+    for (int Index = 0; Index < Locales->Count; Index++)
+    {
+      TListItem * Item = LanguagesView->Items->Add();
+      Item->Caption = Locales->Strings[Index];
+      Item->Data = Locales->Objects[Index];
+      Item->Focused =
+        (reinterpret_cast<LCID>(Locales->Objects[Index]) == GUIConfiguration->Locale);
+      Item->Selected = Item->Focused;
+    }
+
+    FLanguagesLoaded = false;
+  }
+}
+//---------------------------------------------------------------------------
+TTabSheet * __fastcall TPreferencesDialog::FindPageForTreeNode(TTreeNode * Node)
+{
+  for (int pi = 0; pi < PageControl->PageCount; pi++)
+  {
+    TTabSheet * Sheet = PageControl->Pages[pi];
+    if (Sheet->Tag == Node->SelectedIndex)
+    {
+      return Sheet;
+    }
+  }
+  FAIL;
+  return NULL;
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::PrepareNavigationTree(TTreeView * Tree)
+{
+  Tree->FullExpand();
+  int i = 0;
+  while (i < Tree->Items->Count)
+  {
+    TTreeNode * Node = Tree->Items->Item[i];
+    TTabSheet * Sheet = FindPageForTreeNode(Node);
+    if (NOT_NULL(Sheet))
+    {
+      if (Sheet->Enabled)
+      {
+        // gets called multiple times occasionally
+        // (e.g. when called from upload dialog invoked by /upload)
+        if (!Sheet->Caption.IsEmpty())
+        {
+          Node->Text = Sheet->Caption;
+          Sheet->Caption = L"";
+        }
+      }
+      else
+      {
+        Tree->Items->Delete(Node);
+        i--;
+      }
+    }
+    i++;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::LoadConfiguration()
+{
+  FNoUpdate++;
+  try
+  {
+    #define BOOLPROP(PROP) PROP ## Check->Checked = WinConfiguration->PROP;
+    BOOLPROP(DefaultDirIsHome);
+    BOOLPROP(PreservePanelState);
+    BOOLPROP(DeleteToRecycleBin);
+    BOOLPROP(DDTransferConfirmation);
+    BOOLPROP(DDWarnLackOfTempSpace);
+    BOOLPROP(ShowHiddenFiles);
+    BOOLPROP(FormatSizeBytes);
+    BOOLPROP(RenameWholeName);
+    BOOLPROP(ShowInaccesibleDirectories);
+    BOOLPROP(CopyOnDoubleClickConfirmation);
+    BOOLPROP(ConfirmTransferring);
+    BOOLPROP(ConfirmOverwriting);
+    BOOLPROP(ConfirmResume);
+    BOOLPROP(ConfirmDeleting);
+    BOOLPROP(ConfirmRecycling);
+    BOOLPROP(ConfirmClosingSession);
+    BOOLPROP(ConfirmExitOnCompletion);
+    BOOLPROP(ConfirmCommandSession);
+    BOOLPROP(ContinueOnError);
+    BOOLPROP(DDAllowMoveInit);
+    BOOLPROP(BeepOnFinish);
+    BOOLPROP(TemporaryDirectoryAppendSession);
+    BOOLPROP(TemporaryDirectoryAppendPath);
+    BOOLPROP(TemporaryDirectoryCleanup);
+    BOOLPROP(ConfirmTemporaryDirectoryCleanup);
+    BOOLPROP(FullRowSelect);
+
+    if (WinConfiguration->DDTransferConfirmation == asAuto)
+    {
+      // allow greayed state only initially,
+      // once the off state is confirmed, never allow returning
+      // to the undefined state
+      DDTransferConfirmationCheck->AllowGrayed = true;
+    }
+    CheckBoxAutoSwitchLoad(DDTransferConfirmationCheck, WinConfiguration->DDTransferConfirmation);
+
+    BeepOnFinishAfterEdit->AsInteger =
+      int(static_cast<double>(GUIConfiguration->BeepOnFinishAfter) * SecsPerDay);
+    BOOLPROP(BalloonNotifications);
+
+    DDExtEnabledButton->Checked = WinConfiguration->DDExtEnabled;
+    DDExtDisabledButton->Checked = !DDExtEnabledButton->Checked;
+    DDWarnOnMoveCheck->Checked = !WinConfiguration->DDAllowMove;
+
+    if (WinConfiguration->DDTemporaryDirectory.IsEmpty())
+    {
+      DDSystemTemporaryDirectoryButton->Checked = true;
+      DDTemporaryDirectoryEdit->Text = SystemTemporaryDirectory();
+    }
+    else
+    {
+      DDCustomTemporaryDirectoryButton->Checked = true;
+      DDTemporaryDirectoryEdit->Text = WinConfiguration->DDTemporaryDirectory;
+    }
+
+    // Commander
+    if (WinConfiguration->ScpCommander.NortonLikeMode == nlOff)
+    {
+      NortonLikeModeCombo->ItemIndex = 2;
+    }
+    else if (WinConfiguration->ScpCommander.NortonLikeMode == nlKeyboard)
+    {
+      NortonLikeModeCombo->ItemIndex = 1;
+    }
+    else
+    {
+      NortonLikeModeCombo->ItemIndex = 0;
+    }
+
+    SwappedPanelsCheck->Checked =
+      WinConfiguration->ScpCommander.SwappedPanels;
+    TreeOnLeftCheck->Checked = WinConfiguration->ScpCommander.TreeOnLeft;
+
+    ExplorerKeyboardShortcutsCombo->ItemIndex =
+      WinConfiguration->ScpCommander.ExplorerKeyboardShortcuts ? 1 : 0;
+    BOOLPROP(UseLocationProfiles);
+
+    CompareByTimeCheck->Checked = WinConfiguration->ScpCommander.CompareByTime;
+    CompareBySizeCheck->Checked = WinConfiguration->ScpCommander.CompareBySize;
+
+    // Local panel
+    PreserveLocalDirectoryCheck->Checked =
+      WinConfiguration->ScpCommander.PreserveLocalDirectory;
+    SystemContextMenuCheck->Checked =
+      WinConfiguration->ScpCommander.SystemContextMenu;
+
+    // Explorer
+    ShowFullAddressCheck->Checked =
+      WinConfiguration->ScpExplorer.ShowFullAddress;
+
+    RegistryStorageButton->Checked = (Configuration->Storage == stRegistry);
+    IniFileStorageButton2->Checked = (Configuration->Storage != stRegistry);
+
+    RandomSeedFileEdit->Text = Configuration->RandomSeedFile;
+
+    // editor
+    EditorWordWrapCheck->Checked = WinConfiguration->Editor.WordWrap;
+    EditorTabSizeEdit->AsInteger = WinConfiguration->Editor.TabSize;
+    if (WinConfiguration->Editor.Encoding == CP_UTF8)
+    {
+      EditorEncodingCombo->ItemIndex = 1;
+    }
+    else
+    {
+      EditorEncodingCombo->ItemIndex = 0;
+    }
+    FEditorFont->Name = WinConfiguration->Editor.FontName;
+    FEditorFont->Height = WinConfiguration->Editor.FontHeight;
+    FEditorFont->Charset = (TFontCharset)WinConfiguration->Editor.FontCharset;
+    FEditorFont->Style = IntToFontStyles(WinConfiguration->Editor.FontStyle);
+    (*FEditorList) = *WinConfiguration->EditorList;
+    UpdateEditorListView();
+
+    FCopyParams = GUIConfiguration->DefaultCopyParam;
+    ResumeOnButton->Checked = GUIConfiguration->DefaultCopyParam.ResumeSupport == rsOn;
+    ResumeSmartButton->Checked = GUIConfiguration->DefaultCopyParam.ResumeSupport == rsSmart;
+    ResumeOffButton->Checked = GUIConfiguration->DefaultCopyParam.ResumeSupport == rsOff;
+    ResumeThresholdEdit->Value = GUIConfiguration->DefaultCopyParam.ResumeThreshold / 1024;
+    SessionReopenAutoCheck->Checked = (Configuration->SessionReopenAuto > 0);
+    SessionReopenAutoEdit->Value = (Configuration->SessionReopenAuto > 0 ?
+      (Configuration->SessionReopenAuto / MSecsPerSec) : 5);
+    SessionReopenAutoIdleCheck->Checked = (GUIConfiguration->SessionReopenAutoIdle > 0);
+    SessionReopenAutoIdleEdit->Value = (GUIConfiguration->SessionReopenAutoIdle > 0 ?
+      (GUIConfiguration->SessionReopenAutoIdle / MSecsPerSec) : 5);
+    SessionReopenAutoStallCheck->Checked = (Configuration->SessionReopenAutoStall > 0);
+    SessionReopenAutoStallEdit->Value = (Configuration->SessionReopenAutoStall > 0 ?
+      (Configuration->SessionReopenAutoStall / MSecsPerSec) : SecsPerMin);
+    SessionReopenTimeoutEdit->Value = (Configuration->SessionReopenTimeout / MSecsPerSec);
+
+    GeneralSheet->Enabled = WinConfiguration->ExpertMode;
+    ExplorerSheet->Enabled = WinConfiguration->ExpertMode;
+    CommanderSheet->Enabled = WinConfiguration->ExpertMode;
+    EditorSheet->Enabled = WinConfiguration->ExpertMode && !WinConfiguration->DisableOpenEdit;
+
+    StorageGroup->Visible = WinConfiguration->ExpertMode;
+    RandomSeedFileLabel->Visible = WinConfiguration->ExpertMode;
+    RandomSeedFileEdit->Visible = WinConfiguration->ExpertMode;
+
+    FCustomCommandList->Assign(WinConfiguration->CustomCommandList);
+    UpdateCustomCommandsView();
+
+    PuttyPathEdit->Text = GUIConfiguration->PuttyPath;
+    PuttyPasswordCheck2->Checked = GUIConfiguration->PuttyPassword;
+    AutoOpenInPuttyCheck->Checked = WinConfiguration->AutoOpenInPutty;
+    TelnetForFtpInPuttyCheck->Checked = WinConfiguration->TelnetForFtpInPutty;
+    SelectPuttyRegistryStorageKey(GUIConfiguration->PuttyRegistryStorageKey);
+
+    // Queue
+    QueueTransferLimitEdit->AsInteger = GUIConfiguration->QueueTransfersLimit;
+    EnableQueueByDefaultCheck->Checked = WinConfiguration->EnableQueueByDefault;
+    QueueAutoPopupCheck->Checked = GUIConfiguration->QueueAutoPopup;
+    QueueCheck->Checked = GUIConfiguration->DefaultCopyParam.Queue;
+    QueueIndividuallyCheck->Checked = GUIConfiguration->DefaultCopyParam.QueueIndividually;
+    QueueNoConfirmationCheck->Checked = GUIConfiguration->DefaultCopyParam.QueueNoConfirmation;
+    if (!GUIConfiguration->QueueKeepDoneItems)
+    {
+      QueueKeepDoneItemsForCombo->ItemIndex = 0;
+    }
+    else if (GUIConfiguration->QueueKeepDoneItemsFor < 0)
+    {
+      QueueKeepDoneItemsForCombo->ItemIndex = 5;
+    }
+    else if (GUIConfiguration->QueueKeepDoneItemsFor <= 15)
+    {
+      QueueKeepDoneItemsForCombo->ItemIndex = 1;
+    }
+    else if (GUIConfiguration->QueueKeepDoneItemsFor <= 60)
+    {
+      QueueKeepDoneItemsForCombo->ItemIndex = 2;
+    }
+    else if (GUIConfiguration->QueueKeepDoneItemsFor <= 15 * 60)
+    {
+      QueueKeepDoneItemsForCombo->ItemIndex = 3;
+    }
+    else if (GUIConfiguration->QueueKeepDoneItemsFor <= 60 * 60)
+    {
+      QueueKeepDoneItemsForCombo->ItemIndex = 4;
+    }
+    if (WinConfiguration->QueueView.Show == qvShow)
+    {
+      QueueViewShowButton->Checked = true;
+    }
+    else if (WinConfiguration->QueueView.Show == qvHideWhenEmpty)
+    {
+      QueueViewHideWhenEmptyButton->Checked = true;
+    }
+    else
+    {
+      QueueViewHideButton->Checked = true;
+    }
+
+    // window
+    AutoSaveWorkspaceCheck->Checked = WinConfiguration->AutoSaveWorkspace;
+    AutoWorkspaceCombo->Text =
+      (WinConfiguration->AutoWorkspace.IsEmpty() ?
+        WinConfiguration->LastWorkspace : WinConfiguration->AutoWorkspace);
+    AutoSaveWorkspacePasswordsCheck->Checked = WinConfiguration->AutoSaveWorkspacePasswords;
+    if (WinConfiguration->PathInCaption == picFull)
+    {
+      PathInCaptionFullButton->Checked = true;
+    }
+    else if (WinConfiguration->PathInCaption == picShort)
+    {
+      PathInCaptionShortButton->Checked = true;
+    }
+    else
+    {
+      PathInCaptionNoneButton->Checked = true;
+    }
+    BOOLPROP(MinimizeToTray);
+
+    // panels
+    DoubleClickActionCombo->ItemIndex = WinConfiguration->DoubleClickAction;
+    BOOLPROP(AutoReadDirectoryAfterOp);
+    BOOLPROP(RefreshRemotePanel);
+    RefreshRemotePanelIntervalEdit->Value =
+      int(static_cast<double>(WinConfiguration->RefreshRemotePanelInterval) * SecsPerDay);
+
+    // updates
+    TUpdatesConfiguration Updates = WinConfiguration->Updates;
+    if (int(Updates.Period) <= 0)
+    {
+      UpdatesPeriodCombo->ItemIndex = 0;
+    }
+    else if (int(Updates.Period) <= 1)
+    {
+      UpdatesPeriodCombo->ItemIndex = 1;
+    }
+    else if (int(Updates.Period) <= 7)
+    {
+      UpdatesPeriodCombo->ItemIndex = 2;
+    }
+    else
+    {
+      UpdatesPeriodCombo->ItemIndex = 3;
+    }
+
+    CollectUsageCheck->Checked = Configuration->CollectUsage;
+
+    ComboAutoSwitchLoad(UpdatesBetaVersionsCombo, Updates.BetaVersions);
+
+    switch (Updates.ConnectionType)
+    {
+      case ctDirect:
+      default:
+        UpdatesDirectCheck->Checked = true;
+        break;
+
+      case ctAuto:
+        UpdatesAutoCheck->Checked = true;
+        break;
+
+      case ctProxy:
+        UpdatesProxyCheck->Checked = true;
+        break;
+    }
+
+    UpdatesProxyHostEdit->Text = Updates.ProxyHost;
+    UpdatesProxyPortEdit->AsInteger = Updates.ProxyPort;
+
+    // presets
+    (*FCopyParamList) = *WinConfiguration->CopyParamList;
+    UpdateCopyParamListView();
+    CopyParamListView->ItemIndex = 0;
+    BOOLPROP(CopyParamAutoSelectNotice);
+
+    // interface
+    switch (CustomWinConfiguration->Interface)
+    {
+      case ifCommander:
+        CommanderInterfaceButton2->Checked = true;
+        break;
+
+      case ifExplorer:
+        ExplorerInterfaceButton2->Checked = true;
+        break;
+
+      default:
+        FAIL;
+        break;
+    }
+
+    if (WinConfiguration->Theme == L"OfficeXP")
+    {
+      ThemeCombo->ItemIndex = 1;
+    }
+    else if (WinConfiguration->Theme == L"Office2003")
+    {
+      ThemeCombo->ItemIndex = 2;
+    }
+    else
+    {
+      ThemeCombo->ItemIndex = 0;
+    }
+
+    // security
+    UseMasterPasswordCheck->Checked = WinConfiguration->UseMasterPassword;
+    SessionRememberPasswordCheck->Checked = GUIConfiguration->SessionRememberPassword;
+
+    // network
+    RetrieveExternalIpAddressButton->Checked = Configuration->ExternalIpAddress.IsEmpty();
+    CustomExternalIpAddressButton->Checked = !RetrieveExternalIpAddressButton->Checked;
+    CustomExternalIpAddressEdit->Text = Configuration->ExternalIpAddress;
+    TryFtpWhenSshFailsCheck->Checked = Configuration->TryFtpWhenSshFails;
+
+    // logging
+    EnableLoggingCheck->Checked = Configuration->Logging;
+    LogProtocolCombo->ItemIndex = Configuration->LogProtocol;
+    LogToFileCheck->Checked = Configuration->LogToFile;
+    LogFileNameEdit3->Text =
+      !Configuration->LogFileName.IsEmpty() ? Configuration->LogFileName : Configuration->DefaultLogFileName;
+    if (Configuration->LogFileAppend)
+    {
+      LogFileAppendButton->Checked = true;
+    }
+    else
+    {
+      LogFileOverwriteButton->Checked = true;
+    }
+    LogShowWindowCheck->Checked = (CustomWinConfiguration->LogView == lvWindow);
+    if (Configuration->LogWindowComplete)
+    {
+      LogWindowCompleteButton->Checked = true;
+    }
+    else
+    {
+      LogWindowLinesButton->Checked = true;
+    }
+
+    if (!Configuration->LogWindowComplete)
+    {
+      LogWindowLinesEdit->AsInteger = Configuration->LogWindowLines;
+    }
+    else
+    {
+      LogWindowLinesEdit->AsInteger = 500;
+    }
+
+    EnableActionsLoggingCheck->Checked = Configuration->LogActions;
+    ActionsLogFileNameEdit->Text = Configuration->ActionsLogFileName;
+
+    #undef BOOLPROP
+  }
+  __finally
+  {
+    FNoUpdate--;
+  }
+
+  UpdateControls();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::SaveConfiguration()
+{
+  Configuration->BeginUpdate();
+  try
+  {
+    TGUICopyParamType CopyParam = GUIConfiguration->DefaultCopyParam;
+
+    #define BOOLPROP(PROP) WinConfiguration->PROP = PROP ## Check->Checked
+    BOOLPROP(DefaultDirIsHome);
+    BOOLPROP(PreservePanelState);
+    BOOLPROP(DeleteToRecycleBin);
+    BOOLPROP(DDWarnLackOfTempSpace);
+    BOOLPROP(ShowHiddenFiles);
+    BOOLPROP(FormatSizeBytes);
+    BOOLPROP(RenameWholeName);
+    BOOLPROP(ShowInaccesibleDirectories);
+    BOOLPROP(CopyOnDoubleClickConfirmation);
+    BOOLPROP(ConfirmTransferring);
+    BOOLPROP(ConfirmOverwriting);
+    BOOLPROP(ConfirmResume);
+    BOOLPROP(ConfirmDeleting);
+    BOOLPROP(ConfirmRecycling);
+    BOOLPROP(ConfirmClosingSession);
+    BOOLPROP(ConfirmExitOnCompletion);
+    BOOLPROP(ConfirmCommandSession);
+    BOOLPROP(ContinueOnError);
+    BOOLPROP(DDAllowMoveInit);
+    BOOLPROP(BeepOnFinish);
+    BOOLPROP(TemporaryDirectoryAppendSession);
+    BOOLPROP(TemporaryDirectoryAppendPath);
+    BOOLPROP(TemporaryDirectoryCleanup);
+    BOOLPROP(ConfirmTemporaryDirectoryCleanup);
+    BOOLPROP(FullRowSelect);
+
+    WinConfiguration->DDTransferConfirmation =
+      CheckBoxAutoSwitchSave(DDTransferConfirmationCheck);
+
+    GUIConfiguration->BeepOnFinishAfter =
+      static_cast<double>(BeepOnFinishAfterEdit->Value / SecsPerDay);
+    BOOLPROP(BalloonNotifications);
+
+    WinConfiguration->DDAllowMove = !DDWarnOnMoveCheck->Checked;
+    WinConfiguration->DDExtEnabled = DDExtEnabledButton->Checked;
+
+    if (DDSystemTemporaryDirectoryButton->Checked)
+    {
+      WinConfiguration->DDTemporaryDirectory = L"";
+    }
+    else
+    {
+      WinConfiguration->DDTemporaryDirectory = DDTemporaryDirectoryEdit->Text;
+    }
+
+    Configuration->Storage = RegistryStorageButton->Checked ? stRegistry : stIniFile;
+
+    // Commander
+    TScpCommanderConfiguration ScpCommander = WinConfiguration->ScpCommander;
+    if (NortonLikeModeCombo->ItemIndex == 2)
+    {
+      ScpCommander.NortonLikeMode = nlOff;
+    }
+    else if (NortonLikeModeCombo->ItemIndex == 1)
+    {
+      ScpCommander.NortonLikeMode = nlKeyboard;
+    }
+    else
+    {
+      ScpCommander.NortonLikeMode = nlOn;
+    }
+    ScpCommander.SwappedPanels = SwappedPanelsCheck->Checked;
+    ScpCommander.TreeOnLeft = TreeOnLeftCheck->Checked;
+
+    ScpCommander.ExplorerKeyboardShortcuts =
+      (ExplorerKeyboardShortcutsCombo->ItemIndex != 0);
+    BOOLPROP(UseLocationProfiles);
+
+    WinConfiguration->ScpCommander.CompareByTime = CompareByTimeCheck->Checked;
+    WinConfiguration->ScpCommander.CompareBySize = CompareBySizeCheck->Checked;
+
+    // Local panel
+    ScpCommander.PreserveLocalDirectory = PreserveLocalDirectoryCheck->Checked;
+    ScpCommander.SystemContextMenu = SystemContextMenuCheck->Checked;
+
+    WinConfiguration->ScpCommander = ScpCommander;
+
+    // Explorer
+    TScpExplorerConfiguration ScpExplorer = WinConfiguration->ScpExplorer;
+    ScpExplorer.ShowFullAddress = ShowFullAddressCheck->Checked;
+    WinConfiguration->ScpExplorer = ScpExplorer;
+
+    Configuration->RandomSeedFile = RandomSeedFileEdit->Text;
+
+    // editor
+    WinConfiguration->Editor.WordWrap = EditorWordWrapCheck->Checked;
+    WinConfiguration->Editor.TabSize = EditorTabSizeEdit->AsInteger;
+    switch (EditorEncodingCombo->ItemIndex)
+    {
+      case 1:
+        WinConfiguration->Editor.Encoding = CP_UTF8;
+        break;
+
+      default:
+        WinConfiguration->Editor.Encoding = CP_ACP;
+        break;
+    }
+    WinConfiguration->Editor.FontName = FEditorFont->Name;
+    WinConfiguration->Editor.FontHeight = FEditorFont->Height;
+    WinConfiguration->Editor.FontCharset = FEditorFont->Charset;
+    WinConfiguration->Editor.FontStyle = FontStylesToInt(FEditorFont->Style);
+    WinConfiguration->EditorList = FEditorList;
+
+    // overwrites only TCopyParamType fields
+    CopyParam = FCopyParams;
+    if (ResumeOnButton->Checked) CopyParam.ResumeSupport = rsOn;
+    if (ResumeSmartButton->Checked) CopyParam.ResumeSupport = rsSmart;
+    if (ResumeOffButton->Checked) CopyParam.ResumeSupport = rsOff;
+    CopyParam.ResumeThreshold = ResumeThresholdEdit->AsInteger * 1024;
+
+    Configuration->SessionReopenAuto =
+      (SessionReopenAutoCheck->Checked ? (SessionReopenAutoEdit->AsInteger * MSecsPerSec) : 0);
+    GUIConfiguration->SessionReopenAutoIdle =
+      (SessionReopenAutoIdleCheck->Checked ? (SessionReopenAutoIdleEdit->AsInteger * MSecsPerSec) : 0);
+    Configuration->SessionReopenAutoStall =
+      (SessionReopenAutoStallCheck->Checked ? (SessionReopenAutoStallEdit->AsInteger * MSecsPerSec) : 0);
+    Configuration->SessionReopenTimeout = (SessionReopenTimeoutEdit->AsInteger * MSecsPerSec);
+
+    WinConfiguration->CustomCommandList = FCustomCommandList;
+
+    GUIConfiguration->PuttyPath = PuttyPathEdit->Text;
+    GUIConfiguration->PuttyPassword = PuttyPasswordCheck2->Checked;
+    WinConfiguration->AutoOpenInPutty = AutoOpenInPuttyCheck->Checked;
+    WinConfiguration->TelnetForFtpInPutty = TelnetForFtpInPuttyCheck->Checked;
+    // do not overwrite custom keys
+    if (PuttyRegistryStorageKeyEdit->ItemIndex >= 0)
+    {
+      GUIConfiguration->PuttyRegistryStorageKey = PuttyRegistryStorageKeyEdit->Text;
+    }
+
+    // Queue
+    GUIConfiguration->QueueTransfersLimit = QueueTransferLimitEdit->AsInteger;
+    WinConfiguration->EnableQueueByDefault = EnableQueueByDefaultCheck->Checked;
+    GUIConfiguration->QueueAutoPopup = QueueAutoPopupCheck->Checked;
+    CopyParam.Queue = QueueCheck->Checked;
+    CopyParam.QueueIndividually = QueueIndividuallyCheck->Checked;
+    CopyParam.QueueNoConfirmation = QueueNoConfirmationCheck->Checked;
+    GUIConfiguration->QueueKeepDoneItems = (QueueKeepDoneItemsForCombo->ItemIndex != 0);
+    switch (QueueKeepDoneItemsForCombo->ItemIndex)
+    {
+      case 0:
+        GUIConfiguration->QueueKeepDoneItemsFor = 0;
+        break;
+      case 1:
+        GUIConfiguration->QueueKeepDoneItemsFor = 15;
+        break;
+      case 2:
+        GUIConfiguration->QueueKeepDoneItemsFor = 60;
+        break;
+      case 3:
+        GUIConfiguration->QueueKeepDoneItemsFor = 15 * 60;
+        break;
+      case 4:
+        GUIConfiguration->QueueKeepDoneItemsFor = 60 * 60;
+        break;
+      default:
+        GUIConfiguration->QueueKeepDoneItemsFor = -1;
+        break;
+    }
+    if (QueueViewShowButton->Checked)
+    {
+      WinConfiguration->QueueView.Show = qvShow;
+    }
+    else if (QueueViewHideWhenEmptyButton->Checked)
+    {
+      WinConfiguration->QueueView.Show = qvHideWhenEmpty;
+    }
+    else
+    {
+      WinConfiguration->QueueView.Show = qvHide;
+    }
+
+    GUIConfiguration->DefaultCopyParam = CopyParam;
+
+    // window
+    WinConfiguration->AutoSaveWorkspace =
+      !AutoWorkspaceCombo->Text.IsEmpty() &&
+      AutoSaveWorkspaceCheck->Checked;
+    if (!AutoWorkspaceCombo->Text.IsEmpty())
+    {
+      WinConfiguration->AutoWorkspace = AutoWorkspaceCombo->Text;
+    }
+    WinConfiguration->AutoSaveWorkspacePasswords = AutoSaveWorkspacePasswordsCheck->Checked;
+    if (PathInCaptionFullButton->Checked)
+    {
+       WinConfiguration->PathInCaption = picFull;
+    }
+    else if (PathInCaptionShortButton->Checked)
+    {
+      WinConfiguration->PathInCaption = picShort;
+    }
+    else
+    {
+      WinConfiguration->PathInCaption = picNone;
+    }
+    BOOLPROP(MinimizeToTray);
+
+    // panels
+    WinConfiguration->DoubleClickAction = (TDoubleClickAction)DoubleClickActionCombo->ItemIndex;
+    BOOLPROP(AutoReadDirectoryAfterOp);
+    BOOLPROP(RefreshRemotePanel);
+    WinConfiguration->RefreshRemotePanelInterval =
+      static_cast<double>(RefreshRemotePanelIntervalEdit->Value / SecsPerDay);
+
+    // updates
+    TUpdatesConfiguration Updates = WinConfiguration->Updates;
+    if (UpdatesPeriodCombo->ItemIndex == 0)
+    {
+      Updates.Period = 0;
+    }
+    else if (UpdatesPeriodCombo->ItemIndex == 1)
+    {
+      Updates.Period = 1;
+    }
+    else if (UpdatesPeriodCombo->ItemIndex == 2)
+    {
+      Updates.Period = 7;
+    }
+    else
+    {
+      Updates.Period = 30;
+    }
+
+    Configuration->CollectUsage = CollectUsageCheck->Checked;
+
+    Updates.BetaVersions = ComboAutoSwitchSave(UpdatesBetaVersionsCombo);
+
+    if (UpdatesDirectCheck->Checked)
+    {
+      Updates.ConnectionType = ctDirect;
+    }
+    else if (UpdatesAutoCheck->Checked)
+    {
+      Updates.ConnectionType = ctAuto;
+    }
+    else if (UpdatesProxyCheck->Checked)
+    {
+      if (!UpdatesProxyHostEdit->Text.IsEmpty())
+      {
+        Updates.ConnectionType = ctProxy;
+      }
+      else
+      {
+        Updates.ConnectionType = ctDirect;
+      }
+    }
+    Updates.ProxyHost = UpdatesProxyHostEdit->Text;
+    Updates.ProxyPort = UpdatesProxyPortEdit->AsInteger;
+
+    WinConfiguration->Updates = Updates;
+
+    // presets
+    WinConfiguration->CopyParamList = FCopyParamList;
+    BOOLPROP(CopyParamAutoSelectNotice);
+
+    // interface
+    if (GetInterface() != CustomWinConfiguration->Interface)
+    {
+      Configuration->Usage->Inc(L"InterfaceChanges");
+    }
+    CustomWinConfiguration->Interface = GetInterface();
+
+    if (ThemeCombo->ItemIndex == 1)
+    {
+      WinConfiguration->Theme = L"OfficeXP";
+    }
+    else if (ThemeCombo->ItemIndex == 2)
+    {
+      WinConfiguration->Theme = L"Office2003";
+    }
+    else
+    {
+      WinConfiguration->Theme = L"Default";
+    }
+
+    // network
+    Configuration->ExternalIpAddress =
+      (CustomExternalIpAddressButton->Checked ? CustomExternalIpAddressEdit->Text : UnicodeString());
+    Configuration->TryFtpWhenSshFails = TryFtpWhenSshFailsCheck->Checked;
+
+    // security
+    GUIConfiguration->SessionRememberPassword = SessionRememberPasswordCheck->Checked;
+
+    // languages
+    if (LanguagesView->ItemFocused != NULL)
+    {
+      GUIConfiguration->Locale =
+        reinterpret_cast<LCID>(LanguagesView->ItemFocused->Data);
+    }
+
+    // logging
+    Configuration->Logging = EnableLoggingCheck->Checked;
+    Configuration->LogProtocol = LogProtocolCombo->ItemIndex;
+    Configuration->LogFileName = LogToFileCheck->Checked ? LogFileNameEdit3->Text : UnicodeString();
+    Configuration->LogFileAppend = LogFileAppendButton->Checked;
+    CustomWinConfiguration->LogView = LogShowWindowCheck->Checked ? lvWindow : lvNone;
+    Configuration->LogWindowComplete = LogWindowCompleteButton->Checked;
+    if (!LogWindowCompleteButton->Checked)
+    {
+      Configuration->LogWindowLines = LogWindowLinesEdit->AsInteger;
+    }
+
+    Configuration->LogActions = EnableActionsLoggingCheck->Checked;
+    Configuration->ActionsLogFileName = ActionsLogFileNameEdit->Text;
+
+    #undef BOOLPROP
+  }
+  __finally
+  {
+    Configuration->EndUpdate();
+  }
+}
+//---------------------------------------------------------------------------
+TInterface __fastcall TPreferencesDialog::GetInterface()
+{
+  return CommanderInterfaceButton2->Checked ? ifCommander : ifExplorer;
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::FormShow(TObject * /*Sender*/)
+{
+  InstallPathWordBreakProc(RandomSeedFileEdit);
+  InstallPathWordBreakProc(DDTemporaryDirectoryEdit);
+  InstallPathWordBreakProc(PuttyPathEdit);
+  InstallPathWordBreakProc(LogFileNameEdit3);
+  InstallPathWordBreakProc(ActionsLogFileNameEdit);
+
+  PrepareNavigationTree(NavigationTree);
+
+  switch (FPreferencesMode) {
+    case pmEditor: PageControl->ActivePage = EditorSheet; break;
+    case pmCustomCommands: PageControl->ActivePage = CustomCommandsSheet; break;
+    case pmQueue: PageControl->ActivePage = QueueSheet; break;
+    case pmLogging: PageControl->ActivePage = LogSheet; break;
+    case pmUpdates: PageControl->ActivePage = UpdatesSheet; break;
+    case pmPresets: PageControl->ActivePage = CopyParamListSheet; break;
+    case pmEditors: PageControl->ActivePage = EditorSheet; break;
+    default: PageControl->ActivePage = PreferencesSheet; break;
+  }
+  PageControlChange(NULL);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::ControlChange(TObject * /*Sender*/)
+{
+  UpdateControls();
+}
+//---------------------------------------------------------------------------
+UnicodeString __fastcall TPreferencesDialog::TabSample(UnicodeString Values)
+{
+  UnicodeString Result;
+  for (int Index = 1; Index <= Values.Length(); Index++)
+  {
+    if (Index > 1)
+    {
+      Result += L' ';
+      if (EditorTabSizeEdit->AsInteger > 2)
+      {
+        Result += UnicodeString::StringOfChar(L' ', EditorTabSizeEdit->AsInteger - 2);
+      }
+    }
+
+    Result += Values[Index];
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::UpdateControls()
+{
+  if (FNoUpdate == 0)
+  {
+    EnableControl(BeepOnFinishAfterEdit, BeepOnFinishCheck->Checked);
+    EnableControl(BeepOnFinishAfterText, BeepOnFinishCheck->Checked);
+    EnableControl(BalloonNotificationsCheck, ::TTrayIcon::SupportsBalloons());
+
+    EnableControl(ResumeThresholdEdit, ResumeSmartButton->Checked);
+    EnableControl(ResumeThresholdUnitLabel, ResumeThresholdEdit->Enabled);
+    EnableControl(SessionReopenAutoEdit, SessionReopenAutoCheck->Checked);
+    EnableControl(SessionReopenAutoLabel, SessionReopenAutoEdit->Enabled);
+    EnableControl(SessionReopenAutoSecLabel, SessionReopenAutoEdit->Enabled);
+    EnableControl(SessionReopenAutoIdleEdit, SessionReopenAutoIdleCheck->Checked);
+    EnableControl(SessionReopenAutoIdleLabel, SessionReopenAutoIdleEdit->Enabled);
+    EnableControl(SessionReopenAutoIdleSecLabel, SessionReopenAutoIdleEdit->Enabled);
+    EnableControl(SessionReopenAutoStallEdit, SessionReopenAutoStallCheck->Checked);
+    EnableControl(SessionReopenAutoStallLabel, SessionReopenAutoStallEdit->Enabled);
+    EnableControl(SessionReopenAutoStallSecLabel, SessionReopenAutoStallEdit->Enabled);
+    EnableControl(SessionReopenTimeoutEdit,
+      SessionReopenAutoEdit->Enabled || SessionReopenAutoStallCheck->Checked);
+    EnableControl(SessionReopenTimeoutLabel, SessionReopenTimeoutEdit->Enabled);
+    EnableControl(SessionReopenTimeoutSecLabel,SessionReopenTimeoutEdit->Enabled);
+
+    EnableControl(CopyOnDoubleClickConfirmationCheck,
+      (DoubleClickActionCombo->ItemIndex == 1) && ConfirmTransferringCheck->Checked);
+    EnableControl(RefreshRemotePanelIntervalEdit, RefreshRemotePanelCheck->Checked);
+    EnableControl(RefreshRemoteDirectoryUnitLabel, RefreshRemotePanelCheck->Checked);
+
+    UnicodeString EditorFontLabelText;
+    EditorFontLabelText = FMTLOAD(EDITOR_FONT_FMT,
+      (FEditorFont->Name, FEditorFont->Size)) + L"\n\n";
+    EditorFontLabelText += TabSample(L"ABCD") + L"\n";
+    EditorFontLabelText += TabSample(L"1234");
+    EditorFontLabel->Caption = EditorFontLabelText;
+    EditorFontLabel->Font = FEditorFont;
+
+    bool CommandSelected = (CustomCommandsView->Selected != NULL);
+    EnableControl(EditCommandButton, CommandSelected);
+    EnableControl(RemoveCommandButton, CommandSelected);
+    EnableControl(UpCommandButton, CommandSelected &&
+      CustomCommandsView->ItemIndex > 0);
+    EnableControl(DownCommandButton, CommandSelected &&
+      (CustomCommandsView->ItemIndex < CustomCommandsView->Items->Count - 1));
+
+    bool CopyParamSelected = (CopyParamListView->Selected != NULL);
+    EnableControl(EditCopyParamButton, CopyParamSelected);
+    EnableControl(DuplicateCopyParamButton,
+      CopyParamSelected && (CopyParamListView->ItemIndex >= 1));
+    EnableControl(RemoveCopyParamButton,
+      CopyParamSelected && (CopyParamListView->ItemIndex >= 1));
+    EnableControl(UpCopyParamButton,
+      CopyParamSelected && (CopyParamListView->ItemIndex > 1));
+    EnableControl(DownCopyParamButton,
+      CopyParamSelected &&
+      (CopyParamListView->ItemIndex >= 1) &&
+      (CopyParamListView->ItemIndex < CopyParamListView->Items->Count - 1));
+    EnableControl(CopyParamAutoSelectNoticeCheck, FCopyParamList->AnyRule);
+
+    UnicodeString InfoStr;
+    if (CopyParamSelected)
+    {
+      const TCopyParamType * SelectedCopyParam = GetCopyParam(CopyParamListView->ItemIndex);
+      InfoStr = SelectedCopyParam->GetInfoStr(L"; ", 0);
+      if (CopyParamListView->ItemIndex >= 1)
+      {
+        const TCopyParamRule * Rule = FCopyParamList->Rules[CopyParamListView->ItemIndex - 1];
+        if (Rule != NULL)
+        {
+          InfoStr += L"\n" + FORMAT(ReplaceStr(LoadStr(COPY_PARAM_RULE), L"\n", L" "), (Rule->GetInfoStr(L"; ")));
+        }
+      }
+    }
+    CopyParamLabel->Caption = InfoStr;
+    CopyParamLabel->Hint = InfoStr;
+    CopyParamLabel->ShowHint =
+      (CopyParamLabel->Canvas->TextWidth(InfoStr) > (CopyParamLabel->Width * 3 / 2));
+
+    EnableControl(DDExtEnabledButton, WinConfiguration->DDExtInstalled);
+    EnableControl(DDExtEnabledLabel, WinConfiguration->DDExtInstalled);
+    EnableControl(DDExtDisabledPanel, DDExtDisabledButton->Checked);
+    EnableControl(DDTemporaryDirectoryEdit, DDCustomTemporaryDirectoryButton->Enabled &&
+      DDCustomTemporaryDirectoryButton->Checked);
+    EnableControl(DDWarnOnMoveCheck, DDExtDisabledButton->Checked &&
+      DDAllowMoveInitCheck->Checked);
+    EnableControl(ConfirmTemporaryDirectoryCleanupCheck,
+      TemporaryDirectoryCleanupCheck->Checked);
+    IniFileStorageButton2->Caption =
+      AnsiReplaceStr(IniFileStorageButton2->Caption, L"winscp.ini",
+        ExtractFileName(ExpandEnvironmentVariables(Configuration->IniFileStorageNameForReading)));
+
+    EditorFontLabel->WordWrap = EditorWordWrapCheck->Checked;
+    bool EditorSelected = (EditorListView3->Selected != NULL);
+    EnableControl(EditEditorButton, EditorSelected);
+    EnableControl(RemoveEditorButton, EditorSelected);
+    EnableControl(UpEditorButton, EditorSelected &&
+      (EditorListView3->ItemIndex > 0));
+    EnableControl(DownEditorButton, EditorSelected &&
+      (EditorListView3->ItemIndex < EditorListView3->Items->Count - 1));
+
+    EnableControl(UsageViewButton, CollectUsageCheck->Checked);
+    EnableControl(UpdatesProxyHostEdit, UpdatesProxyCheck->Checked);
+    EnableControl(UpdatesProxyHostLabel, UpdatesProxyHostEdit->Enabled);
+    EnableControl(UpdatesProxyPortEdit, UpdatesProxyCheck->Checked);
+    EnableControl(UpdatesProxyPortLabel, UpdatesProxyPortEdit->Enabled);
+
+    bool IsSiteCommand = false;
+    try
+    {
+      TRemoteCustomCommand RemoteCustomCommand;
+      TInteractiveCustomCommand InteractiveCustomCommand(&RemoteCustomCommand);
+      UnicodeString PuttyPath = PuttyPathEdit->Text;
+      PuttyPath = InteractiveCustomCommand.Complete(PuttyPath, false);
+      IsSiteCommand = RemoteCustomCommand.IsSiteCommand(PuttyPath);
+    }
+    catch (...)
+    {
+      // noop
+    }
+    EnableControl(PuttyPasswordCheck2, !PuttyPathEdit->Text.IsEmpty());
+    EnableControl(AutoOpenInPuttyCheck, PuttyPasswordCheck2->Enabled);
+    EnableControl(TelnetForFtpInPuttyCheck,
+      PuttyPasswordCheck2->Enabled && !IsSiteCommand);
+    EnableControl(PuttyRegistryStorageKeyEdit,
+      PuttyPasswordCheck2->Enabled && !IsSiteCommand);
+    EnableControl(PuttyRegistryStorageKeyLabel, PuttyRegistryStorageKeyEdit->Enabled);
+
+    EnableControl(SetMasterPasswordButton, WinConfiguration->UseMasterPassword);
+
+    // network
+    EnableControl(CustomExternalIpAddressEdit, CustomExternalIpAddressButton->Checked);
+
+    // window
+    EnableControl(AutoWorkspaceCombo, AutoSaveWorkspaceCheck->Checked);
+    EnableControl(AutoSaveWorkspacePasswordsCheck,
+      !Configuration->DisablePasswordStoring &&
+      AutoWorkspaceCombo->Enabled);
+      
+    // integration
+    // There's no quick launch in Windows 7
+    EnableControl(QuickLaunchIconButton, !IsWin7());
+
+    // languages
+    LanguageChangeLabel->Visible =
+      !GUIConfiguration->CanApplyLocaleImmediately &&
+      (LanguagesView->ItemFocused != NULL) &&
+      (reinterpret_cast<LCID>(LanguagesView->ItemFocused->Data) != GUIConfiguration->AppliedLocale);
+
+    // logging
+    EnableControl(LogProtocolCombo, EnableLoggingCheck->Checked);
+    EnableControl(LogToFileCheck, LogProtocolCombo->Enabled);
+    EnableControl(LogFileNameEdit3, LogToFileCheck->Enabled && LogToFileCheck->Checked);
+    EnableControl(LogFileNameHintText, LogFileNameEdit3->Enabled);
+    EnableControl(LogFileAppendButton, LogFileNameEdit3->Enabled);
+    EnableControl(LogFileOverwriteButton, LogFileNameEdit3->Enabled);
+
+    EnableControl(LogShowWindowCheck, LogProtocolCombo->Enabled);
+    EnableControl(LogWindowCompleteButton, LogShowWindowCheck->Enabled && LogShowWindowCheck->Checked);
+    EnableControl(LogWindowLinesButton, LogWindowCompleteButton->Enabled);
+    EnableControl(LogWindowLinesEdit, LogWindowLinesButton->Enabled && LogWindowLinesButton->Checked);
+    EnableControl(LogWindowLinesText, LogWindowLinesEdit->Enabled);
+
+    EnableControl(ActionsLogFileNameEdit, EnableActionsLoggingCheck->Checked);
+    EnableControl(ActionsLogFileNameHintText, ActionsLogFileNameEdit->Enabled);
+
+    // interface
+    InterfaceChangeLabel->Visible =
+      !CustomWinConfiguration->CanApplyInterfaceImmediately &&
+      (GetInterface() != CustomWinConfiguration->AppliedInterface);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::EditorFontButtonClick(TObject * /*Sender*/)
+{
+  if (FontDialog(FEditorFont))
+  {
+    UpdateControls();
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::FormCloseQuery(TObject * /*Sender*/,
+  bool & /*CanClose*/)
+{
+  if (ModalResult != mrCancel)
+  {
+    ExitActiveControl(this);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::IconButtonClick(TObject *Sender)
+{
+  UnicodeString IconName, Params;
+  int SpecialFolder;
+
+  if (Sender == DesktopIconButton)
+  {
+    IconName = AppName;
+    int Result =
+      MessageDialog(LoadStr(CREATE_DESKTOP_ICON), qtConfirmation,
+        qaYes | qaNo | qaCancel, HELP_CREATE_ICON);
+    switch (Result)
+    {
+      case qaYes:
+        SpecialFolder = CSIDL_COMMON_DESKTOPDIRECTORY;
+        break;
+
+      case qaNo:
+        SpecialFolder = CSIDL_DESKTOPDIRECTORY;
+        break;
+
+      default:
+        Abort();
+        break;
+    }
+  }
+  else
+  {
+    if (MessageDialog(LoadStr(CONFIRM_CREATE_ICON),
+          qtConfirmation, qaYes | qaNo, HELP_CREATE_ICON) == qaYes)
+    {
+      if (Sender == SendToHookButton)
+      {
+        IconName = FMTLOAD(SENDTO_HOOK_NAME, (AppName));
+        SpecialFolder = CSIDL_SENDTO;
+        Params = L"/upload";
+      }
+      else if (Sender == QuickLaunchIconButton)
+      {
+        IconName = L"Microsoft\\Internet Explorer\\Quick Launch\\" +
+          AppName;
+        SpecialFolder = CSIDL_APPDATA;
+      }
+    }
+    else
+    {
+      Abort();
+    }
+  }
+
+  CreateDesktopShortCut(IconName,
+    Application->ExeName, Params, L"", SpecialFolder);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CustomCommandsViewData(TObject * /*Sender*/,
+      TListItem * Item)
+{
+  assert(FCustomCommandList != NULL);
+  int Index = Item->Index;
+  assert(Index >= 0 && Index <= FCustomCommandList->Count);
+  const TCustomCommandType * Command = FCustomCommandList->Commands[Index];
+  UnicodeString Caption = StripHotkey(Command->Name);
+  if (Command->ShortCut != 0)
+  {
+    Caption = FORMAT(L"%s (%s)", (Caption, ShortCutToText(Command->ShortCut)));
+  }
+  Item->Caption = Caption;
+  assert(!Item->SubItems->Count);
+  Item->SubItems->Add(Command->Command);
+  int Params = Command->Params;
+  Item->SubItems->Add(LoadStr(
+    FLAGSET(Params, ccLocal) ? CUSTOM_COMMAND_LOCAL : CUSTOM_COMMAND_REMOTE));
+  UnicodeString ParamsStr;
+  #define ADDPARAM(PARAM, STR) \
+    if (FLAGSET(Params, PARAM)) \
+      ParamsStr += (ParamsStr.IsEmpty() ? L"" : L"/") + LoadStr(STR);
+  ADDPARAM(ccApplyToDirectories, CUSTOM_COMMAND_DIRECTORIES);
+  ADDPARAM(ccRecursive, CUSTOM_COMMAND_RECURSE);
+  #undef ADDPARAM
+  Item->SubItems->Add(ParamsStr);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::ListViewSelectItem(
+  TObject * /*Sender*/, TListItem * /*Item*/, bool /*Selected*/)
+{
+  UpdateControls();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::UpdateCustomCommandsView()
+{
+  CustomCommandsView->Items->Count = FCustomCommandList->Count;
+  AdjustListColumnsWidth(CustomCommandsView, FCustomCommandList->Count);
+  CustomCommandsView->Invalidate();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CustomCommandsViewKeyDown(
+      TObject * /*Sender*/, WORD & Key, TShiftState /*Shift*/)
+{
+  if (RemoveCommandButton->Enabled && (Key == VK_DELETE))
+  {
+    RemoveCommandButtonClick(NULL);
+  }
+
+  if (AddCommandButton->Enabled && (Key == VK_INSERT))
+  {
+    AddEditCommandButtonClick(AddCommandButton);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CustomCommandsViewDblClick(
+  TObject * /*Sender*/)
+{
+  if (EditCommandButton->Enabled)
+  {
+    AddEditCommandButtonClick(EditCommandButton);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::AddEditCommandButtonClick(TObject * Sender)
+{
+  CALLSTACK;
+  bool Edit = (Sender == EditCommandButton);
+  TCustomCommandType Command;
+
+  if (Edit)
+  {
+    TRACE("1");
+    int Index = CustomCommandsView->ItemIndex;
+    assert(Index >= 0 && Index <= FCustomCommandList->Count);
+
+    Command = *FCustomCommandList->Commands[Index];
+  }
+
+  TRACE("2");
+  TShortCuts ShortCuts;
+  if (WinConfiguration->SharedBookmarks != NULL)
+  {
+    WinConfiguration->SharedBookmarks->ShortCuts(ShortCuts);
+  }
+  FCustomCommandList->ShortCuts(ShortCuts);
+
+  TRACE("3");
+  if (DoCustomCommandDialog(Command, FCustomCommandList,
+        (Edit ? ccmEdit : ccmAdd), 0, NULL, &ShortCuts))
+  {
+    TRACE("4");
+    int Index = CustomCommandsView->ItemIndex;
+    TCustomCommandType * ACommand = new TCustomCommandType(Command);
+    if (Edit)
+    {
+      TRACE("5");
+      FCustomCommandList->Change(Index, ACommand);
+    }
+    else
+    {
+      TRACE("6");
+      if (Index >= 0)
+      {
+        TRACE("7");
+        FCustomCommandList->Insert(Index, ACommand);
+      }
+      else
+      {
+        TRACE("8");
+        FCustomCommandList->Add(ACommand);
+        Index = FCustomCommandList->Count - 1;
+      }
+    }
+
+    TRACE("9");
+    UpdateCustomCommandsView();
+    CustomCommandsView->ItemIndex = Index;
+    UpdateControls();
+  }
+  TRACE("/");
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::RemoveCommandButtonClick(
+      TObject * /*Sender*/)
+{
+  assert(CustomCommandsView->ItemIndex >= 0 &&
+    CustomCommandsView->ItemIndex < FCustomCommandList->Count);
+  FCustomCommandList->Delete(CustomCommandsView->ItemIndex);
+  UpdateCustomCommandsView();
+  UpdateControls();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CustomCommandMove(int Source, int Dest)
+{
+  if (Source >= 0 && Source < FCustomCommandList->Count &&
+      Dest >= 0 && Dest < FCustomCommandList->Count)
+  {
+    FCustomCommandList->Move(Source, Dest);
+    // workaround for bug in VCL
+    CustomCommandsView->ItemIndex = -1;
+    CustomCommandsView->ItemFocused = CustomCommandsView->Selected;
+    CustomCommandsView->ItemIndex = Dest;
+    UpdateCustomCommandsView();
+    UpdateControls();
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::UpDownCommandButtonClick(TObject * Sender)
+{
+  CustomCommandMove(CustomCommandsView->ItemIndex,
+    CustomCommandsView->ItemIndex + (Sender == UpCommandButton ? -1 : 1));
+}
+//---------------------------------------------------------------------------
+TListViewScrollOnDragOver * __fastcall TPreferencesDialog::ScrollOnDragOver(TObject * ListView)
+{
+  if (ListView == CopyParamListView)
+  {
+    return FCopyParamScrollOnDragOver;
+  }
+  else if (ListView == CustomCommandsView)
+  {
+    return FCustomCommandsScrollOnDragOver;
+  }
+  else if (ListView == EditorListView3)
+  {
+    return FEditorScrollOnDragOver;
+  }
+  else
+  {
+    assert(false);
+    return NULL;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::ListViewStartDrag(
+      TObject * Sender, TDragObject *& /*DragObject*/)
+{
+  FListViewDragSource = dynamic_cast<TListView*>(Sender)->ItemIndex;
+  FListViewDragDest = -1;
+  ScrollOnDragOver(Sender)->StartDrag();
+}
+//---------------------------------------------------------------------------
+bool __fastcall TPreferencesDialog::AllowListViewDrag(TObject * Sender, int X, int Y)
+{
+  TListItem * Item = dynamic_cast<TListView*>(Sender)->GetItemAt(X, Y);
+  FListViewDragDest = Item ? Item->Index : -1;
+  return (FListViewDragDest >= 0) && (FListViewDragDest != FListViewDragSource);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CustomCommandsViewDragDrop(
+      TObject * Sender, TObject * Source, int X, int Y)
+{
+  if (Source == CustomCommandsView)
+  {
+    if (AllowListViewDrag(Sender, X, Y))
+    {
+      CustomCommandMove(FListViewDragSource, FListViewDragDest);
+    }
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::ListViewDragOver(
+  TObject * Sender, TObject * Source, int X, int Y,
+  TDragState /*State*/, bool & Accept)
+{
+  if (Source == Sender)
+  {
+    // cannot use AllowListViewDrag(X, Y) because of bug in VCL
+    // (when dropped on item itself, when it was dragged over another item before,
+    // that another item remains highlighted forever)
+    Accept = true;
+
+    ScrollOnDragOver(Source)->DragOver(TPoint(X, Y));
+  }
+}
+//---------------------------------------------------------------------------
+const TCopyParamType * TPreferencesDialog::GetCopyParam(int Index)
+{
+  if (Index == 0)
+  {
+    return &FCopyParams;
+  }
+  else
+  {
+    return FCopyParamList->CopyParams[Index - 1];
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CopyParamMove(int Source, int Dest)
+{
+  if (Source >= 1 && Source < (1 + FCopyParamList->Count) &&
+      Dest >= 0 && Dest < (1 + FCopyParamList->Count))
+  {
+    if (Dest == 0)
+    {
+      Dest = 1;
+    }
+    FCopyParamList->Move(Source - 1, Dest - 1);
+    // workaround for bug in VCL
+    CopyParamListView->ItemIndex = -1;
+    CopyParamListView->ItemFocused = CopyParamListView->Selected;
+    CopyParamListView->ItemIndex = Dest;
+    UpdateCopyParamListView();
+    UpdateControls();
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CopyParamListViewDragDrop(
+  TObject * Sender, TObject * Source, int X, int Y)
+{
+  if (Source == CopyParamListView)
+  {
+    if (AllowListViewDrag(Sender, X, Y))
+    {
+      CopyParamMove(FListViewDragSource, FListViewDragDest);
+    }
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::UpDownCopyParamButtonClick(TObject * Sender)
+{
+  CopyParamMove(CopyParamListView->ItemIndex,
+    CopyParamListView->ItemIndex + (Sender == UpCopyParamButton ? -1 : 1));
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::RemoveCopyParamButtonClick(
+  TObject * /*Sender*/)
+{
+  assert(CopyParamListView->ItemIndex >= 1 &&
+    CopyParamListView->ItemIndex < (1 + FCopyParamList->Count));
+  FCopyParamList->Delete(CopyParamListView->ItemIndex - 1);
+  UpdateCopyParamListView();
+  UpdateControls();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::AddEditCopyParam(TCopyParamPresetMode Mode)
+{
+  CALLSTACK;
+  int Index = CopyParamListView->ItemIndex;
+  bool Result;
+  if ((Index == 0) && (Mode != cpmAdd))
+  {
+    Result = DoCopyParamCustomDialog(FCopyParams, 0);
+  }
+  else
+  {
+    if (Index == 0)
+    {
+      assert(Mode == cpmAdd);
+      Index = 1;
+    }
+
+    TCopyParamRuleData * CopyParamRuleData =
+      (FDialogData != NULL ? FDialogData->CopyParamRuleData : NULL);
+    Index--;
+    Result = DoCopyParamPresetDialog(FCopyParamList, Index, Mode, CopyParamRuleData);
+    if (Result)
+    {
+      UpdateCopyParamListView();
+      CopyParamListView->ItemIndex = Index + 1;
+      // when using duplicate button, focus remains on original item
+      CopyParamListView->ItemFocused = CopyParamListView->Selected;
+    }
+  }
+
+  if (Result)
+  {
+    UpdateControls();
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::AddCopyParamButtonClick(TObject * /*Sender*/)
+{
+  AddEditCopyParam(cpmAdd);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::EditCopyParamButtonClick(TObject * /*Sender*/)
+{
+  AddEditCopyParam(cpmEdit);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::DuplicateCopyParamButtonClick(TObject * /*Sender*/)
+{
+  if (ALWAYS_TRUE(CopyParamListView->ItemIndex >= 1))
+  {
+    AddEditCopyParam(cpmDuplicate);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CopyParamListViewDblClick(
+  TObject * /*Sender*/)
+{
+  if (EditCopyParamButton->Enabled)
+  {
+    AddEditCopyParam(cpmEdit);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CopyParamListViewKeyDown(
+  TObject * /*Sender*/, WORD & Key, TShiftState /*Shift*/)
+{
+  if (RemoveCopyParamButton->Enabled && (Key == VK_DELETE))
+  {
+    RemoveCopyParamButtonClick(NULL);
+  }
+
+  if (AddCopyParamButton->Enabled && (Key == VK_INSERT))
+  {
+    AddEditCopyParam(cpmAdd);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::EditorMove(int Source, int Dest)
+{
+  if (Source >= 0 && Source < FEditorList->Count &&
+      Dest >= 0 && Dest < FEditorList->Count)
+  {
+    FEditorList->Move(Source, Dest);
+    // workaround for bug in VCL
+    EditorListView3->ItemIndex = -1;
+    EditorListView3->ItemFocused = EditorListView3->Selected;
+    EditorListView3->ItemIndex = Dest;
+    UpdateEditorListView();
+    UpdateControls();
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::EditorListView3DragDrop(TObject * Sender,
+  TObject * Source, int X, int Y)
+{
+  if (Source == EditorListView3)
+  {
+    if (AllowListViewDrag(Sender, X, Y))
+    {
+      EditorMove(FListViewDragSource, FListViewDragDest);
+    }
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::UpDownEditorButtonClick(TObject *Sender)
+{
+  EditorMove(EditorListView3->ItemIndex,
+    EditorListView3->ItemIndex + (Sender == UpEditorButton ? -1 : 1));
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::RemoveEditorButtonClick(
+  TObject * /*Sender*/)
+{
+  assert(EditorListView3->ItemIndex >= 0 &&
+    EditorListView3->ItemIndex < FEditorList->Count);
+  FEditorList->Delete(EditorListView3->ItemIndex);
+  UpdateEditorListView();
+  UpdateControls();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::AddEditEditorButtonClick(TObject * Sender)
+{
+  TEditorPreferencesMode Mode = (Sender == EditEditorButton ? epmEdit : epmAdd);
+  int Index = EditorListView3->ItemIndex;
+  TEditorPreferences * Editor;
+  if (Mode == epmEdit)
+  {
+    Editor = new TEditorPreferences(*FEditorList->Editors[Index]);
+  }
+  else
+  {
+    Editor = new TEditorPreferences();
+  }
+
+  try
+  {
+    bool DummyRemember = false;
+    if (DoEditorPreferencesDialog(Editor->GetData(), DummyRemember, Mode, true))
+    {
+      if (Mode == epmEdit)
+      {
+        FEditorList->Change(Index, Editor);
+      }
+      else
+      {
+        if (Index < 0)
+        {
+          Index = FEditorList->Count;
+          FEditorList->Add(Editor);
+        }
+        else
+        {
+          FEditorList->Insert(Index, Editor);
+        }
+      }
+      // ownership of the object lost
+      Editor = NULL;
+
+      UpdateEditorListView();
+      EditorListView3->ItemIndex = Index;
+      UpdateControls();
+    }
+  }
+  __finally
+  {
+    delete Editor;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::EditorListView3DblClick(TObject * /*Sender*/)
+{
+  if (EditEditorButton->Enabled)
+  {
+    AddEditEditorButtonClick(EditEditorButton);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::EditorListView3KeyDown(TObject * /*Sender*/,
+  WORD & Key, TShiftState /*Shift*/)
+{
+  if (RemoveEditorButton->Enabled && (Key == VK_DELETE))
+  {
+    RemoveEditorButtonClick(NULL);
+  }
+
+  if (AddEditorButton->Enabled && (Key == VK_INSERT))
+  {
+    AddEditEditorButtonClick(AddEditorButton);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::UpdateEditorListView()
+{
+  EditorListView3->Items->Count = FEditorList->Count;
+  AdjustListColumnsWidth(EditorListView3, FEditorList->Count);
+  EditorListView3->Invalidate();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::EditorListView3Data(TObject * /*Sender*/,
+  TListItem * Item)
+{
+  int Index = Item->Index;
+  assert(Index >= 0 && Index <= FEditorList->Count);
+  const TEditorPreferences * Editor = FEditorList->Editors[Index];
+  Item->Caption = Editor->Name;
+  Item->SubItems->Add(Editor->Data->FileMask.Masks);
+  if (Editor->Data->Editor == edExternal)
+  {
+    Item->SubItems->Add(BooleanToStr(Editor->Data->ExternalEditorText));
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::NavigationTreeChange(TObject * /*Sender*/,
+  TTreeNode * Node)
+{
+  if (ALWAYS_TRUE(Node->SelectedIndex > 0))
+  {
+    PageControl->ActivePage = NOT_NULL(FindPageForTreeNode(Node));
+    // reshow the accelerators, etc
+    ResetSystemSettings(this);
+    // This is particularly here to enable EditCopyParamButton,
+    // as to some reason CopyParamListView->Selected is NULL until
+    // its page is shown for the first time
+    UpdateControls();
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::PageControlChange(TObject * /*Sender*/)
+{
+  // this is probably only ever called from FormShow (explicitly)
+  bool Found = false;
+  if (ALWAYS_TRUE(PageControl->ActivePage->Tag > 0))
+  {
+    for (int Index = 0; Index < NavigationTree->Items->Count; Index++)
+    {
+      if (NavigationTree->Items->Item[Index]->SelectedIndex ==
+            PageControl->ActivePage->Tag)
+      {
+        NavigationTree->Items->Item[Index]->Selected = true;
+        Found = true;
+      }
+    }
+  }
+
+  if (ALWAYS_TRUE(Found))
+  {
+    UpdateControls();
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CMDialogKey(TWMKeyDown & Message)
+{
+  if (Message.CharCode == VK_TAB)
+  {
+    TShiftState Shift = KeyDataToShiftState(Message.KeyData);
+    if (Shift.Contains(ssCtrl))
+    {
+      TTreeNode * Node = NavigationTree->Selected;
+      if (!Shift.Contains(ssShift))
+      {
+        Node = Node->GetNext();
+        if (!Node) Node = NavigationTree->Items->GetFirstNode();
+      }
+      else
+      {
+        if (Node->GetPrev()) Node = Node->GetPrev();
+          else
+        while (Node->GetNext()) Node = Node->GetNext();
+      }
+      Node->Selected = True;
+      Message.Result = 1;
+      return;
+    }
+  }
+  TForm::Dispatch(&Message);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::WMHelp(TWMHelp & Message)
+{
+  assert(Message.HelpInfo != NULL);
+
+  if (Message.HelpInfo->iContextType == HELPINFO_WINDOW)
+  {
+    // invoke help for active page (not for whole form), regardless of focus
+    // (e.g. even if focus is on control outside pagecontrol)
+    Message.HelpInfo->hItemHandle = PageControl->ActivePage->Handle;
+  }
+  TForm::Dispatch(&Message);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::Dispatch(void *Message)
+{
+  TMessage * M = reinterpret_cast<TMessage*>(Message);
+  assert(M);
+  if (M->Msg == CM_DIALOGKEY)
+  {
+    CMDialogKey(*((TWMKeyDown *)Message));
+  }
+  else if (M->Msg == WM_HELP)
+  {
+    WMHelp(*((TWMHelp *)Message));
+  }
+  else
+  {
+    TForm::Dispatch(Message);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::RegisterAsUrlHandlerButtonClick(
+  TObject * /*Sender*/)
+{
+  if (MessageDialog(LoadStr(CONFIRM_REGISTER_URL),
+        qtConfirmation, qaYes | qaNo, HELP_REGISTER_URL) == qaYes)
+  {
+    RegisterAsUrlHandler();
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::DDExtLabelClick(TObject * Sender)
+{
+  ((Sender == DDExtEnabledLabel) ? DDExtEnabledButton : DDExtDisabledButton)->
+    SetFocus();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::AddSearchPathButtonClick(
+  TObject * /*Sender*/)
+{
+  UnicodeString AppPath = ExtractFilePath(Application->ExeName);
+  if (MessageDialog(FMTLOAD(CONFIRM_ADD_SEARCH_PATH, (AppPath)),
+        qtConfirmation, qaYes | qaNo, HELP_ADD_SEARCH_PATH) == qaYes)
+  {
+    AddSearchPath(AppPath);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::EditorFontLabelDblClick(
+  TObject * Sender)
+{
+  EditorFontButtonClick(Sender);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::UpdateCopyParamListView()
+{
+  CopyParamListView->Items->Count = 1 + FCopyParamList->Count;
+  AdjustListColumnsWidth(CopyParamListView, 1 + FCopyParamList->Count);
+  CopyParamListView->Invalidate();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CopyParamListViewData(TObject * /*Sender*/,
+  TListItem * Item)
+{
+  UnicodeString Name;
+  UnicodeString Rule;
+
+  int Index = Item->Index;
+  if (Index == 0)
+  {
+    Name = StripHotkey(LoadStr(COPY_PARAM_DEFAULT));
+  }
+  else
+  {
+    assert(Index >= 1 && Index <= 1 + FCopyParamList->Count);
+    Name = StripHotkey(FCopyParamList->Names[Index - 1]);
+    Rule = BooleanToStr(FCopyParamList->Rules[Index - 1] != NULL);
+  }
+
+  Item->Caption = Name;
+  Item->SubItems->Add(Rule);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::HelpButtonClick(TObject * /*Sender*/)
+{
+  FormHelp(this);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::PuttyPathBrowseButtonClick(
+  TObject * /*Sender*/)
+{
+  CALLSTACK;
+  UnicodeString Executables = FORMAT("%s;%s", (OriginalPuttyExecutable, KittyExecutable));
+  BrowseForExecutable(PuttyPathEdit, LoadStr(PREFERENCES_SELECT_PUTTY2),
+    FMTLOAD(PREFERENCES_PUTTY_FILTER2, (Executables)), false, false);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::PathEditBeforeDialog(
+  TObject * /*Sender*/, UnicodeString & Name, bool & /*Action*/)
+{
+  FBeforeDialogPath = Name;
+  Name = ExpandEnvironmentVariables(Name);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::PathEditAfterDialog(
+  TObject * /*Sender*/, UnicodeString & Name, bool & /*Action*/)
+{
+  if (CompareFileName(Name, ExpandEnvironmentVariables(FBeforeDialogPath)))
+  {
+    Name = FBeforeDialogPath;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::NavigationTreeCollapsing(
+  TObject * /*Sender*/, TTreeNode * /*Node*/, bool & AllowCollapse)
+{
+  AllowCollapse = false;
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::ListViewEndDrag(
+  TObject * Sender, TObject * /*Target*/, int /*X*/, int /*Y*/)
+{
+  ScrollOnDragOver(Sender)->EndDrag();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::PathEditCreateEditDialog(
+  TObject * Sender, TFileDialogKind DialogKind, TOpenDialog *& Dialog)
+{
+  USEDPARAM(DialogKind);
+  assert(DialogKind == dkOpen);
+  Dialog = new TOpenDialog(dynamic_cast<TComponent *>(Sender));
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::SessionReopenTimeoutEditSetValue(
+  TObject * /*Sender*/, Extended Value, UnicodeString & Text, bool & Handled)
+{
+  if (Value == 0)
+  {
+    Text = LoadStr(PREFERENCES_RECONNECT_TIMEOUT_UNLIMITED);
+    Handled = true;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::SessionReopenTimeoutEditGetValue(
+  TObject * /*Sender*/, UnicodeString Text, Extended & Value, bool & Handled)
+{
+  if (AnsiSameText(Text, LoadStr(PREFERENCES_RECONNECT_TIMEOUT_UNLIMITED)))
+  {
+    Value = 0;
+    Handled = true;
+  }
+}
+//---------------------------------------------------------------------------
+bool __fastcall TPreferencesDialog::CanSetMasterPassword()
+{
+  CALLSTACK;
+  bool Result = false;
+  bool Retry;
+  do
+  {
+    TRACE("1");
+    Retry = false;
+    Result = !AnyOtherInstanceOfSelf();
+
+    if (!Result)
+    {
+      TRACE("2");
+      unsigned int Answer =
+        MessageDialog(
+          LoadStr(MASTER_PASSWORD_OTHER_INSTANCE),
+          qtConfirmation, qaRetry | qaIgnore | qaCancel,
+          HELP_MASTER_PASSWORD);
+
+      switch (Answer)
+      {
+        case qaRetry:
+          Retry = true;
+          break;
+
+        case qaIgnore:
+          Result = true;
+          break;
+
+        case qaCancel:
+        default:
+          // noop
+          break;
+      }
+    }
+  }
+  while (Retry && !Result);
+
+  TRACE_EXIT;
+  return Result;
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::MasterPasswordChanged(
+  UnicodeString Message, TStrings * RecryptPasswordErrors)
+{
+  CALLSTACK;
+  Configuration->Save();
+  if (RecryptPasswordErrors->Count > 0)
+  {
+    Message = FMTLOAD(MASTER_PASSWORD_RECRYPT_ERRORS, (Message));
+  }
+  MoreMessageDialog(
+    Message, RecryptPasswordErrors, qtInformation, qaOK, HELP_MASTER_PASSWORD);
+  TRACE_EXIT;
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::ChangeMasterPassword(UnicodeString Message)
+{
+  CALLSTACK;
+  UnicodeString NewPassword;
+  if (DoChangeMasterPasswordDialog(NewPassword))
+  {
+    TRACE("1");
+    std::auto_ptr<TStrings> RecryptPasswordErrors(new TStringList());
+    WinConfiguration->ChangeMasterPassword(NewPassword, RecryptPasswordErrors.get());
+    MasterPasswordChanged(Message, RecryptPasswordErrors.get());
+  }
+  TRACE_EXIT;
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::UseMasterPasswordCheckClick(
+  TObject * /*Sender*/)
+{
+  CALLSTACK;
+  if (UseMasterPasswordCheck->Checked != WinConfiguration->UseMasterPassword)
+  {
+    TRACE("1");
+    try
+    {
+      if (CanSetMasterPassword())
+      {
+        if (UseMasterPasswordCheck->Checked)
+        {
+          TRACE("2");
+          ChangeMasterPassword(LoadStr(MASTER_PASSWORD_SET));
+        }
+        else
+        {
+          TRACE("3");
+          if (DoMasterPasswordDialog())
+          {
+            TRACE("4");
+            std::auto_ptr<TStrings> RecryptPasswordErrors(new TStringList());
+            WinConfiguration->ClearMasterPassword(RecryptPasswordErrors.get());
+            MasterPasswordChanged(LoadStr(MASTER_PASSWORD_CLEARED), RecryptPasswordErrors.get());
+          }
+        }
+      }
+    }
+    __finally
+    {
+      TRACE("5");
+      UseMasterPasswordCheck->Checked = WinConfiguration->UseMasterPassword;
+      UpdateControls();
+    }
+  }
+  TRACE_EXIT;
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::SetMasterPasswordButtonClick(
+  TObject * /*Sender*/)
+{
+  CALLSTACK;
+  if (CanSetMasterPassword())
+  {
+    ChangeMasterPassword(LoadStr(MASTER_PASSWORD_CHANGED));
+  }
+  TRACE_EXIT;
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::UsageViewButtonClick(TObject * /*Sender*/)
+{
+  TStrings * Data = new TStringList();
+  try
+  {
+    Data->Text = GetUsageData();
+    UnicodeString Message =
+      LoadStr(Data->Text.IsEmpty() ? USAGE_DATA_NONE : USAGE_DATA);
+    MoreMessageDialog(Message, Data, qtInformation, qaOK, HELP_USAGE);
+  }
+  __finally
+  {
+    delete Data;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CopyParamLabelClick(TObject * /*Sender*/)
+{
+  if (EditCopyParamButton->Enabled)
+  {
+    AddEditCopyParam(cpmEdit);
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CopyParamListViewCustomDrawItem(
+  TCustomListView * Sender, TListItem * Item,
+  TCustomDrawState /*State*/, bool & /*DefaultDraw*/)
+{
+  if (Item->Index == 0)
+  {
+    Sender->Canvas->Font->Style = Sender->Canvas->Font->Style << fsBold;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::SelectPuttyRegistryStorageKey(const UnicodeString & Key)
+{
+  CALLSTACK;
+  PuttyRegistryStorageKeyEdit->ItemIndex =
+    PuttyRegistryStorageKeyEdit->Items->IndexOf(Key);
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::PuttyPathEditChange(TObject * /*Sender*/)
+{
+  CALLSTACK;
+  UnicodeString PuttyPath = PuttyPathEdit->Text;
+  if (ContainsText(PuttyPath, OriginalPuttyExecutable))
+  {
+    SelectPuttyRegistryStorageKey(OriginalPuttyRegistryStorageKey);
+  }
+  else if (ContainsText(PuttyPath, KittyExecutable))
+  {
+    SelectPuttyRegistryStorageKey(KittyRegistryStorageKey);
+  }
+
+  UpdateControls();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::NavigationTreeChanging(TObject * /*Sender*/,
+  TTreeNode * Node, bool & /*AllowChange*/)
+{
+  CALLSTACK;
+  TTabSheet * Sheet = FindPageForTreeNode(Node);
+  // delay load as this can be time consuming
+  if (Sheet == LanguagesSheet)
+  {
+    LoadLanguages();
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::LanguagesGetMoreButtonClick(TObject * /*Sender*/)
+{
+  CALLSTACK;
+  OpenBrowser(LoadStr(LOCALES_URL));
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::CommanderClick(TObject * /*Sender*/)
+{
+  CommanderInterfaceButton2->SetFocus();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::ExplorerClick(TObject * /*Sender*/)
+{
+  ExplorerInterfaceButton2->SetFocus();
+}
+//---------------------------------------------------------------------------
+

+ 3 - 3
source/forms/Preferences.dfm

@@ -1387,14 +1387,14 @@ object PreferencesDialog: TPreferencesDialog
             TabOrder = 5
             TabOrder = 5
             OnClick = AddSearchPathButtonClick
             OnClick = AddSearchPathButtonClick
           end
           end
-          object ShellIconsText: TStaticText
+          object ShellIconsText2: TStaticText
             Left = 11
             Left = 11
             Top = 116
             Top = 116
             Width = 330
             Width = 330
             Height = 17
             Height = 17
             Hint = 
             Hint = 
-              'To add shortcuts, which directly open site, use button '#39'Shell ic' +
-              'on'#39' on '#39'Sites'#39' page of Login dialog.'
+              'To add shortcuts, which directly open site, use icon commands in' +
+              ' '#39'Manage'#39' menu on Login dialog.'
             Alignment = taRightJustify
             Alignment = taRightJustify
             Anchors = [akTop, akRight]
             Anchors = [akTop, akRight]
             AutoSize = False
             AutoSize = False

+ 5 - 1
source/forms/Preferences.h

@@ -171,7 +171,7 @@ __published:
   TComboBox *DoubleClickActionCombo;
   TComboBox *DoubleClickActionCombo;
   TLabel *Label8;
   TLabel *Label8;
   TComboBox *NortonLikeModeCombo;
   TComboBox *NortonLikeModeCombo;
-  TStaticText *ShellIconsText;
+  TStaticText *ShellIconsText2;
   TCheckBox *FullRowSelectCheck;
   TCheckBox *FullRowSelectCheck;
   TGroupBox *SessionReopenGroup;
   TGroupBox *SessionReopenGroup;
   TLabel *SessionReopenAutoLabel;
   TLabel *SessionReopenAutoLabel;
@@ -405,6 +405,10 @@ protected:
   TListViewScrollOnDragOver * __fastcall ScrollOnDragOver(TObject * ListView);
   TListViewScrollOnDragOver * __fastcall ScrollOnDragOver(TObject * ListView);
   void __fastcall LoadLanguages();
   void __fastcall LoadLanguages();
   TTabSheet * __fastcall FindPageForTreeNode(TTreeNode * Node);
   TTabSheet * __fastcall FindPageForTreeNode(TTreeNode * Node);
+  bool __fastcall CanSetMasterPassword();
+  void __fastcall ChangeMasterPassword(UnicodeString Message);
+  void __fastcall MasterPasswordChanged(
+    UnicodeString Message, TStrings * RecryptPasswordErrors);
 };
 };
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 #endif
 #endif

+ 72 - 1
source/forms/SiteAdvanced.cpp

@@ -54,6 +54,7 @@ __fastcall TSiteAdvancedDialog::TSiteAdvancedDialog(
   // (so that CM_SHOWINGCHANGED handling is applied)
   // (so that CM_SHOWINGCHANGED handling is applied)
   UseSystemSettings(this);
   UseSystemSettings(this);
   InitControls();
   InitControls();
+  PageControl->ActivePage = EnvironmentSheet;
 }
 }
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
 void __fastcall TSiteAdvancedDialog::InitControls()
 void __fastcall TSiteAdvancedDialog::InitControls()
@@ -100,7 +101,7 @@ void __fastcall TSiteAdvancedDialog::InitControls()
 
 
   UpdateNavigationTree();
   UpdateNavigationTree();
 
 
-  if (FLAGSET(FOptions, loLocalDirectory))
+  if (FLAGCLEAR(FOptions, loLocalDirectory))
   {
   {
     LocalDirectoryLabel->Visible = false;
     LocalDirectoryLabel->Visible = false;
     LocalDirectoryEdit->Visible = false;
     LocalDirectoryEdit->Visible = false;
@@ -385,6 +386,10 @@ void __fastcall TSiteAdvancedDialog::LoadSession()
     // hide selection, which is wrongly shown initially even when the box has not focus
     // hide selection, which is wrongly shown initially even when the box has not focus
     TunnelLocalPortNumberEdit->SelLength = 0;
     TunnelLocalPortNumberEdit->SelLength = 0;
 
 
+    // connection/tls/ssl page
+    MinTlsVersionCombo->ItemIndex = TlsVersionToIndex(FSessionData->MinTlsVersion);
+    MaxTlsVersionCombo->ItemIndex = TlsVersionToIndex(FSessionData->MaxTlsVersion);
+
     // color
     // color
     SetSessionColor((TColor)FSessionData->Color);
     SetSessionColor((TColor)FSessionData->Color);
   }
   }
@@ -613,6 +618,10 @@ void __fastcall TSiteAdvancedDialog::SaveSession()
     FSessionData->TunnelLocalPortNumber = StrToIntDef(TunnelLocalPortNumberEdit->Text, 0);
     FSessionData->TunnelLocalPortNumber = StrToIntDef(TunnelLocalPortNumberEdit->Text, 0);
   }
   }
 
 
+  // connection/tls/ssl page
+  FSessionData->MinTlsVersion = IndexToTlsVersion(MinTlsVersionCombo->ItemIndex);
+  FSessionData->MaxTlsVersion = IndexToTlsVersion(MaxTlsVersionCombo->ItemIndex);
+
   // color
   // color
   FSessionData->Color = FColor;
   FSessionData->Color = FColor;
 }
 }
@@ -733,6 +742,7 @@ void __fastcall TSiteAdvancedDialog::UpdateControls()
     bool ScpProtocol = (FSessionData->FSProtocol == fsSCPonly);
     bool ScpProtocol = (FSessionData->FSProtocol == fsSCPonly);
     bool FtpProtocol = (FSessionData->FSProtocol == fsFTP);
     bool FtpProtocol = (FSessionData->FSProtocol == fsFTP);
     bool WebDavProtocol = (FSessionData->FSProtocol == fsWebDAV);
     bool WebDavProtocol = (FSessionData->FSProtocol == fsWebDAV);
+    bool Ssl = (FtpProtocol || WebDavProtocol) && (FSessionData->Ftps != ftpsNone);
 
 
     // connection sheet
     // connection sheet
     EnableControl(FtpPasvModeCheck, FtpProtocol);
     EnableControl(FtpPasvModeCheck, FtpProtocol);
@@ -947,6 +957,9 @@ void __fastcall TSiteAdvancedDialog::UpdateControls()
     EnableControl(TunnelOptionsGroup, TunnelSessionGroup->Enabled);
     EnableControl(TunnelOptionsGroup, TunnelSessionGroup->Enabled);
     EnableControl(TunnelAuthenticationParamsGroup, TunnelSessionGroup->Enabled);
     EnableControl(TunnelAuthenticationParamsGroup, TunnelSessionGroup->Enabled);
 
 
+    // connection/ssl/tls
+    SslSheet->Enabled = Ssl;
+
     UpdateNavigationTree();
     UpdateNavigationTree();
 
 
     // color
     // color
@@ -1375,3 +1388,61 @@ void __fastcall TSiteAdvancedDialog::SetSessionColor(TColor Color)
   }
   }
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+TTlsVersion __fastcall TSiteAdvancedDialog::IndexToTlsVersion(int Index)
+{
+  switch (Index)
+  {
+    default:
+      FAIL;
+    case 0:
+      return ssl2;
+    case 1:
+      return ssl3;
+    case 2:
+      return tls10;
+    case 3:
+      return tls11;
+    case 4:
+      return tls12;
+  }
+}
+//---------------------------------------------------------------------------
+int __fastcall TSiteAdvancedDialog::TlsVersionToIndex(TTlsVersion TlsVersion)
+{
+  switch (TlsVersion)
+  {
+    default:
+      FAIL;
+    case ssl2:
+      return 0;
+    case ssl3:
+      return 1;
+    case tls10:
+      return 2;
+    case tls11:
+      return 3;
+    case tls12:
+      return 4;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TSiteAdvancedDialog::MinTlsVersionComboChange(TObject */*Sender*/)
+{
+  TTlsVersion MinTlsVersion = IndexToTlsVersion(MinTlsVersionCombo->ItemIndex);
+  TTlsVersion MaxTlsVersion = IndexToTlsVersion(MaxTlsVersionCombo->ItemIndex);
+  if (MaxTlsVersion < MinTlsVersion)
+  {
+    MaxTlsVersionCombo->ItemIndex = MinTlsVersionCombo->ItemIndex;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TSiteAdvancedDialog::MaxTlsVersionComboChange(TObject * /*Sender*/)
+{
+  TTlsVersion MinTlsVersion = IndexToTlsVersion(MinTlsVersionCombo->ItemIndex);
+  TTlsVersion MaxTlsVersion = IndexToTlsVersion(MaxTlsVersionCombo->ItemIndex);
+  if (MinTlsVersion > MaxTlsVersion)
+  {
+    MinTlsVersionCombo->ItemIndex = MaxTlsVersionCombo->ItemIndex;
+  }
+}
+//---------------------------------------------------------------------------

+ 71 - 0
source/forms/SiteAdvanced.dfm

@@ -1503,6 +1503,77 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
           end
           end
         end
         end
       end
       end
+      object SslSheet: TTabSheet
+        Tag = 2
+        HelpType = htKeyword
+        HelpKeyword = 'ui_login_tls'
+        Caption = 'TLS/SSL'
+        ImageIndex = 13
+        TabVisible = False
+        DesignSize = (
+          353
+          382)
+        object SslGroup: TGroupBox
+          Left = 0
+          Top = 6
+          Width = 345
+          Height = 71
+          Anchors = [akLeft, akTop, akRight]
+          Caption = 'TLS/SSL options'
+          TabOrder = 0
+          DesignSize = (
+            345
+            71)
+          object Label1: TLabel
+            Left = 12
+            Top = 20
+            Width = 123
+            Height = 13
+            Caption = 'Mi&nimum TLS/SSL version:'
+            FocusControl = MinTlsVersionCombo
+          end
+          object Label2: TLabel
+            Left = 12
+            Top = 44
+            Width = 127
+            Height = 13
+            Caption = 'Ma&ximum TLS/SSL version:'
+            FocusControl = MaxTlsVersionCombo
+          end
+          object MinTlsVersionCombo: TComboBox
+            Left = 256
+            Top = 15
+            Width = 77
+            Height = 21
+            Style = csDropDownList
+            Anchors = [akTop, akRight]
+            TabOrder = 0
+            OnChange = MinTlsVersionComboChange
+            Items.Strings = (
+              'SSL 2.0'
+              'SSL 3.0'
+              'TLS 1.0'
+              'TLS 1.1'
+              'TLS 1.2')
+          end
+          object MaxTlsVersionCombo: TComboBox
+            Left = 256
+            Top = 39
+            Width = 77
+            Height = 21
+            Style = csDropDownList
+            Anchors = [akTop, akRight]
+            TabOrder = 1
+            OnChange = MaxTlsVersionComboChange
+            Items.Strings = (
+              'SSL 2.0'
+              'SSL 3.0'
+              'TLS 1.0'
+              'TLS 1.1'
+              'TLS 1.2')
+          end
+        end
+      end
       object AdvancedSheet: TTabSheet
       object AdvancedSheet: TTabSheet
         Tag = 1
         Tag = 1
         HelpType = htKeyword
         HelpType = htKeyword

+ 10 - 0
source/forms/SiteAdvanced.h

@@ -239,6 +239,12 @@ __published:
   TMenuItem *PickColorItem;
   TMenuItem *PickColorItem;
   TImageList *ColorImageList;
   TImageList *ColorImageList;
   TButton *ColorButton;
   TButton *ColorButton;
+  TTabSheet *SslSheet;
+  TGroupBox *SslGroup;
+  TLabel *Label1;
+  TComboBox *MinTlsVersionCombo;
+  TLabel *Label2;
+  TComboBox *MaxTlsVersionCombo;
   void __fastcall DataChange(TObject *Sender);
   void __fastcall DataChange(TObject *Sender);
   void __fastcall FormShow(TObject *Sender);
   void __fastcall FormShow(TObject *Sender);
   void __fastcall PageControlChange(TObject *Sender);
   void __fastcall PageControlChange(TObject *Sender);
@@ -265,6 +271,8 @@ __published:
   void __fastcall ColorButtonClick(TObject *Sender);
   void __fastcall ColorButtonClick(TObject *Sender);
   void __fastcall ColorDefaultItemClick(TObject *Sender);
   void __fastcall ColorDefaultItemClick(TObject *Sender);
   void __fastcall PickColorItemClick(TObject *Sender);
   void __fastcall PickColorItemClick(TObject *Sender);
+  void __fastcall MinTlsVersionComboChange(TObject *Sender);
+  void __fastcall MaxTlsVersionComboChange(TObject *Sender);
 
 
 public:
 public:
   virtual __fastcall TSiteAdvancedDialog(TComponent * AOwner, int Options);
   virtual __fastcall TSiteAdvancedDialog(TComponent * AOwner, int Options);
@@ -301,6 +309,8 @@ private:
   void __fastcall UpdateNavigationTree();
   void __fastcall UpdateNavigationTree();
   TSshProt __fastcall GetSshProt();
   TSshProt __fastcall GetSshProt();
   void __fastcall SetSessionColor(TColor Color);
   void __fastcall SetSessionColor(TColor Color);
+  TTlsVersion __fastcall IndexToTlsVersion(int Index);
+  int __fastcall TlsVersionToIndex(TTlsVersion TlsVersion);
 };
 };
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 #endif
 #endif

+ 1 - 1
source/forms/SynchronizeChecklist.dfm

@@ -1002,7 +1002,7 @@ object SynchronizeChecklistDialog: TSynchronizeChecklistDialog
     Left = 648
     Left = 648
     Top = 360
     Top = 360
     Bitmap = {
     Bitmap = {
-      494C010102000400100010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
+      494C0101020004000C0010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
       0000000000003600000028000000400000001000000001002000000000000010
       0000000000003600000028000000400000001000000001002000000000000010
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000000000000000000000000000000000000000000000000000

+ 9 - 24
source/packages/dragndrop/DragDropFilesEx.pas

@@ -549,30 +549,15 @@ begin
           end;
           end;
           if FilenamesAreMapped then
           if FilenamesAreMapped then
           begin
           begin
-               if Win32Platform=VER_PLATFORM_WIN32_WINDOWS then
-               begin
-                    with FE do
-                    begin
-                         cfFormat:=CF_FILENAMEMAP;
-                         ptd:=nil;
-                         dwAspect:=DVASPECT_CONTENT;
-                         lindex:=-1;
-                         tymed:=TYMED_HGLOBAL;
-                    end;
-                    SetData(FE,SM,false);
-               end
-               else
-               begin
-                    with FE do
-                    begin
-                         cfFormat:=CF_FILENAMEMAPW;
-                         ptd:=nil;
-                         dwAspect:=DVASPECT_CONTENT;
-                         lindex:=-1;
-                         tymed:=TYMED_HGLOBAL;
-                    end;
-                    SetData(FE,SM,false);
-               end;
+                with FE do
+                begin
+                     cfFormat:=CF_FILENAMEMAPW;
+                     ptd:=nil;
+                     dwAspect:=DVASPECT_CONTENT;
+                     lindex:=-1;
+                     tymed:=TYMED_HGLOBAL;
+                end;
+                SetData(FE,SM,false);
           end;
           end;
      end;
      end;
 end;
 end;

+ 1 - 3
source/packages/filemng/CustomDirView.pas

@@ -137,7 +137,6 @@ type
     FFormatSizeBytes: Boolean;
     FFormatSizeBytes: Boolean;
     FSortByExtension: Boolean;
     FSortByExtension: Boolean;
     FWantUseDragImages: Boolean;
     FWantUseDragImages: Boolean;
-    FCanUseDragImages: Boolean;
     FDragDropFilesEx: TCustomizableDragDropFilesEx;
     FDragDropFilesEx: TCustomizableDragDropFilesEx;
     FSingleClickToExec: Boolean;
     FSingleClickToExec: Boolean;
     FUseSystemContextMenu: Boolean;
     FUseSystemContextMenu: Boolean;
@@ -874,7 +873,6 @@ begin
   FShowSubDirSize := False;
   FShowSubDirSize := False;
   FFormatSizeBytes := False;
   FFormatSizeBytes := False;
   FWantUseDragImages := True;
   FWantUseDragImages := True;
-  FCanUseDragImages := (Win32PlatForm = VER_PLATFORM_WIN32_NT) or (WinVer.dwMinorVersion > 0);
   FAddParentDir := False;
   FAddParentDir := False;
   FullDrag := True;
   FullDrag := True;
   FSingleClickToExec := False;
   FSingleClickToExec := False;
@@ -1203,7 +1201,7 @@ end;
 
 
 function TCustomDirView.GetUseDragImages: Boolean;
 function TCustomDirView.GetUseDragImages: Boolean;
 begin
 begin
-  Result := FWantUseDragImages and FCanUseDragImages;
+  Result := FWantUseDragImages;
 end;
 end;
 
 
 procedure TCustomDirView.SetTargetPopupMenu(Value: Boolean);
 procedure TCustomDirView.SetTargetPopupMenu(Value: Boolean);

+ 1 - 6
source/packages/filemng/CustomDriveView.pas

@@ -26,7 +26,6 @@ type
   protected
   protected
     FParentForm: TCustomForm;
     FParentForm: TCustomForm;
     FDragFileList: TStringList;
     FDragFileList: TStringList;
-    FUseDragImages: Boolean;
     FDragDropFilesEx: TCustomizableDragDropFilesEx;
     FDragDropFilesEx: TCustomizableDragDropFilesEx;
     FDragImageList: TDragImageList;
     FDragImageList: TDragImageList;
     FDragDrive: TDrive;
     FDragDrive: TDrive;
@@ -204,9 +203,6 @@ type
       read FOnDDCreateDataObject write FOnDDCreateDataObject;
       read FOnDDCreateDataObject write FOnDDCreateDataObject;
     property OnDDMenuPopup: TOnMenuPopup read FOnDDMenuPopup write FOnDDMenuPopup;
     property OnDDMenuPopup: TOnMenuPopup read FOnDDMenuPopup write FOnDDMenuPopup;
 
 
-    { Show drag images during a drag&drop operation }
-    property UseDragImages: Boolean read FUseDragImages write FUseDragImages default True;
-
     { Show popupmenu when dropping a file with the right mouse button }
     { Show popupmenu when dropping a file with the right mouse button }
     property TargetPopUpMenu: Boolean read GetTargetPopUpMenu write SetTargetPopUpMenu default True;
     property TargetPopUpMenu: Boolean read GetTargetPopUpMenu write SetTargetPopUpMenu default True;
 
 
@@ -238,7 +234,6 @@ begin
 
 
   DragMode := dmAutomatic;
   DragMode := dmAutomatic;
   FDragFileList := TStringList.Create;
   FDragFileList := TStringList.Create;
-  FUseDragImages := (Win32PlatForm = VER_PLATFORM_WIN32_NT) or (WinVer.dwMinorVersion > 0);
   FDragDrive := #0;
   FDragDrive := #0;
   FExeDrag := False;
   FExeDrag := False;
   FDDLinkOnExeDrag := True;
   FDDLinkOnExeDrag := True;
@@ -700,7 +695,7 @@ begin
     try
     try
       {Create the dragimage:}
       {Create the dragimage:}
       GlobalDragImageList := FDragImageList;
       GlobalDragImageList := FDragImageList;
-      if UseDragImages and (not AvoidDragImage) then
+      if not AvoidDragImage then
       begin
       begin
         {Hide the selection mark to get a proper dragimage:}
         {Hide the selection mark to get a proper dragimage:}
         if Selected = FDragNode then
         if Selected = FDragNode then

+ 3 - 10
source/packages/filemng/DirView.pas

@@ -2123,8 +2123,6 @@ begin
   if Attr <> 0 then
   if Attr <> 0 then
   begin
   begin
     LowBound := Low(Attrs);
     LowBound := Low(Attrs);
-    if Win32PlatForm <> VER_PLATFORM_WIN32_NT then
-      Inc(LowBound);
 
 
     for Index := LowBound to High(Attrs) do
     for Index := LowBound to High(Attrs) do
       if (Attr and Attrs[Index] <> 0) then
       if (Attr and Attrs[Index] <> 0) then
@@ -3148,7 +3146,7 @@ begin
       end;
       end;
     end;
     end;
 
 
-    if Win32PlatForm = VER_PLATFORM_WIN32_NT then Sleep(250);
+    Sleep(250);
     ValidateSelectedFiles;
     ValidateSelectedFiles;
 
 
   finally
   finally
@@ -3168,11 +3166,11 @@ begin
     if Empty then
     if Empty then
       GetDisplayData(ListItem, IconEmpty and
       GetDisplayData(ListItem, IconEmpty and
         (not FUseIconUpdateThread or
         (not FUseIconUpdateThread or
-         ((ViewStyle <> vsReport) and (Win32PlatForm = VER_PLATFORM_WIN32_NT))));
+         (ViewStyle <> vsReport)));
 
 
     if IconEmpty and
     if IconEmpty and
        (not FUseIconUpdateThread or
        (not FUseIconUpdateThread or
-        ((ViewStyle <> vsReport) and (Win32PlatForm = VER_PLATFORM_WIN32_NT))) and
+        (ViewStyle <> vsReport)) and
        ((DispInfo.Mask and LVIF_IMAGE) <> 0) then
        ((DispInfo.Mask and LVIF_IMAGE) <> 0) then
       GetDisplayData(ListItem, True);
       GetDisplayData(ListItem, True);
 
 
@@ -4407,13 +4405,8 @@ end;
 
 
 {=================================================================}
 {=================================================================}
 
 
-var
-  IsWin7: Boolean;
 initialization
 initialization
   LastClipBoardOperation := cboNone;
   LastClipBoardOperation := cboNone;
   LastIOResult := 0;
   LastIOResult := 0;
-  IsWin7 :=
-    (Win32MajorVersion > 6) or
-    ((Win32MajorVersion = 6) and (Win32MinorVersion >= 1));
   DaylightHack := (not IsWin7) or IsExactly2008R2;
   DaylightHack := (not IsWin7) or IsExactly2008R2;
 end.
 end.

+ 1 - 3
source/packages/filemng/DriveView.pas

@@ -397,8 +397,6 @@ type
 
 
     property DDLinkOnExeDrag;
     property DDLinkOnExeDrag;
 
 
-    property UseDragImages;
-
     property TargetPopUpMenu;
     property TargetPopUpMenu;
 
 
     property OnDDDragEnter;
     property OnDDDragEnter;
@@ -2124,7 +2122,7 @@ begin
           else
           else
         begin
         begin
           Result := False;
           Result := False;
-          if (Win32PlatForm = VER_PLATFORM_WIN32_NT) and (not AllowUndo) then
+          if not AllowUndo then
           begin
           begin
             {WinNT4-Bug: FindFirst still returns the directories search record, even if the
             {WinNT4-Bug: FindFirst still returns the directories search record, even if the
              directory was deleted:}
              directory was deleted:}

+ 1 - 0
source/packages/filemng/IEComboBox.pas

@@ -428,4 +428,5 @@ begin
   end;
   end;
 end;
 end;
 
 
+initialization
 end.
 end.

+ 1 - 0
source/packages/my/ComboEdit.pas

@@ -1331,4 +1331,5 @@ begin
   end;
   end;
 end;
 end;
 
 
+initialization
 end.
 end.

+ 2 - 1
source/packages/my/GrayedCheckBox.pas

@@ -16,7 +16,7 @@ procedure Register;
 implementation
 implementation
 
 
 uses
 uses
-  Classes;
+  Classes, Windows, SysUtils;
 
 
 procedure Register;
 procedure Register;
 begin
 begin
@@ -35,4 +35,5 @@ begin
   end;
   end;
 end;
 end;
 
 
+initialization
 end.
 end.

+ 1 - 0
source/packages/my/HistoryComboBox.pas

@@ -172,4 +172,5 @@ begin
   end;
   end;
 end;
 end;
 
 
+initialization
 end.
 end.

+ 1 - 3
source/packages/my/NortonLikeListView.pas

@@ -222,9 +222,7 @@ begin
   // Doing the same on WinXP makes list view down from the item flicker,
   // Doing the same on WinXP makes list view down from the item flicker,
   // so we avoid this there.
   // so we avoid this there.
   // Not sure about Vista
   // Not sure about Vista
-  FForceUpdateOnItemUnfocus :=
-    (Win32MajorVersion > 6) or
-    ((Win32MajorVersion = 6) and (Win32MinorVersion >= 1));
+  FForceUpdateOnItemUnfocus := IsWin7;
   FNextCharToIgnore := 0;
   FNextCharToIgnore := 0;
 end;
 end;
 
 

+ 7 - 0
source/packages/my/PasTools.pas

@@ -11,6 +11,8 @@ function IsVista: Boolean;
 
 
 function IsExactly2008R2: Boolean;
 function IsExactly2008R2: Boolean;
 
 
+function IsWin7: Boolean;
+
 function CutToChar(var Str: string; Ch: Char; Trim: Boolean): string;
 function CutToChar(var Str: string; Ch: Char; Trim: Boolean): string;
 
 
 procedure FilterToFileTypes(Filter: string; FileTypes: TFileTypeItems);
 procedure FilterToFileTypes(Filter: string; FileTypes: TFileTypeItems);
@@ -139,6 +141,11 @@ begin
   end;
   end;
 end;
 end;
 
 
+function IsWin7: Boolean;
+begin
+  Result := CheckWin32Version(6, 1);
+end;
+
 function CutToChar(var Str: string; Ch: Char; Trim: Boolean): string;
 function CutToChar(var Str: string; Ch: Char; Trim: Boolean): string;
 var
 var
   P: Integer;
   P: Integer;

+ 2 - 1
source/packages/my/PasswordEdit.pas

@@ -79,7 +79,7 @@ procedure Register;
 
 
 implementation
 implementation
 
 
-uses Windows;
+uses Windows, SysUtils;
 
 
 procedure Register;
 procedure Register;
 begin
 begin
@@ -110,4 +110,5 @@ begin
   end;
   end;
 end;
 end;
 
 
+initialization
 end.
 end.

+ 0 - 2
source/packages/png/PngImageList.pas

@@ -1281,8 +1281,6 @@ begin
 end;
 end;
 
 
 initialization
 initialization
-
 finalization
 finalization
   MethodPatches.Free;
   MethodPatches.Free;
-
 end.
 end.

+ 2 - 20
source/packages/tb2k/TB2Common.pas

@@ -70,7 +70,6 @@ procedure HandleWMPrint(const Wnd: HWND; var Message: TMessage;
   const NCPaintFunc: THandleWMPrintNCPaintProc; const AppData: Longint);
   const NCPaintFunc: THandleWMPrintNCPaintProc; const AppData: Longint);
 procedure HandleWMPrintClient(const Control: TWinControl;
 procedure HandleWMPrintClient(const Control: TWinControl;
   var Message: TMessage);
   var Message: TMessage);
-function IsWindowsXP: Boolean;
 procedure ListSortEx(const List: TList; const Compare: TListSortExCompare;
 procedure ListSortEx(const List: TList; const Compare: TListSortExCompare;
   const ExtraData: Pointer);
   const ExtraData: Pointer);
 procedure InitTrackMouseEvent;
 procedure InitTrackMouseEvent;
@@ -510,11 +509,7 @@ const
 var
 var
   FlatMenusEnabled: BOOL;
   FlatMenusEnabled: BOOL;
 begin
 begin
-  { Interestingly, on Windows 2000, SystemParametersInfo(SPI_GETFLATMENU, ...)
-    succeeds and can return True in pvParam^ if the proper bit is set in
-    UserPreferencesMask. Since flat menus are not really used on Windows
-    2000, call IsWindowsXP first to see if we're running at least XP. }
-  Result := IsWindowsXP and SystemParametersInfo(SPI_GETFLATMENU, 0,
+  Result := SystemParametersInfo(SPI_GETFLATMENU, 0,
     @FlatMenusEnabled, 0) and FlatMenusEnabled;
     @FlatMenusEnabled, 0) and FlatMenusEnabled;
 end;
 end;
 
 
@@ -526,7 +521,7 @@ const
 var
 var
   CuesEnabled: BOOL;
   CuesEnabled: BOOL;
 begin
 begin
-  Result := (Win32MajorVersion < 5) or
+  Result :=
     not SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, @CuesEnabled, 0) or
     not SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, @CuesEnabled, 0) or
     CuesEnabled;
     CuesEnabled;
 end;
 end;
@@ -999,12 +994,6 @@ var
   DataSize: DWORD;
   DataSize: DWORD;
   ErrorCode: Longint;
   ErrorCode: Longint;
 begin
 begin
-  if (Win32MajorVersion < 5) or (Win32Platform <> VER_PLATFORM_WIN32_NT) then begin
-    { No need to check pre-Windows 2000 versions since their PlaySound
-      functions don't have the delay; always return True. }
-    Result := True;
-    Exit;
-  end;
   Result := False;
   Result := False;
   if RegOpenKeyEx(HKEY_CURRENT_USER,
   if RegOpenKeyEx(HKEY_CURRENT_USER,
      PChar('AppEvents\Schemes\Apps\.Default\' + Alias + '\.Current'),
      PChar('AppEvents\Schemes\Apps\.Default\' + Alias + '\.Current'),
@@ -1055,13 +1044,6 @@ begin
   end;
   end;
 end;
 end;
 
 
-function IsWindowsXP: Boolean;
-begin
-  Result := (Win32Platform = VER_PLATFORM_WIN32_NT) and
-    ((Win32MajorVersion > 5) or
-     ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1)));
-end;
-
 function GetInputLocaleCodePage: UINT;
 function GetInputLocaleCodePage: UINT;
 { Returns the code page identifier of the active input locale, or CP_ACP if
 { Returns the code page identifier of the active input locale, or CP_ACP if
   for some unknown reason it couldn't be determined. }
   for some unknown reason it couldn't be determined. }

+ 1 - 3
source/packages/tb2k/TB2Dock.pas

@@ -4447,9 +4447,7 @@ var
 begin
 begin
   inherited;
   inherited;
   { Note: TME_NONCLIENT was introduced in Windows 98 and 2000 }
   { Note: TME_NONCLIENT was introduced in Windows 98 and 2000 }
-  if (Win32MajorVersion >= 5) or
-     (Win32MajorVersion = 4) and (Win32MinorVersion >= 10) then
-    CallTrackMouseEvent(Handle, TME_LEAVE or $10 {TME_NONCLIENT});
+  CallTrackMouseEvent(Handle, TME_LEAVE or $10 {TME_NONCLIENT});
   InArea := Message.HitTest = HT_TB2k_Close;
   InArea := Message.HitTest = HT_TB2k_Close;
   if FCloseButtonHover <> InArea then begin
   if FCloseButtonHover <> InArea then begin
     FCloseButtonHover := InArea;
     FCloseButtonHover := InArea;

+ 2 - 6
source/packages/tb2k/TB2Hook.pas

@@ -179,12 +179,8 @@ begin
           This is needed for compatibility with the combination of Tnt Unicode
           This is needed for compatibility with the combination of Tnt Unicode
           Controls and Keyman. See "Widechar's and tb2k" thread on the
           Controls and Keyman. See "Widechar's and tb2k" thread on the
           newsgroup from 2003-09-23 for more information. }
           newsgroup from 2003-09-23 for more information. }
-        if Win32Platform = VER_PLATFORM_WIN32_NT then
-          HookHandles[T] := SetWindowsHookExW(HookIDs[T], HookProcs[T],
-            0, GetCurrentThreadId)
-        else
-          HookHandles[T] := SetWindowsHookEx(HookIDs[T], HookProcs[T],
-            0, GetCurrentThreadId);
+        HookHandles[T] := SetWindowsHookExW(HookIDs[T], HookProcs[T],
+          0, GetCurrentThreadId)
       end;
       end;
     end;
     end;
 end;
 end;

+ 1 - 3
source/packages/tb2k/TB2Item.pas

@@ -6454,9 +6454,7 @@ begin
     Style := (Style and not (WS_CHILD or WS_GROUP or WS_TABSTOP)) or WS_POPUP;
     Style := (Style and not (WS_CHILD or WS_GROUP or WS_TABSTOP)) or WS_POPUP;
     ExStyle := ExStyle or WS_EX_TOPMOST or WS_EX_TOOLWINDOW;
     ExStyle := ExStyle or WS_EX_TOPMOST or WS_EX_TOOLWINDOW;
     WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
     WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
-    { Enable drop shadow effect on Windows XP and later }
-    if IsWindowsXP then
-      WindowClass.Style := WindowClass.Style or CS_DROPSHADOW;
+    WindowClass.Style := WindowClass.Style or CS_DROPSHADOW;
   end;
   end;
 end;
 end;
 
 

+ 4 - 18
source/packages/tbx/TBX.pas

@@ -2214,7 +2214,7 @@ begin
   with Params do
   with Params do
   begin
   begin
     WindowClass.Style := WindowClass.Style and not (CS_DROPSHADOW or CS_DBLCLKS);
     WindowClass.Style := WindowClass.Style and not (CS_DROPSHADOW or CS_DBLCLKS);
-    if GetShowShadow and (CurrentTheme.GetPopupShadowType = PST_WINDOWSXP) and IsWindowsXP then
+    if GetShowShadow and (CurrentTheme.GetPopupShadowType = PST_WINDOWSXP) then
     begin
     begin
       WindowClass.Style := WindowClass.Style or CS_DROPSHADOW;
       WindowClass.Style := WindowClass.Style or CS_DROPSHADOW;
       StrPCopy(WinClassName, ClassName + 'S');
       StrPCopy(WinClassName, ClassName + 'S');
@@ -2229,9 +2229,6 @@ var
   VT: Integer;
   VT: Integer;
   ChevronParent: Boolean;
   ChevronParent: Boolean;
 begin
 begin
-  if (CurrentTheme.GetPopupShadowType = PST_WINDOWS2K) and not
-    ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion >= 5)) then Exit;
-
   PR := Rect(0, 0, 0, 0);
   PR := Rect(0, 0, 0, 0);
   if CurrentTheme.GetPopupShadowType = PST_OFFICEXP then
   if CurrentTheme.GetPopupShadowType = PST_OFFICEXP then
   begin
   begin
@@ -3153,9 +3150,7 @@ var
 begin
 begin
   inherited;
   inherited;
   { Note: TME_NONCLIENT was introduced in Windows 98 and 2000 }
   { Note: TME_NONCLIENT was introduced in Windows 98 and 2000 }
-  if (Win32MajorVersion >= 5) or
-     (Win32MajorVersion = 4) and (Win32MinorVersion >= 10) then
-    CallTrackMouseEvent (Handle, TME_LEAVE or $10 {TME_NONCLIENT});
+  CallTrackMouseEvent (Handle, TME_LEAVE or $10 {TME_NONCLIENT});
   InArea := Message.HitTest = 2001; {HT_TB2k_Close}
   InArea := Message.HitTest = 2001; {HT_TB2k_Close}
   if FCloseButtonHover <> InArea then
   if FCloseButtonHover <> InArea then
   begin
   begin
@@ -3779,16 +3774,8 @@ begin
 end;
 end;
 
 
 function TTBXMenuAnimation.GetAvailableModes: TAnimationModes;
 function TTBXMenuAnimation.GetAvailableModes: TAnimationModes;
-var IsWindows2K: Boolean;
 begin
 begin
-  Result := [amNone];
-  IsWindows2K := (Win32Platform = VER_PLATFORM_WIN32_NT) and
-    TBXCheckWin32Version(5); { MP }
-  if IsWindows2K or ((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and
-    TBXCheckWin32Version(4, 10){Win98}) { MP } then
-      Result := Result+ [amSysDefault, amRandom, amUnfold, amSlide];
-  if IsWindows2K then
-    Include(Result, amFade);
+  Result := [amNone, amSysDefault, amRandom, amUnfold, amSlide, amFade];
 end;
 end;
 
 
 function TTBXMenuAnimation.GetMenuAnimation: TMenuAnimation;
 function TTBXMenuAnimation.GetMenuAnimation: TMenuAnimation;
@@ -3854,8 +3841,7 @@ end;
 procedure FixPlaySoundDelay;
 procedure FixPlaySoundDelay;
 var ThreadId: TThreadID;
 var ThreadId: TThreadID;
 begin
 begin
-  if (Win32Platform = VER_PLATFORM_WIN32_NT) and CheckWin32Version(5) and
-    (FixPlaySoundThreadHandle = 0) then
+  if (FixPlaySoundThreadHandle = 0) then
       FixPlaySoundThreadHandle := CreateThread(nil, $1000,
       FixPlaySoundThreadHandle := CreateThread(nil, $1000,
         @FixPlaySoundThreadFunc, nil, 0, ThreadId);
         @FixPlaySoundThreadFunc, nil, 0, ThreadId);
 end;
 end;

+ 1 - 1
source/packages/tbx/TBXOfficeXPTheme.pas

@@ -96,7 +96,7 @@ type
 
 
 implementation
 implementation
 
 
-uses TBXUtils, TB2Common, TB2Item, Classes, Controls, Commctrl, Forms;
+uses TBXUtils, TB2Common, TB2Item, Classes, Controls, Commctrl, Forms, SysUtils;
 
 
 var
 var
   StockImgList: TImageList;
   StockImgList: TImageList;

+ 1 - 0
source/packages/tbx/TBXStatusBars.pas

@@ -1027,4 +1027,5 @@ begin
   end;
   end;
 end;
 end;
 
 
+initialization
 end.
 end.

+ 2 - 8
source/packages/tbx/TBXThemes.pas

@@ -782,12 +782,7 @@ begin
   end;
   end;
 
 
   SysFlatMenus := False;
   SysFlatMenus := False;
-  if (Win32Platform = VER_PLATFORM_WIN32_NT) and
-    ((Win32MajorVersion > 5) or
-     ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1))) then
-  begin
-    SystemParametersInfo(SPI_GETFLATMENU, 0, @SysFlatMenus, 0);
-  end;
+  SystemParametersInfo(SPI_GETFLATMENU, 0, @SysFlatMenus, 0);
 
 
 
 
   if SysFlatMenus then // System indicates support for flat menus
   if SysFlatMenus then // System indicates support for flat menus
@@ -852,8 +847,7 @@ end;
 procedure TTBXThemeManager.VisualStylesOpen;
 procedure TTBXThemeManager.VisualStylesOpen;
 begin
 begin
   USE_THEMES := False;
   USE_THEMES := False;
-  if (Win32Platform = VER_PLATFORM_WIN32_NT) and ((Win32MajorVersion > 5) or
-     ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1))) and EnableVisualStyles then
+  if EnableVisualStyles then
   begin
   begin
     InitedThemeLibrary := InitThemeLibrary;
     InitedThemeLibrary := InitThemeLibrary;
     USE_THEMES := UseThemes;
     USE_THEMES := UseThemes;

+ 0 - 15
source/packages/tbx/TBXUtils.pas

@@ -24,11 +24,6 @@ function StripAccelCharsW(const S: WideString): WideString;
 function StripTrailingPunctuationW(const S: WideString): WideString;
 function StripTrailingPunctuationW(const S: WideString): WideString;
 {$ENDIF}
 {$ENDIF}
 
 
-{ MP (the function in VCL is buggy even in C++Builder 6) }
-{//$IFNDEF JR_D6}
-{ MP }
-function TBXCheckWin32Version(AMajor: Integer; AMinor: Integer = 0): Boolean; {vb+}
-{//$ENDIF}
 procedure GetRGB(C: TColor; out R, G, B: Integer);
 procedure GetRGB(C: TColor; out R, G, B: Integer);
 function  MixColors(C1, C2: TColor; W1: Integer): TColor;
 function  MixColors(C1, C2: TColor; W1: Integer): TColor;
 function  SameColors(C1, C2: TColor): Boolean;
 function  SameColors(C1, C2: TColor): Boolean;
@@ -402,16 +397,6 @@ end;
 
 
 {$ENDIF}
 {$ENDIF}
 
 
-{ MP (the function in VCL is buggy even in C++Builder 6) }
-{//$IFNDEF JR_D6}
-{ MP }
-function TBXCheckWin32Version(AMajor: Integer; AMinor: Integer = 0): Boolean; {vb+}
-begin
-  Result := (Win32MajorVersion > AMajor) or
-    ((Win32MajorVersion = AMajor) and (Win32MinorVersion >= AMinor));
-end;
-{//$ENDIF}
-
 type
 type
   PPoints = ^TPoints;
   PPoints = ^TPoints;
   TPoints = array [0..0] of TPoint;
   TPoints = array [0..0] of TPoint;

+ 1 - 1
source/resource/HelpWin.h

@@ -46,7 +46,7 @@
 #define HELP_MASTER_PASSWORD         "master_password"
 #define HELP_MASTER_PASSWORD         "master_password"
 #define HELP_MASTER_PASSWORD_SIMPLE  HELP_MASTER_PASSWORD
 #define HELP_MASTER_PASSWORD_SIMPLE  HELP_MASTER_PASSWORD
 #define HELP_USAGE                   "usagestatistics"
 #define HELP_USAGE                   "usagestatistics"
-#define HELP_WORKSPACE_SAVE          "workspace"
+#define HELP_WORKSPACE_SAVE          "ui_save_workspace"
 #define HELP_EDITOR_AUTO_CONFIG      "ui_pref_editor#auto"
 #define HELP_EDITOR_AUTO_CONFIG      "ui_pref_editor#auto"
 #define HELP_IMPORT_SESSIONS         "ui_import"
 #define HELP_IMPORT_SESSIONS         "ui_import"
 #define HELP_IMPORT_CONFIGURATION    "config"
 #define HELP_IMPORT_CONFIGURATION    "config"

+ 8 - 1
source/resource/TextsCore.h

@@ -25,7 +25,7 @@
 #define SCRIPT_GET_HELP6        21
 #define SCRIPT_GET_HELP6        21
 #define SCRIPT_PUT_HELP6        22
 #define SCRIPT_PUT_HELP6        22
 #define SCRIPT_OPTION_HELP6     23
 #define SCRIPT_OPTION_HELP6     23
-#define SCRIPT_SYNCHRONIZE_HELP6 24
+#define SCRIPT_SYNCHRONIZE_HELP7 24
 #define SCRIPT_KEEPUPTODATE_HELP4 25
 #define SCRIPT_KEEPUPTODATE_HELP4 25
 #define SCRIPT_CALL_HELP2       26
 #define SCRIPT_CALL_HELP2       26
 #define SCRIPT_ECHO_HELP        27
 #define SCRIPT_ECHO_HELP        27
@@ -385,6 +385,13 @@
 #define SCRIPT_CMDLINE_SESSION  520
 #define SCRIPT_CMDLINE_SESSION  520
 #define ANY_HOSTKEY      521
 #define ANY_HOSTKEY      521
 #define ANY_CERTIFICATE  522
 #define ANY_CERTIFICATE  522
+#define SCRIPT_SYNC_UPLOAD_NEW  523
+#define SCRIPT_SYNC_DOWNLOAD_NEW 524
+#define SCRIPT_SYNC_UPLOAD_UPDATE 525
+#define SCRIPT_SYNC_DOWNLOAD_UPDATE 526
+#define SCRIPT_SYNC_DELETE_REMOTE 527
+#define SCRIPT_SYNC_DELETE_LOCAL 528
+#define SCRIPT_SYNCHRONIZE_CHECKLIST 529
 
 
 #define CORE_VARIABLE_STRINGS   600
 #define CORE_VARIABLE_STRINGS   600
 #define PUTTY_BASED_ON          601
 #define PUTTY_BASED_ON          601

+ 8 - 1
source/resource/TextsCore1.rc

@@ -338,7 +338,7 @@ BEGIN
   SCRIPT_SYNCHRONIZE_SYNCHRONIZING, "Synchronizing..."
   SCRIPT_SYNCHRONIZE_SYNCHRONIZING, "Synchronizing..."
   SCRIPT_SYNCHRONIZE_NODIFFERENCE, "Nothing to synchronize."
   SCRIPT_SYNCHRONIZE_NODIFFERENCE, "Nothing to synchronize."
   SPEED_UNLIMITED, "Unlimited"
   SPEED_UNLIMITED, "Unlimited"
-  FTPS_IMPLICIT, "SSL/TLS Implicit encryption"
+  FTPS_IMPLICIT, "TLS/SSL Implicit encryption"
   FTPS_EXPLICIT_SSL, "SSL Explicit encryption"
   FTPS_EXPLICIT_SSL, "SSL Explicit encryption"
   FTPS_EXPLICIT_TLS, "TLS Explicit encryption"
   FTPS_EXPLICIT_TLS, "TLS Explicit encryption"
   SCRIPT_ECHO_DESC, "Displays its arguments as message"
   SCRIPT_ECHO_DESC, "Displays its arguments as message"
@@ -350,6 +350,13 @@ BEGIN
   SCRIPT_CMDLINE_SESSION, "Opening session using command-line parameter in scripting is deprecated. Use 'open' command instead."
   SCRIPT_CMDLINE_SESSION, "Opening session using command-line parameter in scripting is deprecated. Use 'open' command instead."
   ANY_HOSTKEY, "WARNING! Giving up security and accepting any key as configured!"
   ANY_HOSTKEY, "WARNING! Giving up security and accepting any key as configured!"
   ANY_CERTIFICATE, "WARNING! Giving up security and accepting any certificate as configured!"
   ANY_CERTIFICATE, "WARNING! Giving up security and accepting any certificate as configured!"
+  SCRIPT_SYNC_UPLOAD_NEW, "New local file %s"
+  SCRIPT_SYNC_DOWNLOAD_NEW, "New remote file %s"
+  SCRIPT_SYNC_UPLOAD_UPDATE, "Local file %s newer than remote file %s"
+  SCRIPT_SYNC_DOWNLOAD_UPDATE, "Remote file %s newer than local file %s"
+  SCRIPT_SYNC_DELETE_REMOTE, "Orphan remote file %s"
+  SCRIPT_SYNC_DELETE_LOCAL, "Orphan local file %s"
+  SCRIPT_SYNCHRONIZE_CHECKLIST, "Differences found:"
 
 
   CORE_VARIABLE_STRINGS, "CORE_VARIABLE"
   CORE_VARIABLE_STRINGS, "CORE_VARIABLE"
   PUTTY_BASED_ON, "SSH and SCP code based on PuTTY %s"
   PUTTY_BASED_ON, "SSH and SCP code based on PuTTY %s"

+ 4 - 3
source/resource/TextsCore2.rc

@@ -67,11 +67,11 @@ BEGIN
     "  -privatekey=<key>  Private key file\n"
     "  -privatekey=<key>  Private key file\n"
     "  -timeout=<sec>     Server response timeout\n"
     "  -timeout=<sec>     Server response timeout\n"
     "  -hostkey=<fingerprint> Fingerprint of server hostkey (SFTP and SCP only).\n"
     "  -hostkey=<fingerprint> Fingerprint of server hostkey (SFTP and SCP only).\n"
-    "  -certificate=<fingerprint> Fingerprint of SSL/TLS certificate (FTPS only)\n"
+    "  -certificate=<fingerprint> Fingerprint of TLS/SSL certificate (FTPS only)\n"
     "  -passive=on|off    Passive mode (FTP protocol only)\n"
     "  -passive=on|off    Passive mode (FTP protocol only)\n"
     "  -implicit          Implicit TLS/SSL (FTPS protocol only)\n"
     "  -implicit          Implicit TLS/SSL (FTPS protocol only)\n"
-    "  -explicitssl       Explicit SSL (FTPS protocol only)\n"
     "  -explicittls       Explicit TLS (FTPS protocol only)\n"
     "  -explicittls       Explicit TLS (FTPS protocol only)\n"
+    "  -explicitssl       Explicit SSL (FTPS protocol only)\n"
     "  -rawsettings setting1=value1 setting2=value2 ...\n"
     "  -rawsettings setting1=value1 setting2=value2 ...\n"
     "                     Configures any session settings using raw format\n"
     "                     Configures any session settings using raw format\n"
     "                     as in an INI file\n"
     "                     as in an INI file\n"
@@ -278,7 +278,7 @@ BEGIN
     "  option\n"
     "  option\n"
     "  option batch\n"
     "  option batch\n"
     "  option confirm off\n"
     "  option confirm off\n"
-  SCRIPT_SYNCHRONIZE_HELP6,
+  SCRIPT_SYNCHRONIZE_HELP7,
     "synchronize local|remote|both [ <local directory> [ <remote directory> ] ]\n"
     "synchronize local|remote|both [ <local directory> [ <remote directory> ] ]\n"
     "  When the first parameter is 'local' synchronises local directory with\n"
     "  When the first parameter is 'local' synchronises local directory with\n"
     "  remote one. When the first parameter is 'remote' synchronises remote\n"
     "  remote one. When the first parameter is 'remote' synchronises remote\n"
@@ -288,6 +288,7 @@ BEGIN
     "  synchronized.\n"
     "  synchronized.\n"
     "  Note: Overwrite confirmations are always off for the command.\n"
     "  Note: Overwrite confirmations are always off for the command.\n"
     "switches:\n"
     "switches:\n"
+    "  -preview             Preview changes only, do not synchronize\n"
     "  -delete              Delete obsolete files\n"
     "  -delete              Delete obsolete files\n"
     "  -mirror              Mirror mode (synchronize also older files).\n"
     "  -mirror              Mirror mode (synchronize also older files).\n"
     "                       Ignored for 'both'.\n"
     "                       Ignored for 'both'.\n"

+ 7 - 7
source/resource/TextsFileZilla.rc

@@ -41,16 +41,16 @@ END
 STRINGTABLE
 STRINGTABLE
 BEGIN
 BEGIN
   IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE, "Could not create socket in the specified port range."
   IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE, "Could not create socket in the specified port range."
-  IDS_ERRORMSG_CANTESTABLISHSSLCONNECTION, "Can't establish SSL connection"
+  IDS_ERRORMSG_CANTESTABLISHSSLCONNECTION, "Can't establish TLS connection"
   IDS_ERRORMSG_CANTGETLIST, "Could not retrieve directory listing"
   IDS_ERRORMSG_CANTGETLIST, "Could not retrieve directory listing"
-  IDS_ERRORMSG_CANTINITSSL, "Can't initialize SSL library"
+  IDS_ERRORMSG_CANTINITSSL, "Can't initialize TLS library"
 END
 END
 
 
 STRINGTABLE
 STRINGTABLE
 BEGIN
 BEGIN
   IDS_STATUSMSG_CONNECTED, "Connected"
   IDS_STATUSMSG_CONNECTED, "Connected"
   IDS_STATUSMSG_CONNECTEDWITH, "Connected with %s. Waiting for welcome message..."
   IDS_STATUSMSG_CONNECTEDWITH, "Connected with %s. Waiting for welcome message..."
-  IDS_STATUSMSG_CONNECTEDWITHSSL, "Connected with %s, negotiating SSL connection..."
+  IDS_STATUSMSG_CONNECTEDWITHSSL, "Connected with %s, negotiating TLS connection..."
   IDS_STATUSMSG_CONNECTING, "Connecting to %s ..."
   IDS_STATUSMSG_CONNECTING, "Connecting to %s ..."
   IDS_STATUSMSG_DIRLISTSUCCESSFUL, "Directory listing successful"
   IDS_STATUSMSG_DIRLISTSUCCESSFUL, "Directory listing successful"
   IDS_STATUSMSG_DISCONNECTED, "Disconnected from server"
   IDS_STATUSMSG_DISCONNECTED, "Disconnected from server"
@@ -62,8 +62,8 @@ END
 STRINGTABLE
 STRINGTABLE
 BEGIN
 BEGIN
   IDS_STATUSMSG_RETRIEVINGDIRLIST, "Retrieving directory listing..."
   IDS_STATUSMSG_RETRIEVINGDIRLIST, "Retrieving directory listing..."
-  IDS_STATUSMSG_SSLESTABLISHED, "SSL connection established. Waiting for welcome message..."
-  IDS_STATUSMSG_SSLESTABLISHEDTRANSFER, "SSL connection established"
+  IDS_STATUSMSG_SSLESTABLISHED, "TLS connection established. Waiting for welcome message..."
+  IDS_STATUSMSG_SSLESTABLISHEDTRANSFER, "TLS connection established"
   IDS_STATUSMSG_UPLOADSTART, "Starting upload of %s"
   IDS_STATUSMSG_UPLOADSTART, "Starting upload of %s"
   IDS_STATUSMSG_UPLOADSUCCESSFUL, "Upload successful"
   IDS_STATUSMSG_UPLOADSUCCESSFUL, "Upload successful"
 END
 END
@@ -78,6 +78,6 @@ END
 STRINGTABLE
 STRINGTABLE
 BEGIN
 BEGIN
   IDS_ERRORMSG_SETFILEPOINTER, "Could not set file pointer"
   IDS_ERRORMSG_SETFILEPOINTER, "Could not set file pointer"
-  IDS_ERRORMSG_UNKNOWNSSLERROR, "Unknown error in SSL layer"
-  IDS_ERRORMSG_SSLCERTIFICATEERROR, "Could not verify SSL certificate"
+  IDS_ERRORMSG_UNKNOWNSSLERROR, "Unknown error in TLS layer"
+  IDS_ERRORMSG_SSLCERTIFICATEERROR, "Could not verify TLS certificate"
 END
 END

+ 4 - 1
source/resource/TextsWin.h

@@ -64,6 +64,7 @@
 #define WORKSPACE_NOT_FOLDER    1173
 #define WORKSPACE_NOT_FOLDER    1173
 #define FOLDER_NOT_WORKSPACE    1174
 #define FOLDER_NOT_WORKSPACE    1174
 #define SHELL_PATTERN_ERROR     1175
 #define SHELL_PATTERN_ERROR     1175
+#define PATH_ENV_TOO_LONG       1176
 
 
 #define WIN_CONFIRMATION_STRINGS 1300
 #define WIN_CONFIRMATION_STRINGS 1300
 #define CONFIRM_OVERWRITE_SESSION 1301
 #define CONFIRM_OVERWRITE_SESSION 1301
@@ -122,6 +123,7 @@
 #define ALL_BUTTON              1359
 #define ALL_BUTTON              1359
 #define YES_TO_ALL_BUTTON       1360
 #define YES_TO_ALL_BUTTON       1360
 #define REPORT_BUTTON           1361
 #define REPORT_BUTTON           1361
+#define MASTER_PASSWORD_OTHER_INSTANCE 1362
 
 
 #define WIN_INFORMATION_STRINGS 1400
 #define WIN_INFORMATION_STRINGS 1400
 #define APP_CAPTION             1401
 #define APP_CAPTION             1401
@@ -210,6 +212,7 @@
 #define DD_TRANSFER_CONFIRM_OFF 1531
 #define DD_TRANSFER_CONFIRM_OFF 1531
 #define COPY_PARAM_PRESET_HEADER 1532
 #define COPY_PARAM_PRESET_HEADER 1532
 #define QUEUE_DONE              1533
 #define QUEUE_DONE              1533
+#define MASTER_PASSWORD_RECRYPT_ERRORS 1534
 
 
 #define WIN_FORMS_STRINGS       1600
 #define WIN_FORMS_STRINGS       1600
 #define LOG_NOLOG               1601
 #define LOG_NOLOG               1601
@@ -356,7 +359,7 @@
 #define STATUS_SECURE           1784
 #define STATUS_SECURE           1784
 #define FSINFO_PROTOCOL_ANY_COMMAND 1785
 #define FSINFO_PROTOCOL_ANY_COMMAND 1785
 #define FSINFO_REMOTE_SYSTEM    1786
 #define FSINFO_REMOTE_SYSTEM    1786
-#define FSINFO_SESSION_PROTOCOL 1787
+#define FSINFO_CRYPTOGRAPHIC_PROTOCOL 1787
 #define SPECIAL_FOLDER_MY_DOCUMENTS 1790
 #define SPECIAL_FOLDER_MY_DOCUMENTS 1790
 #define SPECIAL_FOLDER_DESKTOP  1791
 #define SPECIAL_FOLDER_DESKTOP  1791
 #define COMMAND_LINE_LABEL      1792
 #define COMMAND_LINE_LABEL      1792

+ 4 - 1
source/resource/TextsWin1.rc

@@ -69,6 +69,7 @@ BEGIN
         WORKSPACE_NOT_FOLDER, "'%s' is workspace, not site folder."
         WORKSPACE_NOT_FOLDER, "'%s' is workspace, not site folder."
         FOLDER_NOT_WORKSPACE, "'%s' is site folder, not workspace."
         FOLDER_NOT_WORKSPACE, "'%s' is site folder, not workspace."
         SHELL_PATTERN_ERROR, "Error executing command \"%s\" (%s)."
         SHELL_PATTERN_ERROR, "Error executing command \"%s\" (%s)."
+        PATH_ENV_TOO_LONG, "Cannot add new path to %PATH%, %PATH% is already too long."
 
 
         WIN_CONFIRMATION_STRINGS, "WIN_CONFIRMATION"
         WIN_CONFIRMATION_STRINGS, "WIN_CONFIRMATION"
         CONFIRM_OVERWRITE_SESSION, "Site with name '%s' already exists. Overwrite?"
         CONFIRM_OVERWRITE_SESSION, "Site with name '%s' already exists. Overwrite?"
@@ -123,6 +124,7 @@ BEGIN
         ALL_BUTTON, "A&ll"
         ALL_BUTTON, "A&ll"
         YES_TO_ALL_BUTTON, "Yes to A&ll"
         YES_TO_ALL_BUTTON, "Yes to A&ll"
         REPORT_BUTTON, "Re&port"
         REPORT_BUTTON, "Re&port"
+        MASTER_PASSWORD_OTHER_INSTANCE, "There is other instance of WinSCP running.\n\nSetting or clearing master password, while another instance of WinSCP is running, can cause loss of your stored passwords.\n\nPlease quit other instances of WinSCP before continuing."
 
 
         WIN_INFORMATION_STRINGS, "WIN_INFORMATION"
         WIN_INFORMATION_STRINGS, "WIN_INFORMATION"
         APP_CAPTION, "%s - %s"
         APP_CAPTION, "%s - %s"
@@ -212,6 +214,7 @@ BEGIN
         COPY_PARAM_PRESET_HEADER, "Presets"
         COPY_PARAM_PRESET_HEADER, "Presets"
         QUEUE_DONE, "Completed"
         QUEUE_DONE, "Completed"
         EDITOR_AUTO_CONFIG, "Custom text editor '%s' was detected.\n\nDo you want to use '%s' instead of default internal editor?"
         EDITOR_AUTO_CONFIG, "Custom text editor '%s' was detected.\n\nDo you want to use '%s' instead of default internal editor?"
+        MASTER_PASSWORD_RECRYPT_ERRORS, "%s\n\nThere were some errors when encrypting passwords using new master password or decrypting passwords."
 
 
         WIN_FORMS_STRINGS, "WIN_FORMS_STRINGS"
         WIN_FORMS_STRINGS, "WIN_FORMS_STRINGS"
         LOG_NOLOG, "No session log."
         LOG_NOLOG, "No session log."
@@ -359,7 +362,7 @@ BEGIN
         STATUS_SECURE, "Secure connection (%s)"
         STATUS_SECURE, "Secure connection (%s)"
         FSINFO_PROTOCOL_ANY_COMMAND, "Protocol commands only"
         FSINFO_PROTOCOL_ANY_COMMAND, "Protocol commands only"
         FSINFO_REMOTE_SYSTEM, "Remote system"
         FSINFO_REMOTE_SYSTEM, "Remote system"
-        FSINFO_SESSION_PROTOCOL, "Session protocol"
+        FSINFO_CRYPTOGRAPHIC_PROTOCOL, "Cryptographic protocol"
         SPECIAL_FOLDER_MY_DOCUMENTS, "My documents"
         SPECIAL_FOLDER_MY_DOCUMENTS, "My documents"
         SPECIAL_FOLDER_DESKTOP, "Desktop"
         SPECIAL_FOLDER_DESKTOP, "Desktop"
         COMMAND_LINE_LABEL, "Command"
         COMMAND_LINE_LABEL, "Command"

+ 3 - 3
source/resource/TextsWin2.rc

@@ -23,7 +23,7 @@ BEGIN
 "G:%APP% [session] /synchronize [local_dir] [remote_dir] [/defaults]\n"
 "G:%APP% [session] /synchronize [local_dir] [remote_dir] [/defaults]\n"
 "G:%APP% [session] /keepuptodate [local_dir] [remote_dir] [/defaults]\n"
 "G:%APP% [session] /keepuptodate [local_dir] [remote_dir] [/defaults]\n"
 "G:%APP% [session] /privatekey=<key> /hostkey=<fingerprint>\n"
 "G:%APP% [session] /privatekey=<key> /hostkey=<fingerprint>\n"
-"G:%APP% [session] /certificate=<fingerprint> /implicit|explicitssl|explicittls\n"
+"G:%APP% [session] /certificate=<fingerprint> /implicit|explicittls|explicitssl\n"
 "G:%APP% [session] /passive=on|off /timeout=<sec>\n"
 "G:%APP% [session] /passive=on|off /timeout=<sec>\n"
 "G:%APP% [session] /rawsettings setting1=value1 settings2=value2 ...\n"
 "G:%APP% [session] /rawsettings setting1=value1 settings2=value2 ...\n"
 "G:%APP% [/console] [/script=file] [/command command1...] [/parameter param1...]\n"
 "G:%APP% [/console] [/script=file] [/command command1...] [/parameter param1...]\n"
@@ -51,10 +51,10 @@ BEGIN
 "G: /passive=     Passive mode (FTP protocol only).\n"
 "G: /passive=     Passive mode (FTP protocol only).\n"
 "G: /rawsettings= Configures any session settings using raw format\n"
 "G: /rawsettings= Configures any session settings using raw format\n"
 "G:               as in an INI file.\n"
 "G:               as in an INI file.\n"
-"G: /certificate= Fingerprint of SSL/TLS certificate.\n"
+"G: /certificate= Fingerprint of TLS/SSL certificate.\n"
 "G: /implicit     Implicit TLS/SSL (FTPS protocol only).\n"
 "G: /implicit     Implicit TLS/SSL (FTPS protocol only).\n"
-"G: /explicitssl  Explicit SSL (FTPS protocol only).\n"
 "G: /explicittls  Explicit TLS (FTPS protocol only).\n"
 "G: /explicittls  Explicit TLS (FTPS protocol only).\n"
+"G: /explicitssl  Explicit SSL (FTPS protocol only).\n"
 "G: /update       Queries application homepage for updates.\n"
 "G: /update       Queries application homepage for updates.\n"
 "B: /help         Prints this usage.\n"
 "B: /help         Prints this usage.\n"
 END
 END

+ 20 - 6
source/windows/ConsoleRunner.cpp

@@ -1,4 +1,4 @@
-//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
 #include <vcl.h>
 #include <vcl.h>
 #pragma hdrstop
 #pragma hdrstop
 
 
@@ -1753,9 +1753,23 @@ bool __fastcall TConsoleRunner::DoInput(UnicodeString & Str, bool Echo,
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 void __fastcall TConsoleRunner::MasterPasswordPrompt()
 void __fastcall TConsoleRunner::MasterPasswordPrompt()
 {
 {
-  UnicodeString Password;
-  Input(LoadStr(CONSOLE_MASTER_PASSWORD_PROMPT), Password, false, true);
-  WinConfiguration->SetMasterPassword(Password);
+  bool Retry;
+  do
+  {
+    UnicodeString Password;
+    Input(LoadStr(CONSOLE_MASTER_PASSWORD_PROMPT), Password, false, true);
+    Retry = !WinConfiguration->ValidateMasterPassword(Password);
+    if (Retry)
+    {
+      PrintLine(LoadStr(MASTER_PASSWORD_INCORRECT));
+    }
+    else
+    {
+      WinConfiguration->SetMasterPassword(Password);
+    }
+  }
+  while (Retry);
+
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 UnicodeString TConsoleRunner::ExpandCommand(UnicodeString Command, TStrings * ScriptParameters)
 UnicodeString TConsoleRunner::ExpandCommand(UnicodeString Command, TStrings * ScriptParameters)
@@ -1917,10 +1931,10 @@ void __fastcall LoadScriptFromFile(UnicodeString FileName, TStrings * Lines)
 void __fastcall Usage(TConsole * Console)
 void __fastcall Usage(TConsole * Console)
 {
 {
   UnicodeString Usage = LoadStr(USAGE8, 10240);
   UnicodeString Usage = LoadStr(USAGE8, 10240);
-  UnicodeString ExeBaseName = ChangeFileExt(ExtractFileName(Application->ExeName), L"");
+  UnicodeString ExeBaseName = ExtractFileBaseName(Application->ExeName);
   Usage = ReplaceText(Usage, L"%APP%", ExeBaseName);
   Usage = ReplaceText(Usage, L"%APP%", ExeBaseName);
   UnicodeString Copyright =
   UnicodeString Copyright =
-    ReplaceText(LoadStr(WINSCP_COPYRIGHT), "©", "(c)");
+    ReplaceText(LoadStr(WINSCP_COPYRIGHT), L"©", L"(c)");
   Usage = FORMAT(Usage, (Configuration->VersionStr, Copyright));
   Usage = FORMAT(Usage, (Configuration->VersionStr, Copyright));
   TStrings * Lines = new TStringList();
   TStrings * Lines = new TStringList();
   try
   try

+ 29 - 3
source/windows/CustomWinConfiguration.cpp

@@ -8,6 +8,7 @@
 #include <CoreMain.h>
 #include <CoreMain.h>
 #include <Interface.h>
 #include <Interface.h>
 #include "CustomWinConfiguration.h"
 #include "CustomWinConfiguration.h"
+#include <Exceptions.h>
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
 #pragma package(smart_init)
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
@@ -330,15 +331,29 @@ void __fastcall TCustomWinConfiguration::LoadAdmin(THierarchicalStorage * Storag
   FDefaultInterface = TInterface(Storage->ReadInteger(L"DefaultInterfaceInterface", FDefaultInterface));
   FDefaultInterface = TInterface(Storage->ReadInteger(L"DefaultInterfaceInterface", FDefaultInterface));
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
-void __fastcall TCustomWinConfiguration::RecryptPasswords()
+void __fastcall TCustomWinConfiguration::RecryptPasswords(TStrings * RecryptPasswordErrors)
 {
 {
   Busy(true);
   Busy(true);
   try
   try
   {
   {
-    StoredSessions->RecryptPasswords();
+    StoredSessions->RecryptPasswords(RecryptPasswordErrors);
+
     if (OnMasterPasswordRecrypt != NULL)
     if (OnMasterPasswordRecrypt != NULL)
     {
     {
-      OnMasterPasswordRecrypt(NULL);
+      try
+      {
+        OnMasterPasswordRecrypt(NULL);
+      }
+      catch (Exception & E)
+      {
+        UnicodeString Message;
+        if (ExceptionMessage(&E, Message))
+        {
+          // we do not expect this really to happen,
+          // so we do not bother providing context
+          RecryptPasswordErrors->Add(Message);
+        }
+      }
     }
     }
   }
   }
   __finally
   __finally
@@ -347,6 +362,17 @@ void __fastcall TCustomWinConfiguration::RecryptPasswords()
   }
   }
 }
 }
 //---------------------------------------------------------------------
 //---------------------------------------------------------------------
+void __fastcall TCustomWinConfiguration::AskForMasterPasswordIfNotSetAndNeededToPersistSessionData(
+  TSessionData * SessionData)
+{
+  if (!DisablePasswordStoring &&
+      SessionData->HasAnyPassword() &&
+      UseMasterPassword)
+  {
+    AskForMasterPasswordIfNotSet();
+  }
+}
+//---------------------------------------------------------------------
 void __fastcall TCustomWinConfiguration::SetLogView(TLogView value)
 void __fastcall TCustomWinConfiguration::SetLogView(TLogView value)
 {
 {
   SET_CONFIG_PROPERTY(LogView);
   SET_CONFIG_PROPERTY(LogView);

+ 2 - 1
source/windows/CustomWinConfiguration.h

@@ -65,7 +65,7 @@ protected:
   virtual void __fastcall Saved();
   virtual void __fastcall Saved();
   void __fastcall ClearHistory();
   void __fastcall ClearHistory();
   virtual void __fastcall DefaultHistory();
   virtual void __fastcall DefaultHistory();
-  void __fastcall RecryptPasswords();
+  void __fastcall RecryptPasswords(TStrings * RecryptPasswordErrors);
   virtual bool __fastcall GetUseMasterPassword() = 0;
   virtual bool __fastcall GetUseMasterPassword() = 0;
 
 
 public:
 public:
@@ -73,6 +73,7 @@ public:
   virtual __fastcall ~TCustomWinConfiguration();
   virtual __fastcall ~TCustomWinConfiguration();
   virtual void __fastcall Default();
   virtual void __fastcall Default();
   virtual void __fastcall AskForMasterPasswordIfNotSet() = 0;
   virtual void __fastcall AskForMasterPasswordIfNotSet() = 0;
+  void __fastcall AskForMasterPasswordIfNotSetAndNeededToPersistSessionData(TSessionData * SessionData);
 
 
   __property TLogView LogView = { read = FLogView, write = SetLogView };
   __property TLogView LogView = { read = FLogView, write = SetLogView };
   __property TInterface Interface = { read = FInterface, write = SetInterface };
   __property TInterface Interface = { read = FInterface, write = SetInterface };

+ 62 - 201
source/windows/Setup.cpp

@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <tchar.h>
 #include <tchar.h>
 #include <shlobj.h>
 #include <shlobj.h>
+#include <tlhelp32.h>
 #include <Common.h>
 #include <Common.h>
 #include <CoreMain.h>
 #include <CoreMain.h>
 #include <Exceptions.h>
 #include <Exceptions.h>
@@ -22,28 +23,15 @@
 #include "Setup.h"
 #include "Setup.h"
 #include <StrUtils.hpp>
 #include <StrUtils.hpp>
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
-/* Using quotes or not should make no difference but some programs (for
-   instance cygwin and msys) don't like them. */
-/* #define USE_QUOTES */
-//---------------------------------------------------------------------------
-#define APP_NAME "WinSCP"
 #define KEY _T("SYSTEM\\CurrentControlSet\\Control\\") \
 #define KEY _T("SYSTEM\\CurrentControlSet\\Control\\") \
             _T("Session Manager\\Environment")
             _T("Session Manager\\Environment")
-#define AUTOEXEC_PATH _T("c:\\autoexec.bat")
-#define AUTOEXEC_INTRO _T("rem ***** The following line was added by " \
-                       APP_NAME " *****")
-#ifdef USE_QUOTES
-#  define AUTOEXEC_CMD _T("set PATH=%%PATH%%;\"%s\"")
-#else
-#  define AUTOEXEC_CMD _T("set PATH=%%PATH%%;%s")
-#endif
+// when the PATH registry key is over aprox 2048 characters,
+// PATH as well as WINDIR variables are actually not set, breaking the system
+#define MAX_PATH_LEN 2000
 
 
 /* Command line options. */
 /* Command line options. */
 UnicodeString LastPathError;
 UnicodeString LastPathError;
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
-#define verb_out(msg) ((void)0)
-#define verb_out_param(msg, param) ((void)0)
-//---------------------------------------------------------------------------
 // Display the error "err_msg".
 // Display the error "err_msg".
 void err_out(LPCTSTR err_msg)
 void err_out(LPCTSTR err_msg)
 {
 {
@@ -169,27 +157,28 @@ BOOL add_path_reg(LPCTSTR path){
     else{
     else{
         if (!find_reg_str(reg_str, path, NULL)){
         if (!find_reg_str(reg_str, path, NULL)){
             _tcscat(reg_str, _T(";"));
             _tcscat(reg_str, _T(";"));
-#ifdef USE_QUOTES
-            _tcscat(reg_str, _T(";\""));
-#endif
             _tcscat(reg_str, path);
             _tcscat(reg_str, path);
-#ifdef USE_QUOTES
-            _tcscat(reg_str, _T("\""));
-#endif
-            ret = RegSetValueEx(key, _T("PATH"), 0, REG_EXPAND_SZ,
-                                (LPBYTE)reg_str,
-                                (_tcslen(reg_str) + 1) * sizeof(TCHAR));
-            if (ret != ERROR_SUCCESS){
-                err_out_sys(_T("Cannot write \"PATH\" key."), ret);
-                func_ret = FALSE;
+            size_t len = _tcslen(reg_str);
+            if (len >= MAX_PATH_LEN)
+            {
+              err_out(LoadStr(PATH_ENV_TOO_LONG).c_str());
+              func_ret = FALSE;
+            }
+            else
+            {
+              ret = RegSetValueEx(key, _T("PATH"), 0, REG_EXPAND_SZ,
+                                  (LPBYTE)reg_str,
+                                  (_tcslen(reg_str) + 1) * sizeof(TCHAR));
+              if (ret != ERROR_SUCCESS){
+                  err_out_sys(_T("Cannot write \"PATH\" key."), ret);
+                  func_ret = FALSE;
+              }
+              /* Is this needed to make the new key avaible? */
+              RegFlushKey(key);
+              SetLastError(0);
+              path_reg_propagate();
             }
             }
-            /* Is this needed to make the new key avaible? */
-            RegFlushKey(key);
-            SetLastError(0);
-            path_reg_propagate();
         }
         }
-        else
-            verb_out(_T("Value already exists in the registry."));
     }
     }
 
 
     RegCloseKey(key);
     RegCloseKey(key);
@@ -248,8 +237,6 @@ BOOL remove_path_reg(LPCTSTR path){
             SetLastError(0);
             SetLastError(0);
             path_reg_propagate();
             path_reg_propagate();
         }
         }
-        else
-            verb_out(_T("Value does not exist in the registry."));
     }
     }
 
 
     RegCloseKey(key);
     RegCloseKey(key);
@@ -257,163 +244,10 @@ BOOL remove_path_reg(LPCTSTR path){
     return func_ret;
     return func_ret;
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
-/* Can this program run under Win9x if compiled with unicode support? */
-//---------------------------------------------------------------------------
-// Add "path" to "autoexec.bat". Return "TRUE" if the path has been added or
-// was already in the file, "FALSE" otherwise.
-BOOL add_path_autoexec(LPCTSTR long_path){
-    FILE * file;
-    LPTSTR path;
-    size_t path_size;
-    LPTSTR line;
-    LPTSTR out_line;
-    size_t line_size;
-    size_t sz1, sz2;
-    LPTSTR autoexec_intro;
-    BOOL found;
-    BOOL func_ret = TRUE;
-
-    file = _wfopen(AUTOEXEC_PATH, _T("r+"));
-    if (!file){
-        err_out(_T("Cannot open \"autoexec.bat\"."));
-        return FALSE;
-    }
-
-    path_size = _tcslen(long_path) + 1;
-    path = (LPTSTR)malloc(path_size * sizeof(TCHAR));
-    if (!GetShortPathName(long_path, path, path_size))
-        _tcsncpy(path, long_path, path_size);
-    sz1 = _tcslen(path) + _tcslen(AUTOEXEC_CMD);
-    sz2 = _tcslen(AUTOEXEC_INTRO) + 2 /* '\n' and '\0'. */;
-    line_size = sz1 > sz2 ? sz1 : sz2;
-    line = (LPTSTR)malloc(line_size * sizeof(TCHAR));
-    out_line = (LPTSTR)malloc(line_size * sizeof(TCHAR));
-    _stprintf(out_line, AUTOEXEC_CMD, path);
-    _tcscat(out_line, _T("\n"));
-    autoexec_intro = (LPTSTR)malloc((_tcslen(AUTOEXEC_INTRO) + 2 /* '\0', '\n' */)
-                            * sizeof(TCHAR));
-    _tcscpy(autoexec_intro, AUTOEXEC_INTRO);
-    _tcscat(autoexec_intro, _T("\n"));
-
-    found = FALSE;
-    while (!found && _fgetts(line, line_size, file)){
-        if (_tcscmp(autoexec_intro, line) == 0){
-            _fgetts(line, line_size, file);
-            if (_tcscmp(out_line, line) == 0)
-                found = TRUE;
-        }
-    }
-
-    if (!found){
-        if (fseek(file, 0, SEEK_END) != 0 ||
-            _fputts(_T("\n"), file) == _TEOF ||
-            _fputts(autoexec_intro, file) == _TEOF ||
-            _fputts(out_line, file) == _TEOF)
-                func_ret = FALSE;
-    }
-    else
-        verb_out(_T("Value already exists in \"autoexec.bat\"."));
-
-    fclose(file);
-    free(path);
-    free(line);
-    free(out_line);
-    free(autoexec_intro);
-
-    return func_ret;
-}
-//---------------------------------------------------------------------------
-// Removes "path" from "autoexec.bat". Return "TRUE" if the path has been
-// removed or it wasn't in the file, "FALSE" otherwise.
-BOOL remove_path_autoexec(LPTSTR long_path){
-    FILE * file;
-    LPTSTR path;
-    size_t path_size;
-    LPTSTR data;
-    long file_size;
-    LPTSTR expected_text;
-    size_t expected_text_size;
-    LPTSTR buff;
-    size_t buff_size;
-    LPTSTR begin_pos;
-    LPTSTR final_part;
-    size_t fread_ret;
-    BOOL func_ret = TRUE;
-
-    file = _wfopen(AUTOEXEC_PATH, _T("rb"));
-    if (!file){
-        err_out(_T("Cannot open \"autoexec.bat\" for reading."));
-        return FALSE;
-    }
-    fseek(file, 0, SEEK_END);
-    file_size = ftell(file);
-    data = (LPTSTR)malloc(file_size + sizeof(TCHAR) /* '\0'. */);
-    data[file_size / sizeof(TCHAR)] = '\0';
-    fseek(file, 0, SEEK_SET);
-    fread_ret = fread(data, file_size, 1, file);
-    fclose(file);
-    if (fread_ret != 1){
-        err_out(_T("Cannot read \"autoexec.bat\"."));
-        return FALSE;
-    }
-
-    path_size = _tcslen(long_path) + 1;
-    path = (LPTSTR)malloc(path_size * sizeof(TCHAR));
-    if (!GetShortPathName(long_path, path, path_size))
-        _tcsncpy(path, long_path, path_size);
-    buff_size = _tcslen(AUTOEXEC_CMD) + _tcslen(path);
-    buff = (LPTSTR)malloc(buff_size * sizeof(TCHAR));
-    expected_text_size = buff_size + _tcslen(AUTOEXEC_INTRO)
-                         + 4 /* 2 * '\r\n' */;
-    expected_text = (LPTSTR)malloc(expected_text_size * sizeof(TCHAR));
-    _tcscpy(expected_text, AUTOEXEC_INTRO);
-    _tcscat(expected_text, _T("\r\n"));
-    _stprintf(buff, AUTOEXEC_CMD, path);
-    _tcscat(expected_text, buff);
-    _tcscat(expected_text, _T("\r\n"));
-
-    begin_pos = _tcsstr(data, expected_text);
-    if (begin_pos){
-        file = _wfopen(AUTOEXEC_PATH, _T("wb"));
-        if (!file){
-            err_out(_T("Cannot open \"autoexec.bat\" for writing."));
-            func_ret = FALSE;
-        }
-        else{
-            final_part = begin_pos + _tcslen(expected_text);
-            if ((fwrite(data, begin_pos - data, 1, file) != 1 &&
-                 (begin_pos - data)) || /* "fwrite"fails if the
-                                           second argument is 0 */
-                (fwrite(final_part, _tcslen(final_part), 1, file) != 1 &&
-                 _tcslen(final_part)))
-                    func_ret = FALSE;
-            fclose(file);
-        }
-    }
-    else
-        verb_out(_T("Value does not exist in \"autoexec.bat\"."));
-
-    free(data);
-    free(path);
-    free(buff);
-    free(expected_text);
-
-    return func_ret;
-}
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 void __fastcall AddSearchPath(const UnicodeString Path)
 void __fastcall AddSearchPath(const UnicodeString Path)
 {
 {
-  bool Result;
-  if (Win32Platform == VER_PLATFORM_WIN32_NT)
-  {
-    Result = add_path_reg(Path.c_str());
-  }
-  else
-  {
-    Result = add_path_autoexec(Path.c_str());
-  }
-
-  if (!Result)
+  if (!add_path_reg(Path.c_str()))
   {
   {
     throw ExtException(FMTLOAD(ADD_PATH_ERROR, (Path)), LastPathError);
     throw ExtException(FMTLOAD(ADD_PATH_ERROR, (Path)), LastPathError);
   }
   }
@@ -421,17 +255,7 @@ void __fastcall AddSearchPath(const UnicodeString Path)
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 void __fastcall RemoveSearchPath(const UnicodeString Path)
 void __fastcall RemoveSearchPath(const UnicodeString Path)
 {
 {
-  bool Result;
-  if (Win32Platform == VER_PLATFORM_WIN32_NT)
-  {
-    Result = remove_path_reg(Path.c_str());
-  }
-  else
-  {
-    Result = remove_path_autoexec(Path.c_str());
-  }
-
-  if (!Result)
+  if (!remove_path_reg(Path.c_str()))
   {
   {
     throw ExtException(FMTLOAD(REMOVE_PATH_ERROR, (Path)), LastPathError);
     throw ExtException(FMTLOAD(REMOVE_PATH_ERROR, (Path)), LastPathError);
   }
   }
@@ -1151,3 +975,40 @@ void __fastcall UpdateJumpList(TStrings * SessionNames, TStrings * WorkspaceName
     delete Removed;
     delete Removed;
   }
   }
 }
 }
+//---------------------------------------------------------------------------
+bool __fastcall AnyOtherInstanceOfSelf()
+{
+
+  HANDLE Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
+
+  bool Result = false;
+
+  try
+  {
+    unsigned int Process = GetCurrentProcessId();
+    UnicodeString ExeBaseName = ExtractFileBaseName(Application->ExeName);
+
+    PROCESSENTRY32 ProcessEntry;
+    ProcessEntry.dwSize = sizeof(PROCESSENTRY32);
+
+    if (Process32First(Snapshot, &ProcessEntry))
+    {
+      while (!Result && Process32Next(Snapshot, &ProcessEntry))
+      {
+        // we should check if the process is running in the same session,
+        // but for that we probably need some special priviledges
+        if ((Process != ProcessEntry.th32ProcessID) &&
+            SameText(ExtractFileBaseName(ProcessEntry.szExeFile), ExeBaseName))
+        {
+          Result = true;
+        }
+      }
+    }
+  }
+  __finally
+  {
+    CloseHandle(Snapshot);
+  }
+
+  return Result;
+}

部分文件因为文件数量过多而无法显示