Martin Prikryl 18 years ago
parent
commit
d6159950e1

+ 4 - 4
Console.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 2,0,0,81
-PRODUCTVERSION 2,0,0,81
+FILEVERSION 2,0,0,84
+PRODUCTVERSION 2,0,0,84
 FILEOS 0x4
 FILETYPE 0x1
 {
@@ -10,13 +10,13 @@ FILETYPE 0x1
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Console interface for WinSCP\0"
-            VALUE "FileVersion", "2.0.0.81\0"
+            VALUE "FileVersion", "2.0.0.84\0"
             VALUE "InternalName", "console\0"
             VALUE "LegalCopyright", "(c) 2000-2008 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "winscp.com\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.0.6.0\0"
+            VALUE "ProductVersion", "4.0.7.0\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 4 - 4
DragExt.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 1,1,6,79
-PRODUCTVERSION 1,1,6,79
+FILEVERSION 1,1,6,81
+PRODUCTVERSION 1,1,6,81
 FILEOS 0x4
 FILETYPE 0x2
 {
@@ -10,13 +10,13 @@ FILETYPE 0x2
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Drag&Drop shell extension for WinSCP\0"
-            VALUE "FileVersion", "1.1.6.79\0"
+            VALUE "FileVersion", "1.1.6.81\0"
             VALUE "InternalName", "dragext\0"
             VALUE "LegalCopyright", "(c) 2000-2008 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "dragext.dll\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.0.6.0\0"
+            VALUE "ProductVersion", "4.0.7.0\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 4 - 4
DragExt64.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 1,1,6,79
-PRODUCTVERSION 1,1,6,79
+FILEVERSION 1,1,6,81
+PRODUCTVERSION 1,1,6,81
 FILEOS 0x4
 FILETYPE 0x2
 {
@@ -10,13 +10,13 @@ FILETYPE 0x2
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Drag&Drop shell extension for WinSCP (64-bit)\0"
-            VALUE "FileVersion", "1.1.6.79\0"
+            VALUE "FileVersion", "1.1.6.81\0"
             VALUE "InternalName", "dragext64\0"
             VALUE "LegalCopyright", "(c) 2000-2008 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "dragext64.dll\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.0.6.0\0"
+            VALUE "ProductVersion", "4.0.7.0\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 5 - 5
WinSCP.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 4,0,6,358
-PRODUCTVERSION 4,0,6,358
+FILEVERSION 4,0,7,370
+PRODUCTVERSION 4,0,7,370
 FILEOS 0x4
 FILETYPE 0x1
 {
@@ -10,13 +10,13 @@ FILETYPE 0x1
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Windows SFTP, FTP and SCP client\0"
-            VALUE "FileVersion", "4.0.6.358\0"
+            VALUE "FileVersion", "4.0.7.370\0"
             VALUE "InternalName", "winscp\0"
             VALUE "LegalCopyright", "(c) 2000-2008 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
-            VALUE "OriginalFilename", "winscp406.exe\0"
+            VALUE "OriginalFilename", "winscp407.exe\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.0.6.0\0"
+            VALUE "ProductVersion", "4.0.7.0\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 31 - 21
core/CopyParam.cpp

@@ -231,6 +231,30 @@ void __fastcall TCopyParamType::SetReplaceInvalidChars(bool value)
   }
 }
 //---------------------------------------------------------------------------
+char * __fastcall TCopyParamType::ReplaceChar(AnsiString & FileName, char * InvalidChar) const
+{
+  int Index = InvalidChar - FileName.c_str() + 1;
+  if (FileName.ByteType(Index) == mbSingleByte)
+  {
+    if (InvalidCharsReplacement == TokenReplacement)
+    {
+      FileName.Insert(CharToHex(FileName[Index]), Index + 1);
+      FileName[Index] = TokenPrefix;
+      InvalidChar = FileName.c_str() + Index + 2;
+    }
+    else
+    {
+      FileName[Index] = InvalidCharsReplacement;
+      InvalidChar++;
+    }
+  }
+  else
+  {
+    InvalidChar++;
+  }
+  return InvalidChar; 
+}
+//---------------------------------------------------------------------------
 AnsiString __fastcall TCopyParamType::ValidLocalFileName(AnsiString FileName) const
 {
   if (InvalidCharsReplacement != NoReplacement)
@@ -241,25 +265,13 @@ AnsiString __fastcall TCopyParamType::ValidLocalFileName(AnsiString FileName) co
     char * InvalidChar = FileName.c_str();
     while ((InvalidChar = strpbrk(InvalidChar, Chars)) != NULL)
     {
-      int Index = InvalidChar - FileName.c_str() + 1;
-      if (FileName.ByteType(Index) == mbSingleByte)
-      {
-        if (ATokenReplacement)
-        {
-          FileName.Insert(CharToHex(FileName[Index]), Index + 1);
-          FileName[Index] = TokenPrefix;
-          InvalidChar = FileName.c_str() + Index + 2;
-        }
-        else
-        {
-          FileName[Index] = InvalidCharsReplacement;
-          InvalidChar++;
-        }
-      }
-      else
-      {
-        InvalidChar++;
-      }
+      InvalidChar = ReplaceChar(FileName, InvalidChar);
+    }
+
+    // Windows trim trailing space, hence we must encode it to preserve it
+    if (!FileName.IsEmpty() && (FileName[FileName.Length()] == ' '))
+    {
+      ReplaceChar(FileName, FileName.c_str() + FileName.Length() - 1);
     }
   }
   return FileName;
@@ -342,8 +354,6 @@ bool __fastcall TCopyParamType::UseAsciiTransfer(AnsiString FileName,
 TRights __fastcall TCopyParamType::RemoteFileRights(Integer Attrs) const
 {
   TRights R = Rights;
-/*  if ((Attrs & faReadOnly) && PreserveReadOnly)
-    R.ReadOnly = True;*/
   if ((Attrs & faDirectory) && AddXToDirectories)
     R.AddExecute();
   return R;

+ 1 - 0
core/CopyParam.h

@@ -58,6 +58,7 @@ private:
   void __fastcall SetLocalInvalidChars(AnsiString value);
   bool __fastcall GetReplaceInvalidChars() const;
   void __fastcall SetReplaceInvalidChars(bool value);
+  char * __fastcall ReplaceChar(AnsiString & FileName, char * InvalidChar) const;
 
 public:
   __fastcall TCopyParamType();

+ 27 - 2
core/FtpFileSystem.cpp

@@ -761,6 +761,7 @@ void __fastcall TFTPFileSystem::FileTransferProgress(__int64 TransferSize,
   if (OperationProgress->Cancel == csCancel)
   {
     FFileTransferCancelled = true;
+    FFileTransferAbort = ftaCancel;
     FFileZillaIntf->Cancel();
   }
 }
@@ -1193,6 +1194,8 @@ void __fastcall TFTPFileSystem::Source(const AnsiString FileName,
     {
       FIgnoreFileList = false;
     }
+
+    CheckFileTransferAbort();
   }
 
   /* TODO : Delete also read-only files. */
@@ -1229,6 +1232,7 @@ void __fastcall TFTPFileSystem::DirectorySource(const AnsiString DirectoryName,
       FindAttrs, SearchRec) == 0);
   );
 
+  bool CreateDir = true;
   while (FindOK && !OperationProgress->Cancel)
   {
     AnsiString FileName = DirectoryName + SearchRec.Name;
@@ -1236,6 +1240,10 @@ void __fastcall TFTPFileSystem::DirectorySource(const AnsiString DirectoryName,
     {
       if ((SearchRec.Name != ".") && (SearchRec.Name != ".."))
       {
+        // if any file will get uploaded (at least attempted),
+        // do not try to create directory, as it should be already created
+        // by FZAPI during upload
+        CreateDir = false;
         SourceRobust(FileName, DestFullName, CopyParam, Params, OperationProgress,
           Flags & ~(tfFirstLevel | tfAutoResume));
       }
@@ -1258,6 +1266,17 @@ void __fastcall TFTPFileSystem::DirectorySource(const AnsiString DirectoryName,
 
   FindClose(SearchRec);
 
+  if (CreateDir)
+  {
+    TRemoteProperties Properties;
+    if (CopyParam->PreserveRights)
+    {
+      Properties.Valid = TValidProperties() << vpRights;
+      Properties.Rights = CopyParam->RemoteFileRights(Attrs);
+    }
+    FTerminal->CreateDirectory(DestFullName, &Properties);
+  }
+
   /* TODO : Delete also read-only directories. */
   /* TODO : Show error message on failure. */
   if (!OperationProgress->Cancel)
@@ -2322,6 +2341,10 @@ bool __fastcall TFTPFileSystem::HandleAsynchRequestOverwrite(
       // on retry, use the same answer as on the first attempt
       RequestResult = UserData.OverwriteResult;
     }
+    else if (!FTerminal->Configuration->ConfirmOverwriting)
+    {
+      RequestResult = TFileZillaIntf::FILEEXISTS_OVERWRITE;
+    }
     else
     {
       TFileOperationProgressType * OperationProgress = FTerminal->OperationProgress;
@@ -2376,9 +2399,11 @@ bool __fastcall TFTPFileSystem::HandleAsynchRequestOverwrite(
       {
         RequestResult = TFileZillaIntf::FILEEXISTS_SKIP;
       }
-      // remember the answer for the retries
-      UserData.OverwriteResult = RequestResult;
     }
+
+    // remember the answer for the retries
+    UserData.OverwriteResult = RequestResult;
+
     return true;
   }
 }

+ 113 - 101
core/Terminal.cpp

@@ -478,148 +478,160 @@ void __fastcall TTerminal::Open()
   {
     try
     {
-      ResetConnection();
-      FStatus = ssOpening;
-
       try
       {
-        if (FFileSystem == NULL)
-        {
-          Log->AddStartupInfo();
-        }
-
-        assert(FTunnel == NULL);
-        if (FSessionData->Tunnel)
-        {
-          DoInformation(LoadStr(OPEN_TUNNEL), true);
-          LogEvent("Opening tunnel.");
-          OpenTunnel();
-          Log->AddSeparator();
+        ResetConnection();
+        FStatus = ssOpening;
 
-          FSessionData->ConfigureTunnel(FTunnelLocalPortNumber);
-
-          DoInformation(LoadStr(USING_TUNNEL), false);
-          LogEvent(FORMAT("Connecting via tunnel interface %s:%d.",
-            (FSessionData->HostName, FSessionData->PortNumber)));
-        }
-        else
+        try
         {
-          assert(FTunnelLocalPortNumber == 0);
-        }
+          if (FFileSystem == NULL)
+          {
+            Log->AddStartupInfo();
+          }
 
-        if (FFileSystem == NULL)
-        {
-          if (SessionData->FSProtocol == fsFTP)
+          assert(FTunnel == NULL);
+          if (FSessionData->Tunnel)
           {
-            #ifdef NO_FILEZILLA
-            LogEvent("FTP protocol is not supported by this build.");
-            FatalError(NULL, LoadStr(FTP_UNSUPPORTED));
-            #else
-            FFSProtocol = cfsFTP;
-            FFileSystem = new TFTPFileSystem(this);
-            FFileSystem->Open();
+            DoInformation(LoadStr(OPEN_TUNNEL), true);
+            LogEvent("Opening tunnel.");
+            OpenTunnel();
             Log->AddSeparator();
-            LogEvent("Using FTP protocol.");
-            #endif
+
+            FSessionData->ConfigureTunnel(FTunnelLocalPortNumber);
+
+            DoInformation(LoadStr(USING_TUNNEL), false);
+            LogEvent(FORMAT("Connecting via tunnel interface %s:%d.",
+              (FSessionData->HostName, FSessionData->PortNumber)));
           }
           else
           {
-            assert(FSecureShell == NULL);
-            try
+            assert(FTunnelLocalPortNumber == 0);
+          }
+
+          if (FFileSystem == NULL)
+          {
+            if (SessionData->FSProtocol == fsFTP)
             {
-              FSecureShell = new TSecureShell(this, FSessionData, Log, Configuration);
+              #ifdef NO_FILEZILLA
+              LogEvent("FTP protocol is not supported by this build.");
+              FatalError(NULL, LoadStr(FTP_UNSUPPORTED));
+              #else
+              FFSProtocol = cfsFTP;
+              FFileSystem = new TFTPFileSystem(this);
+              FFileSystem->Open();
+              Log->AddSeparator();
+              LogEvent("Using FTP protocol.");
+              #endif
+            }
+            else
+            {
+              assert(FSecureShell == NULL);
               try
               {
-                FSecureShell->Open();
-              }
-              catch(Exception & E)
-              {
-                assert(!FSecureShell->Active);
-                if (!FSecureShell->Active && !FTunnelError.IsEmpty())
+                FSecureShell = new TSecureShell(this, FSessionData, Log, Configuration);
+                try
                 {
-                  // the only case where we expect this to happen
-                  assert(E.Message == LoadStr(UNEXPECTED_CLOSE_ERROR));
-                  FatalError(&E, FMTLOAD(TUNNEL_ERROR, (FTunnelError)));
+                  FSecureShell->Open();
                 }
-                else
+                catch(Exception & E)
                 {
-                  throw;
+                  assert(!FSecureShell->Active);
+                  if (!FSecureShell->Active && !FTunnelError.IsEmpty())
+                  {
+                    // the only case where we expect this to happen
+                    assert(E.Message == LoadStr(UNEXPECTED_CLOSE_ERROR));
+                    FatalError(&E, FMTLOAD(TUNNEL_ERROR, (FTunnelError)));
+                  }
+                  else
+                  {
+                    throw;
+                  }
                 }
-              }
 
-              Log->AddSeparator();
+                Log->AddSeparator();
 
-              if ((SessionData->FSProtocol == fsSCPonly) ||
-                  (SessionData->FSProtocol == fsSFTP && FSecureShell->SshFallbackCmd()))
-              {
-                FFSProtocol = cfsSCP;
-                FFileSystem = new TSCPFileSystem(this, FSecureShell);
-                FSecureShell = NULL; // ownership passed
-                LogEvent("Using SCP protocol.");
+                if ((SessionData->FSProtocol == fsSCPonly) ||
+                    (SessionData->FSProtocol == fsSFTP && FSecureShell->SshFallbackCmd()))
+                {
+                  FFSProtocol = cfsSCP;
+                  FFileSystem = new TSCPFileSystem(this, FSecureShell);
+                  FSecureShell = NULL; // ownership passed
+                  LogEvent("Using SCP protocol.");
+                }
+                else
+                {
+                  FFSProtocol = cfsSFTP;
+                  FFileSystem = new TSFTPFileSystem(this, FSecureShell);
+                  FSecureShell = NULL; // ownership passed
+                  LogEvent("Using SFTP protocol.");
+                }
               }
-              else
+              __finally
               {
-                FFSProtocol = cfsSFTP;
-                FFileSystem = new TSFTPFileSystem(this, FSecureShell);
-                FSecureShell = NULL; // ownership passed
-                LogEvent("Using SFTP protocol.");
+                delete FSecureShell;
+                FSecureShell = NULL;
               }
             }
-            __finally
-            {
-              delete FSecureShell;
-              FSecureShell = NULL;
-            }
+          }
+          else
+          {
+            FFileSystem->Open();
           }
         }
-        else
+        __finally
         {
-          FFileSystem->Open();
+          if (FSessionData->Tunnel)
+          {
+            FSessionData->RollbackTunnel();
+          }
         }
-      }
-      __finally
-      {
-        if (FSessionData->Tunnel)
+
+        if (SessionData->CacheDirectoryChanges)
         {
-          FSessionData->RollbackTunnel();
+          assert(FDirectoryChangesCache == NULL);
+          FDirectoryChangesCache = new TRemoteDirectoryChangesCache();
+          if (SessionData->PreserveDirectoryChanges)
+          {
+            Configuration->LoadDirectoryChangesCache(SessionData->SessionKey,
+              FDirectoryChangesCache);
+          }
         }
-      }
 
-      if (SessionData->CacheDirectoryChanges)
+        DoStartup();
+
+        DoInformation(LoadStr(STATUS_READY), true);
+        FStatus = ssOpened;
+      }
+      catch(...)
       {
-        assert(FDirectoryChangesCache == NULL);
-        FDirectoryChangesCache = new TRemoteDirectoryChangesCache();
-        if (SessionData->PreserveDirectoryChanges)
+        // rollback
+        if (FDirectoryChangesCache != NULL)
         {
-          Configuration->LoadDirectoryChangesCache(SessionData->SessionKey,
-            FDirectoryChangesCache);
+          delete FDirectoryChangesCache;
+          FDirectoryChangesCache = NULL;
         }
+        throw;
       }
-
-      DoStartup();
-
-      DoInformation(LoadStr(STATUS_READY), true);
-      FStatus = ssOpened;
     }
-    catch(...)
+    __finally
     {
-      // rollback
-      if (FDirectoryChangesCache != NULL)
+      // Prevent calling Information with active=false unless there was at least
+      // one call with active=true
+      if (FAnyInformation)
       {
-        delete FDirectoryChangesCache;
-        FDirectoryChangesCache = NULL;
+        DoInformation("", true, false);
       }
-      throw;
     }
   }
-  __finally
+  catch(EFatal &)
   {
-    // Prevent calling Information with active=false unless there was at least
-    // one call with active=true
-    if (FAnyInformation)
-    {
-      DoInformation("", true, false);
-    }
+    throw;
+  }
+  catch(Exception & E)
+  {
+    // any exception while opening session is fatal
+    FatalError(&E, "");
   }
 }
 //---------------------------------------------------------------------------

+ 4 - 0
filezilla/FtpControlSocket.cpp

@@ -5297,7 +5297,11 @@ void CFtpControlSocket::OnTimer()
 			int diff=COptions::GetOptionVal(OPTION_INTERVALHIGH)-low;
 
 			//Choose a new delay
+#ifdef MPEXT
+			int delay=low+(rand()*diff)/RAND_MAX;
+#else
 			static int delay=low+(rand()*diff)/RAND_MAX;
+#endif
 
 			CTimeSpan span=CTime::GetCurrentTime()-m_LastSendTime;
 			if (span.GetTotalSeconds()>=delay)

+ 1 - 2
forms/CustomScpExplorer.cpp

@@ -2720,8 +2720,7 @@ void __fastcall TCustomScpExplorerForm::TrayIconClick(TObject * /*Sender*/)
 //---------------------------------------------------------------------------
 bool __fastcall TCustomScpExplorerForm::OpenInNewWindow()
 {
-  // VK_SHIFT seems to indicate shift down even when it is not
-  return (GetAsyncKeyState(VK_LSHIFT) != 0) || (GetAsyncKeyState(VK_RSHIFT) != 0);
+  return FLAGSET(GetAsyncKeyState(VK_SHIFT), 0x8000);
 }
 //---------------------------------------------------------------------------
 void __fastcall TCustomScpExplorerForm::NewSession()

+ 6 - 0
forms/ImportSessions.cpp

@@ -25,6 +25,12 @@ Boolean __fastcall DoImportSessionsDialog(TStoredSessionList *SessionList)
     ImportSessionList->DefaultSettings = SessionList->DefaultSettings;
 
     ImportSessionList->Load(Configuration->PuttySessionsKey, true);
+    TSessionData * PuttySession =
+      (TSessionData *)ImportSessionList->FindByName(GUIConfiguration->PuttySession);
+    if (PuttySession != NULL)
+    {
+      ImportSessionList->Remove(PuttySession);
+    }
     ImportSessionList->SelectSessionsToImport(SessionList, True);
     ImportSessionsDialog->SessionList = ImportSessionList;
 

+ 8 - 2
forms/Login.cpp

@@ -1248,9 +1248,14 @@ void __fastcall TLoginDialog::ActionListUpdate(TBasicAction *Action,
   }
   Handled = true;
 
-  if (!LoginButton->Default && !SessionListView->IsEditing())
+  if (!SessionListView->IsEditing())
   {
-    LoginButton->Default = true;
+    // default property setter does not have guard for "the same value"
+    if (!LoginButton->Default)
+    {
+      LoginButton->Default = true;
+    }
+    CloseButton->Cancel = true;
   }
 }
 //---------------------------------------------------------------------------
@@ -1765,6 +1770,7 @@ void __fastcall TLoginDialog::SessionListViewEditing(TObject * /*Sender*/,
   if (AllowEdit)
   {
     LoginButton->Default = false;
+    CloseButton->Cancel = false;
   }
 }
 //---------------------------------------------------------------------------

+ 7 - 2
packages/dragndrop/DragDrop.pas

@@ -1850,8 +1850,13 @@ begin
                             DropEffect_Link: Result:=drLink;
                             else
                             begin
-                                 if WIN32Platform = VER_PLATFORM_WIN32_NT then Result:=drMove
-                                 else Result:=drCancelled;
+                                 {MP}
+                                 {with ddext we actually need to know that
+                                  drag operation ended on no-drop location,
+                                  so we do not issue "cannot detect destination"
+                                  error}
+                                 {if WIN32Platform = VER_PLATFORM_WIN32_NT then Result:=drMove
+                                 else} Result:=drCancelled;
                             end;
                        end
                    else Result:=drCancelled;

+ 1 - 1
release/winscp.u3i

@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <u3manifest version="1.0">
-  <application uuid="48b341d1-d411-4b5a-a82c-f3b5d65602fc" version="4.0.6">
+  <application uuid="48b341d1-d411-4b5a-a82c-f3b5d65602fc" version="4.0.7">
     <icon>winscp.ico</icon>
     <name>WinSCP</name>
     <description>Freeware SFTP (SSH File Transfer Protocol), FTP (File Transfer Protocol) and SCP (Secure CoPy) client for Windows using SSH (Secure SHell). Its main function is safe copying of files between a local and a remote computer.</description>

+ 3 - 1
windows/ConsoleRunner.cpp

@@ -92,7 +92,9 @@ __fastcall TOwnConsole::~TOwnConsole()
 {
   TGuard Guard(&FSection);
 
-  SetConsoleCtrlHandler(HandlerRoutine, false);
+  // deliberatelly do not remove ConsoleCtrlHandler as it causes
+  // failures while exiting
+
   FreeConsole();
 
   assert(FInstance == this);

+ 3 - 1
windows/VCLCommon.cpp

@@ -506,6 +506,8 @@ int CALLBACK PathWordBreakProc(char * Ch, int Current, int Len, int Code)
   {
     ACh = Ch;
   }
+  // it may not be NULL terminated
+  ACh.SetLength(Len);
   if (Code == WB_ISDELIMITER)
   {
     // we return negacy of what WinAPI docs says
@@ -519,7 +521,7 @@ int CALLBACK PathWordBreakProc(char * Ch, int Current, int Len, int Code)
   {
     if (Current == 0)
     {
-      // will be called gain with Current == 1
+      // will be called again with Current == 1
       Result = 0;
     }
     else