Martin Prikryl 12 年之前
父节点
当前提交
43ec878d4b
共有 100 个文件被更改,包括 1481 次插入1227 次删除
  1. 0 2
      deployment/winscp.isl
  2. 0 47
      deployment/winscpsetup.iss
  3. 1 0
      dotnet/GlobalSuppressions.cs
  4. 14 4
      dotnet/Session.cs
  5. 1 1
      dotnet/TransferResumeSupport.cs
  6. 43 1
      dotnet/internal/ExeSessionProcess.cs
  7. 4 0
      dotnet/internal/Logger.cs
  8. 5 2
      dotnet/internal/SessionLogReader.cs
  9. 3 3
      dotnet/properties/AssemblyInfo.cs
  10. 3 0
      libs/openssl/debug.txt
  11. 2 0
      libs/openssl/ssl/s23_pkt.c
  12. 40 0
      libs/openssl/ssl/ssl.h
  13. 3 3
      libs/zlib/src/README
  14. 1 1
      libs/zlib/src/compress.c
  15. 7 5
      libs/zlib/src/deflate.c
  16. 1 1
      libs/zlib/src/deflate.h
  17. 19 3
      libs/zlib/src/gzguts.h
  18. 27 13
      libs/zlib/src/gzlib.c
  19. 13 8
      libs/zlib/src/gzread.c
  20. 38 26
      libs/zlib/src/gzwrite.c
  21. 1 1
      libs/zlib/src/infback.c
  22. 3 3
      libs/zlib/src/inffast.c
  23. 40 24
      libs/zlib/src/inflate.c
  24. 7 7
      libs/zlib/src/inftrees.c
  25. 8 6
      libs/zlib/src/trees.c
  26. 1 1
      libs/zlib/src/uncompr.c
  27. 19 14
      libs/zlib/src/zconf.h
  28. 36 12
      libs/zlib/src/zlib.h
  29. 1 1
      libs/zlib/src/zutil.c
  30. 5 4
      libs/zlib/src/zutil.h
  31. 2 1
      source/Console.cbproj
  32. 1 1
      source/DragExt.cbproj
  33. 2 2
      source/DragExt64.rc
  34. 0 3
      source/Moje.cbproj
  35. 7 16
      source/ScpForms.cbproj
  36. 3 3
      source/WinSCP.cbproj
  37. 2 2
      source/components/LogMemo.cpp
  38. 4 11
      source/components/UnixDirView.cpp
  39. 0 1
      source/components/UnixDirView.h
  40. 19 15
      source/console/Main.cpp
  41. 16 3
      source/core/Common.cpp
  42. 2 0
      source/core/Common.h
  43. 1 1
      source/core/Configuration.cpp
  44. 5 0
      source/core/Configuration.h
  45. 10 0
      source/core/CoreMain.cpp
  46. 1 1
      source/core/Cryptography.cpp
  47. 161 29
      source/core/Exceptions.cpp
  48. 9 6
      source/core/Exceptions.h
  49. 82 31
      source/core/FileMasks.cpp
  50. 16 7
      source/core/FileMasks.h
  51. 5 6
      source/core/FtpFileSystem.cpp
  52. 3 2
      source/core/HierarchicalStorage.cpp
  53. 21 11
      source/core/Interface.h
  54. 11 2
      source/core/PuttyIntf.cpp
  55. 25 14
      source/core/RemoteFiles.cpp
  56. 4 5
      source/core/RemoteFiles.h
  57. 7 4
      source/core/ScpFileSystem.cpp
  58. 9 9
      source/core/Script.cpp
  59. 79 18
      source/core/SecureShell.cpp
  60. 6 4
      source/core/SecureShell.h
  61. 40 14
      source/core/SessionData.cpp
  62. 4 0
      source/core/SessionData.h
  63. 9 21
      source/core/SessionInfo.cpp
  64. 1 1
      source/core/SessionInfo.h
  65. 36 18
      source/core/SftpFileSystem.cpp
  66. 56 38
      source/core/Terminal.cpp
  67. 8 6
      source/core/Terminal.h
  68. 3 3
      source/core/WebDAVFileSystem.cpp
  69. 1 1
      source/filezilla/ApiLog.cpp
  70. 13 2
      source/filezilla/AsyncSslSocketLayer.cpp
  71. 4 0
      source/filezilla/ControlSocket.h
  72. 10 0
      source/filezilla/FileZillaApi.cpp
  73. 1 0
      source/filezilla/FileZillaApi.h
  74. 5 0
      source/filezilla/FileZillaIntf.cpp
  75. 1 0
      source/filezilla/FileZillaIntf.h
  76. 14 6
      source/filezilla/FtpControlSocket.cpp
  77. 4 1
      source/filezilla/FtpControlSocket.h
  78. 28 9
      source/filezilla/FtpListResult.cpp
  79. 7 0
      source/filezilla/MainThread.cpp
  80. 2 0
      source/filezilla/MainThread.h
  81. 11 5
      source/forms/Console.cpp
  82. 37 0
      source/forms/Console.dfm
  83. 1 1
      source/forms/Console.h
  84. 1 0
      source/forms/Copy.cpp
  85. 99 42
      source/forms/Custom.cpp
  86. 1 1
      source/forms/CustomCommand.cpp
  87. 7 80
      source/forms/CustomScpExplorer.cpp
  88. 1 1
      source/forms/CustomScpExplorer.h
  89. 11 6
      source/forms/Editor.cpp
  90. 37 0
      source/forms/FileFind.dfm
  91. 1 0
      source/forms/FullSynchronize.cpp
  92. 0 52
      source/forms/GeneralSettings.cpp
  93. 0 301
      source/forms/GeneralSettings.dfm
  94. 0 31
      source/forms/GeneralSettings.h
  95. 143 0
      source/forms/Glyphs.dfm
  96. 1 0
      source/forms/Glyphs.h
  97. 16 16
      source/forms/ImportSessions.cpp
  98. 4 4
      source/forms/ImportSessions.dfm
  99. 4 4
      source/forms/ImportSessions.h
  100. 0 162
      source/forms/LogSettings.cpp

+ 0 - 2
deployment/winscp.isl

@@ -69,8 +69,6 @@ ExplorerInterfaceC=&Explorer
 ExplorerInterface1=- only remote directory
 ExplorerInterface2=- keyboard shortcuts like in Windows Explorer
 ExplorerInterface3=- drag && drop
-AdditionalOptions=Additional options
-AdvancedLoginOptions=Show &advanced login options
 UserSettingsOverview=Initial user settings (can be changed later)
 FinishedRestartDragExtLabel=To complete the installation of WinSCP, Setup must restart your computer to load updated version of Drag & drop shell extension. You can restart your computer later, if you do not need to use the extension. Would you like to restart now?
 PleaseDonate=Please consider donating to support WinSCP development.

+ 0 - 47
deployment/winscpsetup.iss

@@ -353,17 +353,6 @@ Root: HKCU; SubKey: "{#RegistryKey}\Configuration\Interface"; ValueType: dword;
 Root: HKLM; SubKey: "{#RegistryKey}"; ValueType: dword; \
   ValueName: "DefaultInterfaceInterface"; ValueData: 1; \
   Check: not UserSettings(1); Flags: noerror
-; Advanced tab on login dialog
-Root: HKCU; SubKey: "{#RegistryKey}\Configuration\Interface"; ValueType: dword; \
-  ValueName: "ShowAdvancedLoginOptions"; ValueData: 0; Check: not UserSettings(2)
-Root: HKLM; SubKey: "{#RegistryKey}"; ValueType: dword; \
-  ValueName: "DefaultInterfaceShowAdvancedLoginOptions"; ValueData: 0; \
-  Check: not UserSettings(2); Flags: noerror
-Root: HKCU; SubKey: "{#RegistryKey}\Configuration\Interface"; ValueType: dword; \
-  ValueName: "ShowAdvancedLoginOptions"; ValueData: 1; Check: UserSettings(2)
-Root: HKLM; SubKey: "{#RegistryKey}"; ValueType: dword; \
-  ValueName: "DefaultInterfaceShowAdvancedLoginOptions"; ValueData: 1; \
-  Check: UserSettings(2); Flags: noerror
 ; If installer enabled ddext, let it reset the settings on uninstall,
 ; so the default is used on the next run
 Root: HKCU; SubKey: "{#RegistryKey}\Configuration\Interface"; ValueType: dword; \
@@ -444,8 +433,6 @@ var
   CustomTypeButton: TRadioButton;
   CommanderRadioButton: TRadioButton;
   ExplorerRadioButton: TRadioButton;
-  AdditionalOptionsCaption: TLabel;
-  AdvancedTabsCheckbox: TCheckbox;
   LaunchCheckbox: TCheckbox;
   OpenGettingStartedCheckbox: TCheckbox;
   AreUpdatesEnabled: Boolean;
@@ -499,7 +486,6 @@ function UserSettings(Settings: Integer): Boolean;
 begin
   case Settings of
     1: Result := CommanderRadioButton.Checked;
-    2: Result := AdvancedTabsCheckbox.Checked;
     else Result := False;
   end;
 end;
@@ -775,7 +761,6 @@ procedure InitializeWizard;
 var
   DefaultLang: Boolean;
   UserInterface: Cardinal;
-  AdvancedTabs: Cardinal;
   UpdatesPeriod: Cardinal;
   InterfacePage: TWizardPage;
   SetupTypePage: TWizardPage;
@@ -961,9 +946,6 @@ begin
   UserInterface := 0; { default is commander }
   RegQueryDWordValue(HKCU, '{#RegistryKey}\Configuration\Interface',
     'Interface', UserInterface);
-  AdvancedTabs := 0; { advanced tabs are off by default }
-  RegQueryDWordValue(HKCU, '{#RegistryKey}\Configuration\Interface',
-    'ShowAdvancedLoginOptions', AdvancedTabs);
 
   Caption := TLabel.Create(InterfacePage);
   Caption.Caption := ExpandConstant('{cm:UserInterfaceStyle}');
@@ -1040,22 +1022,6 @@ begin
   else
     I := Image.Top + Image.Height;
 
-  AdditionalOptionsCaption := TLabel.Create(InterfacePage);
-  AdditionalOptionsCaption.Caption := ExpandConstant('{cm:AdditionalOptions}');
-  AdditionalOptionsCaption.Width := InterfacePage.SurfaceWidth;
-  AdditionalOptionsCaption.Top := I + ScaleY(10);
-  AdditionalOptionsCaption.Parent := InterfacePage.Surface;
-
-  AdvancedTabsCheckbox := TCheckbox.Create(InterfacePage);
-  AdvancedTabsCheckbox.Caption := ExpandConstant('{cm:AdvancedLoginOptions}');
-  AdvancedTabsCheckbox.Checked := (AdvancedTabs <> 0);
-  AdvancedTabsCheckbox.Left := ScaleX(4);
-  AdvancedTabsCheckbox.Width := InterfacePage.SurfaceWidth -
-    AdvancedTabsCheckbox.Left;
-  AdvancedTabsCheckbox.Top :=
-    AdditionalOptionsCaption.Top + AdditionalOptionsCaption.Height + ScaleY(6);
-  AdvancedTabsCheckbox.Parent := InterfacePage.Surface;
-
   // run checkbox
   LaunchCheckbox := TCheckbox.Create(WizardForm.FinishedPage);
   LaunchCheckbox.Caption := ExpandConstant('{cm:Launch}');
@@ -1241,12 +1207,6 @@ begin
   OpenCandyCurPageChanged(CurPageID);
 #endif
 
-  if CurPageID = wpInterface then
-  begin
-    AdditionalOptionsCaption.Visible := not TypicalTypeButton.Checked;
-    AdvancedTabsCheckbox.Visible := not TypicalTypeButton.Checked;
-  end
-    else
   if CurPageID = wpFinished then
   begin
     LineHeight := (WizardForm.NoRadio.Top - WizardForm.YesRadio.Top);
@@ -1512,13 +1472,6 @@ begin
   S := S + S2;
   S := S + NewLine;
 
-  if AdvancedTabsCheckbox.Checked then
-  begin
-    S2 := ExpandConstant('{cm:AdvancedLoginOptions}');
-    StringChange(S2, '&', '');
-    S := S + Space + S2 + NewLine;
-  end;
-
   Result := S;
 end;
 

+ 1 - 0
dotnet/GlobalSuppressions.cs

@@ -143,3 +143,4 @@ using System.Diagnostics.CodeAnalysis;
 [assembly: SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule", Scope = "member", Target = "WinSCP.UnsafeNativeMethods.#CreateFileMapping(Microsoft.Win32.SafeHandles.SafeFileHandle,System.IntPtr,WinSCP.FileMapProtection,System.Int32,System.Int32,System.String)")]
 [assembly: SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule", Scope = "member", Target = "WinSCP.UnsafeNativeMethods.#MapViewOfFile(Microsoft.Win32.SafeHandles.SafeFileHandle,WinSCP.FileMapAccess,System.UInt32,System.UInt32,System.UIntPtr)")]
 [assembly: SuppressMessage("Microsoft.Interoperability", "CA1404:CallGetLastErrorImmediatelyAfterPInvoke", Scope = "member", Target = "WinSCP.ExeSessionProcess.#InitializeConsole()")]
+[assembly: SuppressMessage("Microsoft.Interoperability", "CA1404:CallGetLastErrorImmediatelyAfterPInvoke", Scope = "member", Target = "WinSCP.ExeSessionProcess.#Dispose()")]

+ 14 - 4
dotnet/Session.cs

@@ -51,7 +51,10 @@ namespace WinSCP
         public string DebugLogPath { get { CheckNotDisposed(); return Logger.LogPath; } set { CheckNotDisposed(); Logger.LogPath = value; } }
         public string SessionLogPath { get { return _sessionLogPath; } set { CheckNotOpened(); _sessionLogPath = value; } }
         public string XmlLogPath { get { return _xmlLogPath; } set { CheckNotOpened(); _xmlLogPath = value; } }
+        #if DEBUG
         public bool GuardProcessWithJob { get { return _guardProcessWithJob; } set { CheckNotOpened(); _guardProcessWithJob = value; } }
+        public bool TestHandlesClosed { get { return TestHandlesClosedInternal; } set { TestHandlesClosedInternal = value; } }
+        #endif
 
         public TimeSpan Timeout { get; set; }
 
@@ -171,6 +174,11 @@ namespace WinSCP
 
                     WriteCommand("open " + SessionOptionsToOpenArguments(sessionOptions));
 
+                    string logExplanation =
+                        string.Format(CultureInfo.CurrentCulture,
+                            "(response log file {0} was not created). This could indicate lack of write permissions to the log folder or problems starting WinSCP itself.",
+                            XmlLogPath);
+
                     // Wait until the log file gets created or WinSCP terminates (in case of fatal error)
                     do
                     {
@@ -183,16 +191,16 @@ namespace WinSCP
                             _process.WriteStatus();
                             throw new SessionLocalException(this,
                                 string.Format(CultureInfo.CurrentCulture,
-                                    "WinSCP process terminated with exit code {0} and output \"{1}\", without creating a log file.",
-                                    _process.ExitCode, string.Join(Environment.NewLine, output)));
+                                    "WinSCP process terminated with exit code {0} and output \"{1}\", without responding {2}",
+                                    _process.ExitCode, string.Join(Environment.NewLine, output), logExplanation));
                         }
 
                         Thread.Sleep(50);
 
                         CheckForTimeout(
                             string.Format(CultureInfo.CurrentCulture,
-                                "Log file {0} was not created in time, please make sure WinSCP has write permissions to the folder",
-                                XmlLogPath));
+                                "WinSCP has not responded in time {0}",
+                                logExplanation));
 
                     } while (!File.Exists(XmlLogPath));
 
@@ -1433,6 +1441,8 @@ namespace WinSCP
 
         internal const string Namespace = "http://winscp.net/schema/session/1.0";
         internal Logger Logger { get; private set; }
+        internal bool GuardProcessWithJobInternal { get { return _guardProcessWithJob; } set { CheckNotOpened(); _guardProcessWithJob = value; } }
+        internal bool TestHandlesClosedInternal { get; set; }
 
         private ExeSessionProcess _process;
         private DateTime _lastOutput;

+ 1 - 1
dotnet/TransferResumeSupport.cs

@@ -62,7 +62,7 @@ namespace WinSCP
         {
             if (threshold <= 0)
             {
-                throw new ArgumentOutOfRangeException("threshold", "Threshold must be possitive");
+                throw new ArgumentOutOfRangeException("threshold", "Threshold must be positive");
             }
             CheckSmart();
             _threshold = threshold;

+ 43 - 1
dotnet/internal/ExeSessionProcess.cs

@@ -128,7 +128,7 @@ namespace WinSCP
 
                 _logger.WriteLine("Started process {0}", _process.Id);
 
-                if (_session.GuardProcessWithJob)
+                if (_session.GuardProcessWithJobInternal)
                 {
                     _job = new Job();
                     _job.AddProcess(_process.Handle);
@@ -337,6 +337,10 @@ namespace WinSCP
         {
             using (_logger.CreateCallstack())
             {
+                _logger.WriteLine(
+                    "File Name [{0}] - Directory [{1}] - Overall Progress [{2}] - File Progress [{3}] - CPS [{4}]",
+                    e.FileName, e.Directory, e.OverallProgress, e.FileProgress, e.CPS);
+
                 FileTransferProgressEventArgs args = new FileTransferProgressEventArgs();
 
                 switch (e.Operation)
@@ -454,6 +458,23 @@ namespace WinSCP
             return ev;
         }
 
+        private void TestEventClosed(string name)
+        {
+            if (_session.TestHandlesClosedInternal)
+            {
+                _logger.WriteLine("Testing that event {0} is closed", name);
+                EventWaitHandle ev;
+                if (TryCreateEvent(name, out ev))
+                {
+                    ev.Close();
+                }
+                else
+                {
+                    _logger.WriteLine("Exception: Event {0} was not closed yet", name);
+                }
+            }
+        }
+
         public void ExecuteCommand(string command)
         {
             using (_logger.CreateCallstack())
@@ -486,6 +507,10 @@ namespace WinSCP
             {
                 lock (_lock)
                 {
+                    if (_session.TestHandlesClosedInternal)
+                    {
+                        _logger.WriteLine("Will test that handles are closed");
+                    }
                     _abort = true;
                     if (_thread != null)
                     {
@@ -500,19 +525,36 @@ namespace WinSCP
                     if (_requestEvent != null)
                     {
                         _requestEvent.Close();
+                        TestEventClosed(ConsoleEventRequest + _instanceName);
                     }
                     if (_responseEvent != null)
                     {
                         _responseEvent.Close();
+                        TestEventClosed(ConsoleEventResponse + _instanceName);
                     }
                     if (_cancelEvent != null)
                     {
                         _cancelEvent.Close();
+                        TestEventClosed(ConsoleEventCancel + _instanceName);
                     }
                     if (_fileMapping != null)
                     {
                         _fileMapping.Dispose();
                         _fileMapping = null;
+                        if (_session.TestHandlesClosedInternal)
+                        {
+                            _logger.WriteLine("Testing that file mapping is closed");
+                            string fileMappingName = ConsoleMapping + _instanceName;
+                            SafeFileHandle fileMapping = CreateFileMapping(fileMappingName);
+                            if (Marshal.GetLastWin32Error() == UnsafeNativeMethods.ERROR_ALREADY_EXISTS)
+                            {
+                                _logger.WriteLine("Exception: File mapping {0} was not closed yet", fileMappingName);
+                            }
+                            if (!fileMapping.IsInvalid)
+                            {
+                                fileMapping.Dispose();
+                            }
+                        }
                     }
                     if (_inputEvent != null)
                     {

+ 4 - 0
dotnet/internal/Logger.cs

@@ -67,6 +67,10 @@ namespace WinSCP
 
                 AddCounter(new PerformanceCounter("Memory", "Available KBytes"));
             }
+            catch (UnauthorizedAccessException)
+            {
+                WriteLine("Not authorized to get counters");
+            }
             catch (Exception e)
             {
                 WriteLine("Error getting counters: {0}", e);

+ 5 - 2
dotnet/internal/SessionLogReader.cs

@@ -32,8 +32,11 @@ namespace WinSCP
                 _stream = null;
             }
 
-            ((IDisposable)_reader).Dispose();
-            _reader = null;
+            if (_reader != null)
+            {
+                ((IDisposable)_reader).Dispose();
+                _reader = null;
+            }
         }
 
         public override bool Read(LogReadFlags flags)

+ 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
 [assembly: Guid("a0b93468-d98a-4845-a234-8076229ad93f")]
 
-[assembly: AssemblyVersion("1.1.1.0")]
-[assembly: AssemblyFileVersion("1.1.1.0")]
-[assembly: AssemblyInformationalVersionAttribute("5.2.1.0")]
+[assembly: AssemblyVersion("1.1.2.0")]
+[assembly: AssemblyFileVersion("1.1.2.0")]
+[assembly: AssemblyInformationalVersionAttribute("5.2.2.0")]
 
 [assembly: CLSCompliant(true)]
 

+ 3 - 0
libs/openssl/debug.txt

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

+ 2 - 0
libs/openssl/ssl/s23_pkt.c

@@ -81,6 +81,7 @@ int ssl23_write_bytes(SSL *s)
 			s->init_num=num;
 			return(i);
 			}
+			SSL_TRACE_BYTES(s, &(buf[tot]),i, "write: ");
 		s->rwstate=SSL_NOTHING;
 		if (i == num) return(tot+i);
 
@@ -107,6 +108,7 @@ int ssl23_read_bytes(SSL *s, int n)
 			if (j <= 0)
 				return(j);
 			s->rwstate=SSL_NOTHING;
+			SSL_TRACE_BYTES(s, (char *)&(p[s->packet_length]),j, "read: ");
 			s->packet_length+=j;
 			if (s->packet_length >= (unsigned int)n)
 				return(s->packet_length);

+ 40 - 0
libs/openssl/ssl/ssl.h

@@ -2573,6 +2573,46 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_X509_LIB					 268
 #define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS		 269
 
+#if 0
+
+#define SSL_TRACE(s, str) \
+	{ \
+	void (*ssl_trace_cb)(const SSL *ssl,int type,int val)=NULL; \
+	if ((s)->info_callback != NULL) \
+		ssl_trace_cb=(s)->info_callback; \
+	else if ((s)->ctx->info_callback != NULL) \
+		ssl_trace_cb=(s)->ctx->info_callback; \
+	if (ssl_trace_cb != NULL) \
+		{ \
+		char* ssl_trace_buf = CRYPTO_malloc((strlen(__FILE__) + strlen(__FUNC__) + strlen(str) + 100), __FILE__, __LINE__); \
+		sprintf(ssl_trace_buf, "[%s:%s:%d] %s", __FILE__, __FUNC__, __LINE__, str); \
+		ssl_trace_cb((s),SSL_CB_LOOP,(int)ssl_trace_buf); \
+		} \
+	}
+
+#define SSL_TRACE_BYTES(s, data, len, prefix) \
+	{ \
+	if (((s)->info_callback != NULL) || ((s)->ctx->info_callback != NULL)) \
+		{ \
+		char* ssl_trace_bytes_buf = OPENSSL_malloc(strlen(prefix) + ((len)*3) + 100); \
+		int ssl_trace_i; \
+		strcpy(ssl_trace_bytes_buf, (prefix)); \
+		for (ssl_trace_i = 0; ssl_trace_i < (len); ssl_trace_i++) \
+			{ \
+			sprintf(ssl_trace_bytes_buf + strlen(ssl_trace_bytes_buf), "%2.2x ", (unsigned char)((data)[ssl_trace_i])); \
+			} \
+		SSL_TRACE((s),ssl_trace_bytes_buf); \
+		OPENSSL_free(ssl_trace_bytes_buf); \
+		} \
+	}
+
+#else
+
+#define SSL_TRACE(s, str)
+#define SSL_TRACE_BYTES(s, data, len, prefix)
+
+#endif
+
 #ifdef  __cplusplus
 }
 #endif

+ 3 - 3
libs/zlib/src/README

@@ -1,6 +1,6 @@
 ZLIB DATA COMPRESSION LIBRARY
 
-zlib 1.2.7 is a general purpose data compression library.  All the code is
+zlib 1.2.8 is a general purpose data compression library.  All the code is
 thread safe.  The data format used by the zlib library is described by RFCs
 (Request for Comments) 1950 to 1952 in the files
 http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
@@ -31,7 +31,7 @@ Mark Nelson <[email protected]> wrote an article about zlib for the Jan.  1997
 issue of Dr.  Dobb's Journal; a copy of the article is available at
 http://marknelson.us/1997/01/01/zlib-engine/ .
 
-The changes made in version 1.2.7 are documented in the file ChangeLog.
+The changes made in version 1.2.8 are documented in the file ChangeLog.
 
 Unsupported third party contributions are provided in directory contrib/ .
 
@@ -84,7 +84,7 @@ Acknowledgments:
 
 Copyright notice:
 
- (C) 1995-2012 Jean-loup Gailly and Mark Adler
+ (C) 1995-2013 Jean-loup Gailly and Mark Adler
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages

+ 1 - 1
libs/zlib/src/compress.c

@@ -29,7 +29,7 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
     z_stream stream;
     int err;
 
-    stream.next_in = (Bytef*)source;
+    stream.next_in = (z_const Bytef *)source;
     stream.avail_in = (uInt)sourceLen;
 #ifdef MAXSEG_64K
     /* Check for source > 64K on 16-bit machine: */

+ 7 - 5
libs/zlib/src/deflate.c

@@ -1,5 +1,5 @@
 /* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler
+ * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -52,7 +52,7 @@
 #include "deflate.h"
 
 const char deflate_copyright[] =
-   " deflate 1.2.7 Copyright 1995-2012 Jean-loup Gailly and Mark Adler ";
+   " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -305,7 +305,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
     if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
         s->pending_buf == Z_NULL) {
         s->status = FINISH_STATE;
-        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+        strm->msg = ERR_MSG(Z_MEM_ERROR);
         deflateEnd (strm);
         return Z_MEM_ERROR;
     }
@@ -329,7 +329,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
     uInt str, n;
     int wrap;
     unsigned avail;
-    unsigned char *next;
+    z_const unsigned char *next;
 
     if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL)
         return Z_STREAM_ERROR;
@@ -359,7 +359,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
     avail = strm->avail_in;
     next = strm->next_in;
     strm->avail_in = dictLength;
-    strm->next_in = (Bytef *)dictionary;
+    strm->next_in = (z_const Bytef *)dictionary;
     fill_window(s);
     while (s->lookahead >= MIN_MATCH) {
         str = s->strstart;
@@ -513,6 +513,8 @@ int ZEXPORT deflateParams(strm, level, strategy)
         strm->total_in != 0) {
         /* Flush the last buffer: */
         err = deflate(strm, Z_BLOCK);
+        if (err == Z_BUF_ERROR && s->pending == 0)
+            err = Z_OK;
     }
     if (s->level != level) {
         s->level = level;

+ 1 - 1
libs/zlib/src/deflate.h

@@ -104,7 +104,7 @@ typedef struct internal_state {
     int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
     gz_headerp  gzhead;  /* gzip header information to write */
     uInt   gzindex;      /* where in extra, name, or comment */
-    Byte  method;        /* STORED (for zip only) or DEFLATED */
+    Byte  method;        /* can only be DEFLATED */
     int   last_flush;    /* value of flush param for previous deflate call */
 
                 /* used by deflate.c: */

+ 19 - 3
libs/zlib/src/gzguts.h

@@ -1,5 +1,5 @@
 /* gzguts.h -- zlib internal header definitions for gz* operations
- * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -35,6 +35,13 @@
 #  include <io.h>
 #endif
 
+#ifdef WINAPI_FAMILY
+#  define open _open
+#  define read _read
+#  define write _write
+#  define close _close
+#endif
+
 #ifdef NO_DEFLATE       /* for compatibility with old definition */
 #  define NO_GZCOMPRESS
 #endif
@@ -60,7 +67,7 @@
 #ifndef HAVE_VSNPRINTF
 #  ifdef MSDOS
 /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
- but for now we just assume it doesn't. */
+   but for now we just assume it doesn't. */
 #    define NO_vsnprintf
 #  endif
 #  ifdef __TURBOC__
@@ -88,6 +95,14 @@
 #  endif
 #endif
 
+/* unlike snprintf (which is required in C99, yet still not supported by
+   Microsoft more than a decade later!), _snprintf does not guarantee null
+   termination of the result -- however this is only used in gzlib.c where
+   the result is assured to fit in the space provided */
+#ifdef _MSC_VER
+#  define snprintf _snprintf
+#endif
+
 #ifndef local
 #  define local static
 #endif
@@ -127,7 +142,8 @@
 #  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
 #endif
 
-/* default i/o buffer size -- double this for output when reading */
+/* default i/o buffer size -- double this for output when reading (this and
+   twice this must be able to fit in an unsigned type) */
 #define GZBUFSIZE 8192
 
 /* gzip modes, also provide a little integrity check on the passed structure */

+ 27 - 13
libs/zlib/src/gzlib.c

@@ -1,5 +1,5 @@
 /* gzlib.c -- zlib functions common to reading and writing gzip files
- * Copyright (C) 2004, 2010, 2011, 2012 Mark Adler
+ * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -108,7 +108,7 @@ local gzFile gz_open(path, fd, mode)
         return NULL;
 
     /* allocate gzFile structure to return */
-    state = malloc(sizeof(gz_state));
+    state = (gz_statep)malloc(sizeof(gz_state));
     if (state == NULL)
         return NULL;
     state->size = 0;            /* no buffers allocated yet */
@@ -162,8 +162,10 @@ local gzFile gz_open(path, fd, mode)
                 break;
             case 'F':
                 state->strategy = Z_FIXED;
+                break;
             case 'T':
                 state->direct = 1;
+                break;
             default:        /* could consider as an error, but just ignore */
                 ;
             }
@@ -194,8 +196,8 @@ local gzFile gz_open(path, fd, mode)
     }
     else
 #endif
-        len = strlen(path);
-    state->path = malloc(len + 1);
+        len = strlen((const char *)path);
+    state->path = (char *)malloc(len + 1);
     if (state->path == NULL) {
         free(state);
         return NULL;
@@ -208,7 +210,11 @@ local gzFile gz_open(path, fd, mode)
             *(state->path) = 0;
     else
 #endif
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+        snprintf(state->path, len + 1, "%s", (const char *)path);
+#else
         strcpy(state->path, path);
+#endif
 
     /* compute the flags for open() */
     oflag =
@@ -236,7 +242,7 @@ local gzFile gz_open(path, fd, mode)
 #ifdef _WIN32
         fd == -2 ? _wopen(path, oflag, 0666) :
 #endif
-        open(path, oflag, 0666));
+        open((const char *)path, oflag, 0666));
     if (state->fd == -1) {
         free(state->path);
         free(state);
@@ -282,9 +288,13 @@ gzFile ZEXPORT gzdopen(fd, mode)
     char *path;         /* identifier for error messages */
     gzFile gz;
 
-    if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
+    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
         return NULL;
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+    snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
+#else
     sprintf(path, "<fd:%d>", fd);   /* for debugging */
+#endif
     gz = gz_open(path, fd, mode);
     free(path);
     return gz;
@@ -531,7 +541,8 @@ const char * ZEXPORT gzerror(file, errnum)
     /* return error information */
     if (errnum != NULL)
         *errnum = state->err;
-    return state->msg == NULL ? "" : state->msg;
+    return state->err == Z_MEM_ERROR ? "out of memory" :
+                                       (state->msg == NULL ? "" : state->msg);
 }
 
 /* -- see zlib.h -- */
@@ -582,21 +593,24 @@ void ZLIB_INTERNAL gz_error(state, err, msg)
     if (msg == NULL)
         return;
 
-    /* for an out of memory error, save as static string */
-    if (err == Z_MEM_ERROR) {
-        state->msg = (char *)msg;
+    /* for an out of memory error, return literal string when requested */
+    if (err == Z_MEM_ERROR)
         return;
-    }
 
     /* construct error message with path */
-    if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
+    if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
+            NULL) {
         state->err = Z_MEM_ERROR;
-        state->msg = (char *)"out of memory";
         return;
     }
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+    snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
+             "%s%s%s", state->path, ": ", msg);
+#else
     strcpy(state->msg, state->path);
     strcat(state->msg, ": ");
     strcat(state->msg, msg);
+#endif
     return;
 }
 

+ 13 - 8
libs/zlib/src/gzread.c

@@ -1,5 +1,5 @@
 /* gzread.c -- zlib functions for reading gzip files
- * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -58,7 +58,8 @@ local int gz_avail(state)
         return -1;
     if (state->eof == 0) {
         if (strm->avail_in) {       /* copy what's there to the start */
-            unsigned char *p = state->in, *q = strm->next_in;
+            unsigned char *p = state->in;
+            unsigned const char *q = strm->next_in;
             unsigned n = strm->avail_in;
             do {
                 *p++ = *q++;
@@ -90,8 +91,8 @@ local int gz_look(state)
     /* allocate read buffers and inflate memory */
     if (state->size == 0) {
         /* allocate buffers */
-        state->in = malloc(state->want);
-        state->out = malloc(state->want << 1);
+        state->in = (unsigned char *)malloc(state->want);
+        state->out = (unsigned char *)malloc(state->want << 1);
         if (state->in == NULL || state->out == NULL) {
             if (state->out != NULL)
                 free(state->out);
@@ -352,14 +353,14 @@ int ZEXPORT gzread(file, buf, len)
 
         /* large len -- read directly into user buffer */
         else if (state->how == COPY) {      /* read directly */
-            if (gz_load(state, buf, len, &n) == -1)
+            if (gz_load(state, (unsigned char *)buf, len, &n) == -1)
                 return -1;
         }
 
         /* large len -- decompress directly into user buffer */
         else {  /* state->how == GZIP */
             strm->avail_out = len;
-            strm->next_out = buf;
+            strm->next_out = (unsigned char *)buf;
             if (gz_decomp(state) == -1)
                 return -1;
             n = state->x.have;
@@ -378,7 +379,11 @@ int ZEXPORT gzread(file, buf, len)
 }
 
 /* -- see zlib.h -- */
-#undef gzgetc
+#ifdef Z_PREFIX_SET
+#  undef z_gzgetc
+#else
+#  undef gzgetc
+#endif
 int ZEXPORT gzgetc(file)
     gzFile file;
 {
@@ -518,7 +523,7 @@ char * ZEXPORT gzgets(file, buf, len)
 
         /* look for end-of-line in current output buffer */
         n = state->x.have > left ? left : state->x.have;
-        eol = memchr(state->x.next, '\n', n);
+        eol = (unsigned char *)memchr(state->x.next, '\n', n);
         if (eol != NULL)
             n = (unsigned)(eol - state->x.next) + 1;
 

+ 38 - 26
libs/zlib/src/gzwrite.c

@@ -1,5 +1,5 @@
 /* gzwrite.c -- zlib functions for writing gzip files
- * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -19,7 +19,7 @@ local int gz_init(state)
     z_streamp strm = &(state->strm);
 
     /* allocate input buffer */
-    state->in = malloc(state->want);
+    state->in = (unsigned char *)malloc(state->want);
     if (state->in == NULL) {
         gz_error(state, Z_MEM_ERROR, "out of memory");
         return -1;
@@ -28,7 +28,7 @@ local int gz_init(state)
     /* only need output buffer and deflate state if compressing */
     if (!state->direct) {
         /* allocate output buffer */
-        state->out = malloc(state->want);
+        state->out = (unsigned char *)malloc(state->want);
         if (state->out == NULL) {
             free(state->in);
             gz_error(state, Z_MEM_ERROR, "out of memory");
@@ -168,7 +168,6 @@ int ZEXPORT gzwrite(file, buf, len)
     unsigned len;
 {
     unsigned put = len;
-    unsigned n;
     gz_statep state;
     z_streamp strm;
 
@@ -208,16 +207,19 @@ int ZEXPORT gzwrite(file, buf, len)
     if (len < state->size) {
         /* copy to input buffer, compress when full */
         do {
+            unsigned have, copy;
+
             if (strm->avail_in == 0)
                 strm->next_in = state->in;
-            n = state->size - strm->avail_in;
-            if (n > len)
-                n = len;
-            memcpy(strm->next_in + strm->avail_in, buf, n);
-            strm->avail_in += n;
-            state->x.pos += n;
-            buf = (char *)buf + n;
-            len -= n;
+            have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
+            copy = state->size - have;
+            if (copy > len)
+                copy = len;
+            memcpy(state->in + have, buf, copy);
+            strm->avail_in += copy;
+            state->x.pos += copy;
+            buf = (const char *)buf + copy;
+            len -= copy;
             if (len && gz_comp(state, Z_NO_FLUSH) == -1)
                 return 0;
         } while (len);
@@ -229,7 +231,7 @@ int ZEXPORT gzwrite(file, buf, len)
 
         /* directly compress user buffer to file */
         strm->avail_in = len;
-        strm->next_in = (voidp)buf;
+        strm->next_in = (z_const Bytef *)buf;
         state->x.pos += len;
         if (gz_comp(state, Z_NO_FLUSH) == -1)
             return 0;
@@ -244,6 +246,7 @@ int ZEXPORT gzputc(file, c)
     gzFile file;
     int c;
 {
+    unsigned have;
     unsigned char buf[1];
     gz_statep state;
     z_streamp strm;
@@ -267,12 +270,16 @@ int ZEXPORT gzputc(file, c)
 
     /* try writing to input buffer for speed (state->size == 0 if buffer not
        initialized) */
-    if (strm->avail_in < state->size) {
+    if (state->size) {
         if (strm->avail_in == 0)
             strm->next_in = state->in;
-        strm->next_in[strm->avail_in++] = c;
-        state->x.pos++;
-        return c & 0xff;
+        have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
+        if (have < state->size) {
+            state->in[have] = c;
+            strm->avail_in++;
+            state->x.pos++;
+            return c & 0xff;
+        }
     }
 
     /* no room in buffer or not initialized, use gz_write() */
@@ -300,12 +307,11 @@ int ZEXPORT gzputs(file, str)
 #include <stdarg.h>
 
 /* -- see zlib.h -- */
-int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
+int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
 {
     int size, len;
     gz_statep state;
     z_streamp strm;
-    va_list va;
 
     /* get internal structure */
     if (file == NULL)
@@ -335,25 +341,20 @@ int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
     /* do the printf() into the input buffer, put length in len */
     size = (int)(state->size);
     state->in[size - 1] = 0;
-    va_start(va, format);
 #ifdef NO_vsnprintf
 #  ifdef HAS_vsprintf_void
     (void)vsprintf((char *)(state->in), format, va);
-    va_end(va);
     for (len = 0; len < size; len++)
         if (state->in[len] == 0) break;
 #  else
     len = vsprintf((char *)(state->in), format, va);
-    va_end(va);
 #  endif
 #else
 #  ifdef HAS_vsnprintf_void
     (void)vsnprintf((char *)(state->in), size, format, va);
-    va_end(va);
     len = strlen((char *)(state->in));
 #  else
     len = vsnprintf((char *)(state->in), size, format, va);
-    va_end(va);
 #  endif
 #endif
 
@@ -368,6 +369,17 @@ int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
     return len;
 }
 
+int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
+{
+    va_list va;
+    int ret;
+
+    va_start(va, format);
+    ret = gzvprintf(file, format, va);
+    va_end(va);
+    return ret;
+}
+
 #else /* !STDC && !Z_HAVE_STDARG_H */
 
 /* -- see zlib.h -- */
@@ -547,9 +559,9 @@ int ZEXPORT gzclose_w(file)
     }
 
     /* flush, free memory, and close file */
+    if (gz_comp(state, Z_FINISH) == -1)
+        ret = state->err;
     if (state->size) {
-        if (gz_comp(state, Z_FINISH) == -1)
-            ret = state->err;
         if (!state->direct) {
             (void)deflateEnd(&(state->strm));
             free(state->out);

+ 1 - 1
libs/zlib/src/infback.c

@@ -255,7 +255,7 @@ out_func out;
 void FAR *out_desc;
 {
     struct inflate_state FAR *state;
-    unsigned char FAR *next;    /* next input */
+    z_const unsigned char FAR *next;    /* next input */
     unsigned char FAR *put;     /* next output */
     unsigned have, left;        /* available input and output */
     unsigned long hold;         /* bit buffer */

+ 3 - 3
libs/zlib/src/inffast.c

@@ -1,5 +1,5 @@
 /* inffast.c -- fast decoding
- * Copyright (C) 1995-2008, 2010 Mark Adler
+ * Copyright (C) 1995-2008, 2010, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -69,8 +69,8 @@ z_streamp strm;
 unsigned start;         /* inflate()'s starting value for strm->avail_out */
 {
     struct inflate_state FAR *state;
-    unsigned char FAR *in;      /* local strm->next_in */
-    unsigned char FAR *last;    /* while in < last, enough input available */
+    z_const unsigned char FAR *in;      /* local strm->next_in */
+    z_const unsigned char FAR *last;    /* have enough input while in < last */
     unsigned char FAR *out;     /* local strm->next_out */
     unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
     unsigned char FAR *end;     /* while out < end, enough space available */

+ 40 - 24
libs/zlib/src/inflate.c

@@ -93,11 +93,12 @@
 
 /* function prototypes */
 local void fixedtables OF((struct inflate_state FAR *state));
-local int updatewindow OF((z_streamp strm, unsigned out));
+local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
+                           unsigned copy));
 #ifdef BUILDFIXED
    void makefixed OF((void));
 #endif
-local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
                               unsigned len));
 
 int ZEXPORT inflateResetKeep(strm)
@@ -375,12 +376,13 @@ void makefixed()
    output will fall in the output data, making match copies simpler and faster.
    The advantage may be dependent on the size of the processor's data caches.
  */
-local int updatewindow(strm, out)
+local int updatewindow(strm, end, copy)
 z_streamp strm;
-unsigned out;
+const Bytef *end;
+unsigned copy;
 {
     struct inflate_state FAR *state;
-    unsigned copy, dist;
+    unsigned dist;
 
     state = (struct inflate_state FAR *)strm->state;
 
@@ -400,19 +402,18 @@ unsigned out;
     }
 
     /* copy state->wsize or less output bytes into the circular window */
-    copy = out - strm->avail_out;
     if (copy >= state->wsize) {
-        zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+        zmemcpy(state->window, end - state->wsize, state->wsize);
         state->wnext = 0;
         state->whave = state->wsize;
     }
     else {
         dist = state->wsize - state->wnext;
         if (dist > copy) dist = copy;
-        zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
+        zmemcpy(state->window + state->wnext, end - copy, dist);
         copy -= dist;
         if (copy) {
-            zmemcpy(state->window, strm->next_out - copy, copy);
+            zmemcpy(state->window, end - copy, copy);
             state->wnext = copy;
             state->whave = state->wsize;
         }
@@ -606,7 +607,7 @@ z_streamp strm;
 int flush;
 {
     struct inflate_state FAR *state;
-    unsigned char FAR *next;    /* next input */
+    z_const unsigned char FAR *next;    /* next input */
     unsigned char FAR *put;     /* next output */
     unsigned have, left;        /* available input and output */
     unsigned long hold;         /* bit buffer */
@@ -920,7 +921,7 @@ int flush;
             while (state->have < 19)
                 state->lens[order[state->have++]] = 0;
             state->next = state->codes;
-            state->lencode = (code const FAR *)(state->next);
+            state->lencode = (const code FAR *)(state->next);
             state->lenbits = 7;
             ret = inflate_table(CODES, state->lens, 19, &(state->next),
                                 &(state->lenbits), state->work);
@@ -994,7 +995,7 @@ int flush;
                values here (9 and 6) without reading the comments in inftrees.h
                concerning the ENOUGH constants, which depend on those values */
             state->next = state->codes;
-            state->lencode = (code const FAR *)(state->next);
+            state->lencode = (const code FAR *)(state->next);
             state->lenbits = 9;
             ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
                                 &(state->lenbits), state->work);
@@ -1003,7 +1004,7 @@ int flush;
                 state->mode = BAD;
                 break;
             }
-            state->distcode = (code const FAR *)(state->next);
+            state->distcode = (const code FAR *)(state->next);
             state->distbits = 6;
             ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
                             &(state->next), &(state->distbits), state->work);
@@ -1230,7 +1231,7 @@ int flush;
     RESTORE();
     if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
             (state->mode < CHECK || flush != Z_FINISH)))
-        if (updatewindow(strm, out)) {
+        if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
             state->mode = MEM;
             return Z_MEM_ERROR;
         }
@@ -1264,6 +1265,29 @@ z_streamp strm;
     return Z_OK;
 }
 
+int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+Bytef *dictionary;
+uInt *dictLength;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* copy dictionary */
+    if (state->whave && dictionary != Z_NULL) {
+        zmemcpy(dictionary, state->window + state->wnext,
+                state->whave - state->wnext);
+        zmemcpy(dictionary + state->whave - state->wnext,
+                state->window, state->wnext);
+    }
+    if (dictLength != Z_NULL)
+        *dictLength = state->whave;
+    return Z_OK;
+}
+
 int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
 z_streamp strm;
 const Bytef *dictionary;
@@ -1271,8 +1295,6 @@ uInt dictLength;
 {
     struct inflate_state FAR *state;
     unsigned long dictid;
-    unsigned char *next;
-    unsigned avail;
     int ret;
 
     /* check state */
@@ -1291,13 +1313,7 @@ uInt dictLength;
 
     /* copy dictionary to window using updatewindow(), which will amend the
        existing dictionary if appropriate */
-    next = strm->next_out;
-    avail = strm->avail_out;
-    strm->next_out = (Bytef *)dictionary + dictLength;
-    strm->avail_out = 0;
-    ret = updatewindow(strm, dictLength);
-    strm->avail_out = avail;
-    strm->next_out = next;
+    ret = updatewindow(strm, dictionary + dictLength, dictLength);
     if (ret) {
         state->mode = MEM;
         return Z_MEM_ERROR;
@@ -1337,7 +1353,7 @@ gz_headerp head;
  */
 local unsigned syncsearch(have, buf, len)
 unsigned FAR *have;
-unsigned char FAR *buf;
+const unsigned char FAR *buf;
 unsigned len;
 {
     unsigned got;

+ 7 - 7
libs/zlib/src/inftrees.c

@@ -1,5 +1,5 @@
 /* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2012 Mark Adler
+ * Copyright (C) 1995-2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -9,7 +9,7 @@
 #define MAXBITS 15
 
 const char inflate_copyright[] =
-   " inflate 1.2.7 Copyright 1995-2012 Mark Adler ";
+   " inflate 1.2.8 Copyright 1995-2013 Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -62,7 +62,7 @@ unsigned short FAR *work;
         35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
     static const unsigned short lext[31] = { /* Length codes 257..285 extra */
         16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
-        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 78, 68};
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78};
     static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
         257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
@@ -208,8 +208,8 @@ unsigned short FAR *work;
     mask = used - 1;            /* mask for comparing low */
 
     /* check available table space */
-    if ((type == LENS && used >= ENOUGH_LENS) ||
-        (type == DISTS && used >= ENOUGH_DISTS))
+    if ((type == LENS && used > ENOUGH_LENS) ||
+        (type == DISTS && used > ENOUGH_DISTS))
         return 1;
 
     /* process all codes and make table entries */
@@ -277,8 +277,8 @@ unsigned short FAR *work;
 
             /* check for enough space */
             used += 1U << curr;
-            if ((type == LENS && used >= ENOUGH_LENS) ||
-                (type == DISTS && used >= ENOUGH_DISTS))
+            if ((type == LENS && used > ENOUGH_LENS) ||
+                (type == DISTS && used > ENOUGH_DISTS))
                 return 1;
 
             /* point entry in root table to sub-table */

+ 8 - 6
libs/zlib/src/trees.c

@@ -146,8 +146,8 @@ local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
 local int  build_bl_tree  OF((deflate_state *s));
 local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
                               int blcodes));
-local void compress_block OF((deflate_state *s, ct_data *ltree,
-                              ct_data *dtree));
+local void compress_block OF((deflate_state *s, const ct_data *ltree,
+                              const ct_data *dtree));
 local int  detect_data_type OF((deflate_state *s));
 local unsigned bi_reverse OF((unsigned value, int length));
 local void bi_windup      OF((deflate_state *s));
@@ -972,7 +972,8 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
     } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
 #endif
         send_bits(s, (STATIC_TREES<<1)+last, 3);
-        compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+        compress_block(s, (const ct_data *)static_ltree,
+                       (const ct_data *)static_dtree);
 #ifdef DEBUG
         s->compressed_len += 3 + s->static_len;
 #endif
@@ -980,7 +981,8 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
         send_bits(s, (DYN_TREES<<1)+last, 3);
         send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
                        max_blindex+1);
-        compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+        compress_block(s, (const ct_data *)s->dyn_ltree,
+                       (const ct_data *)s->dyn_dtree);
 #ifdef DEBUG
         s->compressed_len += 3 + s->opt_len;
 #endif
@@ -1057,8 +1059,8 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
  */
 local void compress_block(s, ltree, dtree)
     deflate_state *s;
-    ct_data *ltree; /* literal tree */
-    ct_data *dtree; /* distance tree */
+    const ct_data *ltree; /* literal tree */
+    const ct_data *dtree; /* distance tree */
 {
     unsigned dist;      /* distance of matched string */
     int lc;             /* match length or unmatched char (if dist == 0) */

+ 1 - 1
libs/zlib/src/uncompr.c

@@ -30,7 +30,7 @@ int ZEXPORT uncompress (dest, destLen, source, sourceLen)
     z_stream stream;
     int err;
 
-    stream.next_in = (Bytef*)source;
+    stream.next_in = (z_const Bytef *)source;
     stream.avail_in = (uInt)sourceLen;
     /* Check for source > 64K on 16-bit machine: */
     if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;

+ 19 - 14
libs/zlib/src/zconf.h

@@ -1,5 +1,5 @@
 /* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2012 Jean-loup Gailly.
+ * Copyright (C) 1995-2013 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -21,6 +21,7 @@
 #  define _dist_code            z__dist_code
 #  define _length_code          z__length_code
 #  define _tr_align             z__tr_align
+#  define _tr_flush_bits        z__tr_flush_bits
 #  define _tr_flush_block       z__tr_flush_block
 #  define _tr_init              z__tr_init
 #  define _tr_stored_block      z__tr_stored_block
@@ -77,6 +78,7 @@
 #      define gzopen_w              z_gzopen_w
 #    endif
 #    define gzprintf              z_gzprintf
+#    define gzvprintf             z_gzvprintf
 #    define gzputc                z_gzputc
 #    define gzputs                z_gzputs
 #    define gzread                z_gzread
@@ -103,6 +105,7 @@
 #  define inflateReset          z_inflateReset
 #  define inflateReset2         z_inflateReset2
 #  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateGetDictionary  z_inflateGetDictionary
 #  define inflateSync           z_inflateSync
 #  define inflateSyncPoint      z_inflateSyncPoint
 #  define inflateUndermine      z_inflateUndermine
@@ -388,20 +391,14 @@ typedef uLong FAR uLongf;
    typedef Byte       *voidp;
 #endif
 
-/* ./configure may #define Z_U4 here */
-
 #if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
 #  include <limits.h>
 #  if (UINT_MAX == 0xffffffffUL)
 #    define Z_U4 unsigned
-#  else
-#    if (ULONG_MAX == 0xffffffffUL)
-#      define Z_U4 unsigned long
-#    else
-#      if (USHRT_MAX == 0xffffffffUL)
-#        define Z_U4 unsigned short
-#      endif
-#    endif
+#  elif (ULONG_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned long
+#  elif (USHRT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned short
 #  endif
 #endif
 
@@ -425,8 +422,16 @@ typedef uLong FAR uLongf;
 #  endif
 #endif
 
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+#    include <stdarg.h>         /* for va_list */
+#  endif
+#endif
+
 #ifdef _WIN32
-#  include <stddef.h>           /* for wchar_t */
+#  ifndef Z_SOLO
+#    include <stddef.h>         /* for wchar_t */
+#  endif
 #endif
 
 /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
@@ -435,7 +440,7 @@ typedef uLong FAR uLongf;
  * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
  * equivalently requesting no 64-bit operations
  */
-#if defined(LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
 #  undef _LARGEFILE64_SOURCE
 #endif
 
@@ -443,7 +448,7 @@ typedef uLong FAR uLongf;
 #  define Z_HAVE_UNISTD_H
 #endif
 #ifndef Z_SOLO
-#  if defined(Z_HAVE_UNISTD_H) || defined(LARGEFILE64_SOURCE)
+#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
 #    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
 #    ifdef VMS
 #      include <unixio.h>       /* for off_t */

+ 36 - 12
libs/zlib/src/zlib.h

@@ -1,7 +1,7 @@
 /* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 1.2.7, May 2nd, 2012
+  version 1.2.8, April 28th, 2013
 
-  Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler
+  Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -37,11 +37,11 @@
 extern "C" {
 #endif
 
-#define ZLIB_VERSION "1.2.7"
-#define ZLIB_VERNUM 0x1270
+#define ZLIB_VERSION "1.2.8"
+#define ZLIB_VERNUM 0x1280
 #define ZLIB_VER_MAJOR 1
 #define ZLIB_VER_MINOR 2
-#define ZLIB_VER_REVISION 7
+#define ZLIB_VER_REVISION 8
 #define ZLIB_VER_SUBREVISION 0
 
 /*
@@ -839,6 +839,21 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
    inflate().
 */
 
+ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
+                                             Bytef *dictionary,
+                                             uInt  *dictLength));
+/*
+     Returns the sliding dictionary being maintained by inflate.  dictLength is
+   set to the number of bytes in the dictionary, and that many bytes are copied
+   to dictionary.  dictionary must have enough space, where 32768 bytes is
+   always enough.  If inflateGetDictionary() is called with dictionary equal to
+   Z_NULL, then only the dictionary length is returned, and nothing is copied.
+   Similary, if dictLength is Z_NULL, then it is not set.
+
+     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+   stream state is inconsistent.
+*/
+
 ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
 /*
      Skips invalid compressed data until a possible full flush point (see above
@@ -846,7 +861,7 @@ ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
    available input is skipped.  No output is provided.
 
      inflateSync searches for a 00 00 FF FF pattern in the compressed data.
-   All full flush points have this pattern, but not all occurences of this
+   All full flush points have this pattern, but not all occurrences of this
    pattern are full flush points.
 
      inflateSync returns Z_OK if a possible full flush point has been found,
@@ -1007,7 +1022,8 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
    the version of the header file.
 */
 
-typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef unsigned (*in_func) OF((void FAR *,
+                                z_const unsigned char FAR * FAR *));
 typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
 
 ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
@@ -1015,11 +1031,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
                                     out_func out, void FAR *out_desc));
 /*
      inflateBack() does a raw inflate with a single call using a call-back
-   interface for input and output.  This is more efficient than inflate() for
-   file i/o applications in that it avoids copying between the output and the
-   sliding window by simply making the window itself the output buffer.  This
-   function trusts the application to not change the output buffer passed by
-   the output function, at least until inflateBack() returns.
+   interface for input and output.  This is potentially more efficient than
+   inflate() for file i/o applications, in that it avoids copying between the
+   output and the sliding window by simply making the window itself the output
+   buffer.  inflate() can be faster on modern CPUs when used with large
+   buffers.  inflateBack() trusts the application to not change the output
+   buffer passed by the output function, at least until inflateBack() returns.
 
      inflateBackInit() must be called first to allocate the internal state
    and to initialize the state with the user-provided window buffer.
@@ -1736,6 +1753,13 @@ ZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));
 ZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,
                                             const char *mode));
 #endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+ZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,
+                                                  const char *format,
+                                                  va_list va));
+#  endif
+#endif
 
 #ifdef __cplusplus
 }

+ 1 - 1
libs/zlib/src/zutil.c

@@ -14,7 +14,7 @@
 struct internal_state      {int dummy;}; /* for buggy compilers */
 #endif
 
-const char * const z_errmsg[10] = {
+z_const char * const z_errmsg[10] = {
 "need dictionary",     /* Z_NEED_DICT       2  */
 "stream end",          /* Z_STREAM_END      1  */
 "",                    /* Z_OK              0  */

+ 5 - 4
libs/zlib/src/zutil.h

@@ -1,5 +1,5 @@
 /* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2012 Jean-loup Gailly.
+ * Copyright (C) 1995-2013 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -44,13 +44,13 @@ typedef unsigned short ush;
 typedef ush FAR ushf;
 typedef unsigned long  ulg;
 
-extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 /* (size given to avoid silly warnings with Visual C++) */
 
 #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
 
 #define ERR_RETURN(strm,err) \
-  return (strm->msg = (char*)ERR_MSG(err), (err))
+  return (strm->msg = ERR_MSG(err), (err))
 /* To be used only when the state is known to be valid */
 
         /* common constants */
@@ -168,7 +168,8 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 #endif
 
 /* provide prototypes for these when building zlib without LFS */
-#if !defined(_WIN32) && (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
+#if !defined(_WIN32) && \
+    (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
 #endif

+ 2 - 1
source/Console.cbproj

@@ -41,9 +41,10 @@
 			<PackageImports>rtl.bpi;$(PackageImports)</PackageImports>
 			<ProjectType>CppConsoleApplication</ProjectType>
 			<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
-			<VerInfo_Keys>CompanyName=Martin Prikryl;FileDescription=Console interface for WinSCP;FileVersion=4.0.0.0;InternalName=console;LegalCopyright=(c) 2000-2013 Martin Prikryl;LegalTrademarks=;OriginalFilename=winscp.com;ProductName=WinSCP;ProductVersion=5.2.1.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.2.0;ReleaseType=beta;WWW=http://winscp.net/</VerInfo_Keys>
 			<VerInfo_Locale>1033</VerInfo_Locale>
 			<VerInfo_MajorVer>4</VerInfo_MajorVer>
+			<VerInfo_Release>1</VerInfo_Release>
 		</PropertyGroup>
 		<PropertyGroup Condition="'$(Cfg_1)'!=''">
 			<BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>

+ 1 - 1
source/DragExt.cbproj

@@ -42,7 +42,7 @@
 			<ProjectType>CppDynamicLibrary</ProjectType>
 			<VerInfo_DLL>true</VerInfo_DLL>
 			<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.1.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.2.0;ReleaseType=beta;WWW=http://winscp.net/</VerInfo_Keys>
 			<VerInfo_Locale>1033</VerInfo_Locale>
 			<VerInfo_MinorVer>2</VerInfo_MinorVer>
 			<VerInfo_Release>1</VerInfo_Release>

+ 2 - 2
source/DragExt64.rc

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

+ 0 - 3
source/Moje.cbproj

@@ -112,9 +112,6 @@
 			<DelphiCompile Include="packages\my\IEListView.pas">
 				<BuildOrder>10</BuildOrder>
 			</DelphiCompile>
-			<DelphiCompile Include="packages\my\LanguagesDEPfix.pas">
-				<BuildOrder>11</BuildOrder>
-			</DelphiCompile>
 			<DelphiCompile Include="packages\my\ListViewColProperties.pas">
 				<BuildOrder>12</BuildOrder>
 			</DelphiCompile>

+ 7 - 16
source/ScpForms.cbproj

@@ -193,14 +193,6 @@
 				<BuildOrder>32</BuildOrder>
 			</CppCompile>
 			<FormResources Include="forms\FullSynchronize.dfm"/>
-			<CppCompile Include="forms\GeneralSettings.cpp">
-				<BuildOrder>62</BuildOrder>
-				<Form>GeneralSettingsFrame</Form>
-				<DesignClass>TFrame</DesignClass>
-				<DependentOn>forms\GeneralSettings.h</DependentOn>
-				<BuildOrder>19</BuildOrder>
-			</CppCompile>
-			<FormResources Include="forms\GeneralSettings.dfm"/>
 			<CppCompile Include="forms\ImportSessions.cpp">
 				<BuildOrder>68</BuildOrder>
 				<Form>ImportSessionsDialog</Form>
@@ -240,14 +232,6 @@
 				<BuildOrder>1</BuildOrder>
 			</CppCompile>
 			<FormResources Include="forms\Login.dfm"/>
-			<CppCompile Include="forms\LogSettings.cpp">
-				<BuildOrder>83</BuildOrder>
-				<Form>LoggingFrame</Form>
-				<DesignClass>TFrame</DesignClass>
-				<DependentOn>forms\LogSettings.h</DependentOn>
-				<BuildOrder>0</BuildOrder>
-			</CppCompile>
-			<FormResources Include="forms\LogSettings.dfm"/>
 			<CppCompile Include="forms\MessageDlg.cpp">
 				<BuildOrder>8</BuildOrder>
 				<BuildOrder>25</BuildOrder>
@@ -310,6 +294,13 @@
 				<BuildOrder>107</BuildOrder>
 			</CppCompile>
 			<FormResources Include="forms\SelectMask.dfm"/>
+			<CppCompile Include="forms\SiteAdvanced.cpp">
+				<BuildOrder>80</BuildOrder>
+				<Form>SiteAdvancedDialog</Form>
+				<DependentOn>forms\SiteAdvanced.h</DependentOn>
+				<BuildOrder>1</BuildOrder>
+			</CppCompile>
+			<FormResources Include="forms\SiteAdvanced.dfm"/>
 			<CppCompile Include="forms\Symlink.cpp">
 				<BuildOrder>110</BuildOrder>
 				<Form>SymlinkDialog</Form>

+ 3 - 3
source/WinSCP.cbproj

@@ -51,11 +51,11 @@
 			<ProjectType>CppVCLApplication</ProjectType>
 			<UsingDelphiRTL>true</UsingDelphiRTL>
 			<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
-			<VerInfo_Keys>CompanyName=Martin Prikryl;FileDescription=WinSCP: SFTP, FTP and SCP client;FileVersion=5.2.1.0;InternalName=winscp;LegalCopyright=(c) 2000-2013 Martin Prikryl;LegalTrademarks=;OriginalFilename=winscp.exe;ProductName=WinSCP;ProductVersion=5.2.1.0;ReleaseType=beta;WWW=http://winscp.net/</VerInfo_Keys>
+			<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_Locale>1033</VerInfo_Locale>
 			<VerInfo_MajorVer>5</VerInfo_MajorVer>
 			<VerInfo_MinorVer>2</VerInfo_MinorVer>
-			<VerInfo_Release>1</VerInfo_Release>
+			<VerInfo_Release>2</VerInfo_Release>
 		</PropertyGroup>
 		<PropertyGroup Condition="'$(Cfg_1)'!=''">
 			<BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>
@@ -82,7 +82,7 @@
 			<BCC_MonitorInlinePtrAccess>true</BCC_MonitorInlinePtrAccess>
 			<BCC_MonitorThis>true</BCC_MonitorThis>
 			<DCC_DebugDCUs>true</DCC_DebugDCUs>
-			<Debugger_DebugSourcePath>packages\my; packages\filemng;$(Debugger_DebugSourcePath)</Debugger_DebugSourcePath>
+			<Debugger_DebugSourcePath>packages\my; packages\filemng;..\libs\openssl\crypto\bio;..\libs\openssl\ssl;..\libs\openssl\crypto\stack;$(Debugger_DebugSourcePath)</Debugger_DebugSourcePath>
 		</PropertyGroup>
 		<PropertyGroup Condition="'$(Cfg_2)'!=''">
 			<Defines>NDEBUG;$(Defines)</Defines>

+ 2 - 2
source/components/LogMemo.cpp

@@ -5,6 +5,7 @@
 #include <Common.h>
 
 #include "LogMemo.h"
+#include <StrUtils.hpp>
 
 #pragma package(smart_init)
 //---------------------------------------------------------------------------
@@ -179,8 +180,7 @@ void __fastcall TLogMemo::UpdateFromLog()
               {
                 if (SessionLog->Line[LastIndex].Pos(L"\r"))
                 {
-                  Lines->Add(StringReplace(SessionLog->Line[LastIndex], L"\r", L"",
-                    TReplaceFlags() << rfReplaceAll));
+                  Lines->Add(ReplaceStr(SessionLog->Line[LastIndex], L"\r", L""));
                 }
                 else
                 {

+ 4 - 11
source/components/UnixDirView.cpp

@@ -318,9 +318,9 @@ bool __fastcall TUnixDirView::ItemMatchesFilter(TListItem * Item,
     ((!(int)Filter.ModificationFrom) || (File->Modification >= Filter.ModificationFrom)) &&
     ((!(int)Filter.ModificationTo) || (File->Modification <= Filter.ModificationTo)) &&
     ((Filter.Masks.IsEmpty()) ||
-     FileNameMatchesMasks(File->FileName, File->IsDirectory, File->Size, File->Modification, Filter.Masks) ||
+     FileNameMatchesMasks(File->FileName, File->IsDirectory, File->Size, File->Modification, Filter.Masks, false) ||
      (File->IsDirectory && Filter.Directories &&
-      FileNameMatchesMasks(File->FileName, false, File->Size, File->Modification, Filter.Masks)));
+      FileNameMatchesMasks(File->FileName, false, File->Size, File->Modification, Filter.Masks, false)));
 #else
   USEDPARAM(Item);
   USEDPARAM(Filter);
@@ -374,8 +374,8 @@ void __fastcall TUnixDirView::LoadFiles()
         FHiddenCount++;
       }
       else if (!Mask.IsEmpty() &&
-               !File->IsDirectory &&
-               !FileNameMatchesMasks(File->FileName, false, File->Size, File->Modification, Mask))
+               !File->IsParentDirectory && !File->IsThisDirectory &&
+               !FileNameMatchesMasks(File->FileName, File->IsDirectory, File->Size, File->Modification, Mask, true))
       {
         FFilteredCount++;
       }
@@ -871,13 +871,6 @@ void __fastcall TUnixDirView::CreateDirectoryEx(UnicodeString DirName, const TRe
 #endif
 }
 //---------------------------------------------------------------------------
-UnicodeString __fastcall TUnixDirView::MinimizePath(UnicodeString Path, int Length)
-{
-  return StringReplace(MinimizeName(
-    StringReplace(Path, L'/', L'\\', TReplaceFlags() << rfReplaceAll),
-      Canvas, Length), L'\\', L'/', TReplaceFlags() << rfReplaceAll);
-}
-//---------------------------------------------------------------------------
 bool __fastcall TUnixDirView::GetIsRoot()
 {
 #ifndef DESIGN_ONLY

+ 0 - 1
source/components/UnixDirView.h

@@ -64,7 +64,6 @@ protected:
   virtual bool __fastcall ItemMatchesFilter(TListItem * Item, const TFileFilter &Filter);
   virtual Word __fastcall ItemOverlayIndexes(TListItem * Item);
   virtual void __fastcall LoadFiles();
-  virtual UnicodeString __fastcall MinimizePath(UnicodeString Path, int Length);
   virtual void __fastcall PerformItemDragDropOperation(TListItem * Item, int Effect);
   virtual void __fastcall SetAddParentDir(bool Value);
   virtual void __fastcall SetItemImageIndex(TListItem * Item, int Index);

+ 19 - 15
source/console/Main.cpp

@@ -622,22 +622,26 @@ void ProcessChoiceEvent(TConsoleCommStruct::TChoiceEvent& Event)
             else if ((Record.EventType == KEY_EVENT) &&
                      Record.Event.KeyEvent.bKeyDown)
             {
-              wchar_t CStr[2];
-              CStr[0] = Record.Event.KeyEvent.uChar.AsciiChar;
-              CStr[1] = L'\0';
-              CharUpperBuff(CStr, 1);
-              wchar_t C = CStr[0];
-              if (C == 27)
+              // This happens when Shift key is pressed
+              if (Record.Event.KeyEvent.uChar.AsciiChar != 0)
               {
-                Event.Result = Event.Cancel;
-              }
-              else if ((wcschr(Event.Options, C) != NULL) &&
-                       ((Record.Event.KeyEvent.dwControlKeyState &
-                         (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED | LEFT_ALT_PRESSED |
-                         RIGHT_ALT_PRESSED)) == 0))
-
-              {
-                Event.Result = wcschr(Event.Options, C) - Event.Options + 1;
+                wchar_t CStr[2];
+                CStr[0] = Record.Event.KeyEvent.uChar.AsciiChar;
+                CStr[1] = L'\0';
+                CharUpperBuff(CStr, 1);
+                wchar_t C = CStr[0];
+                if (C == 27)
+                {
+                  Event.Result = Event.Cancel;
+                }
+                else if ((wcschr(Event.Options, C) != NULL) &&
+                         ((Record.Event.KeyEvent.dwControlKeyState &
+                           (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED | LEFT_ALT_PRESSED |
+                           RIGHT_ALT_PRESSED)) == 0))
+
+                {
+                  Event.Result = wcschr(Event.Options, C) - Event.Options + 1;
+                }
               }
             }
           }

+ 16 - 3
source/core/Common.cpp

@@ -270,7 +270,7 @@ UnicodeString ExceptionLogString(Exception *E)
       if (MoreMessages)
       {
         Msg += L"\n" +
-          StringReplace(MoreMessages->Text, L"\r", L"", TReplaceFlags() << rfReplaceAll);
+          ReplaceStr(MoreMessages->Text, L"\r", L"");
       }
     }
     return Msg;
@@ -740,6 +740,19 @@ unsigned char __fastcall HexToByte(const UnicodeString Hex)
     static_cast<unsigned char>(((P1 <= 0) || (P2 <= 0)) ? 0 : (((P1 - 1) << 4) + (P2 - 1)));
 }
 //---------------------------------------------------------------------------
+bool __fastcall IsDigit(wchar_t Ch)
+{
+  return (Ch >= '0') && (Ch <= '9');
+}
+//---------------------------------------------------------------------------
+bool __fastcall IsHex(wchar_t Ch)
+{
+  return
+    IsDigit(Ch) ||
+    ((Ch >= 'A') && (Ch <= 'F')) ||
+    ((Ch >= 'a') && (Ch <= 'f'));
+}
+//---------------------------------------------------------------------------
 int __fastcall FindCheck(int Result)
 {
   if ((Result != ERROR_SUCCESS) &&
@@ -1077,7 +1090,7 @@ bool __fastcall TryRelativeStrToDateTime(UnicodeString S, TDateTime & DateTime)
 {
   S = S.Trim();
   int Index = 1;
-  while ((Index <= S.Length()) && (S[Index] >= '0') && (S[Index] <= '9'))
+  while ((Index <= S.Length()) && IsDigit(S[Index]))
   {
     Index++;
   }
@@ -1678,7 +1691,7 @@ UnicodeString __fastcall EncodeUrlString(UnicodeString S)
 //---------------------------------------------------------------------------
 UnicodeString __fastcall EscapeHotkey(const UnicodeString & Caption)
 {
-  return StringReplace(Caption, L"&", L"&&", TReplaceFlags() << rfReplaceAll);
+  return ReplaceStr(Caption, L"&", L"&&");
 }
 //---------------------------------------------------------------------------
 // duplicated in console's Main.cpp

+ 2 - 0
source/core/Common.h

@@ -72,6 +72,8 @@ UnicodeString __fastcall BytesToHex(RawByteString Str, bool UpperCase = true, wc
 UnicodeString __fastcall CharToHex(wchar_t Ch, bool UpperCase = true);
 RawByteString __fastcall HexToBytes(const UnicodeString Hex);
 unsigned char __fastcall HexToByte(const UnicodeString Hex);
+bool __fastcall IsDigit(wchar_t Ch);
+bool __fastcall IsHex(wchar_t Ch);
 UnicodeString __fastcall DecodeUrlChars(UnicodeString S);
 UnicodeString __fastcall EncodeUrlChars(UnicodeString S, UnicodeString Ignore = L"");
 UnicodeString __fastcall EncodeUrlString(UnicodeString S);

+ 1 - 1
source/core/Configuration.cpp

@@ -69,7 +69,7 @@ void __fastcall TConfiguration::Default()
   }
 
   RandomSeedFile = FDefaultRandomSeedFile;
-  PuttyRegistryStorageKey = L"Software\\SimonTatham\\PuTTY";
+  PuttyRegistryStorageKey = OriginalPuttyRegistryStorageKey;
   FConfirmOverwriting = true;
   FConfirmResume = true;
   FAutoReadDirectoryAfterOp = true;

+ 5 - 0
source/core/Configuration.h

@@ -258,4 +258,9 @@ private:
   std::set<TShortCut> FShortCuts;
 };
 //---------------------------------------------------------------------------
+extern const UnicodeString OriginalPuttyRegistryStorageKey;
+extern const UnicodeString KittyRegistryStorageKey;
+extern const UnicodeString OriginalPuttyExecutable;
+extern const UnicodeString KittyExecutable;
+//---------------------------------------------------------------------------
 #endif

+ 10 - 0
source/core/CoreMain.cpp

@@ -39,6 +39,16 @@ TQueryParams::TQueryParams(unsigned int AParams, UnicodeString AHelpKeyword)
   HelpKeyword = AHelpKeyword;
 }
 //---------------------------------------------------------------------------
+TQueryParams::TQueryParams(const TQueryParams & Source)
+{
+  Assign(Source);
+}
+//---------------------------------------------------------------------------
+void TQueryParams::Assign(const TQueryParams & Source)
+{
+  *this = Source;
+}
+//---------------------------------------------------------------------------
 bool __fastcall IsAuthenticationPrompt(TPromptKind Kind)
 {
   return

+ 1 - 1
source/core/Cryptography.cpp

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

+ 161 - 29
source/core/Exceptions.cpp

@@ -5,37 +5,106 @@
 #include "Common.h"
 #include "Exceptions.h"
 #include "TextsCore.h"
+#include "HelpCore.h"
 #include "Configuration.h"
 #include "CoreMain.h"
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
 //---------------------------------------------------------------------------
-bool __fastcall ExceptionMessage(Exception * E, UnicodeString & Message)
+static bool __fastcall WellKnownException(
+  Exception * E, UnicodeString * AMessage, const wchar_t ** ACounterName, Exception ** AClone, bool Rethrow)
 {
+  UnicodeString Message;
+  const wchar_t * CounterName;
+  std::auto_ptr<Exception> Clone;
+
   bool Result = true;
-  if (Configuration->Usage != NULL)
+
+  // EAccessViolation is EExternal
+  if (dynamic_cast<EAccessViolation*>(E) != NULL)
   {
-    if (dynamic_cast<EAccessViolation*>(E) != NULL)
+    if (Rethrow)
     {
-      Configuration->Usage->Inc(L"AccessViolations");
+      throw EAccessViolation(E->Message);
     }
-    else if (dynamic_cast<EExternal*>(E) != NULL)
+    Message = LoadStr(ACCESS_VIOLATION_ERROR3);
+    CounterName = L"AccessViolations";
+    Clone.reset(new EAccessViolation(E->Message));
+  }
+  // EIntError and EMathError are EExternal
+  else if ((dynamic_cast<EListError*>(E) != NULL) ||
+           (dynamic_cast<EStringListError*>(E) != NULL) ||
+           (dynamic_cast<EIntError*>(E) != NULL) ||
+           (dynamic_cast<EMathError*>(E) != NULL) ||
+           (dynamic_cast<EVariantError*>(E) != NULL))
+  {
+    if (Rethrow)
     {
-      Configuration->Usage->Inc(L"ExternalExceptions");
+      throw EIntError(E->Message);
     }
-    else if (dynamic_cast<EHeapException*>(E) != NULL)
+    Message = E->Message;
+    CounterName = L"InternalExceptions";
+    Clone.reset(new EIntError(E->Message));
+  }
+  else if (dynamic_cast<EExternal*>(E) != NULL)
+  {
+    if (Rethrow)
     {
-      Configuration->Usage->Inc(L"HeapExceptions");
+      throw EExternal(E->Message);
     }
+    Message = E->Message;
+    CounterName = L"ExternalExceptions";
+    Clone.reset(new EExternal(E->Message));
+  }
+  else if (dynamic_cast<EHeapException*>(E) != NULL)
+  {
+    if (Rethrow)
+    {
+      throw EHeapException(E->Message);
+    }
+    Message = E->Message;
+    CounterName = L"HeapExceptions";
+    Clone.reset(new EHeapException(E->Message));
+  }
+  else
+  {
+    Result = false;
   }
 
+  if (Result)
+  {
+    if (AMessage != NULL)
+    {
+      (*AMessage) = Message;
+    }
+    if (ACounterName != NULL)
+    {
+      (*ACounterName) = CounterName;
+    }
+    if (AClone != NULL)
+    {
+      (*AClone) = NOT_NULL(Clone.release());
+    }
+  }
+
+  return Result;
+}
+//---------------------------------------------------------------------------
+static bool __fastcall ExceptionMessage(Exception * E, bool Count,
+  UnicodeString & Message, bool & InternalError)
+{
+  bool Result = true;
+  const wchar_t * CounterName = NULL;
+  InternalError = false;
+
+  // this list has to be in sync with CloneException
   if (dynamic_cast<EAbort *>(E) != NULL)
   {
     Result = false;
   }
-  else if (dynamic_cast<EAccessViolation*>(E) != NULL)
+  else if (WellKnownException(E, &Message, &CounterName, NULL, false))
   {
-    Message = LoadStr(ACCESS_VIOLATION_ERROR2);
+    InternalError = true;
   }
   else if (E->Message.IsEmpty())
   {
@@ -45,10 +114,27 @@ bool __fastcall ExceptionMessage(Exception * E, UnicodeString & Message)
   {
     Message = E->Message;
   }
+
+  if (InternalError)
+  {
+    Message = FMTLOAD(REPORT_ERROR, (Message));
+  }
+
+  if (Count && (CounterName != NULL) && (Configuration->Usage != NULL))
+  {
+    Configuration->Usage->Inc(CounterName);
+  }
+
   return Result;
 }
 //---------------------------------------------------------------------------
-TStrings * ExceptionToMoreMessages(Exception * E)
+bool __fastcall ExceptionMessage(Exception * E, UnicodeString & Message)
+{
+  bool InternalError;
+  return ExceptionMessage(E, true, Message, InternalError);
+}
+//---------------------------------------------------------------------------
+TStrings * __fastcall ExceptionToMoreMessages(Exception * E)
 {
   TStrings * Result = NULL;
   UnicodeString Message;
@@ -57,7 +143,7 @@ TStrings * ExceptionToMoreMessages(Exception * E)
     Result = new TStringList();
     Result->Add(Message);
     ExtException * ExtE = dynamic_cast<ExtException *>(E);
-    if (ExtE != NULL)
+    if ((ExtE != NULL) && (ExtE->MoreMessages != NULL))
     {
       Result->AddStrings(ExtE->MoreMessages);
     }
@@ -65,19 +151,60 @@ TStrings * ExceptionToMoreMessages(Exception * E)
   return Result;
 }
 //---------------------------------------------------------------------------
+UnicodeString __fastcall GetExceptionHelpKeyword(Exception * E)
+{
+  UnicodeString HelpKeyword;
+  ExtException * ExtE = dynamic_cast<ExtException *>(E);
+  UnicodeString Message; // not used
+  bool InternalError = false;
+  if (ExtE != NULL)
+  {
+    HelpKeyword = ExtE->HelpKeyword;
+  }
+  else if ((E != NULL) && ExceptionMessage(E, false, Message, InternalError) &&
+           InternalError)
+  {
+    HelpKeyword = HELP_INTERNAL_ERROR;
+  }
+  return HelpKeyword;
+}
+//---------------------------------------------------------------------------
+UnicodeString __fastcall MergeHelpKeyword(const UnicodeString & PrimaryHelpKeyword, const UnicodeString & SecondaryHelpKeyword)
+{
+  if (!PrimaryHelpKeyword.IsEmpty() &&
+      !IsInternalErrorHelpKeyword(SecondaryHelpKeyword))
+  {
+    // we have to yet decide what we have both
+    // PrimaryHelpKeyword and SecondaryHelpKeyword
+    return PrimaryHelpKeyword;
+  }
+  else
+  {
+    return SecondaryHelpKeyword;
+  }
+}
+//---------------------------------------------------------------------------
+bool __fastcall IsInternalErrorHelpKeyword(const UnicodeString & HelpKeyword)
+{
+  return
+    (HelpKeyword == HELP_INTERNAL_ERROR);
+}
+//---------------------------------------------------------------------------
 __fastcall ExtException::ExtException(Exception * E) :
   Exception("")
 {
   AddMoreMessages(E);
+  FHelpKeyword = GetExceptionHelpKeyword(E);
 }
 //---------------------------------------------------------------------------
-__fastcall ExtException::ExtException(Exception* E, UnicodeString Msg):
+__fastcall ExtException::ExtException(Exception* E, UnicodeString Msg, UnicodeString HelpKeyword):
   Exception(Msg)
 {
   AddMoreMessages(E);
+  FHelpKeyword = MergeHelpKeyword(HelpKeyword, GetExceptionHelpKeyword(E));
 }
 //---------------------------------------------------------------------------
-__fastcall ExtException::ExtException(UnicodeString Msg, Exception* E) :
+__fastcall ExtException::ExtException(UnicodeString Msg, Exception* E, UnicodeString HelpKeyword) :
   Exception("")
 {
   // "copy exception"
@@ -98,6 +225,7 @@ __fastcall ExtException::ExtException(UnicodeString Msg, Exception* E) :
       FMoreMessages->Append(Msg);
     }
   }
+  FHelpKeyword = MergeHelpKeyword(GetExceptionHelpKeyword(E), HelpKeyword);
 }
 //---------------------------------------------------------------------------
 __fastcall ExtException::ExtException(UnicodeString Msg, UnicodeString MoreMessages,
@@ -140,14 +268,6 @@ void __fastcall ExtException::AddMoreMessages(Exception* E)
     ExtException * ExtE = dynamic_cast<ExtException *>(E);
     if (ExtE != NULL)
     {
-      if (!ExtE->HelpKeyword.IsEmpty())
-      {
-        // we have to yet decide what to do now
-        assert(HelpKeyword.IsEmpty());
-
-        FHelpKeyword = ExtE->HelpKeyword;
-      }
-
       if (ExtE->MoreMessages != NULL)
       {
         FMoreMessages->Assign(ExtE->MoreMessages);
@@ -202,8 +322,8 @@ __fastcall EOSExtException::EOSExtException(UnicodeString Msg) :
 {
 }
 //---------------------------------------------------------------------------
-__fastcall EFatal::EFatal(Exception* E, UnicodeString Msg) :
-  ExtException(Msg, E),
+__fastcall EFatal::EFatal(Exception* E, UnicodeString Msg, UnicodeString HelpKeyword) :
+  ExtException(Msg, E, HelpKeyword),
   FReopenQueried(false)
 {
   EFatal * F = dynamic_cast<EFatal *>(E);
@@ -229,28 +349,36 @@ __fastcall ECallbackGuardAbort::ECallbackGuardAbort() : EAbort(L"callback abort"
 //---------------------------------------------------------------------------
 Exception * __fastcall CloneException(Exception * E)
 {
+  Exception * Result;
+  // this list has to be in sync with ExceptionMessage
   ExtException * Ext = dynamic_cast<ExtException *>(E);
   if (Ext != NULL)
   {
-    return Ext->Clone();
+    Result = Ext->Clone();
   }
   else if (dynamic_cast<ECallbackGuardAbort *>(E) != NULL)
   {
-    return new ECallbackGuardAbort();
+    Result = new ECallbackGuardAbort();
   }
   else if (dynamic_cast<EAbort *>(E) != NULL)
   {
-    return new EAbort(E->Message);
+    Result = new EAbort(E->Message);
+  }
+  else if (WellKnownException(E, NULL, NULL, &Result, false))
+  {
+    // noop
   }
   else
   {
-    return new Exception(E->Message);
+    Result = new Exception(E->Message);
   }
+  return Result;
 }
 //---------------------------------------------------------------------------
 void __fastcall RethrowException(Exception * E)
 {
-  if (dynamic_cast<EFatal *>(E) != NULL)
+   // this list has to be in sync with ExceptionMessage
+ if (dynamic_cast<EFatal *>(E) != NULL)
   {
     throw EFatal(E, L"");
   }
@@ -262,6 +390,10 @@ void __fastcall RethrowException(Exception * E)
   {
     throw EAbort(E->Message);
   }
+  else if (WellKnownException(E, NULL, NULL, NULL, true))
+  {
+    // noop, should never get here
+  }
   else
   {
     throw ExtException(E, L"");

+ 9 - 6
source/core/Exceptions.h

@@ -9,7 +9,7 @@
 //---------------------------------------------------------------------------
 bool __fastcall ExceptionMessage(Exception * E, UnicodeString & Message);
 UnicodeString __fastcall LastSysErrorMessage();
-TStrings * ExceptionToMoreMessages(Exception * E);
+TStrings * __fastcall ExceptionToMoreMessages(Exception * E);
 //---------------------------------------------------------------------------
 enum TOnceDoneOperation { odoIdle, odoDisconnect, odoShutDown };
 //---------------------------------------------------------------------------
@@ -17,9 +17,9 @@ class ExtException : public Sysutils::Exception
 {
 public:
   __fastcall ExtException(Exception* E);
-  __fastcall ExtException(Exception* E, UnicodeString Msg);
+  __fastcall ExtException(Exception* E, UnicodeString Msg, UnicodeString HelpKeyword = L"");
   // "copy the exception", just append message to the end
-  __fastcall ExtException(UnicodeString Msg, Exception* E);
+  __fastcall ExtException(UnicodeString Msg, Exception* E, UnicodeString HelpKeyword = L"");
   __fastcall ExtException(UnicodeString Msg, UnicodeString MoreMessages, UnicodeString HelpKeyword = "");
   __fastcall ExtException(UnicodeString Msg, TStrings* MoreMessages, bool Own, UnicodeString HelpKeyword = "");
   __fastcall virtual ~ExtException(void);
@@ -47,7 +47,7 @@ private:
   class NAME : public BASE \
   { \
   public: \
-    inline __fastcall NAME(Exception* E, UnicodeString Msg) : BASE(E, Msg) { } \
+    inline __fastcall NAME(Exception* E, UnicodeString Msg, UnicodeString HelpKeyword = L"") : BASE(E, Msg, HelpKeyword) { } \
     inline __fastcall NAME(Exception* E, int Ident) : BASE(E, Ident) { } \
     inline __fastcall virtual ~NAME(void) { } \
     inline __fastcall NAME(const UnicodeString Msg, const TVarRec * Args, const int Args_Size) : BASE(Msg, Args, Args_Size) { } \
@@ -77,7 +77,7 @@ class EFatal : public ExtException
 {
 public:
   // fatal errors are always copied, new message is only appended
-  __fastcall EFatal(Exception* E, UnicodeString Msg);
+  __fastcall EFatal(Exception* E, UnicodeString Msg, UnicodeString HelpKeyword = "");
 
   __property bool ReopenQueried = { read = FReopenQueried, write = FReopenQueried };
 
@@ -91,7 +91,7 @@ private:
   class NAME : public BASE \
   { \
   public: \
-    inline __fastcall NAME(Exception* E, UnicodeString Msg) : BASE(E, Msg) { } \
+    inline __fastcall NAME(Exception* E, UnicodeString Msg, UnicodeString HelpKeyword = "") : BASE(E, Msg, HelpKeyword) { } \
     virtual ExtException * __fastcall Clone() { return new NAME(this, L""); } \
   };
 //---------------------------------------------------------------------------
@@ -120,5 +120,8 @@ public:
 //---------------------------------------------------------------------------
 Exception * __fastcall CloneException(Exception * Exception);
 void __fastcall RethrowException(Exception * E);
+UnicodeString __fastcall GetExceptionHelpKeyword(Exception * E);
+UnicodeString __fastcall MergeHelpKeyword(const UnicodeString & PrimaryHelpKeyword, const UnicodeString & SecondaryHelpKeyword);
+bool __fastcall IsInternalErrorHelpKeyword(const UnicodeString & HelpKeyword);
 //---------------------------------------------------------------------------
 #endif  // Exceptions

+ 82 - 31
source/core/FileMasks.cpp

@@ -9,6 +9,7 @@
 #include "RemoteFiles.h"
 #include "PuttyTools.h"
 #include "Terminal.h"
+#include <StrUtils.hpp>
 //---------------------------------------------------------------------------
 extern const wchar_t IncludeExcludeFileMasksDelimiter = L'|';
 static UnicodeString FileMasksDelimiters = L";,";
@@ -791,35 +792,30 @@ void __fastcall TCustomCommand::GetToken(
   if (Ptr[0] == L'!')
   {
     PatternCmd = Ptr[1];
-    if (PatternCmd == L'!')
+    if (PatternCmd == L'\0')
+    {
+      Len = 1;
+    }
+    else if (PatternCmd == L'!')
     {
       Len = 2;
     }
     else
     {
-      Len = PatternLen(Index, PatternCmd);
+      Len = PatternLen(Command, Index);
     }
 
-    if (Len < 0)
+    if (Len <= 0)
     {
       throw Exception(FMTLOAD(CUSTOM_COMMAND_UNKNOWN, (PatternCmd, Index)));
     }
-    else if (Len > 0)
+    else
     {
       if ((Command.Length() - Index + 1) < Len)
       {
         throw Exception(FMTLOAD(CUSTOM_COMMAND_UNTERMINATED, (PatternCmd, Index)));
       }
     }
-    else if (Len == 0)
-    {
-      const wchar_t * PatternEnd = wcschr(Ptr + 1, L'!');
-      if (PatternEnd == NULL)
-      {
-        throw Exception(FMTLOAD(CUSTOM_COMMAND_UNTERMINATED, (PatternCmd, Index)));
-      }
-      Len = PatternEnd - Ptr + 1;
-    }
   }
   else
   {
@@ -876,12 +872,11 @@ UnicodeString __fastcall TCustomCommand::Complete(const UnicodeString & Command,
       UnicodeString Pattern = Command.SubString(Index, Len);
       UnicodeString Replacement;
       bool Delimit = true;
-      if (PatternReplacement(Index, Pattern, Replacement, Delimit))
+      if (PatternReplacement(Pattern, Replacement, Delimit))
       {
         if (!LastPass)
         {
-          Replacement = StringReplace(Replacement, L"!", L"!!",
-            TReplaceFlags() << rfReplaceAll);
+          Replacement = ReplaceStr(Replacement, L"!", L"!!");
         }
         if (Delimit)
         {
@@ -962,29 +957,55 @@ TInteractiveCustomCommand::TInteractiveCustomCommand(
   FChildCustomCommand = ChildCustomCommand;
 }
 //---------------------------------------------------------------------------
-void __fastcall TInteractiveCustomCommand::Prompt(int /*Index*/,
+void __fastcall TInteractiveCustomCommand::Prompt(
   const UnicodeString & /*Prompt*/, UnicodeString & Value)
 {
   Value = L"";
 }
 //---------------------------------------------------------------------------
-int __fastcall TInteractiveCustomCommand::PatternLen(int Index, wchar_t PatternCmd)
+void __fastcall TInteractiveCustomCommand::Execute(
+  const UnicodeString & /*Command*/, UnicodeString & Value)
+{
+  Value = L"";
+}
+//---------------------------------------------------------------------------
+int __fastcall TInteractiveCustomCommand::PatternLen(const UnicodeString & Command, int Index)
 {
   int Len;
-  switch (PatternCmd)
+  switch (Command[Index + 1])
   {
     case L'?':
-      Len = 0;
+      {
+        const wchar_t * Ptr = Command.c_str() + Index - 1;
+        const wchar_t * PatternEnd = wcschr(Ptr + 1, L'!');
+        if (PatternEnd == NULL)
+        {
+          throw Exception(FMTLOAD(CUSTOM_COMMAND_UNTERMINATED, (Command[Index + 1], Index)));
+        }
+        Len = PatternEnd - Ptr + 1;
+      }
+      break;
+
+    case L'`':
+      {
+        const wchar_t * Ptr = Command.c_str() + Index - 1;
+        const wchar_t * PatternEnd = wcschr(Ptr + 2, L'`');
+        if (PatternEnd == NULL)
+        {
+          throw Exception(FMTLOAD(CUSTOM_COMMAND_UNTERMINATED, (Command[Index + 1], Index)));
+        }
+        Len = PatternEnd - Ptr + 1;
+      }
       break;
 
     default:
-      Len = FChildCustomCommand->PatternLen(Index, PatternCmd);
+      Len = FChildCustomCommand->PatternLen(Command, Index);
       break;
   }
   return Len;
 }
 //---------------------------------------------------------------------------
-bool __fastcall TInteractiveCustomCommand::PatternReplacement(int Index, const UnicodeString & Pattern,
+bool __fastcall TInteractiveCustomCommand::PatternReplacement(const UnicodeString & Pattern,
   UnicodeString & Replacement, bool & Delimit)
 {
   bool Result;
@@ -1007,10 +1028,18 @@ bool __fastcall TInteractiveCustomCommand::PatternReplacement(int Index, const U
       PromptStr = Pattern.SubString(3, Pattern.Length() - 3);
     }
 
-    Prompt(Index, PromptStr, Replacement);
+    Prompt(PromptStr, Replacement);
 
     Result = true;
   }
+  else if ((Pattern.Length() >= 3) && (Pattern[2] == L'`'))
+  {
+    UnicodeString Command = Pattern.SubString(3, Pattern.Length() - 3);
+    Command = FChildCustomCommand->Complete(Command, true);
+    Execute(Command, Replacement);
+    Delimit = false;
+    Result = true;
+  }
   else
   {
     Result = false;
@@ -1026,9 +1055,21 @@ __fastcall TCustomCommandData::TCustomCommandData()
 //---------------------------------------------------------------------------
 __fastcall TCustomCommandData::TCustomCommandData(TTerminal * Terminal)
 {
-  HostName = Terminal->SessionData->HostNameExpanded;
-  UserName = Terminal->SessionData->UserNameExpanded;
-  Password = Terminal->Password;
+  Init(Terminal->SessionData, Terminal->Password);
+}
+//---------------------------------------------------------------------------
+__fastcall TCustomCommandData::TCustomCommandData(
+  TSessionData * SessionData, const UnicodeString & Password)
+{
+  Init(SessionData, Password);
+}
+//---------------------------------------------------------------------------
+void __fastcall TCustomCommandData::Init(
+  TSessionData * SessionData, const UnicodeString & APassword)
+{
+  HostName = SessionData->HostNameExpanded;
+  UserName = SessionData->UserNameExpanded;
+  Password = APassword;
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
@@ -1054,10 +1095,10 @@ TFileCustomCommand::TFileCustomCommand(const TCustomCommandData & Data,
   FFileList = FileList;
 }
 //---------------------------------------------------------------------------
-int __fastcall TFileCustomCommand::PatternLen(int /*Index*/, wchar_t PatternCmd)
+int __fastcall TFileCustomCommand::PatternLen(const UnicodeString & Command, int Index)
 {
   int Len;
-  switch (toupper(PatternCmd))
+  switch (toupper(Command[Index + 1]))
   {
     case L'@':
     case L'U':
@@ -1074,7 +1115,7 @@ int __fastcall TFileCustomCommand::PatternLen(int /*Index*/, wchar_t PatternCmd)
   return Len;
 }
 //---------------------------------------------------------------------------
-bool __fastcall TFileCustomCommand::PatternReplacement(int /*Index*/,
+bool __fastcall TFileCustomCommand::PatternReplacement(
   const UnicodeString & Pattern, UnicodeString & Replacement, bool & Delimit)
 {
   // keep consistent with TSessionLog::OpenLogFile
@@ -1121,7 +1162,7 @@ void __fastcall TFileCustomCommand::Validate(const UnicodeString & Command)
   }
 }
 //---------------------------------------------------------------------------
-void __fastcall TFileCustomCommand::ValidatePattern(const UnicodeString & /*Command*/,
+void __fastcall TFileCustomCommand::ValidatePattern(const UnicodeString & Command,
   int Index, int /*Len*/, wchar_t PatternCmd, void * Arg)
 {
   int * Found = static_cast<int *>(Arg);
@@ -1132,7 +1173,7 @@ void __fastcall TFileCustomCommand::ValidatePattern(const UnicodeString & /*Comm
   {
     Found[0] = Index;
   }
-  else if ((PatternCmd != TEXT_TOKEN) && (PatternLen(Index, PatternCmd) == 1))
+  else if ((PatternCmd != TEXT_TOKEN) && (PatternLen(Command, Index) == 1))
   {
     Found[1] = Index;
   }
@@ -1148,3 +1189,13 @@ bool __fastcall TFileCustomCommand::IsFileCommand(const UnicodeString & Command)
   return FindPattern(Command, L'!') || FindPattern(Command, L'&');
 }
 //---------------------------------------------------------------------------
+bool __fastcall TFileCustomCommand::IsSiteCommand(const UnicodeString & Command)
+{
+  return FindPattern(Command, L'@');
+}
+//---------------------------------------------------------------------------
+bool __fastcall TFileCustomCommand::IsPasswordCommand(const UnicodeString & Command)
+{
+  return FindPattern(Command, L'p');
+}
+//---------------------------------------------------------------------------

+ 16 - 7
source/core/FileMasks.h

@@ -149,8 +149,8 @@ protected:
   virtual void __fastcall ValidatePattern(const UnicodeString & Command,
     int Index, int Len, wchar_t PatternCmd, void * Arg);
 
-  virtual int __fastcall PatternLen(int Index, wchar_t PatternCmd) = 0;
-  virtual bool __fastcall PatternReplacement(int Index, const UnicodeString & Pattern,
+  virtual int __fastcall PatternLen(const UnicodeString & Command, int Index) = 0;
+  virtual bool __fastcall PatternReplacement(const UnicodeString & Pattern,
     UnicodeString & Replacement, bool & Delimit) = 0;
   virtual void __fastcall DelimitReplacement(UnicodeString & Replacement, wchar_t Quote);
 };
@@ -161,10 +161,12 @@ public:
   TInteractiveCustomCommand(TCustomCommand * ChildCustomCommand);
 
 protected:
-  virtual void __fastcall Prompt(int Index, const UnicodeString & Prompt,
+  virtual void __fastcall Prompt(const UnicodeString & Prompt,
     UnicodeString & Value);
-  virtual int __fastcall PatternLen(int Index, wchar_t PatternCmd);
-  virtual bool __fastcall PatternReplacement(int Index, const UnicodeString & Pattern,
+  virtual void __fastcall Execute(const UnicodeString & Command,
+    UnicodeString & Value);
+  virtual int __fastcall PatternLen(const UnicodeString & Command, int Index);
+  virtual bool __fastcall PatternReplacement(const UnicodeString & Pattern,
     UnicodeString & Replacement, bool & Delimit);
 
 private:
@@ -172,14 +174,19 @@ private:
 };
 //---------------------------------------------------------------------------
 class TTerminal;
+class TSessionData;
 struct TCustomCommandData
 {
   __fastcall TCustomCommandData();
   __fastcall TCustomCommandData(TTerminal * Terminal);
+  __fastcall TCustomCommandData(TSessionData * SessionData, const UnicodeString & Password);
 
   UnicodeString HostName;
   UnicodeString UserName;
   UnicodeString Password;
+
+private:
+  void __fastcall Init(TSessionData * SessionData, const UnicodeString & Password);
 };
 //---------------------------------------------------------------------------
 class TFileCustomCommand : public TCustomCommand
@@ -196,10 +203,12 @@ public:
 
   bool __fastcall IsFileListCommand(const UnicodeString & Command);
   virtual bool __fastcall IsFileCommand(const UnicodeString & Command);
+  bool __fastcall IsSiteCommand(const UnicodeString & Command);
+  bool __fastcall IsPasswordCommand(const UnicodeString & Command);
 
 protected:
-  virtual int __fastcall PatternLen(int Index, wchar_t PatternCmd);
-  virtual bool __fastcall PatternReplacement(int Index, const UnicodeString & Pattern,
+  virtual int __fastcall PatternLen(const UnicodeString & Command, int Index);
+  virtual bool __fastcall PatternReplacement(const UnicodeString & Pattern,
     UnicodeString & Replacement, bool & Delimit);
 
 private:

+ 5 - 6
source/core/FtpFileSystem.cpp

@@ -23,7 +23,7 @@
 #pragma package(smart_init)
 //---------------------------------------------------------------------------
 #define FILE_OPERATION_LOOP_EX(ALLOW_SKIP, MESSAGE, OPERATION) \
-  FILE_OPERATION_LOOP_CUSTOM(FTerminal, ALLOW_SKIP, MESSAGE, OPERATION)
+  FILE_OPERATION_LOOP_CUSTOM(FTerminal, ALLOW_SKIP, MESSAGE, OPERATION, L"")
 //---------------------------------------------------------------------------
 const int DummyCodeClass = 8;
 const int DummyTimeoutCode = 801;
@@ -1813,7 +1813,7 @@ void __fastcall TFTPFileSystem::ReadCurrentDirectory()
 //---------------------------------------------------------------------------
 void __fastcall TFTPFileSystem::DoReadDirectory(TRemoteFileList * FileList)
 {
-  FileList->Clear();
+  FileList->Reset();
   // FZAPI does not list parent directory, add it
   FileList->AddFile(new TRemoteParentDirectory(FTerminal));
 
@@ -1836,8 +1836,7 @@ void __fastcall TFTPFileSystem::ReadDirectory(TRemoteFileList * FileList)
 {
   // whole below "-a" logic is for LIST,
   // if we know we are going to use MLSD, skip it
-  if (FTerminal->SessionData->FtpUseMlsd &&
-      (FServerCapabilities->GetCapability(mlsd_command) == yes))
+  if (FFileZillaIntf->UsingMlsd())
   {
     DoReadDirectory(FileList);
   }
@@ -2758,7 +2757,7 @@ void __fastcall TFTPFileSystem::HandleReplyStatus(UnicodeString Response)
     else if (FLastCommand == SYST)
     {
       assert(FSystem.IsEmpty());
-      // Possitive reply to "SYST" must be 215, see RFC 959
+      // Positive reply to "SYST" must be 215, see RFC 959
       if (FLastCode == 215)
       {
         FSystem = FLastResponse->Text.TrimRight();
@@ -3446,7 +3445,7 @@ bool __fastcall TFTPFileSystem::HandleListData(const wchar_t * Path,
              int(Entry->Dir), int(Entry->Link), Entry->Time.Year, Entry->Time.Month, Entry->Time.Day,
              Entry->Time.Hour, Entry->Time.Minute, int(Entry->Time.HasTime),
              int(Entry->Time.HasSeconds), int(Entry->Time.HasDate)));
-        throw ETerminal(&E, FMTLOAD(LIST_LINE_ERROR, (EntryData)));
+        throw ETerminal(&E, FMTLOAD(LIST_LINE_ERROR, (EntryData)), HELP_LIST_LINE_ERROR);
       }
 
       FFileList->AddFile(File);

+ 3 - 2
source/core/HierarchicalStorage.cpp

@@ -7,6 +7,7 @@
 #include "PuttyIntf.h"
 #include "HierarchicalStorage.h"
 #include <TextsCore.h>
+#include <StrUtils.hpp>
 #include <vector>
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
@@ -72,7 +73,7 @@ UnicodeString __fastcall MungeIniName(const UnicodeString Str)
   // make this fast for now
   if (P > 0)
   {
-    return StringReplace(Str, L"=", L"%3D", TReplaceFlags() << rfReplaceAll);
+    return ReplaceStr(Str, L"=", L"%3D");
   }
   else
   {
@@ -86,7 +87,7 @@ UnicodeString __fastcall UnMungeIniName(const UnicodeString Str)
   // make this fast for now
   if (P > 0)
   {
-    return StringReplace(Str, L"%3D", L"=", TReplaceFlags() << rfReplaceAll);
+    return ReplaceStr(Str, L"%3D", L"=");
   }
   else
   {

+ 21 - 11
source/core/Interface.h

@@ -19,18 +19,25 @@ int __fastcall StartThread(void * SecurityAttributes, unsigned StackSize,
   TThreadFunc ThreadFunc, void * Parameter, unsigned CreationFlags,
   TThreadID & ThreadId);
 
+// Order of the values also define order of the buttons/answers on the prompts
+// MessageDlg relies on these to be <= 0x0000FFFF
 const unsigned int qaYes =      0x00000001;
-const unsigned int qaNo =       0x00000002;
-const unsigned int qaOK =       0x00000004;
-const unsigned int qaCancel =   0x00000008;
-const unsigned int qaAbort =    0x00000010;
-const unsigned int qaRetry =    0x00000020;
-const unsigned int qaIgnore =   0x00000040;
-const unsigned int qaAll =      0x00000080;
-const unsigned int qaNoToAll =  0x00000100;
-const unsigned int qaYesToAll = 0x00000200;
-const unsigned int qaHelp =     0x00000400;
-const unsigned int qaSkip =     0x00000800;
+// MessageDlg relies that answer do not conflict with mrCancel (=0x2)
+const unsigned int qaNo =       0x00000004;
+const unsigned int qaOK =       0x00000008;
+const unsigned int qaCancel =   0x00000010;
+const unsigned int qaYesToAll = 0x00000020;
+const unsigned int qaNoToAll =  0x00000040;
+const unsigned int qaAbort =    0x00000080;
+const unsigned int qaRetry =    0x00000100;
+const unsigned int qaIgnore =   0x00000200;
+const unsigned int qaSkip =     0x00000400;
+const unsigned int qaAll =      0x00000800;
+const unsigned int qaHelp =     0x00001000;
+const unsigned int qaReport =   0x00002000;
+
+const unsigned int qaFirst = qaYes;
+const unsigned int qaLast = qaReport;
 
 const unsigned int qaNeverAskAgain = 0x00010000;
 
@@ -55,6 +62,9 @@ typedef void __fastcall (__closure *TQueryParamsTimerEvent)(unsigned int & Resul
 struct TQueryParams
 {
   TQueryParams(unsigned int AParams = 0, UnicodeString AHelpKeyword = HELP_NONE);
+  TQueryParams(const TQueryParams & Source);
+
+  void Assign(const TQueryParams & Source);
 
   const TQueryButtonAlias * Aliases;
   unsigned int AliasesCount;

+ 11 - 2
source/core/PuttyIntf.cpp

@@ -17,6 +17,15 @@ bool SaveRandomSeed;
 char appname_[50];
 const char *const appname = appname_;
 //---------------------------------------------------------------------------
+extern "C"
+{
+#include <winstuff.h>
+}
+const UnicodeString OriginalPuttyRegistryStorageKey(_T(PUTTY_REG_POS));
+const UnicodeString KittyRegistryStorageKey(L"Software\\9bis.com\\KiTTY");
+const UnicodeString OriginalPuttyExecutable("putty.exe");
+const UnicodeString KittyExecutable("kitty.exe");
+//---------------------------------------------------------------------------
 void __fastcall PuttyInitialize()
 {
   SaveRandomSeed = true;
@@ -345,8 +354,8 @@ static long OpenWinSCPKey(HKEY Key, const char * SubKey, HKEY * Result, bool Can
   USEDPARAM(Key);
 
   UnicodeString RegKey = SubKey;
-  int PuttyKeyLen = Configuration->PuttyRegistryStorageKey.Length();
-  assert(RegKey.SubString(1, PuttyKeyLen) == Configuration->PuttyRegistryStorageKey);
+  int PuttyKeyLen = OriginalPuttyRegistryStorageKey.Length();
+  assert(RegKey.SubString(1, PuttyKeyLen) == OriginalPuttyRegistryStorageKey);
   RegKey = RegKey.SubString(PuttyKeyLen + 1, RegKey.Length() - PuttyKeyLen);
   if (!RegKey.IsEmpty())
   {

+ 25 - 14
source/core/RemoteFiles.cpp

@@ -2,15 +2,17 @@
 #include <vcl.h>
 #pragma hdrstop
 
+#include "Common.h"
 #include "RemoteFiles.h"
 
 #include <SysUtils.hpp>
+#include <StrUtils.hpp>
 
-#include "Common.h"
 #include "Exceptions.h"
 #include "Interface.h"
 #include "Terminal.h"
 #include "TextsCore.h"
+#include "HelpCore.h"
 /* TODO 1 : Path class instead of UnicodeString (handle relativity...) */
 //---------------------------------------------------------------------------
 UnicodeString __fastcall UnixIncludeTrailingBackslash(const UnicodeString Path)
@@ -200,12 +202,12 @@ UnicodeString __fastcall AbsolutePath(const UnicodeString & Base, const UnicodeS
 //---------------------------------------------------------------------------
 UnicodeString __fastcall FromUnixPath(const UnicodeString Path)
 {
-  return StringReplace(Path, L"/", L"\\", TReplaceFlags() << rfReplaceAll);
+  return ReplaceStr(Path, L"/", L"\\");
 }
 //---------------------------------------------------------------------------
 UnicodeString __fastcall ToUnixPath(const UnicodeString Path)
 {
-  return StringReplace(Path, L"\\", L"/", TReplaceFlags() << rfReplaceAll);
+  return ReplaceStr(Path, L"\\", L"/");
 }
 //---------------------------------------------------------------------------
 static void __fastcall CutFirstDirectory(UnicodeString & S, bool Unix)
@@ -1210,7 +1212,7 @@ void __fastcall TRemoteFile::SetListingStr(UnicodeString value)
   }
   catch (Exception &E)
   {
-    throw ETerminal(&E, FmtLoadStr(LIST_LINE_ERROR, ARRAYOFCONST((value))));
+    throw ETerminal(&E, FmtLoadStr(LIST_LINE_ERROR, ARRAYOFCONST((value))), HELP_LIST_LINE_ERROR);
   }
 }
 //---------------------------------------------------------------------------
@@ -1371,7 +1373,7 @@ void __fastcall TRemoteFileList::AddFile(TRemoteFile * File)
 //---------------------------------------------------------------------------
 void __fastcall TRemoteFileList::DuplicateTo(TRemoteFileList * Copy)
 {
-  Copy->Clear();
+  Copy->Reset();
   for (int Index = 0; Index < Count; Index++)
   {
     TRemoteFile * File = Files[Index];
@@ -1381,10 +1383,10 @@ void __fastcall TRemoteFileList::DuplicateTo(TRemoteFileList * Copy)
   Copy->FTimestamp = FTimestamp;
 }
 //---------------------------------------------------------------------------
-void __fastcall TRemoteFileList::Clear()
+void __fastcall TRemoteFileList::Reset()
 {
   FTimestamp = Now();
-  TObjectList::Clear();
+  Clear();
 }
 //---------------------------------------------------------------------------
 void __fastcall TRemoteFileList::SetDirectory(UnicodeString value)
@@ -1445,26 +1447,34 @@ __fastcall TRemoteDirectory::TRemoteDirectory(TTerminal * aTerminal, TRemoteDire
   }
 }
 //---------------------------------------------------------------------------
-void __fastcall TRemoteDirectory::Clear()
+__fastcall TRemoteDirectory::~TRemoteDirectory()
 {
-  if (ThisDirectory && !IncludeThisDirectory)
+  ReleaseRelativeDirectories();
+}
+//---------------------------------------------------------------------------
+void __fastcall TRemoteDirectory::ReleaseRelativeDirectories()
+{
+  if ((ThisDirectory != NULL) && !IncludeThisDirectory)
   {
     delete FThisDirectory;
     FThisDirectory = NULL;
   }
-  if (ParentDirectory && !IncludeParentDirectory)
+  if ((ParentDirectory != NULL) && !IncludeParentDirectory)
   {
     delete FParentDirectory;
     FParentDirectory = NULL;
   }
-
-  TRemoteFileList::Clear();
+}
+//---------------------------------------------------------------------------
+void __fastcall TRemoteDirectory::Reset()
+{
+  ReleaseRelativeDirectories();
+  TRemoteFileList::Reset();
 }
 //---------------------------------------------------------------------------
 void __fastcall TRemoteDirectory::SetDirectory(UnicodeString value)
 {
   TRemoteFileList::SetDirectory(value);
-  //Load();
 }
 //---------------------------------------------------------------------------
 void __fastcall TRemoteDirectory::AddFile(TRemoteFile * File)
@@ -1682,7 +1692,7 @@ void __fastcall TRemoteDirectoryCache::DoClearFileList(UnicodeString Directory,
 //---------------------------------------------------------------------------
 void __fastcall TRemoteDirectoryCache::Delete(int Index)
 {
-  delete (TRemoteFileList *)Objects[Index];
+  delete dynamic_cast<TRemoteFileList *>(Objects[Index]);
   TStringList::Delete(Index);
 }
 //---------------------------------------------------------------------------
@@ -1894,6 +1904,7 @@ __fastcall TRights::TRights(const TRights & Source)
   Assign(&Source);
 }
 //---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
 void __fastcall TRights::Assign(const TRights * Source)
 {
   FAllowUndef = Source->AllowUndef;

+ 4 - 5
source/core/RemoteFiles.h

@@ -203,10 +203,9 @@ protected:
   TRemoteFile * __fastcall GetParentDirectory();
   UnicodeString __fastcall GetParentPath();
   __int64 __fastcall GetTotalSize();
-
-  virtual void __fastcall Clear();
 public:
   __fastcall TRemoteFileList();
+  virtual void __fastcall Reset();
   TRemoteFile * __fastcall FindFile(const UnicodeString &FileName);
   virtual void __fastcall DuplicateTo(TRemoteFileList * Copy);
   virtual void __fastcall AddFile(TRemoteFile * File);
@@ -235,12 +234,13 @@ private:
   Boolean __fastcall GetLoaded();
   void __fastcall SetIncludeParentDirectory(Boolean value);
   void __fastcall SetIncludeThisDirectory(Boolean value);
-protected:
-  virtual void __fastcall Clear();
+  void __fastcall ReleaseRelativeDirectories();
 public:
   __fastcall TRemoteDirectory(TTerminal * aTerminal, TRemoteDirectory * Template = NULL);
+  virtual __fastcall ~TRemoteDirectory();
   virtual void __fastcall AddFile(TRemoteFile * File);
   virtual void __fastcall DuplicateTo(TRemoteFileList * Copy);
+  virtual void __fastcall Reset();
   __property TTerminal * Terminal = { read = FTerminal, write = FTerminal };
   __property TStrings * SelectedFiles  = { read=GetSelectedFiles };
   __property Boolean IncludeParentDirectory = { read = FIncludeParentDirectory, write = SetIncludeParentDirectory };
@@ -334,7 +334,6 @@ public:
   __fastcall TRights();
   __fastcall TRights(const TRights & Source);
   __fastcall TRights(unsigned short Number);
-
   void __fastcall Assign(const TRights * Source);
   void __fastcall AddExecute();
   void __fastcall AllUndef();

+ 7 - 4
source/core/ScpFileSystem.cpp

@@ -9,6 +9,7 @@
 #include "Exceptions.h"
 #include "Interface.h"
 #include "TextsCore.h"
+#include "HelpCore.h"
 #include "SecureShell.h"
 
 #include <stdio.h>
@@ -16,7 +17,7 @@
 #pragma package(smart_init)
 //---------------------------------------------------------------------------
 #define FILE_OPERATION_LOOP_EX(ALLOW_SKIP, MESSAGE, OPERATION) \
-  FILE_OPERATION_LOOP_CUSTOM(FTerminal, ALLOW_SKIP, MESSAGE, OPERATION)
+  FILE_OPERATION_LOOP_CUSTOM(FTerminal, ALLOW_SKIP, MESSAGE, OPERATION, L"")
 //---------------------------------------------------------------------------
 const int coRaiseExcept = 1;
 const int coExpectNoOutput = 2;
@@ -710,7 +711,7 @@ void __fastcall TSCPFileSystem::SkipStartupMessage()
   }
   catch (Exception & E)
   {
-    FTerminal->CommandError(&E, LoadStr(SKIP_STARTUP_MESSAGE_ERROR));
+    FTerminal->CommandError(&E, LoadStr(SKIP_STARTUP_MESSAGE_ERROR), 0, HELP_SKIP_STARTUP_MESSAGE_ERROR);
   }
 }
 //---------------------------------------------------------------------------
@@ -890,7 +891,7 @@ void __fastcall TSCPFileSystem::ReadDirectory(TRemoteFileList * FileList)
 {
   assert(FileList);
   // emptying file list moved before command execution
-  FileList->Clear();
+  FileList->Reset();
 
   bool Again;
 
@@ -977,7 +978,9 @@ void __fastcall TSCPFileSystem::ReadDirectory(TRemoteFileList * FileList)
 
         if (Empty)
         {
-          throw Exception(FMTLOAD(EMPTY_DIRECTORY, (FileList->Directory)));
+          throw ExtException(
+            NULL, FMTLOAD(EMPTY_DIRECTORY, (FileList->Directory)),
+            HELP_EMPTY_DIRECTORY);
         }
       }
 

+ 9 - 9
source/core/Script.cpp

@@ -357,17 +357,17 @@ void __fastcall TScript::Init()
   FCommands->Register(L"ln", SCRIPT_LN_DESC, SCRIPT_LN_HELP, &LnProc, 2, 2, false);
   FCommands->Register(L"symlink", 0, SCRIPT_LN_HELP, &LnProc, 2, 2, false);
   FCommands->Register(L"mkdir", SCRIPT_MKDIR_DESC, SCRIPT_MKDIR_HELP, &MkDirProc, 1, 1, false);
-  FCommands->Register(L"get", SCRIPT_GET_DESC, SCRIPT_GET_HELP5, &GetProc, 1, -1, true);
-  FCommands->Register(L"recv", 0, SCRIPT_GET_HELP5, &GetProc, 1, -1, false);
-  FCommands->Register(L"mget", 0, SCRIPT_GET_HELP5, &GetProc, 1, -1, false);
-  FCommands->Register(L"put", SCRIPT_PUT_DESC, SCRIPT_PUT_HELP5, &PutProc, 1, -1, true);
-  FCommands->Register(L"send", 0, SCRIPT_PUT_HELP5, &PutProc, 1, -1, false);
-  FCommands->Register(L"mput", 0, SCRIPT_PUT_HELP5, &PutProc, 1, -1, false);
+  FCommands->Register(L"get", SCRIPT_GET_DESC, SCRIPT_GET_HELP6, &GetProc, 1, -1, true);
+  FCommands->Register(L"recv", 0, SCRIPT_GET_HELP6, &GetProc, 1, -1, false);
+  FCommands->Register(L"mget", 0, SCRIPT_GET_HELP6, &GetProc, 1, -1, false);
+  FCommands->Register(L"put", SCRIPT_PUT_DESC, SCRIPT_PUT_HELP6, &PutProc, 1, -1, true);
+  FCommands->Register(L"send", 0, SCRIPT_PUT_HELP6, &PutProc, 1, -1, false);
+  FCommands->Register(L"mput", 0, SCRIPT_PUT_HELP6, &PutProc, 1, -1, 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"binary", 0, SCRIPT_OPTION_HELP6, &BinaryProc, 0, 0, false);
-  FCommands->Register(L"synchronize", SCRIPT_SYNCHRONIZE_DESC, SCRIPT_SYNCHRONIZE_HELP5, &SynchronizeProc, 1, 3, true);
-  FCommands->Register(L"keepuptodate", SCRIPT_KEEPUPTODATE_DESC, SCRIPT_KEEPUPTODATE_HELP3, &KeepUpToDateProc, 0, 2, true);
+  FCommands->Register(L"synchronize", SCRIPT_SYNCHRONIZE_DESC, SCRIPT_SYNCHRONIZE_HELP6, &SynchronizeProc, 1, 3, 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
   FCommands->Register(L"echo", SCRIPT_ECHO_DESC, SCRIPT_ECHO_HELP, &EchoProc, -1, -1, true);
   FCommands->Register(L"stat", SCRIPT_STAT_DESC, SCRIPT_STAT_HELP, &StatProc, 1, 1, false);
@@ -1783,7 +1783,7 @@ void __fastcall TManagementScript::TerminalOperationProgress(
       time_t Time = time(NULL);
 
       if ((OnProgress != NULL) && WantsProgress &&
-          (DoPrint || (FLastProgressEventTime != Time)))
+          (DoPrint || (FLastProgressEventTime != Time) || ProgressData.IsTransferDone()))
       {
         FLastProgressEventTime = Time;
 

+ 79 - 18
source/core/SecureShell.cpp

@@ -23,6 +23,7 @@ struct TPuttyTranslation
 {
   const wchar_t * Original;
   int Translation;
+  UnicodeString HelpKeyword;
 };
 //---------------------------------------------------------------------------
 char * __fastcall AnsiStrNew(const wchar_t * S)
@@ -61,6 +62,7 @@ __fastcall TSecureShell::TSecureShell(TSessionUI* UI,
   FFrozen = false;
   FSimple = false;
   FCollectPrivateKeyUsage = false;
+  FWaitingForData = 0;
 }
 //---------------------------------------------------------------------------
 __fastcall TSecureShell::~TSecureShell()
@@ -1100,7 +1102,8 @@ void __fastcall TSecureShell::SendLine(UnicodeString Line)
 }
 //---------------------------------------------------------------------------
 int __fastcall TSecureShell::TranslatePuttyMessage(
-  const TPuttyTranslation * Translation, size_t Count, UnicodeString & Message)
+  const TPuttyTranslation * Translation, size_t Count, UnicodeString & Message,
+  UnicodeString * HelpKeyword)
 {
   int Result = -1;
   for (unsigned int Index = 0; Index < Count; Index++)
@@ -1132,10 +1135,17 @@ int __fastcall TSecureShell::TranslatePuttyMessage(
       }
     }
   }
+
+  if ((HelpKeyword != NULL) && (Result >= 0))
+  {
+    *HelpKeyword = Translation[Result].HelpKeyword;
+  }
+
   return Result;
 }
 //---------------------------------------------------------------------------
-int __fastcall TSecureShell::TranslateAuthenticationMessage(UnicodeString & Message)
+int __fastcall TSecureShell::TranslateAuthenticationMessage(
+  UnicodeString & Message, UnicodeString * HelpKeyword)
 {
   static const TPuttyTranslation Translation[] = {
     { L"Using username \"%\".", AUTH_TRANSL_USERNAME },
@@ -1151,7 +1161,7 @@ int __fastcall TSecureShell::TranslateAuthenticationMessage(UnicodeString & Mess
     { L"Server refused our key", AUTH_TRANSL_KEY_REFUSED }
   };
 
-  int Result = TranslatePuttyMessage(Translation, LENOF(Translation), Message);
+  int Result = TranslatePuttyMessage(Translation, LENOF(Translation), Message, HelpKeyword);
 
   if (FCollectPrivateKeyUsage &&
       ((Result == 2) || (Result == 3) || (Result == 4)))
@@ -1223,16 +1233,21 @@ void __fastcall TSecureShell::CaptureOutput(TLogLineType Type,
   FLog->Add(Type, Line);
 }
 //---------------------------------------------------------------------------
-int __fastcall TSecureShell::TranslateErrorMessage(UnicodeString & Message)
+int __fastcall TSecureShell::TranslateErrorMessage(
+  UnicodeString & Message, UnicodeString * HelpKeyword)
 {
   static const TPuttyTranslation Translation[] = {
-    { L"Server unexpectedly closed network connection", UNEXPECTED_CLOSE_ERROR },
-    { L"Network error: Connection refused", NET_TRANSL_REFUSED },
-    { L"Network error: Connection reset by peer", NET_TRANSL_RESET },
-    { L"Network error: Connection timed out", NET_TRANSL_TIMEOUT },
+    { L"Server unexpectedly closed network connection", UNEXPECTED_CLOSE_ERROR, HELP_UNEXPECTED_CLOSE_ERROR },
+    { L"Network error: Connection refused", NET_TRANSL_REFUSED, HELP_NET_TRANSL_REFUSED },
+    { L"Network error: Connection reset by peer", NET_TRANSL_RESET, HELP_NET_TRANSL_RESET },
+    { L"Network error: Connection timed out", NET_TRANSL_TIMEOUT, HELP_NET_TRANSL_TIMEOUT },
+    { L"Network error: No route to host", NET_TRANSL_NO_ROUTE, HELP_NET_TRANSL_NO_ROUTE },
+    { L"Network error: Software caused connection abort", NET_TRANSL_CONN_ABORTED, HELP_NET_TRANSL_CONN_ABORTED },
+    { L"Host does not exist", NET_TRANSL_HOST_NOT_EXIST, HELP_NET_TRANSL_HOST_NOT_EXIST },
+    { L"Incoming packet was garbled on decryption", NET_TRANSL_PACKET_GARBLED, HELP_NET_TRANSL_PACKET_GARBLED },
   };
 
-  int Index = TranslatePuttyMessage(Translation, LENOF(Translation), Message);
+  int Index = TranslatePuttyMessage(Translation, LENOF(Translation), Message, HelpKeyword);
 
   if ((Index == 0) || (Index == 1) || (Index == 2) || (Index == 3))
   {
@@ -1244,14 +1259,15 @@ int __fastcall TSecureShell::TranslateErrorMessage(UnicodeString & Message)
 //---------------------------------------------------------------------------
 void __fastcall TSecureShell::PuttyFatalError(UnicodeString Error)
 {
-  TranslateErrorMessage(Error);
+  UnicodeString HelpKeyword;
+  TranslateErrorMessage(Error, &HelpKeyword);
 
-  FatalError(Error);
+  FatalError(Error, HelpKeyword);
 }
 //---------------------------------------------------------------------------
-void __fastcall TSecureShell::FatalError(UnicodeString Error)
+void __fastcall TSecureShell::FatalError(UnicodeString Error, UnicodeString HelpKeyword)
 {
-  FUI->FatalError(NULL, Error);
+  FUI->FatalError(NULL, Error, HelpKeyword);
 }
 //---------------------------------------------------------------------------
 void __fastcall inline TSecureShell::LogEvent(const UnicodeString & Str)
@@ -1406,13 +1422,25 @@ void inline __fastcall TSecureShell::CheckConnection(int Message)
 {
   if (!FActive || get_ssh_state_closed(FBackendHandle))
   {
-    UnicodeString Str = LoadStr(Message >= 0 ? Message : NOT_CONNECTED);
+    UnicodeString Str;
+    UnicodeString HelpKeyword;
+
+    if (Message >= 0)
+    {
+      Str = LoadStr(Message);
+    }
+    else
+    {
+      Str = LoadStr(NOT_CONNECTED);
+      HelpKeyword = HELP_NOT_CONNECTED;
+    }
+
     int ExitCode = get_ssh_exitcode(FBackendHandle);
     if (ExitCode >= 0)
     {
       Str += L" " + FMTLOAD(SSH_EXITCODE, (ExitCode));
     }
-    FatalError(Str);
+    FatalError(Str, HelpKeyword);
   }
 }
 //---------------------------------------------------------------------------
@@ -1488,6 +1516,9 @@ void __fastcall TSecureShell::WaitForData()
     IncomingData = EventSelectLoop(FSessionData->Timeout * MSecsPerSec, true, NULL);
     if (!IncomingData)
     {
+      assert(FWaitingForData == 0);
+      TAutoNestingCounter NestingCounter(FWaitingForData);
+
       WSANETWORKEVENTS Events;
       memset(&Events, 0, sizeof(Events));
       TPoolForDataEvent Event(this, Events);
@@ -1722,7 +1753,12 @@ void __fastcall TSecureShell::Idle(unsigned int MSec)
 
   call_ssh_timer(FBackendHandle);
 
-  EventSelectLoop(MSec, false, NULL);
+  // if we are actively waiting for data in WaitForData,
+  // do not read here, otherwise we swallow read event and never wake
+  if (FWaitingForData <= 0)
+  {
+    EventSelectLoop(MSec, false, NULL);
+  }
 }
 //---------------------------------------------------------------------------
 void __fastcall TSecureShell::KeepAlive()
@@ -1827,10 +1863,35 @@ struct TClipboardHandler
   }
 };
 //---------------------------------------------------------------------------
+UnicodeString __fastcall TSecureShell::FormatKeyStr(UnicodeString KeyStr)
+{
+  int Index = 1;
+  int Digits = 0;
+  while (Index <= KeyStr.Length())
+  {
+    if (IsHex(KeyStr[Index]))
+    {
+      Digits++;
+      if (Digits >= 16)
+      {
+        KeyStr.Insert(L" ", Index + 1);
+        Index++;
+        Digits = 0;
+      }
+    }
+    else
+    {
+      Digits = 0;
+    }
+    Index++;
+  }
+  return KeyStr;
+}
+//---------------------------------------------------------------------------
 void __fastcall TSecureShell::VerifyHostKey(UnicodeString Host, int Port,
   const UnicodeString KeyType, UnicodeString KeyStr, const UnicodeString Fingerprint)
 {
-  LogEvent(FORMAT(L"Verifying host key %s %s with fingerprint %s", (KeyType, KeyStr, Fingerprint)));
+  LogEvent(FORMAT(L"Verifying host key %s %s with fingerprint %s", (KeyType, FormatKeyStr(KeyStr), Fingerprint)));
 
   GotHostKey();
 
@@ -1889,7 +1950,7 @@ void __fastcall TSecureShell::VerifyHostKey(UnicodeString Host, int Port,
         }
         else
         {
-          LogEvent(FORMAT(L"Host key does not match cached key %s", (StoredKey)));
+          LogEvent(FORMAT(L"Host key does not match cached key %s", (FormatKeyStr(StoredKey))));
         }
       }
     }

+ 6 - 4
source/core/SecureShell.h

@@ -47,6 +47,7 @@ private:
   bool FSimple;
   bool FNoConnectionResponse;
   bool FCollectPrivateKeyUsage;
+  int FWaitingForData;
 
   unsigned PendLen;
   unsigned PendSize;
@@ -96,13 +97,14 @@ protected:
 
   void __fastcall GotHostKey();
   int __fastcall TranslatePuttyMessage(const TPuttyTranslation * Translation,
-    size_t Count, UnicodeString & Message);
-  int __fastcall TranslateAuthenticationMessage(UnicodeString & Message);
-  int __fastcall TranslateErrorMessage(UnicodeString & Message);
+    size_t Count, UnicodeString & Message, UnicodeString * HelpKeyword = NULL);
+  int __fastcall TranslateAuthenticationMessage(UnicodeString & Message, UnicodeString * HelpKeyword = NULL);
+  int __fastcall TranslateErrorMessage(UnicodeString & Message, UnicodeString * HelpKeyword = NULL);
   void __fastcall AddStdError(UnicodeString Str);
   void __fastcall AddStdErrorLine(const UnicodeString & Str);
   void __fastcall inline LogEvent(const UnicodeString & Str);
-  void __fastcall FatalError(UnicodeString Error);
+  void __fastcall FatalError(UnicodeString Error, UnicodeString HelpKeyword = L"");
+  UnicodeString __fastcall FormatKeyStr(UnicodeString KeyStr);
   static void __fastcall ClearConfig(Config * cfg);
   static void __fastcall StoreToConfig(TSessionData * Data, Config * cfg, bool Simple);
 

+ 40 - 14
source/core/SessionData.cpp

@@ -1661,7 +1661,7 @@ UnicodeString __fastcall TSessionData::GetSshProtStr()
 //---------------------------------------------------------------------
 bool __fastcall TSessionData::GetUsesSsh()
 {
-  return (FSProtocol == fsSCPonly) || (FSProtocol == fsSFTP) || (FSProtocol == fsSFTPonly);
+  return IsSshProtocol(FSProtocol);
 }
 //---------------------------------------------------------------------
 void __fastcall TSessionData::SetCipher(int Index, TCipher value)
@@ -2353,17 +2353,23 @@ UnicodeString __fastcall TSessionData::GetInfoTip()
   }
 }
 //---------------------------------------------------------------------
+UnicodeString __fastcall TSessionData::ExtractLocalName(const UnicodeString & Name)
+{
+  UnicodeString Result = Name;
+  int P = Result.LastDelimiter(L"/");
+  if (P > 0)
+  {
+    Result.Delete(1, P);
+  }
+  return Result;
+}
+//---------------------------------------------------------------------
 UnicodeString __fastcall TSessionData::GetLocalName()
 {
   UnicodeString Result;
   if (HasSessionName())
   {
-    Result = Name;
-    int P = Result.LastDelimiter(L"/");
-    if (P > 0)
-    {
-      Result.Delete(1, P);
-    }
+    Result = ExtractLocalName(Name);
   }
   else
   {
@@ -2372,19 +2378,32 @@ UnicodeString __fastcall TSessionData::GetLocalName()
   return Result;
 }
 //---------------------------------------------------------------------
+UnicodeString __fastcall TSessionData::ExtractFolderName(const UnicodeString & Name)
+{
+  UnicodeString Result;
+  int P = Name.LastDelimiter(L"/");
+  if (P > 0)
+  {
+    Result = Name.SubString(1, P - 1);
+  }
+  return Result;
+}
+//---------------------------------------------------------------------
 UnicodeString __fastcall TSessionData::GetFolderName()
 {
   UnicodeString Result;
   if (HasSessionName() || IsWorkspace)
   {
-    int P = Name.LastDelimiter(L"/");
-    if (P > 0)
-    {
-      Result = Name.SubString(1, P - 1);
-    }
+    Result = ExtractFolderName(Name);
   }
   return Result;
 }
+//---------------------------------------------------------------------
+UnicodeString __fastcall TSessionData::ComposePath(
+  const UnicodeString & Path, const UnicodeString & Name)
+{
+  return UnixIncludeTrailingBackslash(Path) + Name;
+}
 //=== TStoredSessionList ----------------------------------------------
 __fastcall TStoredSessionList::TStoredSessionList(bool aReadOnly):
   TNamedObjectList(), FReadOnly(aReadOnly)
@@ -2751,7 +2770,7 @@ void __fastcall TStoredSessionList::UpdateStaticUsage()
     {
       Workspaces = true;
     }
-    else if (Data->Name.Pos(L"/") > 0)
+    else if (!Data->FolderName.IsEmpty())
     {
       Folders = true;
     }
@@ -3009,7 +3028,7 @@ void __fastcall TStoredSessionList::NewWorkspace(
 
     TSessionData * Data2 = new TSessionData(L"");
     Data2->Assign(Data);
-    Data2->Name = Name + L"/" + Data->Name;
+    Data2->Name = TSessionData::ComposePath(Name, Data->Name);
     // make sure, that new stored session is saved to registry
     Data2->Modified = true;
     Add(Data2);
@@ -3120,3 +3139,10 @@ UnicodeString GetExpandedLogFileName(UnicodeString LogFileName, TSessionData * S
   return ANewFileName;
 }
 //---------------------------------------------------------------------
+bool __fastcall IsSshProtocol(TFSProtocol FSProtocol)
+{
+  return
+    (FSProtocol == fsSFTPonly) || (FSProtocol == fsSFTP) ||
+    (FSProtocol == fsSCPonly);
+}
+//---------------------------------------------------------------------

+ 4 - 0
source/core/SessionData.h

@@ -341,6 +341,9 @@ public:
   bool __fastcall IsInFolderOrWorkspace(UnicodeString Name);
   static void __fastcall ValidatePath(const UnicodeString Path);
   static void __fastcall ValidateName(const UnicodeString Name);
+  static UnicodeString __fastcall ExtractLocalName(const UnicodeString & Name);
+  static UnicodeString __fastcall ExtractFolderName(const UnicodeString & Name);
+  static UnicodeString __fastcall ComposePath(const UnicodeString & Path, const UnicodeString & Name);
 
   __property UnicodeString HostName  = { read=FHostName, write=SetHostName };
   __property UnicodeString HostNameExpanded  = { read=GetHostNameExpanded };
@@ -529,5 +532,6 @@ private:
 };
 //---------------------------------------------------------------------------
 UnicodeString GetExpandedLogFileName(UnicodeString LogFileName, TSessionData * SessionData);
+bool __fastcall IsSshProtocol(TFSProtocol FSProtocol);
 //---------------------------------------------------------------------------
 #endif

+ 9 - 21
source/core/SessionInfo.cpp

@@ -71,23 +71,6 @@ UnicodeString __fastcall XmlAttributeEscape(UnicodeString Str)
   return DoXmlEscape(Str, true);
 }
 //---------------------------------------------------------------------------
-TStrings * __fastcall ExceptionToMessages(Exception * E)
-{
-  TStrings * Result = NULL;
-  UnicodeString Message;
-  if (ExceptionMessage(E, Message))
-  {
-    Result = new TStringList();
-    Result->Add(Message);
-    ExtException * EE = dynamic_cast<ExtException *>(E);
-    if ((EE != NULL) && (EE->MoreMessages != NULL))
-    {
-      Result->AddStrings(EE->MoreMessages);
-    }
-  }
-  return Result;
-}
-//---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 #pragma warn -inl
 class TSessionActionRecord
@@ -221,7 +204,7 @@ public:
   void __fastcall Rollback(Exception * E)
   {
     assert(FErrorMessages == NULL);
-    FErrorMessages = ExceptionToMessages(E);
+    FErrorMessages = ExceptionToMoreMessages(E);
     Close(RolledBack);
   }
 
@@ -1039,10 +1022,15 @@ void __fastcall TSessionLog::DoAddStartupInfo(TSessionData * Data)
             Ftps = L"None";
             break;
         }
-        ADF(L"FTP: FTPS: %s; Passive: %s [Force IP: %s]; MLSD: %s",
+        ADF(L"FTP: FTPS: %s; Passive: %s [Force IP: %s]; MLSD: %s [List all: %s]",
           (Ftps, BooleanToEngStr(Data->FtpPasvMode),
            BugFlags[Data->FtpForcePasvIp],
-           BugFlags[Data->FtpUseMlsd]));
+           BugFlags[Data->FtpUseMlsd],
+           BugFlags[Data->FtpListAll]));
+        if (Data->Ftps != ftpsNone)
+        {
+          ADF(L"Session reuse: %s", (BooleanToEngStr(Data->SslSessionReuse)));
+        }
       }
       ADF(L"Local directory: %s, Remote directory: %s, Update: %s, Cache: %s",
         ((Data->LocalDirectory.IsEmpty() ? UnicodeString(L"default") : Data->LocalDirectory),
@@ -1177,7 +1165,7 @@ void __fastcall TActionLog::AddFailure(TStrings * Messages)
 //---------------------------------------------------------------------------
 void __fastcall TActionLog::AddFailure(Exception * E)
 {
-  TStrings * Messages = ExceptionToMessages(E);
+  TStrings * Messages = ExceptionToMoreMessages(E);
   if (Messages != NULL)
   {
     try

+ 1 - 1
source/core/SessionInfo.h

@@ -63,7 +63,7 @@ public:
     UnicodeString Name, UnicodeString Instructions, TStrings * Prompts,
     TStrings * Results) = 0;
   virtual void __fastcall DisplayBanner(const UnicodeString & Banner) = 0;
-  virtual void __fastcall FatalError(Exception * E, UnicodeString Msg) = 0;
+  virtual void __fastcall FatalError(Exception * E, UnicodeString Msg, UnicodeString HelpKeyword = L"") = 0;
   virtual void __fastcall HandleExtendedException(Exception * E) = 0;
   virtual void __fastcall Closed() = 0;
 };

+ 36 - 18
source/core/SftpFileSystem.cpp

@@ -18,12 +18,13 @@
 #pragma package(smart_init)
 //---------------------------------------------------------------------------
 #define FILE_OPERATION_LOOP_EX(ALLOW_SKIP, MESSAGE, OPERATION) \
-  FILE_OPERATION_LOOP_CUSTOM(FTerminal, ALLOW_SKIP, MESSAGE, OPERATION)
+  FILE_OPERATION_LOOP_CUSTOM(FTerminal, ALLOW_SKIP, MESSAGE, OPERATION, L"")
 //---------------------------------------------------------------------------
 #define SSH_FX_OK                                 0
 #define SSH_FX_EOF                                1
 #define SSH_FX_NO_SUCH_FILE                       2
 #define SSH_FX_PERMISSION_DENIED                  3
+#define SSH_FX_FAILURE                            4
 #define SSH_FX_OP_UNSUPPORTED                     8
 
 #define SSH_FXP_INIT               1
@@ -798,7 +799,7 @@ public:
     while (Index < Dump.Length())
     {
       char C = Dump[Index];
-      if (((C >= '0') && (C <= '9')) || ((C >= 'A') && (C <= 'Z')))
+      if (IsHex(C))
       {
         if (Byte[0] == '\0')
         {
@@ -2136,9 +2137,20 @@ unsigned long __fastcall TSFTPFileSystem::GotStatusPacket(TSFTPPacket * Packet,
     {
       LanguageTag = FORMAT(L" (%s)", (LanguageTag));
     }
+    UnicodeString HelpKeyword;
+    switch (Code)
+    {
+      case SSH_FX_FAILURE:
+        HelpKeyword = HELP_SFTP_STATUS_FAILURE;
+        break;
+
+      case SSH_FX_PERMISSION_DENIED:
+        HelpKeyword = HELP_SFTP_STATUS_PERMISSION_DENIED;
+        break;
+    }
     UnicodeString Error = FMTLOAD(SFTP_ERROR_FORMAT3, (MessageStr,
       int(Code), LanguageTag, ServerMessage));
-    FTerminal->TerminalError(NULL, Error);
+    FTerminal->TerminalError(NULL, Error, HelpKeyword);
     return 0;
   }
   else
@@ -2179,7 +2191,7 @@ inline int __fastcall TSFTPFileSystem::PacketLength(unsigned char * LenBuf, int
       Message = FMTLOAD(SFTP_PACKET_TOO_BIG_INIT_EXPLAIN,
         (Message, DisplayableStr(LenString)));
     }
-    FTerminal->FatalError(NULL, Message);
+    FTerminal->FatalError(NULL, Message, HELP_SFTP_PACKET_TOO_BIG);
   }
   return Length;
 }
@@ -2437,7 +2449,7 @@ UnicodeString __fastcall TSFTPFileSystem::RealPath(const UnicodeString Path,
     if (!Path.IsEmpty())
     {
       // this condition/block was outside (before) current block
-      // but it dod not work when Path was empty
+      // but it did not work when Path was empty
       if (!BaseDir.IsEmpty())
       {
         APath = UnixIncludeTrailingBackslash(BaseDir);
@@ -2984,7 +2996,7 @@ void __fastcall TSFTPFileSystem::ReadDirectory(TRemoteFileList * FileList)
 
   // moved before SSH_FXP_OPENDIR, so directory listing does not retain
   // old data (e.g. parent directory) when reading fails
-  FileList->Clear();
+  FileList->Reset();
 
   TSFTPPacket Packet(SSH_FXP_OPENDIR);
   RawByteString Handle;
@@ -3122,7 +3134,9 @@ void __fastcall TSFTPFileSystem::ReadDirectory(TRemoteFileList * FileList)
 
       if (Failure)
       {
-        throw Exception(FMTLOAD(EMPTY_DIRECTORY, (FileList->Directory)));
+        throw ExtException(
+          NULL, FMTLOAD(EMPTY_DIRECTORY, (FileList->Directory)),
+          HELP_EMPTY_DIRECTORY);
       }
     }
   }
@@ -3381,7 +3395,7 @@ void __fastcall TSFTPFileSystem::ChangeFileProperties(const UnicodeString FileNa
     }
 
     // SFTP can change owner and group at the same time only, not individually.
-    // Fortunatelly we know current owner/group, so if only one is present,
+    // Fortunately we know current owner/group, so if only one is present,
     // we can supplement the other.
     TRemoteProperties Properties(*AProperties);
     if (Properties.Valid.Contains(vpGroup) &&
@@ -4015,7 +4029,7 @@ void __fastcall TSFTPFileSystem::SFTPSource(const UnicodeString FileName,
 
       TDateTime Modification = UnixToDateTime(MTime, FTerminal->SessionData->DSTMode);
 
-      // Will we use ASCII of BINARY file tranfer?
+      // Will we use ASCII of BINARY file transfer?
       TFileMasks::TParams MaskParams;
       MaskParams.Size = Size;
       MaskParams.Modification = Modification;
@@ -4283,9 +4297,11 @@ void __fastcall TSFTPFileSystem::SFTPSource(const UnicodeString FileName,
 
         // originally this was before CLOSE (last __finally statement),
         // on VShell it failed
-        FILE_OPERATION_LOOP(FMTLOAD(RENAME_AFTER_RESUME_ERROR,
+        FILE_OPERATION_LOOP_CUSTOM(FTerminal, true,
+          FMTLOAD(RENAME_AFTER_RESUME_ERROR,
             (UnixExtractFileName(OpenParams.RemoteFileName), DestFileName)),
-          RenameFile(OpenParams.RemoteFileName, DestFileName);
+          RenameFile(OpenParams.RemoteFileName, DestFileName),
+          HELP_RENAME_AFTER_RESUME_ERROR
         );
       }
 
@@ -4316,7 +4332,7 @@ void __fastcall TSFTPFileSystem::SFTPSource(const UnicodeString FileName,
             SendPacket(&PropertiesRequest);
           }
           bool Resend = false;
-          FILE_OPERATION_LOOP(FMTLOAD(PRESERVE_TIME_PERM_ERROR, (DestFileName)),
+          FILE_OPERATION_LOOP_CUSTOM(FTerminal, true, FMTLOAD(PRESERVE_TIME_PERM_ERROR2, (DestFileName)),
             try
             {
               TSFTPPacket DummyResponse;
@@ -4346,6 +4362,8 @@ void __fastcall TSFTPFileSystem::SFTPSource(const UnicodeString FileName,
                 throw;
               }
             }
+            ,
+            HELP_PRESERVE_TIME_PERM_ERROR
           );
         }
         catch(Exception & E)
@@ -4556,7 +4574,7 @@ int __fastcall TSFTPFileSystem::SFTPOpenRemote(void * AOpenParams, void * /*Para
       }
       else if (FTerminal->Active)
       {
-        // if file overwritting was confirmed, it means that the file already exists,
+        // if file overwriting was confirmed, it means that the file already exists,
         // if not, check now
         if (!OpenParams->Confirmed)
         {
@@ -4714,7 +4732,7 @@ void __fastcall TSFTPFileSystem::SFTPDirectorySource(const UnicodeString Directo
         SUSPEND_OPERATION (
           // here a message to user was displayed, which was not appropriate
           // when user refused to overwrite the file in subdirectory.
-          // hopefuly it won't be missing in other situations.
+          // hopefully it won't be missing in other situations.
           if (!FTerminal->HandleException(&E)) throw;
         );
       }
@@ -4921,7 +4939,7 @@ void __fastcall TSFTPFileSystem::SFTPSink(const UnicodeString FileName,
     bool ResumeTransfer = false;
     __int64 ResumeOffset;
 
-    // Will we use ASCII of BINARY file tranfer?
+    // Will we use ASCII of BINARY file transfer?
     OperationProgress->SetAsciiTransfer(
       CopyParam->UseAsciiTransfer(FileName, osRemote, MaskParams));
     FTerminal->LogEvent(UnicodeString((OperationProgress->AsciiTransfer ? L"Ascii" : L"Binary")) +
@@ -5084,7 +5102,7 @@ void __fastcall TSFTPFileSystem::SFTPSink(const UnicodeString FileName,
 
         if (OverwriteMode == omOverwrite)
         {
-          // is NULL when overwritting read-only file
+          // is NULL when overwriting read-only file
           if (LocalHandle)
           {
             CloseHandle(LocalHandle);
@@ -5093,7 +5111,7 @@ void __fastcall TSFTPFileSystem::SFTPSink(const UnicodeString FileName,
         }
         else
         {
-          // is NULL when overwritting read-only file, so following will
+          // is NULL when overwriting read-only file, so following will
           // probably fail anyway
           if (LocalHandle == NULL)
           {
@@ -5191,7 +5209,7 @@ void __fastcall TSFTPFileSystem::SFTPSink(const UnicodeString FileName,
               if ((Missing == 0) && PrevIncomplete)
               {
                 // This can happen only if last request returned less bytes
-                // than expected, but exacly number of bytes missing to last
+                // than expected, but exactly number of bytes missing to last
                 // known file size, but actually EOF was not reached.
                 // Can happen only when filesize has changed since directory
                 // listing and server returns less bytes than requested and

+ 56 - 38
source/core/Terminal.cpp

@@ -61,7 +61,7 @@
   }
 
 #define FILE_OPERATION_LOOP_EX(ALLOW_SKIP, MESSAGE, OPERATION) \
-  FILE_OPERATION_LOOP_CUSTOM(this, ALLOW_SKIP, MESSAGE, OPERATION)
+  FILE_OPERATION_LOOP_CUSTOM(this, ALLOW_SKIP, MESSAGE, OPERATION, L"")
 //---------------------------------------------------------------------------
 struct TMoveFileParams
 {
@@ -279,7 +279,7 @@ public:
     UnicodeString Name, UnicodeString Instructions, TStrings * Prompts,
     TStrings * Results);
   virtual void __fastcall DisplayBanner(const UnicodeString & Banner);
-  virtual void __fastcall FatalError(Exception * E, UnicodeString Msg);
+  virtual void __fastcall FatalError(Exception * E, UnicodeString Msg, UnicodeString HelpContext);
   virtual void __fastcall HandleExtendedException(Exception * E);
   virtual void __fastcall Closed();
 
@@ -364,9 +364,9 @@ void __fastcall TTunnelUI::DisplayBanner(const UnicodeString & Banner)
   }
 }
 //---------------------------------------------------------------------------
-void __fastcall TTunnelUI::FatalError(Exception * E, UnicodeString Msg)
+void __fastcall TTunnelUI::FatalError(Exception * E, UnicodeString Msg, UnicodeString HelpKeyword)
 {
-  throw ESshFatal(E, Msg);
+  throw ESshFatal(E, Msg, HelpKeyword);
 }
 //---------------------------------------------------------------------------
 void __fastcall TTunnelUI::HandleExtendedException(Exception * E)
@@ -389,7 +389,7 @@ public:
   inline __fastcall TCallbackGuard(TTerminal * FTerminal);
   inline __fastcall ~TCallbackGuard();
 
-  void __fastcall FatalError(Exception * E, const UnicodeString & Msg);
+  void __fastcall FatalError(Exception * E, const UnicodeString & Msg, const UnicodeString & HelpKeyword);
   inline void __fastcall Verify();
   void __fastcall Dismiss();
 
@@ -421,7 +421,7 @@ __fastcall TCallbackGuard::~TCallbackGuard()
   delete FFatalError;
 }
 //---------------------------------------------------------------------------
-void __fastcall TCallbackGuard::FatalError(Exception * E, const UnicodeString & Msg)
+void __fastcall TCallbackGuard::FatalError(Exception * E, const UnicodeString & Msg, const UnicodeString & HelpKeyword)
 {
   assert(FGuarding);
 
@@ -431,7 +431,7 @@ void __fastcall TCallbackGuard::FatalError(Exception * E, const UnicodeString &
   if (dynamic_cast<ECallbackGuardAbort *>(E) == NULL)
   {
     delete FFatalError;
-    FFatalError = new ExtException(E, Msg);
+    FFatalError = new ExtException(E, Msg, HelpKeyword);
   }
 
   // silently abort what we are doing.
@@ -1107,26 +1107,39 @@ unsigned int __fastcall TTerminal::QueryUserException(const UnicodeString Query,
   TQueryType QueryType)
 {
   unsigned int Result;
-  TStrings * MoreMessages = new TStringList();
-  try
+  UnicodeString ExMessage;
+  if (ALWAYS_TRUE(ExceptionMessage(E, ExMessage) || !Query.IsEmpty()))
   {
-    if (!E->Message.IsEmpty() && !Query.IsEmpty())
+    TStrings * MoreMessages = new TStringList();
+    try
     {
-      MoreMessages->Add(E->Message);
-    }
+      if (!ExMessage.IsEmpty() && !Query.IsEmpty())
+      {
+        MoreMessages->Add(ExMessage);
+      }
+
+      ExtException * EE = dynamic_cast<ExtException*>(E);
+      if ((EE != NULL) && (EE->MoreMessages != NULL))
+      {
+        MoreMessages->AddStrings(EE->MoreMessages);
+      }
+
+      TQueryParams HelpKeywordOverrideParams;
+      if (Params != NULL)
+      {
+        HelpKeywordOverrideParams.Assign(*Params);
+      }
+      HelpKeywordOverrideParams.HelpKeyword =
+        MergeHelpKeyword(HelpKeywordOverrideParams.HelpKeyword, GetExceptionHelpKeyword(E));
 
-    ExtException * EE = dynamic_cast<ExtException*>(E);
-    if ((EE != NULL) && (EE->MoreMessages != NULL))
+      Result = QueryUser(!Query.IsEmpty() ? Query : ExMessage,
+        MoreMessages->Count ? MoreMessages : NULL,
+        Answers, &HelpKeywordOverrideParams, QueryType);
+    }
+    __finally
     {
-      MoreMessages->AddStrings(EE->MoreMessages);
+      delete MoreMessages;
     }
-    Result = QueryUser(!Query.IsEmpty() ? Query : UnicodeString(E->Message),
-      MoreMessages->Count ? MoreMessages : NULL,
-      Answers, Params, QueryType);
-  }
-  __finally
-  {
-    delete MoreMessages;
   }
   return Result;
 }
@@ -1291,9 +1304,10 @@ void __fastcall TTerminal::TerminalError(UnicodeString Msg)
   TerminalError(NULL, Msg);
 }
 //---------------------------------------------------------------------------
-void __fastcall TTerminal::TerminalError(Exception * E, UnicodeString Msg)
+void __fastcall TTerminal::TerminalError(
+  Exception * E, UnicodeString Msg, UnicodeString HelpKeyword)
 {
-  throw ETerminal(E, Msg);
+  throw ETerminal(E, Msg, HelpKeyword);
 }
 //---------------------------------------------------------------------------
 bool __fastcall TTerminal::DoQueryReopen(Exception * E)
@@ -1366,7 +1380,7 @@ bool __fastcall TTerminal::QueryReopen(Exception * E, int Params,
 //---------------------------------------------------------------------------
 bool __fastcall TTerminal::FileOperationLoopQuery(Exception & E,
   TFileOperationProgressType * OperationProgress, const UnicodeString Message,
-  bool AllowSkip, UnicodeString SpecialRetry)
+  bool AllowSkip, UnicodeString SpecialRetry, UnicodeString HelpKeyword)
 {
   bool Result = false;
   Log->AddException(&E);
@@ -1383,6 +1397,7 @@ bool __fastcall TTerminal::FileOperationLoopQuery(Exception & E,
       FLAGMASK(SkipPossible, (qaSkip | qaAll)) |
       FLAGMASK(!SpecialRetry.IsEmpty(), qaYes);
     TQueryParams Params(qpAllowContinueOnError | FLAGMASK(!AllowSkip, qpFatalAbort));
+    Params.HelpKeyword = HelpKeyword;
     TQueryButtonAlias Aliases[2];
     int AliasCount = 0;
 
@@ -1782,7 +1797,7 @@ void __fastcall TTerminal::FatalAbort()
   FatalError(NULL, "");
 }
 //---------------------------------------------------------------------------
-void __fastcall TTerminal::FatalError(Exception * E, UnicodeString Msg)
+void __fastcall TTerminal::FatalError(Exception * E, UnicodeString Msg, UnicodeString HelpKeyword)
 {
   bool SecureShellActive = (FSecureShell != NULL) && FSecureShell->Active;
   if (Active || SecureShellActive)
@@ -1809,11 +1824,11 @@ void __fastcall TTerminal::FatalError(Exception * E, UnicodeString Msg)
 
   if (FCallbackGuard != NULL)
   {
-    FCallbackGuard->FatalError(E, Msg);
+    FCallbackGuard->FatalError(E, Msg, HelpKeyword);
   }
   else
   {
-    throw ESshFatal(E, Msg);
+    throw ESshFatal(E, Msg, HelpKeyword);
   }
 }
 //---------------------------------------------------------------------------
@@ -1823,7 +1838,7 @@ void __fastcall TTerminal::CommandError(Exception * E, const UnicodeString Msg)
 }
 //---------------------------------------------------------------------------
 unsigned int __fastcall TTerminal::CommandError(Exception * E, const UnicodeString Msg,
-  unsigned int Answers)
+  unsigned int Answers, const UnicodeString HelpKeyword)
 {
   // may not be, particularly when TTerminal::Reopen is being called
   // from within OnShowExtendedException handler
@@ -1831,7 +1846,7 @@ unsigned int __fastcall TTerminal::CommandError(Exception * E, const UnicodeStri
   unsigned int Result = 0;
   if (E && E->InheritsFrom(__classid(EFatal)))
   {
-    FatalError(E, Msg);
+    FatalError(E, Msg, HelpKeyword);
   }
   else if (E && E->InheritsFrom(__classid(EAbort)))
   {
@@ -1840,11 +1855,11 @@ unsigned int __fastcall TTerminal::CommandError(Exception * E, const UnicodeStri
   }
   else if (ExceptionOnFail)
   {
-    throw ECommand(E, Msg);
+    throw ECommand(E, Msg, HelpKeyword);
   }
   else if (!Answers)
   {
-    ECommand * ECmd = new ECommand(E, Msg);
+    ECommand * ECmd = new ECommand(E, Msg, HelpKeyword);
     try
     {
       HandleExtendedException(ECmd);
@@ -1864,7 +1879,7 @@ unsigned int __fastcall TTerminal::CommandError(Exception * E, const UnicodeStri
     }
     else
     {
-      TQueryParams Params(qpAllowContinueOnError);
+      TQueryParams Params(qpAllowContinueOnError, HelpKeyword);
       TQueryButtonAlias Aliases[1];
       if (CanSkip)
       {
@@ -2003,7 +2018,7 @@ unsigned int __fastcall TTerminal::ConfirmFileOverwrite(const UnicodeString File
     }
     if (ALWAYS_TRUE(QueryParams->HelpKeyword.IsEmpty()))
     {
-      QueryParams->HelpKeyword = L"ui_overwrite";
+      QueryParams->HelpKeyword = HELP_OVERWRITE;
     }
     Result = QueryUser(Message, NULL, Answers, QueryParams);
     switch (Result)
@@ -2182,8 +2197,11 @@ void __fastcall TTerminal::ReloadDirectory()
 //---------------------------------------------------------------------------
 void __fastcall TTerminal::RefreshDirectory()
 {
-  if (SessionData->CacheDirectories &&
-      FDirectoryCache->HasNewerFileList(CurrentDirectory, FFiles->Timestamp))
+  if (!SessionData->CacheDirectories)
+  {
+    LogEvent(L"Not refreshing directory, caching is off.");
+  }
+  else if (FDirectoryCache->HasNewerFileList(CurrentDirectory, FFiles->Timestamp))
   {
     // Second parameter was added to allow (rather force) using the cache.
     // Before, the directory was reloaded always, it seems useless,
@@ -2976,7 +2994,7 @@ void __fastcall TTerminal::DoCustomCommandOnFile(UnicodeString FileName,
         // until transaction ends. But we need to know CurrentDirectory to
         // expand !/ pattern.
         // Doing this only, when current directory of the main and secondary shell differs,
-        // what would be the case before the first file in transation.
+        // what would be the case before the first file in transaction.
         // Otherwise we would be reading pwd before every time as the
         // CustomCommandOnFile on its own sets FReadCurrentDirectoryPending
         if (FCommandSession->FReadCurrentDirectoryPending)
@@ -4243,7 +4261,7 @@ void __fastcall TTerminal::DoSynchronizeCollectDirectory(const UnicodeString Loc
       }
 
       // can we expect that ProcessDirectory would take so little time
-      // that we can pospone showing progress window until anything actually happens?
+      // that we can postpone showing progress window until anything actually happens?
       bool Cached = FLAGSET(Params, spUseCache) && SessionData->CacheDirectories &&
         FDirectoryCache->HasFileList(RemoteDirectory);
 

+ 8 - 6
source/core/Terminal.h

@@ -70,7 +70,7 @@ typedef void __fastcall (__closure *TInformationEvent)
 #define THROW_SKIP_FILE_NULL THROW_SKIP_FILE(NULL, L"")
 
 /* TODO : Better user interface (query to user) */
-#define FILE_OPERATION_LOOP_CUSTOM(TERMINAL, ALLOW_SKIP, MESSAGE, OPERATION) { \
+#define FILE_OPERATION_LOOP_CUSTOM(TERMINAL, ALLOW_SKIP, MESSAGE, OPERATION, HELPKEYWORD) { \
   bool DoRepeat; \
   do { \
     DoRepeat = false; \
@@ -91,7 +91,8 @@ typedef void __fastcall (__closure *TInformationEvent)
     }                                                                       \
     catch (Exception & E)                                                   \
     {                                                                       \
-      TERMINAL->FileOperationLoopQuery(E, OperationProgress, MESSAGE, ALLOW_SKIP); \
+      TERMINAL->FileOperationLoopQuery(                                     \
+        E, OperationProgress, MESSAGE, ALLOW_SKIP, L"", HELPKEYWORD);       \
       DoRepeat = true;                                                      \
     } \
   } while (DoRepeat); }
@@ -202,7 +203,8 @@ private:
   bool FEnableSecureShellUsage;
 
   void __fastcall CommandError(Exception * E, const UnicodeString Msg);
-  unsigned int __fastcall CommandError(Exception * E, const UnicodeString Msg, unsigned int Answers);
+  unsigned int __fastcall CommandError(Exception * E, const UnicodeString Msg,
+    unsigned int Answers, const UnicodeString HelpKeyword = L"");
   UnicodeString __fastcall GetCurrentDirectory();
   bool __fastcall GetExceptionOnFail() const;
   const TRemoteTokenList * __fastcall GetGroups();
@@ -310,7 +312,7 @@ protected:
   TStrings * __fastcall GetFixedPaths();
   void __fastcall DoStartup();
   virtual bool __fastcall DoQueryReopen(Exception * E);
-  virtual void __fastcall FatalError(Exception * E, UnicodeString Msg);
+  virtual void __fastcall FatalError(Exception * E, UnicodeString Msg, UnicodeString HelpKeyword = L"");
   void __fastcall ResetConnection();
   virtual bool __fastcall DoPromptUser(TSessionData * Data, TPromptKind Kind,
     UnicodeString Name, UnicodeString Instructions, TStrings * Prompts,
@@ -404,7 +406,7 @@ public:
     const TRemoteProperties * Properties);
   bool __fastcall LoadFilesProperties(TStrings * FileList);
   void __fastcall TerminalError(UnicodeString Msg);
-  void __fastcall TerminalError(Exception * E, UnicodeString Msg);
+  void __fastcall TerminalError(Exception * E, UnicodeString Msg, UnicodeString HelpKeyword = L"");
   void __fastcall ReloadDirectory();
   void __fastcall RefreshDirectory();
   void __fastcall RenameFile(const UnicodeString FileName, const UnicodeString NewName);
@@ -440,7 +442,7 @@ public:
   UnicodeString __fastcall FileUrl(const UnicodeString FileName);
   bool __fastcall FileOperationLoopQuery(Exception & E,
     TFileOperationProgressType * OperationProgress, const UnicodeString Message,
-    bool AllowSkip, UnicodeString SpecialRetry = L"");
+    bool AllowSkip, UnicodeString SpecialRetry = L"", UnicodeString HelpKeyword = L"");
   TUsableCopyParamAttrs __fastcall UsableCopyParamAttrs(int Params);
   bool __fastcall QueryReopen(Exception * E, int Params,
     TFileOperationProgressType * OperationProgress);

+ 3 - 3
source/core/WebDAVFileSystem.cpp

@@ -12143,7 +12143,7 @@ private:
 //---------------------------------------------------------------------------
 #undef FILE_OPERATION_LOOP_EX
 #define FILE_OPERATION_LOOP_EX(ALLOW_SKIP, MESSAGE, OPERATION) \
-  FILE_OPERATION_LOOP_CUSTOM(FTerminal, ALLOW_SKIP, MESSAGE, OPERATION)
+  FILE_OPERATION_LOOP_CUSTOM(FTerminal, ALLOW_SKIP, MESSAGE, OPERATION, L"")
 //---------------------------------------------------------------------------
 static const UnicodeString CONST_WEBDAV_PROTOCOL_BASE_NAME = L"WebDAV";
 
@@ -12444,7 +12444,7 @@ void __fastcall TWebDAVFileSystem::CachedChangeDirectory(const UnicodeString Dir
 
 void __fastcall TWebDAVFileSystem::DoReadDirectory(TRemoteFileList * FileList)
 {
-  FileList->Clear();
+  FileList->Reset();
   // add parent directory
   FileList->AddFile(new TRemoteParentDirectory(FTerminal));
 
@@ -13603,7 +13603,7 @@ bool __fastcall TWebDAVFileSystem::HandleListData(const wchar_t * Path,
                  Entry->Size,
                  int(Entry->Dir), int(Entry->Link), Entry->Time.Year, Entry->Time.Month, Entry->Time.Day,
                  Entry->Time.Hour, Entry->Time.Minute, int(Entry->Time.HasTime), int(Entry->Time.HasDate)));
-        throw ETerminal(&E, FMTLOAD(LIST_LINE_ERROR, (EntryData.c_str())));
+        throw ETerminal(&E, FMTLOAD(LIST_LINE_ERROR, (EntryData.c_str())), HELP_LIST_LINE_ERROR);
       }
 
       FFileList->AddFile(File);

+ 1 - 1
source/filezilla/ApiLog.cpp

@@ -94,7 +94,7 @@ void CApiLog::LogMessageRaw(int nMessageType, LPCTSTR pMsg) const
 	ASSERT(m_hTargetWnd || m_pApiLogParent);
 	if (nMessageType>=FZ_LOG_APIERROR && (nMessageType-FZ_LOG_APIERROR)>=m_pApiLogParent->m_nDebugLevel)
 		return;
-	
+
 #ifdef MPEXT
 	if (nMessageType>=FZ_LOG_DEBUG)
 		return;

+ 13 - 2
source/filezilla/AsyncSslSocketLayer.cpp

@@ -1406,7 +1406,7 @@ void CAsyncSslSocketLayer::apps_ssl_info_callback(const SSL *s, int where, int r
 	m_sCriticalSection.Unlock();
 
 	// Called while unloading?
-	if (!pLayer->m_bUseSSL)
+	if (!pLayer->m_bUseSSL && (where != SSL_CB_LOOP))
 		return;
 
 	char * str;
@@ -1459,10 +1459,21 @@ void CAsyncSslSocketLayer::apps_ssl_info_callback(const SSL *s, int where, int r
 
 	if (where & SSL_CB_LOOP)
 	{
-		char *buffer = new char[4096];
+		char* debug = NULL;
+		// exact SSL_CB_LOOP is abused for debugging
+		if (where == SSL_CB_LOOP)
+		{
+			debug = reinterpret_cast<char*>(ret);
+		}
+		char *buffer = new char[4096 + ((debug != NULL) ? strlen(debug) : 0)];
 		sprintf(buffer, "%s: %s",
 				str,
 				pSSL_state_string_long(s));
+		if (debug != NULL)
+		{
+			sprintf(buffer + strlen(buffer), " [%s]", debug);
+			OPENSSL_free(debug);
+		}
 		pLayer->DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_VERBOSE_INFO, 0, buffer);
 	}
 	else if (where & SSL_CB_ALERT)

+ 4 - 0
source/filezilla/ControlSocket.h

@@ -113,6 +113,10 @@ public:
 	void ShowStatus(UINT nID, int type) const;
 	void ShowStatus(CString status,int type) const;
 
+#ifdef MPEXT
+	virtual bool __fastcall UsingMlsd() = 0;
+#endif
+
 	virtual int OnLayerCallback(std::list<t_callbackMsg>& callbacks);
 protected:
 

+ 10 - 0
source/filezilla/FileZillaApi.cpp

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

+ 1 - 0
source/filezilla/FileZillaApi.h

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

+ 5 - 0
source/filezilla/FileZillaIntf.cpp

@@ -518,3 +518,8 @@ inline bool __fastcall TFileZillaIntf::Check(int ReturnCode,
     return CheckError(ReturnCode, Context);
   }
 }
+//---------------------------------------------------------------------------
+bool __fastcall TFileZillaIntf::UsingMlsd()
+{
+  return FFileZillaApi->UsingMlsd();
+}

+ 1 - 0
source/filezilla/FileZillaIntf.h

@@ -157,6 +157,7 @@ public:
 
   bool __fastcall SetCurrentPath(const wchar_t * Path);
   bool __fastcall GetCurrentPath(wchar_t * Path, size_t MaxLen);
+  bool __fastcall UsingMlsd();
 
   bool __fastcall Cancel();
 

+ 14 - 6
source/filezilla/FtpControlSocket.cpp

@@ -1507,13 +1507,21 @@ void CFtpControlSocket::FtpCommand(LPCTSTR pCommand)
 	Send(pCommand);
 }
 
+#ifdef MPEXT
+bool __fastcall CFtpControlSocket::UsingMlsd()
+{
+	return
+		// 0 = on, 1 = off, 2 = auto
+		(m_CurrentServer.iUseMlsd == 0) ||
+		((m_CurrentServer.iUseMlsd != 1) &&
+		 (m_serverCapabilities.GetCapability(mlsd_command) == yes));
+}
+#endif
+
 CString CFtpControlSocket::GetListingCmd()
 {
 	CString cmd;
-	// 0 = on, 1 = off, 2 = auto
-	if ((m_CurrentServer.iUseMlsd == 0) ||
-		((m_CurrentServer.iUseMlsd != 1) &&
-		 (m_serverCapabilities.GetCapability(mlsd_command) == yes)))
+	if (UsingMlsd())
 	{
 		cmd = _T("MLSD");
 	}
@@ -5132,7 +5140,7 @@ int CFtpControlSocket::CheckOverwriteFile()
 				if (pData->transferfile.get)
 				{
 					int pos = pData->transferfile.localfile.ReverseFind(_MPT('\\'));
-					ASSERT(pos!=-1);
+					// pos can be -1 here, e.g. in scripting, the code below still works then
 					pOverwriteData->FileName1 = pData->transferfile.localfile.Mid(pos+1);
 					pOverwriteData->FileName2 = pData->transferfile.remotefile;
 					pOverwriteData->path1 = pData->transferfile.localfile.Left(pos+1);
@@ -5143,7 +5151,7 @@ int CFtpControlSocket::CheckOverwriteFile()
 				else
 				{
 					int pos = pData->transferfile.localfile.ReverseFind(_MPT('\\'));
-					ASSERT(pos!=-1);
+					// pos can be -1 here, e.g. in scripting, the code below still works then
 					pOverwriteData->FileName1 = pData->transferfile.remotefile;
 					pOverwriteData->FileName2 = pData->transferfile.localfile.Mid(pos+1);
 					pOverwriteData->path1 = pData->transferfile.remotepath.GetPath();

+ 4 - 1
source/filezilla/FtpControlSocket.h

@@ -86,7 +86,10 @@ public:
 	// Other servers return "550 No files found."
 	bool IsMisleadingListResponse();
 
-	
+#ifdef MPEXT
+	virtual bool __fastcall UsingMlsd();
+#endif
+
 	// Vom Klassen-Assistenten generierte virtuelle Funktionsüberschreibungen
 	//{{AFX_VIRTUAL(CFtpControlSocket)
 	public:

+ 28 - 9
source/filezilla/FtpListResult.cpp

@@ -1322,7 +1322,9 @@ BOOL CFtpListResult::parseAsMlsd(const char *line, const int linelen, t_director
 
 		int pos = facts.Find('=');
 		if (pos < 1 || pos > delim)
+		{
 			return FALSE;
+		}
 
 		CString factname = facts.Left(pos);
 		factname.MakeLower();
@@ -1365,13 +1367,21 @@ BOOL CFtpListResult::parseAsMlsd(const char *line, const int linelen, t_director
 			direntry.permissionstr = value;
 		}
 		else if (factname == _T("unix.owner") || factname == _T("unix.user"))
+		{
 			owner = value;
+		}
 		else if (factname == _T("unix.group"))
+		{
 			group = value;
+		}
 		else if (factname == _T("unix.uid"))
+		{
 			uid = value;
+		}
 		else if (factname == _T("unix.gid"))
+		{
 			gid = value;
+		}
 
 		facts = facts.Mid(delim + 1);
 	}
@@ -1424,15 +1434,24 @@ bool CFtpListResult::parseMlsdDateTime(const CString value, t_directory::t_diren
 	}
 	if (result)
 	{
-		direntry.date.year = Year;
-		direntry.date.month = Month;
-		direntry.date.day = Day;
-		direntry.date.hour = Hours;
-		direntry.date.minute = Minutes;
-		direntry.date.second = Seconds;
-		direntry.date.utc = TRUE;
-		CTime dateTime(Year, Month, Day, Hours, Minutes, Seconds);
-		direntry.EntryTime = dateTime;
+		try
+		{
+			CTime dateTime(Year, Month, Day, Hours, Minutes, Seconds);
+			direntry.date.year = Year;
+			direntry.date.month = Month;
+			direntry.date.day = Day;
+			direntry.date.hour = Hours;
+			direntry.date.minute = Minutes;
+			direntry.date.second = Seconds;
+			direntry.date.utc = TRUE;
+			direntry.EntryTime = dateTime;
+		}
+		// Does not really seem to ever throw in our version of MFC/ATL
+		catch (CException &)
+		{
+			direntry.date.hasdate = FALSE;
+			direntry.date.hastime = FALSE;
+		}
 	}
 	return result;
 }

+ 7 - 0
source/filezilla/MainThread.cpp

@@ -410,6 +410,13 @@ void CMainThread::SetOption(int nOption, int nValue)
 	m_Options[nOption]=nValue;
 	LCS;
 }
+#else
+bool __fastcall CMainThread::UsingMlsd()
+{
+	if (!IsConnected())
+		return false;
+	return m_pControlSocket->UsingMlsd();
+}
 #endif
 
 BOOL CMainThread::GetWorkingDir(t_directory *pWorkingDir)

+ 2 - 0
source/filezilla/MainThread.h

@@ -67,6 +67,8 @@ public:
 #ifndef MPEXT
 	void SetOption(int nOption, int nValue);
 	int GetOption(int nOption);
+#else
+    bool __fastcall UsingMlsd();
 #endif
 	t_command m_LastCommand;
 #ifndef MPEXT_NO_CACHE

+ 11 - 5
source/forms/Console.cpp

@@ -42,7 +42,7 @@ __fastcall TConsoleDialog::TConsoleDialog(TComponent* AOwner)
   FOldChangeDirectory = NULL;
   FPrevTerminalClose = NULL;;
   FLastTerminal = NULL;
-  FAnyCommandExecuted = false;
+  FDirectoryChanged = false;
   OutputMemo->Color = clBlack;
   OutputMemo->Font->Color = (TColor)0x00BBBBBB; //clGray;
   FixComboBoxResizeBug(CommandEdit);
@@ -77,9 +77,9 @@ void __fastcall TConsoleDialog::SetTerminal(TTerminal * value)
       assert(FTerminal->OnChangeDirectory == DoChangeDirectory);
       FTerminal->OnChangeDirectory = FOldChangeDirectory;
       FOldChangeDirectory = NULL;
-      if (FAnyCommandExecuted)
+      if (FDirectoryChanged)
       {
-        FAnyCommandExecuted = false;
+        FDirectoryChanged = false;
         if (FTerminal->Active)
         {
           // directory would be read from EndTransaction anyway,
@@ -195,11 +195,11 @@ void __fastcall TConsoleDialog::DoExecuteCommand()
   CommandEdit->SelectAll();
   FTerminal->ExceptionOnFail = true;
   FClearExceptionOnFail = true;
+  UnicodeString CurrentDirectory = FTerminal->CurrentDirectory;
   try
   {
     UnicodeString Command = CommandEdit->Text;
-    OutputMemo->Lines->Add(FORMAT(L"%s$ %s", (FTerminal->CurrentDirectory, Command)));
-    FAnyCommandExecuted = true;
+    OutputMemo->Lines->Add(FORMAT(L"%s$ %s", (CurrentDirectory, Command)));
     Configuration->Usage->Inc(L"RemoteCommandExecutions");
     FTerminal->AnyCommand(Command, AddLine);
   }
@@ -216,6 +216,12 @@ void __fastcall TConsoleDialog::DoExecuteCommand()
       }
     }
   }
+
+  if (CurrentDirectory != FTerminal->CurrentDirectory)
+  {
+    FDirectoryChanged = true;
+  }
+
 }
 //---------------------------------------------------------------------------
 void __fastcall TConsoleDialog::ExecuteCommand()

+ 37 - 0
source/forms/Console.dfm

@@ -11,6 +11,43 @@ object ConsoleDialog: TConsoleDialog
   Constraints.MinHeight = 250
   Constraints.MinWidth = 380
   ParentFont = True
+  Icon.Data = {
+    0000010001001010000001002000680400001600000028000000100000002000
+    0000010020000000000040040000000000000000000000000000000000000000
+    0000000000000000000000000000000000000000000000000000000000000000
+    0000000000000000000000000000000000000000000000000000000000002721
+    1CF128211CFF28211CFF28211CFF28211CFF28211CFF28211CFF28211CFF2821
+    1CFF28211CFF28211CFF28211CFF28211CFF28211CFF28211CFF27211CF12721
+    1CFF2F2722FF2F2722FF2F2722FF2F2722FF2F2722FF2F2722FF2F2722FF2F27
+    22FF2F2722FF2F2722FF2F2722FF2F2722FF2F2722FF2F2722FF27211CFF2721
+    1CFF534A45FFDAD6D3FF726A65FF362D27FF362D27FF362D27FF362D27FF362D
+    27FF362D27FF362D27FF362D27FF362D27FF362D27FF362D27FF27211CFF2721
+    1CFF3D332CFF645B55FFCFCAC6FFB6B1ACFF504640FF3D332CFF3D332CFF3D33
+    2CFF3D332CFF3D332CFF3D332CFF3D332CFF3D332CFF3D332CFF27211CFF2721
+    1CFF443931FF443931FF534841FFD9D4D1FFC1BBB6FF443931FF443931FF4439
+    31FF443931FF443931FF443931FF443931FF443931FF443931FF27211CFF2721
+    1CFF4B3F36FF80766FFFDCD8D4FFA8A19BFF544840FF4B3F36FF4B3F36FF4B3F
+    36FF4B3F36FF4B3F36FF4B3F36FF4B3F36FF4B3F36FF4B3F36FF27211CFF2721
+    1CFF695C53FFCEC8C3FF766A62FF53453BFF53453BFF53453BFF53453BFF5345
+    3BFF53453BFF53453BFF53453BFF53453BFF53453BFF53453BFF27211CFF2721
+    1CFF5A4B40FF5A4B40FF5A4B40FF5A4B40FF5A4B40FF5A4B40FF5A4B40FF5A4B
+    40FF5A4B40FF5A4B40FF5A4B40FF5A4B40FF5A4B40FF5A4B40FF27211CFF2721
+    1CFF615145FF615145FF615145FF615145FF615145FF615145FF615145FF6151
+    45FF615145FF615145FF615145FF615145FF615145FF615145FF27211CFF2721
+    1CFF68574AFF68574AFF68574AFF68574AFF68574AFF68574AFF68574AFF6857
+    4AFF68574AFF68574AFF68574AFF68574AFF68574AFF68574AFF27211CFF2721
+    1CFF6F5D4FFF6F5D4FFF6F5D4FFF6F5D4FFF6F5D4FFF6F5D4FFF6F5D4FFF6F5D
+    4FFF6F5D4FFF6F5D4FFF6F5D4FFF6F5D4FFF6F5D4FFF6F5D4FFF27211CFF7036
+    0CFFCA7232FFCA7232FFCA7232FFCA7232FFCA7232FFCA7232FFCA7232FFCA72
+    32FFCA7232FFCA7232FFCA7232FFCA7232FFCA7232FFCA7232FF70360CFF7036
+    0CFFF1AA76FFF1AA76FFF1AA76FFF1AA76FFF1AA76FFF1AA76FFF1AA76FFF1AA
+    76FFF1AA76FFF1AA76FFF1AA76FFF1AA76FFF1AA76FFF1AA76FF70360CFF7036
+    0CD870360CFF70360CFF70360CFF70360CFF70360CFF70360CFF70360CFF7036
+    0CFF70360CFF70360CFF70360CFF70360CFF70360CFF70360CFF70360CD80000
+    0000000000000000000000000000000000000000000000000000000000000000
+    000000000000000000000000000000000000000000000000000000000000FFFF
+    0000000000000000000000000000000000000000000000000000000000000000
+    0000000000000000000000000000000000000000000000000000FFFF0000}
   OldCreateOrder = True
   OnShow = FormShow
   DesignSize = (

+ 1 - 1
source/forms/Console.h

@@ -56,7 +56,7 @@ private:
   TNotifyEvent FPrevTerminalClose;
   TRect FAutoBounds;
   bool FClearExceptionOnFail;
-  bool FAnyCommandExecuted;
+  bool FDirectoryChanged;
 
   void __fastcall DoExecuteCommand();
   void __fastcall ExecuteCommand();

+ 1 - 0
source/forms/Copy.cpp

@@ -75,6 +75,7 @@ __fastcall TCopyDialog::TCopyDialog(
   FPresetsMenu = new TPopupMenu(this);
 
   HotTrackLabel(CopyParamLabel);
+  CopyParamListButton(TransferSettingsButton);
 
   UseSystemSettings(this);
 }

+ 99 - 42
source/forms/Custom.cpp

@@ -186,46 +186,57 @@ void __fastcall TCustomDialog::AddButtonControl(TButtonControl * Control)
 class TSaveSessionDialog : public TCustomDialog
 {
 public:
-  __fastcall TSaveSessionDialog(TSessionData * OriginalSession, bool CanSavePassword, bool NotRecommendedSavingPassword);
+  __fastcall TSaveSessionDialog(bool CanSavePassword, bool NotRecommendedSavingPassword);
 
   bool __fastcall Execute(UnicodeString & SessionName, bool & SavePassword);
 
 protected:
-  DYNAMIC void __fastcall DoShow();
   virtual void __fastcall DoValidate();
   virtual void __fastcall DoChange(bool & CanSubmit);
 
 private:
-  TSessionData * FOriginalSession;
-  TComboBox * SessionNameCombo;
+  UnicodeString FOriginalSessionName;
+  TEdit * SessionNameEdit;
+  TComboBox * FolderCombo;
   TCheckBox * SavePasswordCheck;
+  UnicodeString FRootFolder;
+
+  UnicodeString __fastcall GetSessionName();
 };
 //---------------------------------------------------------------------------
 __fastcall TSaveSessionDialog::TSaveSessionDialog(
-    TSessionData * OriginalSession, bool CanSavePassword, bool NotRecommendedSavingPassword) :
-  TCustomDialog(HELP_SESSION_SAVE),
-  FOriginalSession(OriginalSession)
+    bool CanSavePassword, bool NotRecommendedSavingPassword) :
+  TCustomDialog(HELP_SESSION_SAVE)
 {
   Caption = LoadStr(SAVE_SESSION_CAPTION);
 
-  SessionNameCombo = new TComboBox(this);
-  SessionNameCombo->AutoComplete = false;
-  AddComboBox(SessionNameCombo, CreateLabel(LoadStr(SAVE_SESSION_PROMPT)));
-  SessionNameCombo->Items->BeginUpdate();
+  SessionNameEdit = new TEdit(this);
+  AddEdit(SessionNameEdit, CreateLabel(LoadStr(SAVE_SESSION_PROMPT)));
+
+  FolderCombo = new TComboBox(this);
+  AddComboBox(FolderCombo, CreateLabel(LoadStr(SAVE_SESSION_FOLDER)));
+  FolderCombo->Items->BeginUpdate();
   try
   {
+    FRootFolder = LoadStr(SAVE_SESSION_ROOT_FOLDER);
+    FolderCombo->Items->Add(FRootFolder);
+
     for (int Index = 0; Index < StoredSessions->Count; Index++)
     {
       TSessionData * Data = StoredSessions->Sessions[Index];
-      if (!Data->Special)
+      if (!Data->Special && !Data->IsWorkspace)
       {
-        SessionNameCombo->Items->Add(Data->Name);
+        UnicodeString Folder = Data->FolderName;
+        if (!Folder.IsEmpty() && FolderCombo->Items->IndexOf(Folder) < 0)
+        {
+          FolderCombo->Items->Add(Folder);
+        }
       }
     }
   }
   __finally
   {
-    SessionNameCombo->Items->EndUpdate();
+    FolderCombo->Items->EndUpdate();
   }
 
   SavePasswordCheck = new TCheckBox(this);
@@ -239,36 +250,43 @@ __fastcall TSaveSessionDialog::TSaveSessionDialog(
 //---------------------------------------------------------------------------
 bool __fastcall TSaveSessionDialog::Execute(UnicodeString & SessionName, bool & SavePassword)
 {
-  SessionNameCombo->Text = SessionName;
+  FOriginalSessionName = SessionName;
+  SessionNameEdit->Text = TSessionData::ExtractLocalName(SessionName);
+  UnicodeString Folder = TSessionData::ExtractFolderName(SessionName);
+  if (Folder.IsEmpty())
+  {
+    FolderCombo->Text = FRootFolder;
+  }
+  else
+  {
+    FolderCombo->Text = Folder;
+  }
   SavePasswordCheck->Checked = SavePassword;
   bool Result = TCustomDialog::Execute();
   if (Result)
   {
-    SessionName = SessionNameCombo->Text;
+    SessionName = GetSessionName();
     SavePassword = SavePasswordCheck->Checked;
   }
   return Result;
 }
 //---------------------------------------------------------------------------
-void __fastcall TSaveSessionDialog::DoShow()
+UnicodeString __fastcall TSaveSessionDialog::GetSessionName()
 {
-  InstallPathWordBreakProc(SessionNameCombo);
-
-  int P = SessionNameCombo->Text.LastDelimiter(L"/");
-  if (P > 0)
+  UnicodeString Folder;
+  if (FolderCombo->Text != FRootFolder)
   {
-    SessionNameCombo->SetFocus();
-    SessionNameCombo->SelStart = P;
-    SessionNameCombo->SelLength = SessionNameCombo->Text.Length() - P;
+    Folder = FolderCombo->Text;
   }
-  TCustomDialog::DoShow();
+  return TSessionData::ComposePath(Folder, SessionNameEdit->Text);
 }
 //---------------------------------------------------------------------------
 void __fastcall TSaveSessionDialog::DoValidate()
 {
-  SessionNameValidate(SessionNameCombo->Text, FOriginalSession);
+  TSessionData::ValidateName(SessionNameEdit->Text);
+  SessionNameValidate(GetSessionName(), FOriginalSessionName);
 
-  UnicodeString Folder = UnixExtractFileDir(SessionNameCombo->Text);
+  UnicodeString Folder = TSessionData::ExtractFolderName(GetSessionName());
   if (!Folder.IsEmpty() && StoredSessions->IsWorkspace(Folder))
   {
     throw Exception(FMTLOAD(WORKSPACE_NOT_FOLDER, (Folder)));
@@ -285,34 +303,73 @@ void __fastcall TSaveSessionDialog::DoValidate()
 //---------------------------------------------------------------------------
 void __fastcall TSaveSessionDialog::DoChange(bool & CanSubmit)
 {
-  CanSubmit = !SessionNameCombo->Text.IsEmpty();
+  CanSubmit = !SessionNameEdit->Text.IsEmpty();
   TCustomDialog::DoChange(CanSubmit);
 }
 //---------------------------------------------------------------------------
-bool __fastcall DoSaveSessionDialog(UnicodeString & SessionName,
-  bool * SavePassword, TSessionData * OriginalSession, bool NotRecommendedSavingPassword)
+TSessionData * __fastcall DoSaveSession(TSessionData * SessionData,
+  TSessionData * OriginalSession, bool ForceDialog)
 {
+  bool SavePassword = false;
+  bool * PSavePassword;
+  bool NotRecommendedSavingPassword =
+    !CustomWinConfiguration->UseMasterPassword &&
+    !SameText(SessionData->UserName, AnonymousUserName);
+
+  if (Configuration->DisablePasswordStoring ||
+      !SessionData->HasAnyPassword())
+  {
+    PSavePassword = NULL;
+  }
+  else
+  {
+    PSavePassword = &SavePassword;
+    SavePassword =
+      ((OriginalSession != NULL) &&
+       !OriginalSession->Password.IsEmpty()) ||
+      !NotRecommendedSavingPassword;
+  }
+
+  UnicodeString SessionName = SessionData->SessionName;
+
   bool Result;
-  TSaveSessionDialog * Dialog = new TSaveSessionDialog(
-    OriginalSession, (SavePassword != NULL), NotRecommendedSavingPassword);
-  try
+  if (!ForceDialog && ((PSavePassword == NULL) || SavePassword))
+  {
+    Result = true;
+  }
+  else
   {
-    bool Dummy = false;
-    if (SavePassword == NULL)
+    TSaveSessionDialog * Dialog =
+      new TSaveSessionDialog((PSavePassword != NULL), NotRecommendedSavingPassword);
+    try
+    {
+      Result = Dialog->Execute(SessionName, SavePassword);
+    }
+    __finally
     {
-      SavePassword = &Dummy;
+      delete Dialog;
     }
-    Result = Dialog->Execute(SessionName, *SavePassword);
   }
-  __finally
+
+  TSessionData * NewSession = NULL;
+  if (Result)
   {
-    delete Dialog;
+    if ((PSavePassword != NULL) && !SavePassword)
+    {
+      SessionData->Password = L"";
+    }
+
+    NewSession =
+      StoredSessions->NewSession(SessionName, SessionData);
+    // modified only, explicit
+    StoredSessions->Save(false, true);
   }
-  return Result;
+
+  return NewSession;
 }
 //---------------------------------------------------------------------------
 void __fastcall SessionNameValidate(const UnicodeString & Text,
-  TSessionData * RenamingSession)
+  const UnicodeString & OriginalName)
 {
   TSessionData::ValidatePath(Text);
 
@@ -324,7 +381,7 @@ void __fastcall SessionNameValidate(const UnicodeString & Text,
       qtError, qaOK, HELP_NONE);
     Abort();
   }
-  else if (Data && (Data != RenamingSession) &&
+  else if ((Data != NULL) && (Text != OriginalName) &&
     MessageDialog(FMTLOAD(CONFIRM_OVERWRITE_SESSION, (Text)),
       qtConfirmation, qaYes | qaNo, HELP_SESSION_SAVE_OVERWRITE) != qaYes)
   {

+ 1 - 1
source/forms/CustomCommand.cpp

@@ -47,7 +47,7 @@ __fastcall TCustomCommandDialog::TCustomCommandDialog(TComponent* Owner,
   FCustomCommandList = CustomCommandList;
   FMode = Mode;
   FOnValidate = OnValidate;
-  HintLabel(HintText, LoadStr(CUSTOM_COMMAND_PATTERNS_HINT2));
+  HintLabel(HintText, LoadStr(CUSTOM_COMMAND_PATTERNS_HINT3));
 
   int CaptionRes;
   switch (FMode)

+ 7 - 80
source/forms/CustomScpExplorer.cpp

@@ -1963,7 +1963,7 @@ bool __fastcall TCustomScpExplorerForm::ExecuteFileOperation(TFileOperation Oper
         TMessageParams Params(mpNeverAskAgainCheck);
         Params.ImageName = L"DELETE_FILE";
         unsigned int Answer = MessageDialog(Query, qtConfirmation,
-          qaOK | qaCancel, HELP_NONE, &Params);
+          qaOK | qaCancel, HELP_DELETE_FILE, &Params);
         if (Answer == qaNeverAskAgain)
         {
           Result = true;
@@ -4493,38 +4493,7 @@ void __fastcall TCustomScpExplorerForm::SaveCurrentSession()
 
     TSessionData * EditingSessionData = StoredSessions->FindSame(SessionData);
 
-    bool SavePassword;
-    bool * PSavePassword;
-    bool NotRecommendedSavingPassword =
-      !CustomWinConfiguration->UseMasterPassword &&
-      !SameText(SessionData->UserName, AnonymousUserName);
-
-    if (Configuration->DisablePasswordStoring ||
-        !SessionData->HasAnyPassword())
-    {
-      PSavePassword = NULL;
-    }
-    else
-    {
-      PSavePassword = &SavePassword;
-      SavePassword =
-        ((EditingSessionData != NULL) &&
-         (EditingSessionData->Password == SessionData->Password)) ||
-        !NotRecommendedSavingPassword;
-    }
-
-    UnicodeString SessionName = Terminal->SessionData->SessionName;
-    if (DoSaveSessionDialog(SessionName, PSavePassword, EditingSessionData, NotRecommendedSavingPassword))
-    {
-      if ((PSavePassword != NULL) && !*PSavePassword)
-      {
-        SessionData->Password = L"";
-      }
-
-      StoredSessions->NewSession(SessionName, SessionData);
-      // modified only, explicit
-      StoredSessions->Save(false, true);
-    }
+    DoSaveSession(SessionData, EditingSessionData, true);
   }
   __finally
   {
@@ -4638,7 +4607,7 @@ bool __fastcall TCustomScpExplorerForm::SaveWorkspace(bool EnableAutoSave)
 
     if (CreateShortcut)
     {
-      CreateDesktopSessionShortCut(Name, L"", L"");
+      CreateDesktopSessionShortCut(Name, L"", L"", -1, WORKSPACE_ICON);
     }
 
     if (EnableAutoSave)
@@ -5442,20 +5411,7 @@ unsigned int __fastcall TCustomScpExplorerForm::MoreMessageDialog(const UnicodeS
       MoreMessagesCopy->Assign(MoreMessages);
     }
     FErrorList->AddObject(Message, MoreMessagesCopy);
-    if (Answers & qaSkip) return qaSkip;
-      else
-    if (Answers & qaIgnore) return qaIgnore;
-      else
-    if (Answers & qaOK) return qaOK;
-      else
-    if (Answers & qaYes) return qaYes;
-      else
-    if (Answers & qaRetry) return qaRetry;
-      else
-    {
-      assert(false);
-      return qaYes;
-    }
+    return ContinueAnswer(Answers);
   }
   else
   {
@@ -6499,7 +6455,7 @@ void __fastcall TCustomScpExplorerForm::RemoteFileControlDDQueryContinueDrag(
 //---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::DirViewMatchMask(
   TObject * /*Sender*/, UnicodeString FileName, bool Directory, __int64 Size,
-  TDateTime Modification, UnicodeString Masks, bool & Matches)
+  TDateTime Modification, UnicodeString Masks, bool & Matches, bool AllowImplicitMatches)
 {
   TFileMasks::TParams MaskParams;
   MaskParams.Size = Size;
@@ -6509,7 +6465,7 @@ void __fastcall TCustomScpExplorerForm::DirViewMatchMask(
   bool ImplicitMatch;
   Matches =
     FDirViewMatchMask.Matches(FileName, Directory, UnicodeString(L""), &MaskParams, ImplicitMatch) &&
-    !ImplicitMatch;
+    (AllowImplicitMatches || !ImplicitMatch);
 }
 //---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::DirViewGetOverlay(
@@ -7609,36 +7565,7 @@ int __fastcall TCustomScpExplorerForm::AddSessionColor(TColor Color, bool Shadow
 {
   if (Color != 0)
   {
-    if (Shadowed)
-    {
-      Color = GetShadowColor(Color);
-    }
-
-    int R, G, B;
-    GetRGB(Color, R, G, B);
-    TColor TransparentColor =
-      (TColor)
-      ((static_cast<int>(static_cast<unsigned char>(~B)) << 16) +
-       (static_cast<int>(static_cast<unsigned char>(~G)) << 8) +
-       static_cast<int>(static_cast<unsigned char>(~R)));
-
-    TBitmap * Bitmap = new TBitmap();
-    Bitmap->SetSize(FSessionColors->Width, FSessionColors->Height);
-    Bitmap->Canvas->Brush->Color = TransparentColor;
-    Bitmap->Canvas->Brush->Style = bsSolid;
-    TRect Rect(0, 0, FSessionColors->Width, FSessionColors->Height);
-    Bitmap->Canvas->FillRect(Rect);
-
-    const int Padding = 2;
-    TRect RoundRect(Padding, Padding + 1, FSessionColors->Width - Padding - 1, FSessionColors->Height - Padding);
-
-    Bitmap->Canvas->Pen->Color = Color;
-    Bitmap->Canvas->Pen->Style = psSolid;
-    Bitmap->Canvas->Brush->Color = Color;
-    Bitmap->Canvas->RoundRect(RoundRect, 4, 4);
-
-    FSessionColors->AddMasked(Bitmap, TransparentColor);
-    delete Bitmap;
+    AddSessionColorImage(FSessionColors, Color, Shadowed);
     return FSessionColors->Count - 1;
   }
   else

+ 1 - 1
source/forms/CustomScpExplorer.h

@@ -140,7 +140,7 @@ __published:
   void __fastcall RemoteDriveViewEnter(TObject *Sender);
   void __fastcall DirViewMatchMask(TObject *Sender, UnicodeString FileName,
     bool Directory, __int64 Size, TDateTime Modification,
-    UnicodeString Masks, bool &Matches);
+    UnicodeString Masks, bool &Matches, bool AllowImplicitMatches);
   void __fastcall DirViewGetOverlay(TObject *Sender, TListItem *Item,
     WORD &Indexes);
   void __fastcall DirViewHistoryChange(TCustomDirView *Sender);

+ 11 - 6
source/forms/Editor.cpp

@@ -294,7 +294,8 @@ static int __fastcall AdjustLineBreaks(unsigned char * Dest, const TBytes & Sour
         *P = 0;
         P++;
         // Skip #10 if preceeded by #13
-        if ((Source[I + 2] == 10) && (Source[I + 3] == 0))
+        if ((I < (Len - 3)) &&
+            (Source[I + 2] == 10) && (Source[I + 3] == 0))
         {
           I += 2;
         }
@@ -318,12 +319,14 @@ struct TStreamLoadInfo
 };
 //---------------------------------------------------------------------------
 // Copy from Vcl.ComCtrls.pas,
-/// WORKAROUND for bug in BCB XE2 VCL
+// WORKAROUND for bug in BCB XE2 VCL
 // Fixes conversion from UTF-8, when read buffer ends in the middle of UTF-8 char
 static unsigned long __stdcall StreamLoad(DWORD_PTR Cookie, unsigned char * Buff, long Read, long * WasRead)
 {
   TStreamLoadInfo * LoadInfo = reinterpret_cast<TStreamLoadInfo *>(Cookie);
-  return LoadInfo->RichEdit->StreamLoad(LoadInfo->StreamInfo, Buff, Read, *WasRead) ? 0 : 1;
+  unsigned long Result =
+    LoadInfo->RichEdit->StreamLoad(LoadInfo->StreamInfo, Buff, Read, *WasRead) ? 0 : 1;
+  return Result;
 }
 //---------------------------------------------------------------------------
 void __fastcall TRichEdit20::EMStreamIn(TMessage & Message)
@@ -411,6 +414,7 @@ bool __stdcall TRichEdit20::StreamLoad(
 {
   WasRead = 0;
 
+  bool Result;
   try
   {
     if (StreamInfo->Converter != NULL)
@@ -476,19 +480,20 @@ bool __stdcall TRichEdit20::StreamLoad(
       }
     }
 
-    return true;
+    Result = true;
   }
   catch (EEncodingError & E)
   {
     FStreamLoadError = true;
     FStreamLoadEncodingError = true;
-    return false;
+    Result = false;
   }
   catch (Exception & E)
   {
     FStreamLoadError = true;
-    return false;
+    Result = false;
   }
+  return Result;
 }
 //---------------------------------------------------------------------------
 bool __fastcall TRichEdit20::LoadFromStream(TStream * Stream, TEncoding * Encoding, bool & EncodingError)

+ 37 - 0
source/forms/FileFind.dfm

@@ -15,6 +15,43 @@ object FileFindDialog: TFileFindDialog
   Font.Height = -11
   Font.Name = 'MS Sans Serif'
   Font.Style = []
+  Icon.Data = {
+    0000010001001010000001002000680400001600000028000000100000002000
+    0000010020000000000040040000000000000000000000000000000000000000
+    000000000000000000000000000000000000736152CE736052FF736052FF7360
+    52FF736152CE00000000736152CE736052FF736052FF736052FF736152CE0000
+    000000000000000000000000000000000000736052FFD3C9C2FFFFFFFFFFA590
+    80FF736052FF00000000736052FFB9A89CFFFFFFFFFFEDE9E6FF736052FF0000
+    00000000000000000000000000000000000035302EF5292626FF292626FF2926
+    26FF35302EF50000000035302DF6292626FF292626FF292626FF35302DF60000
+    000000000000000000000000000000000000292626E751443AFF99816FFFB9AD
+    A5FF292626E700000000292626E7B8ACA4FF99816FFF51443AFF292626E70000
+    0000000000000000000000000000000000002A2727A54D423BFF8E7867FF8E84
+    7DFF2A2727A5000000002A2727A58E847DFF8E7867FF4D423BFF2A2727A51D84
+    B1F31E84B2FF1E84B2FF1E84B2FF1E84B2FF226381FF423A35FF5D5047FF4B46
+    44FF225F7BFF1E84B2FF235D78F84B4644FF5D5047FF423A35FF2825255A1E84
+    B2FF84E9FEFF84E9FEFF84E9FEFF84E9FEFF4F7780FF292626FF292626FF2926
+    26FF292626FF292626FF292626FF292626FF292626FF292626FF292525961E84
+    B2FF3AC6F0FF37C5F0FF37C5F0FF37C5F0FF2E5E6DFF65564CFFBBAB9FFF9981
+    6FFFB4A396FFBBAEA4FF8A796DFF99816FFFBBAB9FFF65564CFF292626A71E84
+    B2FF56E3FFFF49E1FFFF49E1FFFF48E1FFFF3EA3B8FF453C37FFBBAB9FFF9981
+    6FFF292626FF292626FF292626FF99816FFFBBAB9FFF453C37FF2B2727541E84
+    B2FF65E8FFFF4EE4FFFF4EE4FFFF4EE4FFFF4BDAF5FF2E3E42FF292626FF2926
+    26FF292626FF2B3031FF292626FF292626FF292626FF292626DC2B2B2B0C1E84
+    B2FF73EBFFFF54E7FFFF53E7FFFF53E7FFFF53E6FFFF52E6FFFF292626FFBAAA
+    9EFF292626FF51E5FFFF292626FFBAAA9EFF292626FF00000000000000001E84
+    B2FFEAFDFFFFEAFDFFFFEAFDFFFFEAFDFFFFEAFDFFFFEAFDFFFF555757FF2926
+    26FF535556FFEAFDFFFF263B46FF292626FF292626C700000000000000001E84
+    B2FF1E84B2FF1E84B2FF1E84B2FF1E84B2FF1E84B2FF1E84B2FF1E84B2FF1E84
+    B2FF1E84B2FF1E84B2FF1E84B2FF000000000000000000000000000000001E84
+    B2FF34CCF6FF34CCF6FF34CCF6FF34CCF6FF34CCF6FF34CCF6FF34CCF6FF34CC
+    F6FF34CCF6FF34CCF6FF1E84B2FF000000000000000000000000000000001E85
+    B2CA31B4DBFF41DDFFFF41DDFFFF41DDFFFF2EADD6FF1E84B2FF1E84B2FF1E84
+    B2FF1E84B2FF1E84B2FF1E84B2C3000000000000000000000000000000001A80
+    B3141E84B2C91E84B2FF1E84B2FF1E84B2FF1D84B2C71B80B61C000000000000
+    000000000000000000000000000000000000000000000000000000000000F820
+    0000F8200000F8200000F8200000F82000000000000000000000000000000000
+    0000000000000003000000030000000F0000000F0000000F000001FF0000}
   KeyPreview = True
   OldCreateOrder = False
   Position = poOwnerFormCenter

+ 1 - 0
source/forms/FullSynchronize.cpp

@@ -68,6 +68,7 @@ __fastcall TFullSynchronizeDialog::TFullSynchronizeDialog(TComponent* Owner)
   FPresetsMenu = new TPopupMenu(this);
   FSynchronizeBySizeCaption = SynchronizeBySizeCheck->Caption;
   HotTrackLabel(CopyParamLabel);
+  CopyParamListButton(TransferSettingsButton);
 }
 //---------------------------------------------------------------------------
 __fastcall TFullSynchronizeDialog::~TFullSynchronizeDialog()

+ 0 - 52
source/forms/GeneralSettings.cpp

@@ -1,52 +0,0 @@
-//---------------------------------------------------------------------------
-#include <vcl.h>
-#pragma hdrstop
-
-#include "GeneralSettings.h"
-
-#include <Common.h>
-#include <Configuration.h>
-#include <CoreMain.h>
-#include "CustomWinConfiguration.h"
-//---------------------------------------------------------------------------
-#pragma package(smart_init)
-#ifndef NO_RESOURCES
-#pragma resource "*.dfm"
-#endif
-//---------------------------------------------------------------------------
-__fastcall TGeneralSettingsFrame::TGeneralSettingsFrame(TComponent* Owner)
-        : TFrame(Owner)
-{
-}
-//---------------------------------------------------------------------------
-void __fastcall TGeneralSettingsFrame::CommanderClick(TObject * /*Sender*/)
-{
-  CommanderInterfaceButton2->SetFocus();
-}
-//---------------------------------------------------------------------------
-void __fastcall TGeneralSettingsFrame::ExplorerClick(TObject * /*Sender*/)
-{
-  ExplorerInterfaceButton2->SetFocus();
-}
-//---------------------------------------------------------------------------
-void __fastcall TGeneralSettingsFrame::SaveConfiguration()
-{
-  assert(CustomWinConfiguration);
-  TInterface NewInterface =
-    CommanderInterfaceButton2->Checked ? ifCommander : ifExplorer;
-  if (NewInterface != CustomWinConfiguration->Interface)
-  {
-    Configuration->Usage->Inc(L"InterfaceChanges");
-  }
-  CustomWinConfiguration->Interface = NewInterface;
-}
-//---------------------------------------------------------------------------
-void __fastcall TGeneralSettingsFrame::LoadConfiguration()
-{
-  assert(CustomWinConfiguration);
-  switch (CustomWinConfiguration->Interface) {
-    case ifCommander: CommanderInterfaceButton2->Checked = True; break;
-    case ifExplorer: ExplorerInterfaceButton2->Checked = True; break;
-    default: assert(false); break;
-  }
-}

+ 0 - 301
source/forms/GeneralSettings.dfm

@@ -1,301 +0,0 @@
-object GeneralSettingsFrame: TGeneralSettingsFrame
-  Left = 0
-  Top = 0
-  Width = 306
-  Height = 202
-  TabOrder = 0
-  DesignSize = (
-    306
-    202)
-  object InterfaceGroup: TGroupBox
-    Left = 0
-    Top = 0
-    Width = 306
-    Height = 202
-    Anchors = [akLeft, akTop, akRight, akBottom]
-    Caption = 'User Interface'
-    TabOrder = 0
-    DesignSize = (
-      306
-      202)
-    object CommanderDescriptionLabel2: TLabel
-      Left = 132
-      Top = 19
-      Width = 167
-      Height = 115
-      Anchors = [akLeft, akTop, akRight]
-      AutoSize = False
-      Caption = 
-        '- two panels (left for local directory, right for remote directo' +
-        'ry)'#13#10'- keyboard shortcuts like in Norton Commander (and other si' +
-        'milar programs as Total Commander, Midnight Commander...)'#13#10'- dra' +
-        'g && drop to/from both panels'
-      WordWrap = True
-      OnClick = CommanderClick
-    end
-    object ExplorerDescriptionLabel: TLabel
-      Left = 132
-      Top = 133
-      Width = 169
-      Height = 62
-      Anchors = [akLeft, akTop, akRight]
-      AutoSize = False
-      Caption = 
-        '- only remote directory'#13#10'- keyboard shortcuts like in Windows Ex' +
-        'plorer'#13#10'- drag && drop'
-      WordWrap = True
-      OnClick = ExplorerClick
-    end
-    object CommanderInterfacePicture: TImage
-      Left = 55
-      Top = 41
-      Width = 32
-      Height = 32
-      AutoSize = True
-      Picture.Data = {
-        0954506E67496D61676589504E470D0A1A0A0000000D49484452000000200000
-        00200806000000737A7AF4000000097048597300000EC400000EC401952B0E1B
-        00000A4F6943435050686F746F73686F70204943432070726F66696C65000078
-        DA9D53675453E9163DF7DEF4424B8880944B6F5215082052428B801491262A21
-        09104A8821A1D91551C1114545041BC8A088038E8E808C15512C0C8A0AD807E4
-        21A28E83A3888ACAFBE17BA36BD6BCF7E6CDFEB5D73EE7ACF39DB3CF07C0080C
-        9648335135800CA9421E11E083C7C4C6E1E42E40810A2470001008B3642173FD
-        230100F87E3C3C2B22C007BE000178D30B0800C04D9BC0301C87FF0FEA42995C
-        01808401C07491384B08801400407A8E42A600404601809D98265300A0040060
-        CB6362E300502D0060277FE6D300809DF8997B01005B94211501A09100201365
-        884400683B00ACCF568A450058300014664BC43900D82D00304957664800B0B7
-        00C0CE100BB200080C00305188852900047B0060C8232378008499001446F257
-        3CF12BAE10E72A00007899B23CB9243945815B082D710757572E1E28CE49172B
-        14366102619A402EC27999193281340FE0F3CC0000A0911511E083F3FD78CE0E
-        AECECE368EB60E5F2DEABF06FF226262E3FEE5CFAB70400000E1747ED1FE2C2F
-        B31A803B06806DFEA225EE04685E0BA075F78B66B20F40B500A0E9DA57F370F8
-        7E3C3C45A190B9D9D9E5E4E4D84AC4425B61CA577DFE67C25FC057FD6CF97E3C
-        FCF7F5E0BEE22481325D814704F8E0C2CCF44CA51CCF92098462DCE68F47FCB7
-        0BFFFC1DD322C44962B9582A14E35112718E449A8CF332A52289429229C525D2
-        FF64E2DF2CFB033EDF3500B06A3E017B912DA85D6303F64B27105874C0E2F700
-        00F2BB6FC1D4280803806883E1CF77FFEF3FFD47A02500806649927100005E44
-        242E54CAB33FC708000044A0812AB0411BF4C1182CC0061CC105DCC10BFC6036
-        844224C4C24210420A64801C726029AC82422886CDB01D2A602FD4401D34C051
-        688693700E2EC255B80E3D700FFA61089EC128BC81090441C808136121DA8801
-        628A58238E08179985F821C14804128B2420C9881451224B91354831528A5420
-        55481DF23D720239875C46BA913BC8003282FC86BC47319481B2513DD40CB543
-        B9A8371A8446A20BD06474319A8F16A09BD072B41A3D8C36A1E7D0AB680FDA8F
-        3E43C730C0E8180733C46C302EC6C342B1382C099363CBB122AC0CABC61AB056
-        AC03BB89F563CFB17704128145C0093604774220611E4148584C584ED848A820
-        1C243411DA093709038451C2272293A84BB426BA11F9C4186232318758482C23
-        D6128F132F107B8843C437241289433227B9900249B1A454D212D246D26E5223
-        E92CA99B34481A2393C9DA646BB20739942C202BC885E49DE4C3E433E41BE421
-        F25B0A9D624071A4F853E22852CA6A4A19E510E534E5066598324155A39A52DD
-        A8A15411358F5A42ADA1B652AF5187A81334759A39CD8316494BA5ADA295D31A
-        681768F769AFE874BA11DD951E4E97D057D2CBE947E897E803F4770C0D861583
-        C7886728199B18071867197718AF984CA619D38B19C754303731EB98E7990F99
-        6F55582AB62A7C1591CA0A954A9526951B2A2F54A9AAA6AADEAA0B55F355CB54
-        8FA95E537DAE46553353E3A909D496AB55AA9D50EB531B5367A93BA887AA67A8
-        6F543FA47E59FD890659C34CC34F43A451A0B15FE3BCC6200B6319B3782C216B
-        0DAB86758135C426B1CDD97C762ABB98FD1DBB8B3DAAA9A13943334A3357B352
-        F394663F07E39871F89C744E09E728A797F37E8ADE14EF29E2291BA6344CB931
-        655C6BAA96979658AB48AB51AB47EBBD36AEEDA79DA6BD45BB59FB810E41C74A
-        275C2747678FCE059DE753D953DDA70AA7164D3D3AF5AE2EAA6BA51BA1BB4477
-        BF6EA7EE989EBE5E809E4C6FA7DE79BDE7FA1C7D2FFD54FD6DFAA7F5470C5806
-        B30C2406DB0CCE183CC535716F3C1D2FC7DBF151435DC34043A561956197E184
-        91B9D13CA3D5468D460F8C69C65CE324E36DC66DC6A326062621264B4DEA4DEE
-        9A524DB9A629A63B4C3B4CC7CDCCCDA2CDD699359B3D31D732E79BE79BD79BDF
-        B7605A785A2CB6A8B6B86549B2E45AA659EEB6BC6E855A3959A558555A5DB346
-        AD9DAD25D6BBADBBA711A7B94E934EAB9ED667C3B0F1B6C9B6A9B719B0E5D806
-        DBAEB66DB67D6167621767B7C5AEC3EE93BD937DBA7D8DFD3D070D87D90EAB1D
-        5A1D7E73B472143A563ADE9ACE9CEE3F7DC5F496E92F6758CF10CFD833E3B613
-        CB29C4699D539BD347671767B97383F3888B894B82CB2E973E2E9B1BC6DDC8BD
-        E44A74F5715DE17AD2F59D9BB39BC2EDA8DBAFEE36EE69EE87DC9FCC349F299E
-        593373D0C3C843E051E5D13F0B9F95306BDFAC7E4F434F8167B5E7232F632F91
-        57ADD7B0B7A577AAF761EF173EF63E729FE33EE33C37DE32DE595FCC37C0B7C8
-        B7CB4FC36F9E5F85DF437F23FF64FF7AFFD100A78025016703898141815B02FB
-        F87A7C21BF8E3F3ADB65F6B2D9ED418CA0B94115418F82AD82E5C1AD2168C8EC
-        90AD21F7E798CE91CE690E85507EE8D6D00761E6618BC37E0C2785878557863F
-        8E7088581AD131973577D1DC4373DF44FA449644DE9B67314F39AF2D4A352A3E
-        AA2E6A3CDA37BA34BA3FC62E6659CCD5589D58496C4B1C392E2AAE366E6CBEDF
-        FCEDF387E29DE20BE37B17982FC85D7079A1CEC2F485A716A92E122C3A96404C
-        884E3894F041102AA8168C25F21377258E0A79C21DC267222FD136D188D8435C
-        2A1E4EF2482A4D7A92EC91BC357924C533A52CE5B98427A990BC4C0D4CDD9B3A
-        9E169A76206D323D3ABD31839291907142AA214D93B667EA67E66676CBAC6585
-        B2FEC56E8BB72F1E9507C96BB390AC05592D0AB642A6E8545A28D72A07B26765
-        5766BFCD89CA3996AB9E2BCDEDCCB3CADB90379CEF9FFFED12C212E192B6A586
-        4B572D1D58E6BDAC6A39B23C7179DB0AE315052B865606AC3CB88AB62A6DD54F
-        ABED5797AE7EBD267A4D6B815EC1CA82C1B5016BEB0B550AE5857DEBDCD7ED5D
-        4F582F59DFB561FA869D1B3E15898AAE14DB1797157FD828DC78E51B876FCABF
-        99DC94B4A9ABC4B964CF66D266E9E6DE2D9E5B0E96AA97E6970E6E0DD9DAB40D
-        DF56B4EDF5F645DB2F97CD28DBBB83B643B9A3BF3CB8BC65A7C9CECD3B3F54A4
-        54F454FA5436EED2DDB561D7F86ED1EE1B7BBCF634ECD5DB5BBCF7FD3EC9BEDB
-        5501554DD566D565FB49FBB3F73FAE89AAE9F896FB6D5DAD4E6D71EDC703D203
-        FD07230EB6D7B9D4D51DD23D54528FD62BEB470EC71FBEFE9DEF772D0D360D55
-        8D9CC6E223704479E4E9F709DFF71E0D3ADA768C7BACE107D31F761D671D2F6A
-        429AF29A469B539AFB5B625BBA4FCC3ED1D6EADE7AFC47DB1F0F9C343C59794A
-        F354C969DAE982D39367F2CF8C9D959D7D7E2EF9DC60DBA2B67BE763CEDF6A0F
-        6FEFBA1074E1D245FF8BE73BBC3BCE5CF2B874F2B2DBE51357B8579AAF3A5F6D
-        EA74EA3CFE93D34FC7BB9CBB9AAEB95C6BB9EE7ABDB57B66F7E91B9E37CEDDF4
-        BD79F116FFD6D59E393DDDBDF37A6FF7C5F7F5DF16DD7E7227FDCECBBBD97727
-        EEADBC4FBC5FF440ED41D943DD87D53F5BFEDCD8EFDC7F6AC077A0F3D1DC47F7
-        068583CFFE91F58F0F43058F998FCB860D86EB9E383E3939E23F72FDE9FCA743
-        CF64CF269E17FEA2FECBAE17162F7EF8D5EBD7CED198D1A197F29793BF6D7CA5
-        FDEAC0EB19AFDBC6C2C61EBEC97833315EF456FBEDC177DC771DEFA3DF0F4FE4
-        7C207F28FF68F9B1F553D0A7FB93199393FF040398F3FC63332DDB000002AD49
-        44415478DA63FCFFFF3FC34002C65107801CC06B5E7803C856A7B3DD373F9FEC
-        D78039E07F5649235D6D9FD653CF00740023DC016A36517475C0AD23CB501DB0
-        765E03C986EC3C7A9EC1DDDA902C070427350C32077C3AD18FA28098BC513AFB
-        004377AA03590EE0B7284475C087E37D241B5236E72043578A3D590E10B02C42
-        75C07BA0033E3636405C57DF409421E540077426DB3374AEBC0AE1876B13D403
-        0B59212B3407BC3B06744013D4017510BA62EE41AC867424DBC3E53BB0380097
-        3E106887EA154677C0DBA3A44741E5BC830CED49F644A5177420628DE6803747
-        7A19BA0E427C5E668F88027C8657CF3FC4D09A68C7F0E17C17982F605846B403
-        446D8A511DF00AE8806EA8034AA10EA8015A800DB4002D85C9B76071002E7D60
-        BD0910BD62B6680E7879B897E460AC5D7088A1196A20A9401CDD012F0EF5327C
-        BC00F109BF01714159B7F0104353BC1DC3D716488871D7344065B0471CB2A8A4
-        5D09AA039E1FEA61F874A11B2CC967500AA6EB171EC66A50639C2D447ED16130
-        FB6B0BA422E3AAA907D30D8BB0EB03CB41F54AD9A339E0D9C11EBCBEC5E6A746
-        A045F550034905D2E80E787AA087A16FED35B06451B0165E8B61A069F16186BA
-        585B867EA8BE42247D84808C039A031EEFEFC130A87909F6A0AC8DB185CB83D8
-        087D9A50F123382DAE8DB101D3B28EA5A80E78B4BF9BE4606C015A540335102B
-        C0137C724E680E78B8AF9BE1EB258823B8F54A897240EBD2230CD5D1360C138E
-        42126181753D5EF5C8EE514077C083BDDD0CDF2E431CC0A50B7140DB32EC4159
-        1565039707B127421D90077540FB32DC515009D5ABE88CE680FB7BF14701B6D6
-        73C7F2A30C1591D64485163A5072294375C0DD3D5D241BD209744039290E40F2
-        83B22B9A03D292FDC9F209B960D6DC8D94B709290154699452D30157806284DB
-        53D405889ED140820177000047FBBCD0A8A483CB0000000049454E44AE426082}
-      OnClick = CommanderClick
-    end
-    object ExplorerInterfacePicture: TImage
-      Left = 55
-      Top = 155
-      Width = 32
-      Height = 32
-      AutoSize = True
-      Picture.Data = {
-        0954506E67496D61676589504E470D0A1A0A0000000D49484452000000200000
-        00200806000000737A7AF4000000097048597300000EC400000EC401952B0E1B
-        00000A4F6943435050686F746F73686F70204943432070726F66696C65000078
-        DA9D53675453E9163DF7DEF4424B8880944B6F5215082052428B801491262A21
-        09104A8821A1D91551C1114545041BC8A088038E8E808C15512C0C8A0AD807E4
-        21A28E83A3888ACAFBE17BA36BD6BCF7E6CDFEB5D73EE7ACF39DB3CF07C0080C
-        9648335135800CA9421E11E083C7C4C6E1E42E40810A2470001008B3642173FD
-        230100F87E3C3C2B22C007BE000178D30B0800C04D9BC0301C87FF0FEA42995C
-        01808401C07491384B08801400407A8E42A600404601809D98265300A0040060
-        CB6362E300502D0060277FE6D300809DF8997B01005B94211501A09100201365
-        884400683B00ACCF568A450058300014664BC43900D82D00304957664800B0B7
-        00C0CE100BB200080C00305188852900047B0060C8232378008499001446F257
-        3CF12BAE10E72A00007899B23CB9243945815B082D710757572E1E28CE49172B
-        14366102619A402EC27999193281340FE0F3CC0000A0911511E083F3FD78CE0E
-        AECECE368EB60E5F2DEABF06FF226262E3FEE5CFAB70400000E1747ED1FE2C2F
-        B31A803B06806DFEA225EE04685E0BA075F78B66B20F40B500A0E9DA57F370F8
-        7E3C3C45A190B9D9D9E5E4E4D84AC4425B61CA577DFE67C25FC057FD6CF97E3C
-        FCF7F5E0BEE22481325D814704F8E0C2CCF44CA51CCF92098462DCE68F47FCB7
-        0BFFFC1DD322C44962B9582A14E35112718E449A8CF332A52289429229C525D2
-        FF64E2DF2CFB033EDF3500B06A3E017B912DA85D6303F64B27105874C0E2F700
-        00F2BB6FC1D4280803806883E1CF77FFEF3FFD47A02500806649927100005E44
-        242E54CAB33FC708000044A0812AB0411BF4C1182CC0061CC105DCC10BFC6036
-        844224C4C24210420A64801C726029AC82422886CDB01D2A602FD4401D34C051
-        688693700E2EC255B80E3D700FFA61089EC128BC81090441C808136121DA8801
-        628A58238E08179985F821C14804128B2420C9881451224B91354831528A5420
-        55481DF23D720239875C46BA913BC8003282FC86BC47319481B2513DD40CB543
-        B9A8371A8446A20BD06474319A8F16A09BD072B41A3D8C36A1E7D0AB680FDA8F
-        3E43C730C0E8180733C46C302EC6C342B1382C099363CBB122AC0CABC61AB056
-        AC03BB89F563CFB17704128145C0093604774220611E4148584C584ED848A820
-        1C243411DA093709038451C2272293A84BB426BA11F9C4186232318758482C23
-        D6128F132F107B8843C437241289433227B9900249B1A454D212D246D26E5223
-        E92CA99B34481A2393C9DA646BB20739942C202BC885E49DE4C3E433E41BE421
-        F25B0A9D624071A4F853E22852CA6A4A19E510E534E5066598324155A39A52DD
-        A8A15411358F5A42ADA1B652AF5187A81334759A39CD8316494BA5ADA295D31A
-        681768F769AFE874BA11DD951E4E97D057D2CBE947E897E803F4770C0D861583
-        C7886728199B18071867197718AF984CA619D38B19C754303731EB98E7990F99
-        6F55582AB62A7C1591CA0A954A9526951B2A2F54A9AAA6AADEAA0B55F355CB54
-        8FA95E537DAE46553353E3A909D496AB55AA9D50EB531B5367A93BA887AA67A8
-        6F543FA47E59FD890659C34CC34F43A451A0B15FE3BCC6200B6319B3782C216B
-        0DAB86758135C426B1CDD97C762ABB98FD1DBB8B3DAAA9A13943334A3357B352
-        F394663F07E39871F89C744E09E728A797F37E8ADE14EF29E2291BA6344CB931
-        655C6BAA96979658AB48AB51AB47EBBD36AEEDA79DA6BD45BB59FB810E41C74A
-        275C2747678FCE059DE753D953DDA70AA7164D3D3AF5AE2EAA6BA51BA1BB4477
-        BF6EA7EE989EBE5E809E4C6FA7DE79BDE7FA1C7D2FFD54FD6DFAA7F5470C5806
-        B30C2406DB0CCE183CC535716F3C1D2FC7DBF151435DC34043A561956197E184
-        91B9D13CA3D5468D460F8C69C65CE324E36DC66DC6A326062621264B4DEA4DEE
-        9A524DB9A629A63B4C3B4CC7CDCCCDA2CDD699359B3D31D732E79BE79BD79BDF
-        B7605A785A2CB6A8B6B86549B2E45AA659EEB6BC6E855A3959A558555A5DB346
-        AD9DAD25D6BBADBBA711A7B94E934EAB9ED667C3B0F1B6C9B6A9B719B0E5D806
-        DBAEB66DB67D6167621767B7C5AEC3EE93BD937DBA7D8DFD3D070D87D90EAB1D
-        5A1D7E73B472143A563ADE9ACE9CEE3F7DC5F496E92F6758CF10CFD833E3B613
-        CB29C4699D539BD347671767B97383F3888B894B82CB2E973E2E9B1BC6DDC8BD
-        E44A74F5715DE17AD2F59D9BB39BC2EDA8DBAFEE36EE69EE87DC9FCC349F299E
-        593373D0C3C843E051E5D13F0B9F95306BDFAC7E4F434F8167B5E7232F632F91
-        57ADD7B0B7A577AAF761EF173EF63E729FE33EE33C37DE32DE595FCC37C0B7C8
-        B7CB4FC36F9E5F85DF437F23FF64FF7AFFD100A78025016703898141815B02FB
-        F87A7C21BF8E3F3ADB65F6B2D9ED418CA0B94115418F82AD82E5C1AD2168C8EC
-        90AD21F7E798CE91CE690E85507EE8D6D00761E6618BC37E0C2785878557863F
-        8E7088581AD131973577D1DC4373DF44FA449644DE9B67314F39AF2D4A352A3E
-        AA2E6A3CDA37BA34BA3FC62E6659CCD5589D58496C4B1C392E2AAE366E6CBEDF
-        FCEDF387E29DE20BE37B17982FC85D7079A1CEC2F485A716A92E122C3A96404C
-        884E3894F041102AA8168C25F21377258E0A79C21DC267222FD136D188D8435C
-        2A1E4EF2482A4D7A92EC91BC357924C533A52CE5B98427A990BC4C0D4CDD9B3A
-        9E169A76206D323D3ABD31839291907142AA214D93B667EA67E66676CBAC6585
-        B2FEC56E8BB72F1E9507C96BB390AC05592D0AB642A6E8545A28D72A07B26765
-        5766BFCD89CA3996AB9E2BCDEDCCB3CADB90379CEF9FFFED12C212E192B6A586
-        4B572D1D58E6BDAC6A39B23C7179DB0AE315052B865606AC3CB88AB62A6DD54F
-        ABED5797AE7EBD267A4D6B815EC1CA82C1B5016BEB0B550AE5857DEBDCD7ED5D
-        4F582F59DFB561FA869D1B3E15898AAE14DB1797157FD828DC78E51B876FCABF
-        99DC94B4A9ABC4B964CF66D266E9E6DE2D9E5B0E96AA97E6970E6E0DD9DAB40D
-        DF56B4EDF5F645DB2F97CD28DBBB83B643B9A3BF3CB8BC65A7C9CECD3B3F54A4
-        54F454FA5436EED2DDB561D7F86ED1EE1B7BBCF634ECD5DB5BBCF7FD3EC9BEDB
-        5501554DD566D565FB49FBB3F73FAE89AAE9F896FB6D5DAD4E6D71EDC703D203
-        FD07230EB6D7B9D4D51DD23D54528FD62BEB470EC71FBEFE9DEF772D0D360D55
-        8D9CC6E223704479E4E9F709DFF71E0D3ADA768C7BACE107D31F761D671D2F6A
-        429AF29A469B539AFB5B625BBA4FCC3ED1D6EADE7AFC47DB1F0F9C343C59794A
-        F354C969DAE982D39367F2CF8C9D959D7D7E2EF9DC60DBA2B67BE763CEDF6A0F
-        6FEFBA1074E1D245FF8BE73BBC3BCE5CF2B874F2B2DBE51357B8579AAF3A5F6D
-        EA74EA3CFE93D34FC7BB9CBB9AAEB95C6BB9EE7ABDB57B66F7E91B9E37CEDDF4
-        BD79F116FFD6D59E393DDDBDF37A6FF7C5F7F5DF16DD7E7227FDCECBBBD97727
-        EEADBC4FBC5FF440ED41D943DD87D53F5BFEDCD8EFDC7F6AC077A0F3D1DC47F7
-        068583CFFE91F58F0F43058F998FCB860D86EB9E383E3939E23F72FDE9FCA743
-        CF64CF269E17FEA2FECBAE17162F7EF8D5EBD7CED198D1A197F29793BF6D7CA5
-        FDEAC0EB19AFDBC6C2C61EBEC97833315EF456FBEDC177DC771DEFA3DF0F4FE4
-        7C207F28FF68F9B1F553D0A7FB93199393FF040398F3FC63332DDB0000029949
-        44415478DA63FCFFFF3FC3400246900378CC8BEE3132FC57A4B6E1FF1918EF7F
-        3DD5AF84531E6837D801BCE685FFB34A1AA9EEBB693DF50C5F4E4D6024CA016A
-        36515477C0AD23CB8877C0DA790D5477407052C31072C09BA37D547780887511
-        F10E7875B8172CF863FE34B8028EC42C140D3FAF55C1D9EC5A6D287273AE4E80
-        B353B40BC0B4986D31F10E787EA8072CF8BDBF13AE80B3B01C45C3B74BB57036
-        975E338ADCA4D3AD70769E69359896B42B21DE014F0E401DD0508D7040432B8A
-        862FE7EBE06C1EC32614B9CE4388D029B783848E8C03090E78B4AF9B81DA40CE
-        A9947807DCDF0B7140FBB22370059551360C76D1ED0C8F5FBCA3BAE340A5E497
-        937D4A7007DCD9DD8555A18A6B1903AD4AC9CF27FB19E10EB8B5AB13AB4235B7
-        72065A9592280EB8BE03E280F9073FC11525DAF331687A9433D0AA904271C095
-        6D1D6089193B9FC11565B84B31E87855D0C70197B6421C3069C32DB8A2BC0035
-        063DEF0A065A9592280E38BFB91DAB4243DF4A06582989ADB48381C9BB3EC0D9
-        B96E022872D84A57502989E280331B210E98B5E9045C719A9F0583897F2503AC
-        94C456DAC140EFC6277076B1BF0C8A1CB6D215544AA238E0D406D4B21D06CC02
-        AA1860A524B6D20E06DA57DE80B32BC335501D80A5740595927007106A92D1AA
-        94843B8091116769C9C0635680B39444090112E5149D497000AE529212002A61
-        897600AE529212002A61897600AC94645E3A132EFE373A1D451DEB5D445BE1B7
-        326A5B01BD74050150094BB40360A524D3B41EB8F8BFAC1214754C37EB1172EA
-        A895177AE90A02A012966807C04A49A6764483E45F256A83E4FF5584A58CDAF5
-        2872E8A52B08804A58A21D80AB94A404804A58A21D80AB944406A4CA814A58A2
-        1D80AB94A404804A58A21CC06D5648B38E2BBC493690000005DADFD0D42C4D64
-        0000000049454E44AE426082}
-      Transparent = True
-      OnClick = ExplorerClick
-    end
-    object CommanderInterfaceButton2: TRadioButton
-      Left = 16
-      Top = 19
-      Width = 117
-      Height = 17
-      Caption = '&Commander'
-      Checked = True
-      TabOrder = 0
-      TabStop = True
-    end
-    object ExplorerInterfaceButton2: TRadioButton
-      Left = 16
-      Top = 133
-      Width = 111
-      Height = 17
-      Caption = '&Explorer'
-      TabOrder = 1
-    end
-  end
-end

+ 0 - 31
source/forms/GeneralSettings.h

@@ -1,31 +0,0 @@
-//---------------------------------------------------------------------------
-#ifndef GeneralSettingsH
-#define GeneralSettingsH
-//---------------------------------------------------------------------------
-#include <Classes.hpp>
-#include <Controls.hpp>
-#include <StdCtrls.hpp>
-#include <Forms.hpp>
-#include <ExtCtrls.hpp>
-#include <Graphics.hpp>
-#include <Vcl.Imaging.pngimage.hpp>
-//---------------------------------------------------------------------------
-class TGeneralSettingsFrame : public TFrame
-{
-__published:
-  TGroupBox *InterfaceGroup;
-  TLabel *CommanderDescriptionLabel2;
-  TLabel *ExplorerDescriptionLabel;
-  TImage *CommanderInterfacePicture;
-  TImage *ExplorerInterfacePicture;
-  TRadioButton *CommanderInterfaceButton2;
-  TRadioButton *ExplorerInterfaceButton2;
-  void __fastcall CommanderClick(TObject *Sender);
-  void __fastcall ExplorerClick(TObject *Sender);
-public:
-  void __fastcall LoadConfiguration();
-  void __fastcall SaveConfiguration();
-  __fastcall TGeneralSettingsFrame(TComponent* Owner);
-};
-//---------------------------------------------------------------------------
-#endif

+ 143 - 0
source/forms/Glyphs.dfm

@@ -11911,4 +11911,147 @@ object GlyphsModule: TGlyphsModule
       FFFFFFFF00000000FFFFFFFF0000000000000000000000000000000000000000
       000000000000}
   end
+  object ButtonImages: TImageList
+    Left = 136
+    Top = 152
+    Bitmap = {
+      494C010102000400480010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
+      0000000000003600000028000000400000001000000001002000000000000010
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000A0A0A00000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000A0A0A000A0A0A000A0A0A000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000A0A0A000A0A0A000A0A0A000A0A0A000A0A0A0000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000A0A0A000A0A0A000A0A0A000A0A0A000A0A0A000A0A0A000A0A0
+      A000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000A0A0A000A0A0A000A0A0A000A0A0A000A0A0A000A0A0A000A0A0A000A0A0
+      A000A0A0A0000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000424D3E000000000000003E000000
+      2800000040000000100000000100010000000000800000000000000000000000
+      000000000000000000000000FFFFFF00FFFFFFFF00000000FFFFFFFF00000000
+      FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FF7FFF7F00000000
+      FE3FFE3F00000000FC1FFC1F00000000F80FF80F00000000F007F00700000000
+      FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000
+      FFFFFFFF00000000FFFFFFFF0000000000000000000000000000000000000000
+      000000000000}
+  end
 end

+ 1 - 0
source/forms/Glyphs.h

@@ -15,6 +15,7 @@ __published:
   TPngImageList *QueueImages;
   TPngImageList *LogImages;
   TImageList *ArrowImages;
+  TImageList *ButtonImages;
 
 public:
   __fastcall TGlyphsModule(TComponent * Owner);

+ 16 - 16
source/forms/ImportSessions.cpp

@@ -87,12 +87,12 @@ TStoredSessionList * __fastcall TImportSessionsDialog::GetSessionList(int Index)
 //---------------------------------------------------------------------
 void __fastcall TImportSessionsDialog::UpdateControls()
 {
-  EnableControl(OKButton, ListViewAnyChecked(SessionListView));
+  EnableControl(OKButton, ListViewAnyChecked(SessionListView2));
 
   bool AnySshChecked = false;
-  for (int Index = 0; Index < SessionListView->Items->Count; Index++)
+  for (int Index = 0; Index < SessionListView2->Items->Count; Index++)
   {
-    TListItem * Item = SessionListView->Items->Item[Index];
+    TListItem * Item = SessionListView2->Items->Item[Index];
     TSessionData * Data = (TSessionData*)Item->Data;
     if (Item->Checked && Data->UsesSsh)
     {
@@ -103,8 +103,8 @@ void __fastcall TImportSessionsDialog::UpdateControls()
 
   EnableControl(ImportKeysCheck, AnySshChecked);
 
-  EnableControl(CheckAllButton, SessionListView->Items->Count > 0);
-  AdjustListColumnsWidth(SessionListView);
+  EnableControl(CheckAllButton, SessionListView2->Items->Count > 0);
+  AdjustListColumnsWidth(SessionListView2);
 }
 //---------------------------------------------------------------------
 void __fastcall TImportSessionsDialog::ClearSelections()
@@ -121,24 +121,24 @@ void __fastcall TImportSessionsDialog::ClearSelections()
 //---------------------------------------------------------------------
 void __fastcall TImportSessionsDialog::SaveSelection()
 {
-  for (int Index = 0; Index < SessionListView->Items->Count; Index++)
+  for (int Index = 0; Index < SessionListView2->Items->Count; Index++)
   {
-    ((TSessionData*)SessionListView->Items->Item[Index]->Data)->Selected =
-      SessionListView->Items->Item[Index]->Checked;
+    ((TSessionData*)SessionListView2->Items->Item[Index]->Data)->Selected =
+      SessionListView2->Items->Item[Index]->Checked;
   }
 }
 //---------------------------------------------------------------------
 void __fastcall TImportSessionsDialog::LoadSessions()
 {
-  SessionListView->Items->BeginUpdate();
+  SessionListView2->Items->BeginUpdate();
   try
   {
-    SessionListView->Items->Clear();
+    SessionListView2->Items->Clear();
     TStoredSessionList * SessionList = GetSessionList(SourceComboBox->ItemIndex);
     for (int Index = 0; Index < SessionList->Count; Index++)
     {
       TSessionData * Session = SessionList->Sessions[Index];
-      TListItem * Item = SessionListView->Items->Add();
+      TListItem * Item = SessionListView2->Items->Add();
       Item->Data = Session;
       Item->Caption = Session->Name;
       Item->Checked = Session->Selected;
@@ -146,25 +146,25 @@ void __fastcall TImportSessionsDialog::LoadSessions()
   }
   __finally
   {
-    SessionListView->Items->EndUpdate();
+    SessionListView2->Items->EndUpdate();
   }
   UpdateControls();
 }
 //---------------------------------------------------------------------------
-void __fastcall TImportSessionsDialog::SessionListViewInfoTip(
+void __fastcall TImportSessionsDialog::SessionListView2InfoTip(
       TObject * /*Sender*/, TListItem * Item, UnicodeString & InfoTip)
 {
   InfoTip = ((TSessionData*)Item->Data)->InfoTip;
 }
 //---------------------------------------------------------------------------
-void __fastcall TImportSessionsDialog::SessionListViewMouseDown(
+void __fastcall TImportSessionsDialog::SessionListView2MouseDown(
       TObject * /*Sender*/, TMouseButton /*Button*/, TShiftState /*Shift*/,
       int /*X*/, int /*Y*/)
 {
   UpdateControls();
 }
 //---------------------------------------------------------------------------
-void __fastcall TImportSessionsDialog::SessionListViewKeyUp(
+void __fastcall TImportSessionsDialog::SessionListView2KeyUp(
       TObject * /*Sender*/, WORD & /*Key*/, TShiftState /*Shift*/)
 {
   UpdateControls();
@@ -177,7 +177,7 @@ void __fastcall TImportSessionsDialog::FormShow(TObject * /*Sender*/)
 //---------------------------------------------------------------------------
 void __fastcall TImportSessionsDialog::CheckAllButtonClick(TObject * /*Sender*/)
 {
-  ListViewCheckAll(SessionListView, caToggle);
+  ListViewCheckAll(SessionListView2, caToggle);
   UpdateControls();
 }
 //---------------------------------------------------------------------------

+ 4 - 4
source/forms/ImportSessions.dfm

@@ -48,7 +48,7 @@ object ImportSessionsDialog: TImportSessionsDialog
     ModalResult = 2
     TabOrder = 5
   end
-  object SessionListView: TListView
+  object SessionListView2: TListView
     Left = 8
     Top = 35
     Width = 361
@@ -70,9 +70,9 @@ object ImportSessionsDialog: TImportSessionsDialog
     ShowHint = True
     TabOrder = 1
     ViewStyle = vsReport
-    OnInfoTip = SessionListViewInfoTip
-    OnKeyUp = SessionListViewKeyUp
-    OnMouseDown = SessionListViewMouseDown
+    OnInfoTip = SessionListView2InfoTip
+    OnKeyUp = SessionListView2KeyUp
+    OnMouseDown = SessionListView2MouseDown
   end
   object CheckAllButton: TButton
     Left = 8

+ 4 - 4
source/forms/ImportSessions.h

@@ -14,17 +14,17 @@ class TImportSessionsDialog : public TForm
 __published:
   TButton *OKButton;
   TButton *CancelButton;
-  TListView *SessionListView;
+  TListView *SessionListView2;
   TLabel *Label;
   TButton *CheckAllButton;
   TCheckBox *ImportKeysCheck;
   TButton *HelpButton;
   TComboBox *SourceComboBox;
-  void __fastcall SessionListViewInfoTip(TObject *Sender,
+  void __fastcall SessionListView2InfoTip(TObject *Sender,
     TListItem *Item, UnicodeString &InfoTip);
-  void __fastcall SessionListViewMouseDown(TObject *Sender,
+  void __fastcall SessionListView2MouseDown(TObject *Sender,
     TMouseButton Button, TShiftState Shift, int X, int Y);
-  void __fastcall SessionListViewKeyUp(TObject *Sender, WORD &Key,
+  void __fastcall SessionListView2KeyUp(TObject *Sender, WORD &Key,
     TShiftState Shift);
   void __fastcall FormShow(TObject *Sender);
   void __fastcall CheckAllButtonClick(TObject *Sender);

+ 0 - 162
source/forms/LogSettings.cpp

@@ -1,162 +0,0 @@
-//---------------------------------------------------------------------------
-#include <vcl.h>
-#pragma hdrstop
-
-#include <Common.h>
-
-#include "LogSettings.h"
-
-#include <CoreMain.h>
-#include <TextsWin.h>
-
-#include <VCLCommon.h>
-#include <Tools.h>
-#include "CustomWinConfiguration.h"
-//---------------------------------------------------------------------------
-#pragma package(smart_init)
-#pragma link "ComboEdit"
-#pragma link "UpDownEdit"
-#ifndef NO_RESOURCES
-#pragma resource "*.dfm"
-#endif
-TLoggingFrame *LoggingFrame;
-//---------------------------------------------------------------------------
-__fastcall TLoggingFrame::TLoggingFrame(TComponent* Owner)
-        : TFrame(Owner)
-{
-  FEnableLogWindow = true;
-}
-//---------------------------------------------------------------------------
-void __fastcall TLoggingFrame::Init()
-{
-  HintLabel(LogFileNameHintText, LoadStr(LOG_FILE_HINT3));
-  HintLabel(ActionsLogFileNameHintText, LoadStr(LOG_FILE_HINT3));
-
-  // anchors does not apply for some reason to this particular control
-  LogFileNameHintText->Left = LogFileNameEdit3->Left + LogFileNameEdit3->Width -
-    LogFileNameHintText->Width;
-}
-//---------------------------------------------------------------------------
-void __fastcall TLoggingFrame::LoadConfiguration()
-{
-  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;
-}
-//---------------------------------------------------------------------------
-void __fastcall TLoggingFrame::SaveConfiguration()
-{
-  Configuration->BeginUpdate();
-  try
-  {
-    Configuration->Logging = EnableLoggingCheck->Checked;
-    Configuration->LogProtocol = LogProtocolCombo->ItemIndex;
-    Configuration->LogFileName = LogToFileCheck->Checked ? LogFileNameEdit3->Text : UnicodeString();
-    Configuration->LogFileAppend = LogFileAppendButton->Checked;
-    if (EnableLogWindow)
-    {
-      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;
-  }
-  __finally
-  {
-    Configuration->EndUpdate();
-  }
-}
-//---------------------------------------------------------------------------
-void __fastcall TLoggingFrame::UpdateControls()
-{
-  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 && EnableLogWindow);
-  EnableControl(LogWindowCompleteButton, LogShowWindowCheck->Enabled && LogShowWindowCheck->Checked);
-  EnableControl(LogWindowLinesButton, LogWindowCompleteButton->Enabled);
-  EnableControl(LogWindowLinesText, LogWindowCompleteButton->Enabled);
-  EnableControl(LogWindowLinesEdit, LogWindowLinesButton->Enabled && LogWindowLinesButton->Checked);
-
-  EnableControl(ActionsLogFileNameEdit, EnableActionsLoggingCheck->Checked);
-  EnableControl(ActionsLogFileNameHintText, ActionsLogFileNameEdit->Enabled);
-}
-//---------------------------------------------------------------------------
-void __fastcall TLoggingFrame::DataChange(TObject * /*Sender*/)
-{
-  UpdateControls();
-}
-//---------------------------------------------------------------------------
-void __fastcall TLoggingFrame::SetEnableLogWindow(bool value)
-{
-  if (EnableLogWindow != value)
-  {
-    FEnableLogWindow = value;
-    UpdateControls();
-  }
-}
-//---------------------------------------------------------------------------
-void __fastcall TLoggingFrame::LogFileNameEditBeforeDialog(TObject * /*Sender*/,
-  UnicodeString & Name, bool & /*Action*/)
-{
-  FBeforeDialogPath = Name;
-  Name = ExpandEnvironmentVariables(Name);
-}
-//---------------------------------------------------------------------------
-void __fastcall TLoggingFrame::LogFileNameEditAfterDialog(TObject * /*Sender*/,
-  UnicodeString & Name, bool & /*Action*/)
-{
-  if (CompareFileName(Name, ExpandEnvironmentVariables(FBeforeDialogPath)))
-  {
-    Name = FBeforeDialogPath;
-  }
-}
-//---------------------------------------------------------------------------
-void __fastcall TLoggingFrame::LogFileNameEditCreateEditDialog(
-  TObject * Sender, TFileDialogKind DialogKind, TOpenDialog *& Dialog)
-{
-  USEDPARAM(DialogKind);
-  assert(DialogKind == dkOpen);
-  Dialog = new TOpenDialog(dynamic_cast<TComponent *>(Sender));
-}
-//---------------------------------------------------------------------------
-void __fastcall TLoggingFrame::CreateWnd()
-{
-  TFrame::CreateWnd();
-
-  if (LogFileNameEdit3 != NULL)
-  {
-    InstallPathWordBreakProc(LogFileNameEdit3);
-  }
-  if (ActionsLogFileNameEdit != NULL)
-  {
-    InstallPathWordBreakProc(ActionsLogFileNameEdit);
-  }
-}
-//---------------------------------------------------------------------------

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