Martin Prikryl 14 years ago
parent
commit
d29e380355
56 changed files with 1482 additions and 252 deletions
  1. 6 6
      Console.rc
  2. 6 6
      DragExt.rc
  3. 6 6
      DragExt64.rc
  4. 4 2
      Putty.bpr
  5. 6 6
      WinSCP.rc
  6. 1 1
      core/CopyParam.cpp
  7. 1 1
      core/FileInfo.cpp
  8. 4 0
      core/FtpFileSystem.cpp
  9. 1 0
      core/SecureShell.cpp
  10. 9 1
      core/SftpFileSystem.cpp
  11. 32 18
      core/Terminal.cpp
  12. 2 0
      core/Terminal.h
  13. 2 0
      filezilla/FtpControlSocket.cpp
  14. 1 1
      forms/NonVisual.dfm
  15. 1 1
      openssl/LICENSE
  16. 6 2
      openssl/Makefile
  17. 12 5
      openssl/crypto/asn1/a_strex.c
  18. 1 1
      openssl/crypto/asn1/a_strnid.c
  19. 1 1
      openssl/crypto/asn1/ameth_lib.c
  20. 1 1
      openssl/crypto/asn1/asn1.h
  21. 9 3
      openssl/crypto/bio/bss_file.c
  22. 2 2
      openssl/crypto/buildinf.h
  23. 1 2
      openssl/crypto/comp/c_rle.c
  24. 0 18
      openssl/crypto/dsa/dsa_ossl.c
  25. 3 3
      openssl/crypto/opensslv.h
  26. 30 30
      openssl/crypto/stack/safestack.h
  27. 2 3
      openssl/crypto/ts/ts_verify_ctx.c
  28. 6 0
      openssl/crypto/x509v3/v3_addr.c
  29. 15 16
      openssl/crypto/x509v3/v3_asid.c
  30. 1 5
      openssl/ssl/d1_enc.c
  31. 2 1
      openssl/ssl/d1_pkt.c
  32. 3 2
      openssl/ssl/s2_srvr.c
  33. 7 1
      openssl/ssl/t1_lib.c
  34. 1 1
      packages/filemng/CustomDirView.hpp
  35. 9 9
      packages/filemng/CustomDirView.pas
  36. 8 5
      packages/filemng/CustomDriveView.pas
  37. 1 1
      packages/filemng/DirView.pas
  38. 2 1
      packages/my/NortonLikeListView.hpp
  39. 25 3
      packages/my/NortonLikeListView.pas
  40. 6 2
      putty/SSH.C
  41. 2 0
      putty/SSH.H
  42. 815 14
      putty/SSHBN.C
  43. 81 5
      putty/SSHRSA.C
  44. 17 0
      putty/putty.h
  45. 2 0
      putty/windows/WINNET.C
  46. 8 0
      putty/windows/WINNOJMP.C
  47. 90 1
      putty/windows/WINPGNTC.C
  48. 173 0
      putty/windows/WINSTORE.C
  49. 46 2
      putty/windows/WINSTUFF.H
  50. 0 27
      release/install.u3.bat
  51. 0 4
      release/u3.ini
  52. 0 21
      release/winscp.u3i
  53. 3 3
      resource/TextsCore1.rc
  54. 1 1
      resource/TextsWin1.rc
  55. 3 3
      windows/Setup.cpp
  56. 5 4
      windows/WinConfiguration.cpp

+ 6 - 6
Console.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 3,0,0,126
-PRODUCTVERSION 3,0,0,126
+FILEVERSION 3,0,0,127
+PRODUCTVERSION 3,0,0,127
 FILEOS 0x4
 FILETYPE 0x1
 {
@@ -10,14 +10,14 @@ FILETYPE 0x1
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Console interface for WinSCP\0"
-            VALUE "FileVersion", "3.0.0.126\0"
+            VALUE "FileVersion", "3.0.0.127\0"
             VALUE "InternalName", "console\0"
-            VALUE "LegalCopyright", "(c) 2000-2010 Martin Prikryl\0"
+            VALUE "LegalCopyright", "(c) 2000-2011 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "winscp.com\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.3.1.0\0"
-            VALUE "ReleaseType", "beta\0"
+            VALUE "ProductVersion", "4.3.2.0\0"
+            VALUE "ReleaseType", "stable\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 6 - 6
DragExt.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 1,1,9,118
-PRODUCTVERSION 1,1,9,118
+FILEVERSION 1,1,9,119
+PRODUCTVERSION 1,1,9,119
 FILEOS 0x4
 FILETYPE 0x2
 {
@@ -10,14 +10,14 @@ FILETYPE 0x2
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Drag&Drop shell extension for WinSCP (32-bit)\0"
-            VALUE "FileVersion", "1.1.9.118\0"
+            VALUE "FileVersion", "1.1.9.119\0"
             VALUE "InternalName", "dragext32\0"
-            VALUE "LegalCopyright", "(c) 2000-2010 Martin Prikryl\0"
+            VALUE "LegalCopyright", "(c) 2000-2011 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "dragext.dll\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.3.1.0\0"
-            VALUE "ReleaseType", "beta\0"
+            VALUE "ProductVersion", "4.3.2.0\0"
+            VALUE "ReleaseType", "stable\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 6 - 6
DragExt64.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 1,1,9,118
-PRODUCTVERSION 1,1,9,118
+FILEVERSION 1,1,9,119
+PRODUCTVERSION 1,1,9,119
 FILEOS 0x4
 FILETYPE 0x2
 {
@@ -10,14 +10,14 @@ FILETYPE 0x2
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "Drag&Drop shell extension for WinSCP (64-bit)\0"
-            VALUE "FileVersion", "1.1.9.118\0"
+            VALUE "FileVersion", "1.1.9.119\0"
             VALUE "InternalName", "dragext64\0"
-            VALUE "LegalCopyright", "(c) 2000-2010 Martin Prikryl\0"
+            VALUE "LegalCopyright", "(c) 2000-2011 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "dragext64.dll\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.3.1.0\0"
-            VALUE "ReleaseType", "beta\0"
+            VALUE "ProductVersion", "4.3.2.0\0"
+            VALUE "ReleaseType", "stable\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 4 - 2
Putty.bpr

@@ -14,8 +14,9 @@
       putty\CHARSET\UTF8.obj putty\WILDCARD.obj putty\WINDOWS\WINGSS.obj
       putty\WINDOWS\WINHANDL.obj putty\WINDOWS\WINMISC.obj
       putty\WINDOWS\WINNET.obj putty\WINDOWS\WINNOISE.obj
-      putty\WINDOWS\WINPGNTC.obj putty\WINDOWS\WINPROXY.obj
-      putty\WINDOWS\WINSTORE_.obj putty\WINDOWS\WINTIME.obj putty\X11FWD.obj"/>
+      putty\WINDOWS\WINNOJMP.obj putty\WINDOWS\WINPGNTC.obj
+      putty\WINDOWS\WINPROXY.obj putty\WINDOWS\WINSTORE_.obj
+      putty\WINDOWS\WINTIME.obj putty\X11FWD.obj"/>
     <RESFILES value=""/>
     <DEFFILE value=""/>
     <RESDEPEN value="$(RESFILES)"/>
@@ -86,6 +87,7 @@
       <FILE FILENAME="putty\WINDOWS\WINMISC.C" FORMNAME="" UNITNAME="WINMISC.C" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>
       <FILE FILENAME="putty\WINDOWS\WINNET.C" FORMNAME="" UNITNAME="WINNET.C" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>
       <FILE FILENAME="putty\WINDOWS\WINNOISE.C" FORMNAME="" UNITNAME="WINNOISE.C" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>
+      <FILE FILENAME="putty\WINDOWS\WINNOJMP.C" FORMNAME="" UNITNAME="WINNOJMP.C" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>
       <FILE FILENAME="putty\WINDOWS\WINPGNTC.C" FORMNAME="" UNITNAME="WINPGNTC.C" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>
       <FILE FILENAME="putty\WINDOWS\WINPROXY.C" FORMNAME="" UNITNAME="WINPROXY.C" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>
       <FILE FILENAME="putty\WINDOWS\WINSTORE_.C" FORMNAME="" UNITNAME="WINSTORE_.C" CONTAINERID="CCompiler" DESIGNCLASS="" LOCALCOMMAND=""/>

+ 6 - 6
WinSCP.rc

@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION 4,3,1,1099
-PRODUCTVERSION 4,3,1,1099
+FILEVERSION 4,3,2,1201
+PRODUCTVERSION 4,3,2,1201
 FILEOS 0x4
 FILETYPE 0x1
 {
@@ -10,14 +10,14 @@ FILETYPE 0x1
         {
             VALUE "CompanyName", "Martin Prikryl\0"
             VALUE "FileDescription", "WinSCP: SFTP, FTP and SCP client\0"
-            VALUE "FileVersion", "4.3.1.1099\0"
+            VALUE "FileVersion", "4.3.2.1201\0"
             VALUE "InternalName", "winscp\0"
-            VALUE "LegalCopyright", "(c) 2000-2010 Martin Prikryl\0"
+            VALUE "LegalCopyright", "(c) 2000-2011 Martin Prikryl\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "winscp.exe\0"
             VALUE "ProductName", "WinSCP\0"
-            VALUE "ProductVersion", "4.3.1.0\0"
-            VALUE "ReleaseType", "beta\0"
+            VALUE "ProductVersion", "4.3.2.0\0"
+            VALUE "ReleaseType", "stable\0"
             VALUE "WWW", "http://winscp.net/\0"
         }
     }

+ 1 - 1
core/CopyParam.cpp

@@ -31,7 +31,7 @@ void __fastcall TCopyParamType::Default()
   PreserveRights = false; // Was True until #106
   IgnorePermErrors = false;
   AsciiFileMask.Masks = "*.*html; *.htm; *.txt; *.php; *.php3; *.cgi; *.c; *.cpp; *.h; *.pas; "
-    "*.bas; *.tex; *.pl; .htaccess; *.xtml; *.css; *.cfg; *.ini; *.sh; *.xml";
+    "*.bas; *.tex; *.pl; *.js; .htaccess; *.xtml; *.css; *.cfg; *.ini; *.sh; *.xml";
   TransferMode = tmAutomatic;
   AddXToDirectories = true;
   ResumeSupport = rsSmart;

+ 1 - 1
core/FileInfo.cpp

@@ -255,7 +255,7 @@ AnsiString __fastcall GetFileInfoString(void * FileInfo,
 int __fastcall CalculateCompoundVersion(int MajorVer,
   int MinorVer, int Release, int Build)
 {
-  int CompoundVer = Build + 1000 * (Release + 100 * (MinorVer +
+  int CompoundVer = Build + 10000 * (Release + 100 * (MinorVer +
     100 * MajorVer));
   return CompoundVer;
 }

+ 4 - 0
core/FtpFileSystem.cpp

@@ -264,6 +264,10 @@ void __fastcall TFTPFileSystem::Open()
   // on reconnect, typically there may be pending status messages from previous session
   DiscardMessages();
 
+  ResetCaches();
+  FCurrentDirectory = "";
+  FHomeDirectory = "";
+
   TSessionData * Data = FTerminal->SessionData;
 
   FSessionInfo.LoginTime = Now();

+ 1 - 0
core/SecureShell.cpp

@@ -290,6 +290,7 @@ void __fastcall TSecureShell::StoreToConfig(TSessionData * Data, Config * cfg, b
   // permanent settings
   cfg->nopty = TRUE;
   cfg->tcp_keepalives = 0;
+  cfg->ssh_show_banner = TRUE;
   for (int Index = 0; Index < ngsslibs; Index++)
   {
     cfg->ssh_gsslist[Index] = gsslibkeywords[Index].v;

+ 9 - 1
core/SftpFileSystem.cpp

@@ -2069,12 +2069,18 @@ unsigned long __fastcall TSFTPFileSystem::GotStatusPacket(TSFTPPacket * Packet,
     AnsiString MessageStr = LoadStr(Message);
     AnsiString ServerMessage;
     AnsiString LanguageTag;
-    if (FVersion >= 3)
+    if ((FVersion >= 3) ||
+        // if version is not decided yet (i.e. this is status response
+        // to the init request), go on only if there are any more data
+        ((FVersion < 0) && (Packet->RemainingLength > 0)))
     {
       // message is in UTF only since SFTP specification 01 (specification 00
       // is also version 3)
       // (in other words, always use UTF unless server is know to be buggy)
       ServerMessage = Packet->GetString(!FUtfNever);
+      // SSH-2.0-Maverick_SSHD omits the language tag
+      // and I believe I've seen one more server doind the same.
+      // On the next instance, we should probably already implement workround.
       LanguageTag = Packet->GetString();
       if ((FVersion >= 5) && (Message == SFTP_STATUS_UNKNOWN_PRINCIPAL))
       {
@@ -2548,6 +2554,8 @@ AnsiString __fastcall TSFTPFileSystem::GetCurrentDirectory()
 //---------------------------------------------------------------------------
 void __fastcall TSFTPFileSystem::DoStartup()
 {
+  // do not know yet
+  FVersion = -1;
   FFileSystemInfoValid = false;
   TSFTPPacket Packet(SSH_FXP_INIT);
   int MaxVersion = FTerminal->SessionData->SFTPMaxVersion;

+ 32 - 18
core/Terminal.cpp

@@ -937,7 +937,7 @@ void __fastcall TTerminal::Reopen(int Params)
   AnsiString PrevRemoteDirectory = SessionData->RemoteDirectory;
   bool PrevReadCurrentDirectoryPending = FReadCurrentDirectoryPending;
   bool PrevReadDirectoryPending = FReadDirectoryPending;
-  int PrevInTransaction = FInTransaction;
+  assert(!FSuspendTransaction);
   bool PrevAutoReadDirectory = FAutoReadDirectory;
   // here used to be a check for FExceptionOnFail being 0
   // but it can happen, e.g. when we are downloading file to execute it.
@@ -947,7 +947,7 @@ void __fastcall TTerminal::Reopen(int Params)
   {
     FReadCurrentDirectoryPending = false;
     FReadDirectoryPending = false;
-    FInTransaction = 0;
+    FSuspendTransaction = true;
     FExceptionOnFail = 0;
     // typically, we avoid reading directory, when there is operation ongoing,
     // for file list which may reference files from current directory
@@ -976,7 +976,7 @@ void __fastcall TTerminal::Reopen(int Params)
     FAutoReadDirectory = PrevAutoReadDirectory;
     FReadCurrentDirectoryPending = PrevReadCurrentDirectoryPending;
     FReadDirectoryPending = PrevReadDirectoryPending;
-    FInTransaction = PrevInTransaction;
+    FSuspendTransaction = false;
     FExceptionOnFail = PrevExceptionOnFail;
   }
 }
@@ -1219,7 +1219,7 @@ void __fastcall TTerminal::ReactOnCommand(int /*TFSCommand*/ Cmd)
 
   if (ChangesDirectory)
   {
-    if (!FInTransaction)
+    if (!InTransaction())
     {
       ReadCurrentDirectory();
       if (AutoReadDirectory)
@@ -1239,7 +1239,7 @@ void __fastcall TTerminal::ReactOnCommand(int /*TFSCommand*/ Cmd)
     else
   if (ModifiesFiles && AutoReadDirectory && Configuration->AutoReadDirectoryAfterOp)
   {
-    if (!FInTransaction) ReadDirectory(true);
+    if (!InTransaction()) ReadDirectory(true);
       else FReadDirectoryPending = true;
   }
 }
@@ -1623,9 +1623,14 @@ void __fastcall TTerminal::DoReadDirectoryProgress(int Progress, bool & Cancel)
   }
 }
 //---------------------------------------------------------------------------
+bool __fastcall TTerminal::InTransaction()
+{
+  return (FInTransaction > 0) && !FSuspendTransaction;
+}
+//---------------------------------------------------------------------------
 void __fastcall TTerminal::BeginTransaction()
 {
-  if (!FInTransaction)
+  if (FInTransaction == 0)
   {
     FReadCurrentDirectoryPending = false;
     FReadDirectoryPending = false;
@@ -1640,7 +1645,7 @@ void __fastcall TTerminal::BeginTransaction()
 //---------------------------------------------------------------------------
 void __fastcall TTerminal::EndTransaction()
 {
-  if (!FInTransaction)
+  if (FInTransaction == 0)
     TerminalError("Can't end transaction, not in transaction");
   assert(FInTransaction > 0);
   FInTransaction--;
@@ -2546,22 +2551,31 @@ bool __fastcall TTerminal::ProcessFiles(TStrings * FileList,
           FileName = FileList->Strings[Index];
           try
           {
-            Success = false;
-            if (!Ex)
+            try
             {
-              ProcessFile(FileName, (TRemoteFile *)FileList->Objects[Index], Param);
+              Success = false;
+              if (!Ex)
+              {
+                ProcessFile(FileName, (TRemoteFile *)FileList->Objects[Index], Param);
+              }
+              else
+              {
+                // not used anymore
+                TProcessFileEventEx ProcessFileEx = (TProcessFileEventEx)ProcessFile;
+                ProcessFileEx(FileName, (TRemoteFile *)FileList->Objects[Index], Param, Index);
+              }
+              Success = true;
             }
-            else
+            __finally
             {
-              // not used anymore
-              TProcessFileEventEx ProcessFileEx = (TProcessFileEventEx)ProcessFile;
-              ProcessFileEx(FileName, (TRemoteFile *)FileList->Objects[Index], Param, Index);
+              Progress.Finish(FileName, Success, OnceDoneOperation);
             }
-            Success = true;
           }
-          __finally
+          catch(EScpSkipFile & E)
           {
-            Progress.Finish(FileName, Success, OnceDoneOperation);
+            SUSPEND_OPERATION (
+              if (!HandleException(&E)) throw;
+            );
           }
           Index++;
         }
@@ -3407,7 +3421,7 @@ TTerminal * __fastcall TTerminal::GetCommandSession()
   {
     // transaction cannot be started yet to allow proper matching transation
     // levels between main and command session
-    assert(!FInTransaction);
+    assert(FInTransaction == 0);
 
     try
     {

+ 2 - 0
core/Terminal.h

@@ -155,6 +155,7 @@ private:
   Integer FExceptionOnFail;
   TRemoteDirectory * FFiles;
   int FInTransaction;
+  bool FSuspendTransaction;
   TNotifyEvent FOnChangeDirectory;
   TReadDirectoryEvent FOnReadDirectory;
   TNotifyEvent FOnStartReadDirectory;
@@ -220,6 +221,7 @@ private:
   AnsiString __fastcall GetPassword();
   AnsiString __fastcall GetTunnelPassword();
   bool __fastcall GetStoredCredentialsTried();
+  inline bool __fastcall InTransaction();
 
 protected:
   bool FReadCurrentDirectoryPending;

+ 2 - 0
filezilla/FtpControlSocket.cpp

@@ -1398,7 +1398,9 @@ void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath pa
 			pData->pDirectoryListing->path = m_pOwner->GetCurrentPath();
 
 		if (m_Operation.nOpState!=LIST_WAITFINISH)
+		{
 			return;
+		}
 		else
 		{
 			delete m_pTransferSocket;

+ 1 - 1
forms/NonVisual.dfm

@@ -1199,7 +1199,7 @@ object NonVisualDataModule: TNonVisualDataModule
         'Compare directories|Mark different files in local and remote dir' +
         'ectory'
       ImageIndex = 52
-      ShortCut = 16451
+      ShortCut = 8305
     end
     object SynchronizeAction: TAction
       Tag = 15

+ 1 - 1
openssl/LICENSE

@@ -12,7 +12,7 @@
   ---------------
 
 /* ====================================================================
- * Copyright (c) 1998-2008 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2011 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions

+ 6 - 2
openssl/Makefile

@@ -15,7 +15,7 @@
 
 # Set your compiler options
 CC=bcc32
-CFLAG=-DWIN32_LEAN_AND_MEAN -q -w-ccc -w-rch -w-pia -w-aus -w-par -w-inl -w-eff -w-sus -w-dup -w-spa -w-csu -w-rvl  -c -tWC -tWM -DOPENSSL_SYSNAME_WIN32 -DL_ENDIAN -DDSO_WIN32 -D_stricmp=stricmp -D_strnicmp=strnicmp -O2 -ff -fp -DBN_ASM -DMD5_ASM -DSHA1_ASM -DRMD160_ASM -DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_SEED -DOPENSSL_NO_RC5 -DOPENSSL_NO_MDC2 -DOPENSSL_NO_TLSEXT -DOPENSSL_NO_CMS -DOPENSSL_NO_CAPIENG -DOPENSSL_NO_KRB5 -DOPENSSL_NO_ENGINE -DOPENSSL_NO_DYNAMIC_ENGINE -DOPENSSL_DISABLE_OLD_DES_SUPPORT -DNO_CHMOD -DOPENSSL_NO_SOCK -DOPENSSL_NO_DGRAM -DOPENSSL_NO_EC -DOPENSSL_NO_ECDH -DOPENSSL_NO_ECDSA
+CFLAG=-DWIN32_LEAN_AND_MEAN -q -w-ccc -w-rch -w-pia -w-aus -w-par -w-inl -w-eff -w-sus -w-dup -w-spa -w-csu -w-rvl  -c -tWC -tWM -DOPENSSL_SYSNAME_WIN32 -DL_ENDIAN -DDSO_WIN32 -D_stricmp=stricmp -D_strnicmp=strnicmp -O2 -ff -fp -DBN_ASM -DMD5_ASM -DSHA1_ASM -DRMD160_ASM -DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_SEED -DOPENSSL_NO_RC5 -DOPENSSL_NO_MDC2 -DOPENSSL_NO_CMS -DOPENSSL_NO_CAPIENG -DOPENSSL_NO_KRB5 -DOPENSSL_NO_ENGINE -DOPENSSL_NO_DYNAMIC_ENGINE -DOPENSSL_DISABLE_OLD_DES_SUPPORT -DNO_CHMOD -DOPENSSL_NO_SOCK -DOPENSSL_NO_DGRAM -DOPENSSL_NO_EC -DOPENSSL_NO_ECDH -DOPENSSL_NO_ECDSA
 LIB_CFLAG=
 
 # The OpenSSL directory
@@ -131,7 +131,8 @@ SSLOBJ=$(OBJ_D)\s2_meth.obj \
     $(OBJ_D)\s23_meth.obj $(OBJ_D)\s23_srvr.obj $(OBJ_D)\s23_clnt.obj \
     $(OBJ_D)\s23_lib.obj $(OBJ_D)\s23_pkt.obj $(OBJ_D)\t1_meth.obj \
     $(OBJ_D)\t1_srvr.obj $(OBJ_D)\t1_clnt.obj $(OBJ_D)\t1_lib.obj \
-    $(OBJ_D)\t1_enc.obj $(OBJ_D)\d1_meth.obj $(OBJ_D)\d1_srvr.obj \
+    $(OBJ_D)\t1_enc.obj $(OBJ_D)\t1_reneg.obj \
+    $(OBJ_D)\d1_meth.obj $(OBJ_D)\d1_srvr.obj \
     $(OBJ_D)\d1_clnt.obj $(OBJ_D)\d1_lib.obj $(OBJ_D)\d1_pkt.obj \
     $(OBJ_D)\d1_both.obj $(OBJ_D)\d1_enc.obj $(OBJ_D)\ssl_lib.obj \
     $(OBJ_D)\ssl_err2.obj $(OBJ_D)\ssl_cert.obj $(OBJ_D)\ssl_sess.obj \
@@ -673,6 +674,9 @@ $(OBJ_D)\t1_lib.obj: $(SRC_D)\ssl\t1_lib.c
 $(OBJ_D)\t1_enc.obj: $(SRC_D)\ssl\t1_enc.c
     $(CC) -o$(OBJ_D)\t1_enc.obj  $(LIB_CFLAGS) -c $(SRC_D)\ssl\t1_enc.c
 
+$(OBJ_D)\t1_reneg.obj: $(SRC_D)\ssl\t1_reneg.c
+    $(CC) -o$(OBJ_D)\t1_reneg.obj  $(LIB_CFLAGS) -c $(SRC_D)\ssl\t1_reneg.c
+
 $(OBJ_D)\d1_meth.obj: $(SRC_D)\ssl\d1_meth.c
     $(CC) -o$(OBJ_D)\d1_meth.obj  $(LIB_CFLAGS) -c $(SRC_D)\ssl\d1_meth.c
 

+ 12 - 5
openssl/crypto/asn1/a_strex.c

@@ -74,6 +74,11 @@
 
 #define CHARTYPE_BS_ESC		(ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
 
+#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
+		  ASN1_STRFLGS_ESC_QUOTE | \
+		  ASN1_STRFLGS_ESC_CTRL | \
+		  ASN1_STRFLGS_ESC_MSB)
+
 
 /* Three IO functions for sending data to memory, a BIO and
  * and a FILE pointer.
@@ -148,6 +153,13 @@ static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes, ch
 		if(!io_ch(arg, tmphex, 3)) return -1;
 		return 3;
 	}
+	/* If we get this far and do any escaping at all must escape 
+	 * the escape character itself: backslash.
+	 */
+	if (chtmp == '\\' && flags & ESC_FLAGS) {
+		if(!io_ch(arg, "\\\\", 2)) return -1;
+		return 2;
+	}
 	if(!io_ch(arg, &chtmp, 1)) return -1;
 	return 1;
 }
@@ -292,11 +304,6 @@ static const signed char tag2nbyte[] = {
 	4, -1, 2		/* 28-30 */
 };
 
-#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
-		  ASN1_STRFLGS_ESC_QUOTE | \
-		  ASN1_STRFLGS_ESC_CTRL | \
-		  ASN1_STRFLGS_ESC_MSB)
-
 /* This is the main function, print out an
  * ASN1_STRING taking note of various escape
  * and display options. Returns number of

+ 1 - 1
openssl/crypto/asn1/a_strnid.c

@@ -95,7 +95,7 @@ unsigned long ASN1_STRING_get_default_mask(void)
  * default:   the default value, Printable, T61, BMP.
  */
 
-int ASN1_STRING_set_default_mask_asc(char *p)
+int ASN1_STRING_set_default_mask_asc(const char *p)
 {
 	unsigned long mask;
 	char *end;

+ 1 - 1
openssl/crypto/asn1/ameth_lib.c

@@ -172,7 +172,6 @@ static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type)
 	{
 	const EVP_PKEY_ASN1_METHOD *t;
-	ENGINE *e;
 
 	for (;;)
 		{
@@ -184,6 +183,7 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type)
 	if (pe)
 		{
 #ifndef OPENSSL_NO_ENGINE
+		ENGINE *e;
 		/* type will contain the final unaliased type */
 		e = ENGINE_get_pkey_asn1_meth_engine(type);
 		if (e)

+ 1 - 1
openssl/crypto/asn1/asn1.h

@@ -1067,7 +1067,7 @@ ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d,
 ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct);
 
 void ASN1_STRING_set_default_mask(unsigned long mask);
-int ASN1_STRING_set_default_mask_asc(char *p);
+int ASN1_STRING_set_default_mask_asc(const char *p);
 unsigned long ASN1_STRING_get_default_mask(void);
 int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
 					int inform, unsigned long mask);

+ 9 - 3
openssl/crypto/bio/bss_file.c

@@ -123,6 +123,7 @@ BIO *BIO_new_file(const char *filename, const char *mode)
 
 #if defined(_WIN32) && defined(CP_UTF8)
 	int sz, len_0 = (int)strlen(filename)+1;
+	DWORD flags;
 
 	/*
 	 * Basically there are three cases to cover: a) filename is
@@ -136,17 +137,22 @@ BIO *BIO_new_file(const char *filename, const char *mode)
 	 * ERROR_NO_UNICODE_TRANSLATION, in which case we fall
 	 * back to fopen...
 	 */
-	if ((sz=MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,
+	if ((sz=MultiByteToWideChar(CP_UTF8,(flags=MB_ERR_INVALID_CHARS),
+					filename,len_0,NULL,0))>0 ||
+	    (GetLastError()==ERROR_INVALID_FLAGS &&
+	     (sz=MultiByteToWideChar(CP_UTF8,(flags=0),
 					filename,len_0,NULL,0))>0)
+	   )
 		{
 		WCHAR  wmode[8];
 		WCHAR *wfilename = _alloca(sz*sizeof(WCHAR));
 
-		if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,
+		if (MultiByteToWideChar(CP_UTF8,flags,
 					filename,len_0,wfilename,sz) &&
 		    MultiByteToWideChar(CP_UTF8,0,mode,strlen(mode)+1,
 			    		wmode,sizeof(wmode)/sizeof(wmode[0])) &&
-		    (file=_wfopen(wfilename,wmode))==NULL && errno==ENOENT
+		    (file=_wfopen(wfilename,wmode))==NULL &&
+		    (errno==ENOENT || errno==EBADF)
 		   )	/* UTF-8 decode succeeded, but no file, filename
 			 * could still have been locale-ized... */
 			file = fopen(filename,mode);

+ 2 - 2
openssl/crypto/buildinf.h

@@ -9,11 +9,11 @@
   /* auto-generated/updated by util/mk1mf.pl for crypto/cversion.c */
   #define CFLAGS "cl  /MD /Ox /O2 /Ob2 -DOPENSSL_THREADS  -DDSO_WIN32  -DOPENSSL_USE_APPLINK -I. -DOPENSSL_NO_RC5 -DOPENSSL_NO_MD2 -DOPENSSL_NO_KRB5 -DOPENSSL_NO_JPAKE -DOPENSSL_NO_STATIC_ENGINE    "
   #define PLATFORM "VC-WIN32"
-  #define DATE "Sun Dec  5 15:27:45 2010"
+  #define DATE "Sun Feb 13 07:14:22 2011"
 #endif
 #ifdef MK1MF_PLATFORM_BC_NT
   /* auto-generated/updated by util/mk1mf.pl for crypto/cversion.c */
   #define CFLAGS "bcc32 -DWIN32_LEAN_AND_MEAN -q -w-ccc -w-rch -w-pia -w-aus -w-par -w-inl  -c -tWC -tWM -DOPENSSL_SYSNAME_WIN32 -DL_ENDIAN -DDSO_WIN32 -D_stricmp=stricmp -D_strnicmp=strnicmp -O2 -ff -fp -DBN_ASM -DMD5_ASM -DSHA1_ASM -DRMD160_ASM -DOPENSSL_NO_RC5 -DOPENSSL_NO_MD2 -DOPENSSL_NO_KRB5 -DOPENSSL_NO_JPAKE -DOPENSSL_NO_DYNAMIC_ENGINE    "
   #define PLATFORM "BC-NT"
-  #define DATE "Sun Dec  5 15:27:46 2010"
+  #define DATE "Sun Feb 13 07:14:23 2011"
 #endif

+ 1 - 2
openssl/crypto/comp/c_rle.c

@@ -46,7 +46,7 @@ static int rle_expand_block(COMP_CTX *ctx, unsigned char *out,
 	{
 	int i;
 
-	if (olen < (ilen-1))
+	if (ilen == 0 || olen < (ilen-1))
 		{
 		/* ZZZZZZZZZZZZZZZZZZZZZZ */
 		return(-1);
@@ -59,4 +59,3 @@ static int rle_expand_block(COMP_CTX *ctx, unsigned char *out,
 		}
 	return(ilen-1);
 	}
-

+ 0 - 18
openssl/crypto/dsa/dsa_ossl.c

@@ -148,15 +148,6 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
 
 	s=BN_new();
 	if (s == NULL) goto err;
-
-	/* reject a excessive digest length (currently at most
-	 * dsa-with-SHA256 is supported) */
-	if (dlen > SHA256_DIGEST_LENGTH)
-		{
-		reason=DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE;
-		goto err;
-		}
-
 	ctx=BN_CTX_new();
 	if (ctx == NULL) goto err;
 
@@ -325,15 +316,6 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
 		DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MODULUS_TOO_LARGE);
 		return -1;
 		}
-
-	/* reject a excessive digest length (currently at most
-	 * dsa-with-SHA256 is supported) */
-	if (dgst_len > SHA256_DIGEST_LENGTH)
-		{
-		DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
-		return -1;
-		}
-
 	BN_init(&u1);
 	BN_init(&u2);
 	BN_init(&t1);

+ 3 - 3
openssl/crypto/opensslv.h

@@ -25,11 +25,11 @@
  * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
  *  major minor fix final patch/beta)
  */
-#define OPENSSL_VERSION_NUMBER	0x1000003f
+#define OPENSSL_VERSION_NUMBER	0x1000004fL
 #ifdef OPENSSL_FIPS
-#define OPENSSL_VERSION_TEXT	"OpenSSL 1.0.0c-fips 2 Dec 2010"
+#define OPENSSL_VERSION_TEXT	"OpenSSL 1.0.0d-fips 8 Feb 2011"
 #else
-#define OPENSSL_VERSION_TEXT	"OpenSSL 1.0.0c 2 Dec 2010"
+#define OPENSSL_VERSION_TEXT	"OpenSSL 1.0.0d 8 Feb 2011"
 #endif
 #define OPENSSL_VERSION_PTEXT	" part of " OPENSSL_VERSION_TEXT
 

+ 30 - 30
openssl/crypto/stack/safestack.h

@@ -2033,75 +2033,75 @@ DECLARE_SPECIAL_STACK_OF(OPENSSL_BLOCK, void)
 
 #define sk_OPENSSL_STRING_new(cmp) ((STACK_OF(OPENSSL_STRING) *)sk_new(CHECKED_SK_CMP_FUNC(char, cmp)))
 #define sk_OPENSSL_STRING_new_null() ((STACK_OF(OPENSSL_STRING) *)sk_new_null())
-#define sk_OPENSSL_STRING_push(st, val) sk_push(CHECKED_PTR_OF(STACK_OF(OPENSSL_STRING), st), CHECKED_PTR_OF(char, val))
-#define sk_OPENSSL_STRING_find(st, val) sk_find(CHECKED_PTR_OF(STACK_OF(OPENSSL_STRING), st), CHECKED_PTR_OF(char, val))
-#define sk_OPENSSL_STRING_value(st, i) ((OPENSSL_STRING)sk_value(CHECKED_PTR_OF(STACK_OF(OPENSSL_STRING), st), i))
+#define sk_OPENSSL_STRING_push(st, val) sk_push(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, val))
+#define sk_OPENSSL_STRING_find(st, val) sk_find(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, val))
+#define sk_OPENSSL_STRING_value(st, i) ((OPENSSL_STRING)sk_value(CHECKED_STACK_OF(OPENSSL_STRING, st), i))
 #define sk_OPENSSL_STRING_num(st) SKM_sk_num(OPENSSL_STRING, st)
-#define sk_OPENSSL_STRING_pop_free(st, free_func) sk_pop_free(CHECKED_PTR_OF(STACK_OF(OPENSSL_STRING), st), CHECKED_SK_FREE_FUNC2(OPENSSL_STRING, free_func))
-#define sk_OPENSSL_STRING_insert(st, val, i) sk_insert(CHECKED_PTR_OF(STACK_OF(OPENSSL_STRING), st), CHECKED_PTR_OF(char, val), i)
+#define sk_OPENSSL_STRING_pop_free(st, free_func) sk_pop_free(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_SK_FREE_FUNC2(OPENSSL_STRING, free_func))
+#define sk_OPENSSL_STRING_insert(st, val, i) sk_insert(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, val), i)
 #define sk_OPENSSL_STRING_free(st) SKM_sk_free(OPENSSL_STRING, st)
-#define sk_OPENSSL_STRING_set(st, i, val) sk_set((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_STRING), st), i, CHECKED_PTR_OF(char, val))
+#define sk_OPENSSL_STRING_set(st, i, val) sk_set(CHECKED_STACK_OF(OPENSSL_STRING, st), i, CHECKED_PTR_OF(char, val))
 #define sk_OPENSSL_STRING_zero(st) SKM_sk_zero(OPENSSL_STRING, (st))
-#define sk_OPENSSL_STRING_unshift(st, val) sk_unshift((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_STRING), st), CHECKED_PTR_OF(char, val))
+#define sk_OPENSSL_STRING_unshift(st, val) sk_unshift(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, val))
 #define sk_OPENSSL_STRING_find_ex(st, val) sk_find_ex((_STACK *)CHECKED_CONST_PTR_OF(STACK_OF(OPENSSL_STRING), st), CHECKED_CONST_PTR_OF(char, val))
 #define sk_OPENSSL_STRING_delete(st, i) SKM_sk_delete(OPENSSL_STRING, (st), (i))
-#define sk_OPENSSL_STRING_delete_ptr(st, ptr) (OPENSSL_STRING *)sk_delete_ptr((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_STRING), st), CHECKED_PTR_OF(char, ptr))
+#define sk_OPENSSL_STRING_delete_ptr(st, ptr) (OPENSSL_STRING *)sk_delete_ptr(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, ptr))
 #define sk_OPENSSL_STRING_set_cmp_func(st, cmp)  \
 	((int (*)(const char * const *,const char * const *)) \
-	sk_set_cmp_func((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_STRING), st), CHECKED_SK_CMP_FUNC(char, cmp)))
+	sk_set_cmp_func(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_SK_CMP_FUNC(char, cmp)))
 #define sk_OPENSSL_STRING_dup(st) SKM_sk_dup(OPENSSL_STRING, st)
 #define sk_OPENSSL_STRING_shift(st) SKM_sk_shift(OPENSSL_STRING, (st))
-#define sk_OPENSSL_STRING_pop(st) (char *)sk_pop((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_STRING), st))
+#define sk_OPENSSL_STRING_pop(st) (char *)sk_pop(CHECKED_STACK_OF(OPENSSL_STRING, st))
 #define sk_OPENSSL_STRING_sort(st) SKM_sk_sort(OPENSSL_STRING, (st))
 #define sk_OPENSSL_STRING_is_sorted(st) SKM_sk_is_sorted(OPENSSL_STRING, (st))
 
 
 #define sk_OPENSSL_BLOCK_new(cmp) ((STACK_OF(OPENSSL_BLOCK) *)sk_new(CHECKED_SK_CMP_FUNC(void, cmp)))
 #define sk_OPENSSL_BLOCK_new_null() ((STACK_OF(OPENSSL_BLOCK) *)sk_new_null())
-#define sk_OPENSSL_BLOCK_push(st, val) sk_push(CHECKED_PTR_OF(STACK_OF(OPENSSL_BLOCK), st), CHECKED_PTR_OF(void, val))
-#define sk_OPENSSL_BLOCK_find(st, val) sk_find(CHECKED_PTR_OF(STACK_OF(OPENSSL_BLOCK), st), CHECKED_PTR_OF(void, val))
-#define sk_OPENSSL_BLOCK_value(st, i) ((OPENSSL_BLOCK)sk_value(CHECKED_PTR_OF(STACK_OF(OPENSSL_BLOCK), st), i))
+#define sk_OPENSSL_BLOCK_push(st, val) sk_push(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_PTR_OF(void, val))
+#define sk_OPENSSL_BLOCK_find(st, val) sk_find(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_PTR_OF(void, val))
+#define sk_OPENSSL_BLOCK_value(st, i) ((OPENSSL_BLOCK)sk_value(CHECKED_STACK_OF(OPENSSL_BLOCK, st), i))
 #define sk_OPENSSL_BLOCK_num(st) SKM_sk_num(OPENSSL_BLOCK, st)
-#define sk_OPENSSL_BLOCK_pop_free(st, free_func) sk_pop_free(CHECKED_PTR_OF(STACK_OF(OPENSSL_BLOCK), st), CHECKED_SK_FREE_FUNC2(OPENSSL_BLOCK, free_func))
-#define sk_OPENSSL_BLOCK_insert(st, val, i) sk_insert(CHECKED_PTR_OF(STACK_OF(OPENSSL_BLOCK), st), CHECKED_PTR_OF(void, val), i)
+#define sk_OPENSSL_BLOCK_pop_free(st, free_func) sk_pop_free(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_SK_FREE_FUNC2(OPENSSL_BLOCK, free_func))
+#define sk_OPENSSL_BLOCK_insert(st, val, i) sk_insert(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_PTR_OF(void, val), i)
 #define sk_OPENSSL_BLOCK_free(st) SKM_sk_free(OPENSSL_BLOCK, st)
-#define sk_OPENSSL_BLOCK_set(st, i, val) sk_set((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_BLOCK), st), i, CHECKED_PTR_OF(void, val))
+#define sk_OPENSSL_BLOCK_set(st, i, val) sk_set(CHECKED_STACK_OF(OPENSSL_BLOCK, st), i, CHECKED_PTR_OF(void, val))
 #define sk_OPENSSL_BLOCK_zero(st) SKM_sk_zero(OPENSSL_BLOCK, (st))
-#define sk_OPENSSL_BLOCK_unshift(st, val) sk_unshift((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_BLOCK), st), CHECKED_PTR_OF(void, val))
+#define sk_OPENSSL_BLOCK_unshift(st, val) sk_unshift(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_PTR_OF(void, val))
 #define sk_OPENSSL_BLOCK_find_ex(st, val) sk_find_ex((_STACK *)CHECKED_CONST_PTR_OF(STACK_OF(OPENSSL_BLOCK), st), CHECKED_CONST_PTR_OF(void, val))
 #define sk_OPENSSL_BLOCK_delete(st, i) SKM_sk_delete(OPENSSL_BLOCK, (st), (i))
-#define sk_OPENSSL_BLOCK_delete_ptr(st, ptr) (OPENSSL_BLOCK *)sk_delete_ptr((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_BLOCK), st), CHECKED_PTR_OF(void, ptr))
+#define sk_OPENSSL_BLOCK_delete_ptr(st, ptr) (OPENSSL_BLOCK *)sk_delete_ptr(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_PTR_OF(void, ptr))
 #define sk_OPENSSL_BLOCK_set_cmp_func(st, cmp)  \
 	((int (*)(const void * const *,const void * const *)) \
-	sk_set_cmp_func((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_BLOCK), st), CHECKED_SK_CMP_FUNC(void, cmp)))
+	sk_set_cmp_func(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_SK_CMP_FUNC(void, cmp)))
 #define sk_OPENSSL_BLOCK_dup(st) SKM_sk_dup(OPENSSL_BLOCK, st)
 #define sk_OPENSSL_BLOCK_shift(st) SKM_sk_shift(OPENSSL_BLOCK, (st))
-#define sk_OPENSSL_BLOCK_pop(st) (void *)sk_pop((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_BLOCK), st))
+#define sk_OPENSSL_BLOCK_pop(st) (void *)sk_pop(CHECKED_STACK_OF(OPENSSL_BLOCK, st))
 #define sk_OPENSSL_BLOCK_sort(st) SKM_sk_sort(OPENSSL_BLOCK, (st))
 #define sk_OPENSSL_BLOCK_is_sorted(st) SKM_sk_is_sorted(OPENSSL_BLOCK, (st))
 
 
 #define sk_OPENSSL_PSTRING_new(cmp) ((STACK_OF(OPENSSL_PSTRING) *)sk_new(CHECKED_SK_CMP_FUNC(OPENSSL_STRING, cmp)))
 #define sk_OPENSSL_PSTRING_new_null() ((STACK_OF(OPENSSL_PSTRING) *)sk_new_null())
-#define sk_OPENSSL_PSTRING_push(st, val) sk_push(CHECKED_PTR_OF(STACK_OF(OPENSSL_PSTRING), st), CHECKED_PTR_OF(OPENSSL_STRING, val))
-#define sk_OPENSSL_PSTRING_find(st, val) sk_find(CHECKED_PTR_OF(STACK_OF(OPENSSL_PSTRING), st), CHECKED_PTR_OF(OPENSSL_STRING, val))
-#define sk_OPENSSL_PSTRING_value(st, i) ((OPENSSL_PSTRING)sk_value(CHECKED_PTR_OF(STACK_OF(OPENSSL_PSTRING), st), i))
+#define sk_OPENSSL_PSTRING_push(st, val) sk_push(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, val))
+#define sk_OPENSSL_PSTRING_find(st, val) sk_find(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, val))
+#define sk_OPENSSL_PSTRING_value(st, i) ((OPENSSL_PSTRING)sk_value(CHECKED_STACK_OF(OPENSSL_PSTRING, st), i))
 #define sk_OPENSSL_PSTRING_num(st) SKM_sk_num(OPENSSL_PSTRING, st)
-#define sk_OPENSSL_PSTRING_pop_free(st, free_func) sk_pop_free(CHECKED_PTR_OF(STACK_OF(OPENSSL_PSTRING), st), CHECKED_SK_FREE_FUNC2(OPENSSL_PSTRING, free_func))
-#define sk_OPENSSL_PSTRING_insert(st, val, i) sk_insert(CHECKED_PTR_OF(STACK_OF(OPENSSL_PSTRING), st), CHECKED_PTR_OF(OPENSSL_STRING, val), i)
+#define sk_OPENSSL_PSTRING_pop_free(st, free_func) sk_pop_free(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_SK_FREE_FUNC2(OPENSSL_PSTRING, free_func))
+#define sk_OPENSSL_PSTRING_insert(st, val, i) sk_insert(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, val), i)
 #define sk_OPENSSL_PSTRING_free(st) SKM_sk_free(OPENSSL_PSTRING, st)
-#define sk_OPENSSL_PSTRING_set(st, i, val) sk_set((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_PSTRING), st), i, CHECKED_PTR_OF(OPENSSL_STRING, val))
+#define sk_OPENSSL_PSTRING_set(st, i, val) sk_set(CHECKED_STACK_OF(OPENSSL_PSTRING, st), i, CHECKED_PTR_OF(OPENSSL_STRING, val))
 #define sk_OPENSSL_PSTRING_zero(st) SKM_sk_zero(OPENSSL_PSTRING, (st))
-#define sk_OPENSSL_PSTRING_unshift(st, val) sk_unshift((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_PSTRING), st), CHECKED_PTR_OF(OPENSSL_STRING, val))
+#define sk_OPENSSL_PSTRING_unshift(st, val) sk_unshift(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, val))
 #define sk_OPENSSL_PSTRING_find_ex(st, val) sk_find_ex((_STACK *)CHECKED_CONST_PTR_OF(STACK_OF(OPENSSL_PSTRING), st), CHECKED_CONST_PTR_OF(OPENSSL_STRING, val))
 #define sk_OPENSSL_PSTRING_delete(st, i) SKM_sk_delete(OPENSSL_PSTRING, (st), (i))
-#define sk_OPENSSL_PSTRING_delete_ptr(st, ptr) (OPENSSL_PSTRING *)sk_delete_ptr((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_PSTRING), st), CHECKED_PTR_OF(OPENSSL_STRING, ptr))
+#define sk_OPENSSL_PSTRING_delete_ptr(st, ptr) (OPENSSL_PSTRING *)sk_delete_ptr(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, ptr))
 #define sk_OPENSSL_PSTRING_set_cmp_func(st, cmp)  \
 	((int (*)(const OPENSSL_STRING * const *,const OPENSSL_STRING * const *)) \
-	sk_set_cmp_func((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_PSTRING), st), CHECKED_SK_CMP_FUNC(OPENSSL_STRING, cmp)))
+	sk_set_cmp_func(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_SK_CMP_FUNC(OPENSSL_STRING, cmp)))
 #define sk_OPENSSL_PSTRING_dup(st) SKM_sk_dup(OPENSSL_PSTRING, st)
 #define sk_OPENSSL_PSTRING_shift(st) SKM_sk_shift(OPENSSL_PSTRING, (st))
-#define sk_OPENSSL_PSTRING_pop(st) (OPENSSL_STRING *)sk_pop((_STACK *)CHECKED_PTR_OF(STACK_OF(OPENSSL_PSTRING), st))
+#define sk_OPENSSL_PSTRING_pop(st) (OPENSSL_STRING *)sk_pop(CHECKED_STACK_OF(OPENSSL_PSTRING, st))
 #define sk_OPENSSL_PSTRING_sort(st) SKM_sk_sort(OPENSSL_PSTRING, (st))
 #define sk_OPENSSL_PSTRING_is_sorted(st) SKM_sk_is_sorted(OPENSSL_PSTRING, (st))
 

+ 2 - 3
openssl/crypto/ts/ts_verify_ctx.c

@@ -56,7 +56,6 @@
  *
  */
 
-#include <assert.h>
 #include "cryptlib.h"
 #include <openssl/objects.h>
 #include <openssl/ts.h>
@@ -74,7 +73,7 @@ TS_VERIFY_CTX *TS_VERIFY_CTX_new(void)
 
 void TS_VERIFY_CTX_init(TS_VERIFY_CTX *ctx)
 	{
-	assert(ctx != NULL);
+	OPENSSL_assert(ctx != NULL);
 	memset(ctx, 0, sizeof(TS_VERIFY_CTX));
 	}
 
@@ -116,7 +115,7 @@ TS_VERIFY_CTX *TS_REQ_to_TS_VERIFY_CTX(TS_REQ *req, TS_VERIFY_CTX *ctx)
 	ASN1_OCTET_STRING *msg;
 	const ASN1_INTEGER *nonce;
 
-	assert(req != NULL);
+	OPENSSL_assert(req != NULL);
 	if (ret)
 		TS_VERIFY_CTX_cleanup(ret);
 	else

+ 6 - 0
openssl/crypto/x509v3/v3_addr.c

@@ -177,12 +177,18 @@ static int i2r_address(BIO *out,
   unsigned char addr[ADDR_RAW_BUF_LEN];
   int i, n;
 
+  if (bs->length < 0)
+    return 0;
   switch (afi) {
   case IANA_AFI_IPV4:
+    if (bs->length > 4)
+      return 0;
     addr_expand(addr, bs, 4, fill);
     BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
     break;
   case IANA_AFI_IPV6:
+    if (bs->length > 16)
+      return 0;
     addr_expand(addr, bs, 16, fill);
     for (n = 16; n > 1 && addr[n-1] == 0x00 && addr[n-2] == 0x00; n -= 2)
       ;

+ 15 - 16
openssl/crypto/x509v3/v3_asid.c

@@ -61,7 +61,6 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 #include "cryptlib.h"
 #include <openssl/conf.h>
 #include <openssl/asn1.h>
@@ -172,11 +171,11 @@ static int ASIdOrRange_cmp(const ASIdOrRange * const *a_,
 {
   const ASIdOrRange *a = *a_, *b = *b_;
 
-  assert((a->type == ASIdOrRange_id && a->u.id != NULL) ||
+  OPENSSL_assert((a->type == ASIdOrRange_id && a->u.id != NULL) ||
 	 (a->type == ASIdOrRange_range && a->u.range != NULL &&
 	  a->u.range->min != NULL && a->u.range->max != NULL));
 
-  assert((b->type == ASIdOrRange_id && b->u.id != NULL) ||
+  OPENSSL_assert((b->type == ASIdOrRange_id && b->u.id != NULL) ||
 	 (b->type == ASIdOrRange_range && b->u.range != NULL &&
 	  b->u.range->min != NULL && b->u.range->max != NULL));
 
@@ -215,7 +214,7 @@ int v3_asid_add_inherit(ASIdentifiers *asid, int which)
   if (*choice == NULL) {
     if ((*choice = ASIdentifierChoice_new()) == NULL)
       return 0;
-    assert((*choice)->u.inherit == NULL);
+    OPENSSL_assert((*choice)->u.inherit == NULL);
     if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL)
       return 0;
     (*choice)->type = ASIdentifierChoice_inherit;
@@ -250,7 +249,7 @@ int v3_asid_add_id_or_range(ASIdentifiers *asid,
   if (*choice == NULL) {
     if ((*choice = ASIdentifierChoice_new()) == NULL)
       return 0;
-    assert((*choice)->u.asIdsOrRanges == NULL);
+    OPENSSL_assert((*choice)->u.asIdsOrRanges == NULL);
     (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp);
     if ((*choice)->u.asIdsOrRanges == NULL)
       return 0;
@@ -286,7 +285,7 @@ static void extract_min_max(ASIdOrRange *aor,
 			    ASN1_INTEGER **min,
 			    ASN1_INTEGER **max)
 {
-  assert(aor != NULL && min != NULL && max != NULL);
+  OPENSSL_assert(aor != NULL && min != NULL && max != NULL);
   switch (aor->type) {
   case ASIdOrRange_id:
     *min = aor->u.id;
@@ -373,7 +372,7 @@ static int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice)
 int v3_asid_is_canonical(ASIdentifiers *asid)
 {
   return (asid == NULL ||
-	  (ASIdentifierChoice_is_canonical(asid->asnum) ||
+	  (ASIdentifierChoice_is_canonical(asid->asnum) &&
 	   ASIdentifierChoice_is_canonical(asid->rdi)));
 }
 
@@ -395,7 +394,7 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
   /*
    * We have a list.  Sort it.
    */
-  assert(choice->type == ASIdentifierChoice_asIdsOrRanges);
+  OPENSSL_assert(choice->type == ASIdentifierChoice_asIdsOrRanges);
   sk_ASIdOrRange_sort(choice->u.asIdsOrRanges);
 
   /*
@@ -413,7 +412,7 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
     /*
      * Make sure we're properly sorted (paranoia).
      */
-    assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0);
+    OPENSSL_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0);
 
     /*
      * Check for overlaps.
@@ -472,7 +471,7 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
     }
   }
 
-  assert(ASIdentifierChoice_is_canonical(choice)); /* Paranoia */
+  OPENSSL_assert(ASIdentifierChoice_is_canonical(choice)); /* Paranoia */
 
   ret = 1;
 
@@ -709,9 +708,9 @@ static int v3_asid_validate_path_internal(X509_STORE_CTX *ctx,
   int i, ret = 1, inherit_as = 0, inherit_rdi = 0;
   X509 *x;
 
-  assert(chain != NULL && sk_X509_num(chain) > 0);
-  assert(ctx != NULL || ext != NULL);
-  assert(ctx == NULL || ctx->verify_cb != NULL);
+  OPENSSL_assert(chain != NULL && sk_X509_num(chain) > 0);
+  OPENSSL_assert(ctx != NULL || ext != NULL);
+  OPENSSL_assert(ctx == NULL || ctx->verify_cb != NULL);
 
   /*
    * Figure out where to start.  If we don't have an extension to
@@ -724,7 +723,7 @@ static int v3_asid_validate_path_internal(X509_STORE_CTX *ctx,
   } else {
     i = 0;
     x = sk_X509_value(chain, i);
-    assert(x != NULL);
+    OPENSSL_assert(x != NULL);
     if ((ext = x->rfc3779_asid) == NULL)
       goto done;
   }
@@ -757,7 +756,7 @@ static int v3_asid_validate_path_internal(X509_STORE_CTX *ctx,
    */
   for (i++; i < sk_X509_num(chain); i++) {
     x = sk_X509_value(chain, i);
-    assert(x != NULL);
+    OPENSSL_assert(x != NULL);
     if (x->rfc3779_asid == NULL) {
       if (child_as != NULL || child_rdi != NULL)
 	validation_err(X509_V_ERR_UNNESTED_RESOURCE);
@@ -800,7 +799,7 @@ static int v3_asid_validate_path_internal(X509_STORE_CTX *ctx,
   /*
    * Trust anchor can't inherit.
    */
-  assert(x != NULL);
+  OPENSSL_assert(x != NULL);
   if (x->rfc3779_asid != NULL) {
     if (x->rfc3779_asid->asnum != NULL &&
 	x->rfc3779_asid->asnum->type == ASIdentifierChoice_inherit)

+ 1 - 5
openssl/ssl/d1_enc.c

@@ -231,11 +231,7 @@ int dtls1_enc(SSL *s, int send)
 		if (!send)
 			{
 			if (l == 0 || l%bs != 0)
-				{
-				SSLerr(SSL_F_DTLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
-				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
-				return 0;
-				}
+				return -1;
 			}
 		
 		EVP_Cipher(ds,rec->data,rec->input,l);

+ 2 - 1
openssl/ssl/d1_pkt.c

@@ -414,7 +414,8 @@ dtls1_process_record(SSL *s)
 			goto err;
 
 		/* otherwise enc_err == -1 */
-		goto err;
+		al=SSL_AD_BAD_RECORD_MAC;
+		goto f_err;
 		}
 
 #ifdef TLS_DEBUG

+ 3 - 2
openssl/ssl/s2_srvr.c

@@ -403,13 +403,14 @@ static int get_client_master_key(SSL *s)
 		p+=3;
 		n2s(p,i); s->s2->tmp.clear=i;
 		n2s(p,i); s->s2->tmp.enc=i;
-		n2s(p,i); s->session->key_arg_length=i;
-		if(s->session->key_arg_length > SSL_MAX_KEY_ARG_LENGTH)
+		n2s(p,i);
+		if(i > SSL_MAX_KEY_ARG_LENGTH)
 			{
 			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
 			SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_KEY_ARG_TOO_LONG);
 			return -1;
 			}
+		s->session->key_arg_length=i;
 		s->state=SSL2_ST_GET_CLIENT_MASTER_KEY_B;
 		}
 

+ 7 - 1
openssl/ssl/t1_lib.c

@@ -917,6 +917,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
 						}
 					n2s(data, idsize);
 					dsize -= 2 + idsize;
+					size -= 2 + idsize;
 					if (dsize < 0)
 						{
 						*al = SSL_AD_DECODE_ERROR;
@@ -955,9 +956,14 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
 					}
 
 				/* Read in request_extensions */
+				if (size < 2)
+					{
+					*al = SSL_AD_DECODE_ERROR;
+					return 0;
+					}
 				n2s(data,dsize);
 				size -= 2;
-				if (dsize > size) 
+				if (dsize != size)
 					{
 					*al = SSL_AD_DECODE_ERROR;
 					return 0;

+ 1 - 1
packages/filemng/CustomDirView.hpp

@@ -288,7 +288,7 @@ protected:
 	virtual void __fastcall ClearItems(void);
 	virtual bool __fastcall GetDirOK(void) = 0 ;
 	virtual void __fastcall DDDragDetect(int grfKeyState, const Types::TPoint &DetectStart, const Types::TPoint &Point, Dragdrop::TDragDetectStatus DragStatus);
-	void __fastcall DDDragEnter(_di_IDataObject DataObj, int grfKeyState, const Types::TPoint &Point, int &dwEffect, bool &Accept);
+	void __fastcall DDDragEnter(_di_IDataObject DataObj, int KeyState, const Types::TPoint &Point, int &Effect, bool &Accept);
 	void __fastcall DDDragLeave(void);
 	void __fastcall DDDragOver(int grfKeyState, const Types::TPoint &Point, int &dwEffect);
 	virtual void __fastcall DDChooseEffect(int grfKeyState, int &dwEffect);

+ 9 - 9
packages/filemng/CustomDirView.pas

@@ -252,7 +252,7 @@ type
     procedure ClearItems; override;
     function GetDirOK: Boolean; virtual; abstract;
     procedure DDDragDetect(grfKeyState: Longint; DetectStart, Point: TPoint; DragStatus: TDragDetectStatus); virtual;
-    procedure DDDragEnter(DataObj: IDataObject; grfKeyState: Longint; Point: TPoint; var dwEffect: longint; var Accept: Boolean);
+    procedure DDDragEnter(DataObj: IDataObject; KeyState: Longint; Point: TPoint; var Effect: longint; var Accept: Boolean);
     procedure DDDragLeave;
     procedure DDDragOver(grfKeyState: Longint; Point: TPoint; var dwEffect: Longint);
     procedure DDChooseEffect(grfKeyState: Integer; var dwEffect: Integer); virtual;
@@ -1969,16 +1969,15 @@ begin
   GlobalDragImageList.ShowDragImage;
 end;
 
-procedure TCustomDirView.DDDragEnter(DataObj: IDataObject; grfKeyState: Longint;
-  Point: TPoint; var dwEffect: longint; var Accept: Boolean);
+procedure TCustomDirView.DDDragEnter(DataObj: IDataObject; KeyState: Longint;
+  Point: TPoint; var Effect: longint; var Accept: Boolean);
 var
   Index: Integer;
 begin
   Accept := Accept and DirOK and (not Loading);
-  if Accept and (DragDropFilesEx.FileList.Count > 0) and
-     (Length(TFDDListItem(DragDropFilesEx.FileList[0]^).Name) > 2) and
-     ((TFDDListItem(DragDropFilesEx.FileList[0]^).Name[2] = ':') or
-     (TFDDListItem(DragDropFilesEx.FileList[0]^).Name[2] = '\')) and
+  if Accept and
+     (DragDropFilesEx.FileList.Count > 0) and
+     (Length(TFDDListItem(DragDropFilesEx.FileList[0]^).Name) > 0) and
      (not IsRecycleBin or not DragDropFilesEx.FileNamesAreMapped) then
   begin
     FDragDrive := Upcase(TFDDListItem(DragDropFilesEx.FileList[0]^).Name[1]);
@@ -1987,23 +1986,24 @@ begin
       ((DragDropFilesEx.AvailableDropEffects and DropEffect_Link) <> 0);
 
     if FExeDrag then
+    begin
       for Index := 0 to DragDropFilesEx.FileList.Count - 1 do
         if not IsExecutable(TFDDListItem(DragDropFilesEx.FileList[Index]^).Name) then
         begin
           FExeDrag := False;
           Break;
         end;
+    end;
   end
     else
   begin
     FDragDrive := #0;
-    Accept := False;
   end;
 
   FScrollOnDragOver.StartDrag;
 
   if Assigned(FOnDDDragEnter) then
-    FOnDDDragEnter(Self, DataObj, grfKeyState, Point, dwEffect, Accept);
+    FOnDDDragEnter(Self, DataObj, KeyState, Point, Effect, Accept);
 end;
 
 procedure TCustomDirView.DDDragLeave;

+ 8 - 5
packages/filemng/CustomDriveView.pas

@@ -385,17 +385,20 @@ end;
 procedure TCustomDriveView.DDDragEnter(DataObj: IDataObject; KeyState: Longint;
   Point: TPoint; var Effect: Longint; var Accept: Boolean);
 var
-  i: Integer;
+  Index: Integer;
 begin
   if (FDragDropFilesEx.FileList.Count > 0) and
      (Length(TFDDListItem(FDragDropFilesEx.FileList[0]^).Name) > 0) Then
   begin
-    FDragDrive := TFDDListItem(FDragDropFilesEx.FileList[0]^).Name[1];
-    FExeDrag := FDDLinkOnExeDrag and ((FDragDropFilesEx.AvailableDropEffects and DropEffect_Link) <> 0);
+    FDragDrive := Upcase(TFDDListItem(FDragDropFilesEx.FileList[0]^).Name[1]);
+    FExeDrag := FDDLinkOnExeDrag and
+      (deLink in DragDropFilesEx.TargetEffects) and
+      ((DragDropFilesEx.AvailableDropEffects and DropEffect_Link) <> 0);
+
     if FExeDrag then
     begin
-      for i := 0 to FDragDropFilesEx.FileList.Count - 1 do
-        if not IsExecutable(TFDDListItem(FDragDropFilesEx.FileList[i]^).Name) then
+      for Index := 0 to FDragDropFilesEx.FileList.Count - 1 do
+        if not IsExecutable(TFDDListItem(FDragDropFilesEx.FileList[Index]^).Name) then
         begin
           FExeDrag := False;
           Break;

+ 1 - 1
packages/filemng/DirView.pas

@@ -3348,7 +3348,7 @@ begin
       FDiscMonitor.SetDirectory(PathName);
       FDiscMonitor.Open;
     end;
-  end
+  end;
 end; {StartWatchThread}
 
 {$ENDIF}

+ 2 - 1
packages/my/NortonLikeListView.hpp

@@ -58,13 +58,14 @@ private:
 	bool FManageSelection;
 	int FFirstSelected;
 	int FLastSelected;
-	bool FFocusedWhenClicked;
+	System::TDateTime FNotFocusedWhenClicked;
 	HIDESBASE MESSAGE void __fastcall WMLButtonDown(Messages::TWMMouse &Message);
 	HIDESBASE MESSAGE void __fastcall WMRButtonDown(Messages::TWMMouse &Message);
 	HIDESBASE MESSAGE void __fastcall WMKeyDown(Messages::TWMKey &Message);
 	HIDESBASE MESSAGE void __fastcall WMChar(Messages::TWMKey &Message);
 	HIDESBASE MESSAGE void __fastcall WMNotify(Messages::TWMNotify &Message);
 	HIDESBASE MESSAGE void __fastcall CNNotify(Messages::TWMNotify &Message);
+	MESSAGE void __fastcall LVMEditLabel(Messages::TMessage &Message);
 	int __fastcall GetMarkedCount(void);
 	Comctrls::TListItem* __fastcall GetMarkedFile(void);
 	void __fastcall ItemSelected(Comctrls::TListItem* Item, int Index);

+ 25 - 3
packages/my/NortonLikeListView.pas

@@ -26,13 +26,14 @@ type
     FManageSelection: Boolean;
     FFirstSelected: Integer;
     FLastSelected: Integer;
-    FFocusedWhenClicked: Boolean;
+    FNotFocusedWhenClicked: TDateTime;
     procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
     procedure WMRButtonDown(var Message: TWMRButtonDown); message WM_RBUTTONDOWN;
     procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
     procedure WMChar(var Message: TWMChar); message WM_CHAR;
     procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
     procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
+    procedure LVMEditLabel(var Message: TMessage); message LVM_EDITLABEL;
     function GetMarkedCount: Integer;
     function GetMarkedFile: TListItem;
     procedure ItemSelected(Item: TListItem; Index: Integer);
@@ -198,6 +199,7 @@ begin
   // cannot use Win32MajorVersion as it is affected by compatibility mode and
   // the bug is present even in compatibility mode
   FManageSelection := IsVista;
+  FNotFocusedWhenClicked := 0;
 end;
 
 destructor TCustomNortonLikeListView.Destroy;
@@ -618,12 +620,13 @@ var
   PDontSelectItem: Boolean;
   Shift: TShiftState;
 begin
+  if not Focused then FNotFocusedWhenClicked := Now
+    else FNotFocusedWhenClicked := 0;
   Shift := KeysToShiftState(Message.Keys);
   PDontSelectItem := FDontSelectItem;
   PDontUnSelectItem := FDontUnSelectItem;
   FDontSelectItem := FDontSelectItem or ((NortonLike = nlOn) and ((Shift * [ssCtrl, ssShift]) = []));
   FDontUnSelectItem := FDontUnSelectItem or ((NortonLike = nlOn) and ((Shift * [ssCtrl]) = []));
-  FFocusedWhenClicked := Focused;
   try
     inherited;
   finally
@@ -806,9 +809,28 @@ begin
   ColProperties.ListViewWndCreated;
 end;
 
+procedure TCustomNortonLikeListView.LVMEditLabel(var Message: TMessage);
+begin
+  // explicitly requesting editing (e.g. F2),
+  // so we do not care anymore what state the view was in when last clicked
+  FNotFocusedWhenClicked := 0;
+  inherited;
+end;
+
 function TCustomNortonLikeListView.CanEdit(Item: TListItem): Boolean;
+var
+  N: TDateTime;
+  Delta: Double;
 begin
-  Result := inherited CanEdit(Item) and FFocusedWhenClicked;
+  N := Now;
+  Result := inherited CanEdit(Item);
+  if Result and (FNotFocusedWhenClicked > 0) then
+  begin
+    Delta := N - FNotFocusedWhenClicked;
+    // it takes little more than 500ms to trigger editing after click
+    Result := Delta > (750.0/(24*60*60*1000));
+  end;
+  FNotFocusedWhenClicked := 0;
 end;
 
 end.

+ 6 - 2
putty/SSH.C

@@ -2866,6 +2866,7 @@ static int ssh_do_close(Ssh ssh, int notify_exit)
 		x11_close(c->u.x11.s);
 		break;
 	      case CHAN_SOCKDATA:
+	      case CHAN_SOCKDATA_DORMANT:
 		pfd_close(c->u.pfd.s);
 		break;
 	    }
@@ -7203,12 +7204,14 @@ static void ssh2_msg_channel_open(Ssh ssh, struct Packet *pktin)
 }
 
 /*
- * Buffer banner messages for later display at some convenient point.
+ * Buffer banner messages for later display at some convenient point,
+ * if we're going to display them.
  */
 static void ssh2_msg_userauth_banner(Ssh ssh, struct Packet *pktin)
 {
     /* Arbitrary limit to prevent unbounded inflation of buffer */
-    if (bufchain_size(&ssh->banner) <= 131072) {
+    if (ssh->cfg.ssh_show_banner &&
+	bufchain_size(&ssh->banner) <= 131072) {
 	char *banner = NULL;
 	int size = 0;
 	ssh_pkt_getstring(pktin, &banner, &size);
@@ -9375,6 +9378,7 @@ static void ssh_free(void *handle)
 		    x11_close(c->u.x11.s);
 		break;
 	      case CHAN_SOCKDATA:
+	      case CHAN_SOCKDATA_DORMANT:
 		if (c->u.pfd.s != NULL)
 		    pfd_close(c->u.pfd.s);
 		break;

+ 2 - 0
putty/SSH.H

@@ -457,6 +457,8 @@ int ssh1_write_bignum(void *data, Bignum bn);
 Bignum biggcd(Bignum a, Bignum b);
 unsigned short bignum_mod_short(Bignum number, unsigned short modulus);
 Bignum bignum_add_long(Bignum number, unsigned long addend);
+Bignum bigadd(Bignum a, Bignum b);
+Bignum bigsub(Bignum a, Bignum b);
 Bignum bigmul(Bignum a, Bignum b);
 Bignum bigmuladd(Bignum a, Bignum b, Bignum addend);
 Bignum bigdiv(Bignum a, Bignum b);

+ 815 - 14
putty/SSHBN.C

@@ -63,7 +63,34 @@ typedef unsigned __int64 BignumDblInt;
     __asm mov q, eax \
 } while(0)
 #endif
+#elif defined _LP64
+/* 64-bit architectures can do 32x32->64 chunks at a time */
+typedef unsigned int BignumInt;
+typedef unsigned long BignumDblInt;
+#define BIGNUM_INT_MASK  0xFFFFFFFFU
+#define BIGNUM_TOP_BIT   0x80000000U
+#define BIGNUM_INT_BITS  32
+#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
+#define DIVMOD_WORD(q, r, hi, lo, w) do { \
+    BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
+    q = n / w; \
+    r = n % w; \
+} while (0)
+#elif defined _LLP64
+/* 64-bit architectures in which unsigned long is 32 bits, not 64 */
+typedef unsigned long BignumInt;
+typedef unsigned long long BignumDblInt;
+#define BIGNUM_INT_MASK  0xFFFFFFFFUL
+#define BIGNUM_TOP_BIT   0x80000000UL
+#define BIGNUM_INT_BITS  32
+#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
+#define DIVMOD_WORD(q, r, hi, lo, w) do { \
+    BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
+    q = n / w; \
+    r = n % w; \
+} while (0)
 #else
+/* Fallback for all other cases */
 typedef unsigned short BignumInt;
 typedef unsigned long BignumDblInt;
 #define BIGNUM_INT_MASK  0xFFFFU
@@ -144,32 +171,431 @@ Bignum bn_power_2(int n)
     return ret;
 }
 
+/*
+ * Internal addition. Sets c = a - b, where 'a', 'b' and 'c' are all
+ * big-endian arrays of 'len' BignumInts. Returns a BignumInt carried
+ * off the top.
+ */
+static BignumInt internal_add(const BignumInt *a, const BignumInt *b,
+                              BignumInt *c, int len)
+{
+    int i;
+    BignumDblInt carry = 0;
+
+    for (i = len-1; i >= 0; i--) {
+        carry += (BignumDblInt)a[i] + b[i];
+        c[i] = (BignumInt)carry;
+        carry >>= BIGNUM_INT_BITS;
+    }
+
+    return (BignumInt)carry;
+}
+
+/*
+ * Internal subtraction. Sets c = a - b, where 'a', 'b' and 'c' are
+ * all big-endian arrays of 'len' BignumInts. Any borrow from the top
+ * is ignored.
+ */
+static void internal_sub(const BignumInt *a, const BignumInt *b,
+                         BignumInt *c, int len)
+{
+    int i;
+    BignumDblInt carry = 1;
+
+    for (i = len-1; i >= 0; i--) {
+        carry += (BignumDblInt)a[i] + (b[i] ^ BIGNUM_INT_MASK);
+        c[i] = (BignumInt)carry;
+        carry >>= BIGNUM_INT_BITS;
+    }
+}
+
 /*
  * Compute c = a * b.
  * Input is in the first len words of a and b.
  * Result is returned in the first 2*len words of c.
  */
-static void internal_mul(BignumInt *a, BignumInt *b,
+#define KARATSUBA_THRESHOLD 50
+static void internal_mul(const BignumInt *a, const BignumInt *b,
 			 BignumInt *c, int len)
 {
     int i, j;
     BignumDblInt t;
 
-    for (j = 0; j < 2 * len; j++)
-	c[j] = 0;
+    if (len > KARATSUBA_THRESHOLD) {
+
+        /*
+         * Karatsuba divide-and-conquer algorithm. Cut each input in
+         * half, so that it's expressed as two big 'digits' in a giant
+         * base D:
+         *
+         *   a = a_1 D + a_0
+         *   b = b_1 D + b_0
+         *
+         * Then the product is of course
+         *
+         *  ab = a_1 b_1 D^2 + (a_1 b_0 + a_0 b_1) D + a_0 b_0
+         *
+         * and we compute the three coefficients by recursively
+         * calling ourself to do half-length multiplications.
+         *
+         * The clever bit that makes this worth doing is that we only
+         * need _one_ half-length multiplication for the central
+         * coefficient rather than the two that it obviouly looks
+         * like, because we can use a single multiplication to compute
+         *
+         *   (a_1 + a_0) (b_1 + b_0) = a_1 b_1 + a_1 b_0 + a_0 b_1 + a_0 b_0
+         *
+         * and then we subtract the other two coefficients (a_1 b_1
+         * and a_0 b_0) which we were computing anyway.
+         *
+         * Hence we get to multiply two numbers of length N in about
+         * three times as much work as it takes to multiply numbers of
+         * length N/2, which is obviously better than the four times
+         * as much work it would take if we just did a long
+         * conventional multiply.
+         */
+
+        int toplen = len/2, botlen = len - toplen; /* botlen is the bigger */
+        int midlen = botlen + 1;
+        BignumInt *scratch;
+        BignumDblInt carry;
+#ifdef KARA_DEBUG
+        int i;
+#endif
 
-    for (i = len - 1; i >= 0; i--) {
-	t = 0;
-	for (j = len - 1; j >= 0; j--) {
-	    t += MUL_WORD(a[i], (BignumDblInt) b[j]);
-	    t += (BignumDblInt) c[i + j + 1];
-	    c[i + j + 1] = (BignumInt) t;
-	    t = t >> BIGNUM_INT_BITS;
-	}
-	c[i] = (BignumInt) t;
+        /*
+         * The coefficients a_1 b_1 and a_0 b_0 just avoid overlapping
+         * in the output array, so we can compute them immediately in
+         * place.
+         */
+
+#ifdef KARA_DEBUG
+        printf("a1,a0 = 0x");
+        for (i = 0; i < len; i++) {
+            if (i == toplen) printf(", 0x");
+            printf("%0*x", BIGNUM_INT_BITS/4, a[i]);
+        }
+        printf("\n");
+        printf("b1,b0 = 0x");
+        for (i = 0; i < len; i++) {
+            if (i == toplen) printf(", 0x");
+            printf("%0*x", BIGNUM_INT_BITS/4, b[i]);
+        }
+        printf("\n");
+#endif
+
+        /* a_1 b_1 */
+        internal_mul(a, b, c, toplen);
+#ifdef KARA_DEBUG
+        printf("a1b1 = 0x");
+        for (i = 0; i < 2*toplen; i++) {
+            printf("%0*x", BIGNUM_INT_BITS/4, c[i]);
+        }
+        printf("\n");
+#endif
+
+        /* a_0 b_0 */
+        internal_mul(a + toplen, b + toplen, c + 2*toplen, botlen);
+#ifdef KARA_DEBUG
+        printf("a0b0 = 0x");
+        for (i = 0; i < 2*botlen; i++) {
+            printf("%0*x", BIGNUM_INT_BITS/4, c[2*toplen+i]);
+        }
+        printf("\n");
+#endif
+
+        /*
+         * We must allocate scratch space for the central coefficient,
+         * and also for the two input values that we multiply when
+         * computing it. Since either or both may carry into the
+         * (botlen+1)th word, we must use a slightly longer length
+         * 'midlen'.
+         */
+        scratch = snewn(4 * midlen, BignumInt);
+
+        /* Zero padding. midlen exceeds toplen by at most 2, so just
+         * zero the first two words of each input and the rest will be
+         * copied over. */
+        scratch[0] = scratch[1] = scratch[midlen] = scratch[midlen+1] = 0;
+
+        for (j = 0; j < toplen; j++) {
+            scratch[midlen - toplen + j] = a[j]; /* a_1 */
+            scratch[2*midlen - toplen + j] = b[j]; /* b_1 */
+        }
+
+        /* compute a_1 + a_0 */
+        scratch[0] = internal_add(scratch+1, a+toplen, scratch+1, botlen);
+#ifdef KARA_DEBUG
+        printf("a1plusa0 = 0x");
+        for (i = 0; i < midlen; i++) {
+            printf("%0*x", BIGNUM_INT_BITS/4, scratch[i]);
+        }
+        printf("\n");
+#endif
+        /* compute b_1 + b_0 */
+        scratch[midlen] = internal_add(scratch+midlen+1, b+toplen,
+                                       scratch+midlen+1, botlen);
+#ifdef KARA_DEBUG
+        printf("b1plusb0 = 0x");
+        for (i = 0; i < midlen; i++) {
+            printf("%0*x", BIGNUM_INT_BITS/4, scratch[midlen+i]);
+        }
+        printf("\n");
+#endif
+
+        /*
+         * Now we can do the third multiplication.
+         */
+        internal_mul(scratch, scratch + midlen, scratch + 2*midlen, midlen);
+#ifdef KARA_DEBUG
+        printf("a1plusa0timesb1plusb0 = 0x");
+        for (i = 0; i < 2*midlen; i++) {
+            printf("%0*x", BIGNUM_INT_BITS/4, scratch[2*midlen+i]);
+        }
+        printf("\n");
+#endif
+
+        /*
+         * Now we can reuse the first half of 'scratch' to compute the
+         * sum of the outer two coefficients, to subtract from that
+         * product to obtain the middle one.
+         */
+        scratch[0] = scratch[1] = scratch[2] = scratch[3] = 0;
+        for (j = 0; j < 2*toplen; j++)
+            scratch[2*midlen - 2*toplen + j] = c[j];
+        scratch[1] = internal_add(scratch+2, c + 2*toplen,
+                                  scratch+2, 2*botlen);
+#ifdef KARA_DEBUG
+        printf("a1b1plusa0b0 = 0x");
+        for (i = 0; i < 2*midlen; i++) {
+            printf("%0*x", BIGNUM_INT_BITS/4, scratch[i]);
+        }
+        printf("\n");
+#endif
+
+        internal_sub(scratch + 2*midlen, scratch,
+                     scratch + 2*midlen, 2*midlen);
+#ifdef KARA_DEBUG
+        printf("a1b0plusa0b1 = 0x");
+        for (i = 0; i < 2*midlen; i++) {
+            printf("%0*x", BIGNUM_INT_BITS/4, scratch[2*midlen+i]);
+        }
+        printf("\n");
+#endif
+
+        /*
+         * And now all we need to do is to add that middle coefficient
+         * back into the output. We may have to propagate a carry
+         * further up the output, but we can be sure it won't
+         * propagate right the way off the top.
+         */
+        carry = internal_add(c + 2*len - botlen - 2*midlen,
+                             scratch + 2*midlen,
+                             c + 2*len - botlen - 2*midlen, 2*midlen);
+        j = 2*len - botlen - 2*midlen - 1;
+        while (carry) {
+            assert(j >= 0);
+            carry += c[j];
+            c[j] = (BignumInt)carry;
+            carry >>= BIGNUM_INT_BITS;
+            j--;
+        }
+#ifdef KARA_DEBUG
+        printf("ab = 0x");
+        for (i = 0; i < 2*len; i++) {
+            printf("%0*x", BIGNUM_INT_BITS/4, c[i]);
+        }
+        printf("\n");
+#endif
+
+        /* Free scratch. */
+        for (j = 0; j < 4 * midlen; j++)
+            scratch[j] = 0;
+        sfree(scratch);
+
+    } else {
+
+        /*
+         * Multiply in the ordinary O(N^2) way.
+         */
+
+        for (j = 0; j < 2 * len; j++)
+            c[j] = 0;
+
+        for (i = len - 1; i >= 0; i--) {
+            t = 0;
+            for (j = len - 1; j >= 0; j--) {
+                t += MUL_WORD(a[i], (BignumDblInt) b[j]);
+                t += (BignumDblInt) c[i + j + 1];
+                c[i + j + 1] = (BignumInt) t;
+                t = t >> BIGNUM_INT_BITS;
+            }
+            c[i] = (BignumInt) t;
+        }
     }
 }
 
+/*
+ * Variant form of internal_mul used for the initial step of
+ * Montgomery reduction. Only bothers outputting 'len' words
+ * (everything above that is thrown away).
+ */
+static void internal_mul_low(const BignumInt *a, const BignumInt *b,
+                             BignumInt *c, int len)
+{
+    int i, j;
+    BignumDblInt t;
+
+    if (len > KARATSUBA_THRESHOLD) {
+
+        /*
+         * Karatsuba-aware version of internal_mul_low. As before, we
+         * express each input value as a shifted combination of two
+         * halves:
+         *
+         *   a = a_1 D + a_0
+         *   b = b_1 D + b_0
+         *
+         * Then the full product is, as before,
+         *
+         *  ab = a_1 b_1 D^2 + (a_1 b_0 + a_0 b_1) D + a_0 b_0
+         *
+         * Provided we choose D on the large side (so that a_0 and b_0
+         * are _at least_ as long as a_1 and b_1), we don't need the
+         * topmost term at all, and we only need half of the middle
+         * term. So there's no point in doing the proper Karatsuba
+         * optimisation which computes the middle term using the top
+         * one, because we'd take as long computing the top one as
+         * just computing the middle one directly.
+         *
+         * So instead, we do a much more obvious thing: we call the
+         * fully optimised internal_mul to compute a_0 b_0, and we
+         * recursively call ourself to compute the _bottom halves_ of
+         * a_1 b_0 and a_0 b_1, each of which we add into the result
+         * in the obvious way.
+         *
+         * In other words, there's no actual Karatsuba _optimisation_
+         * in this function; the only benefit in doing it this way is
+         * that we call internal_mul proper for a large part of the
+         * work, and _that_ can optimise its operation.
+         */
+
+        int toplen = len/2, botlen = len - toplen; /* botlen is the bigger */
+        BignumInt *scratch;
+
+        /*
+         * Allocate scratch space for the various bits and pieces
+         * we're going to be adding together. We need botlen*2 words
+         * for a_0 b_0 (though we may end up throwing away its topmost
+         * word), and toplen words for each of a_1 b_0 and a_0 b_1.
+         * That adds up to exactly 2*len.
+         */
+        scratch = snewn(len*2, BignumInt);
+
+        /* a_0 b_0 */
+        internal_mul(a + toplen, b + toplen, scratch + 2*toplen, botlen);
+
+        /* a_1 b_0 */
+        internal_mul_low(a, b + len - toplen, scratch + toplen, toplen);
+
+        /* a_0 b_1 */
+        internal_mul_low(a + len - toplen, b, scratch, toplen);
+
+        /* Copy the bottom half of the big coefficient into place */
+        for (j = 0; j < botlen; j++)
+            c[toplen + j] = scratch[2*toplen + botlen + j];
+
+        /* Add the two small coefficients, throwing away the returned carry */
+        internal_add(scratch, scratch + toplen, scratch, toplen);
+
+        /* And add that to the large coefficient, leaving the result in c. */
+        internal_add(scratch, scratch + 2*toplen + botlen - toplen,
+                     c, toplen);
+
+        /* Free scratch. */
+        for (j = 0; j < len*2; j++)
+            scratch[j] = 0;
+        sfree(scratch);
+
+    } else {
+
+        for (j = 0; j < len; j++)
+            c[j] = 0;
+
+        for (i = len - 1; i >= 0; i--) {
+            t = 0;
+            for (j = len - 1; j >= len - i - 1; j--) {
+                t += MUL_WORD(a[i], (BignumDblInt) b[j]);
+                t += (BignumDblInt) c[i + j + 1 - len];
+                c[i + j + 1 - len] = (BignumInt) t;
+                t = t >> BIGNUM_INT_BITS;
+            }
+        }
+
+    }
+}
+
+/*
+ * Montgomery reduction. Expects x to be a big-endian array of 2*len
+ * BignumInts whose value satisfies 0 <= x < rn (where r = 2^(len *
+ * BIGNUM_INT_BITS) is the Montgomery base). Returns in the same array
+ * a value x' which is congruent to xr^{-1} mod n, and satisfies 0 <=
+ * x' < n.
+ *
+ * 'n' and 'mninv' should be big-endian arrays of 'len' BignumInts
+ * each, containing respectively n and the multiplicative inverse of
+ * -n mod r.
+ *
+ * 'tmp' is an array of at least '3*len' BignumInts used as scratch
+ * space.
+ */
+static void monty_reduce(BignumInt *x, const BignumInt *n,
+                         const BignumInt *mninv, BignumInt *tmp, int len)
+{
+    int i;
+    BignumInt carry;
+
+    /*
+     * Multiply x by (-n)^{-1} mod r. This gives us a value m such
+     * that mn is congruent to -x mod r. Hence, mn+x is an exact
+     * multiple of r, and is also (obviously) congruent to x mod n.
+     */
+    internal_mul_low(x + len, mninv, tmp, len);
+
+    /*
+     * Compute t = (mn+x)/r in ordinary, non-modular, integer
+     * arithmetic. By construction this is exact, and is congruent mod
+     * n to x * r^{-1}, i.e. the answer we want.
+     *
+     * The following multiply leaves that answer in the _most_
+     * significant half of the 'x' array, so then we must shift it
+     * down.
+     */
+    internal_mul(tmp, n, tmp+len, len);
+    carry = internal_add(x, tmp+len, x, 2*len);
+    for (i = 0; i < len; i++)
+        x[len + i] = x[i], x[i] = 0;
+
+    /*
+     * Reduce t mod n. This doesn't require a full-on division by n,
+     * but merely a test and single optional subtraction, since we can
+     * show that 0 <= t < 2n.
+     *
+     * Proof:
+     *  + we computed m mod r, so 0 <= m < r.
+     *  + so 0 <= mn < rn, obviously
+     *  + hence we only need 0 <= x < rn to guarantee that 0 <= mn+x < 2rn
+     *  + yielding 0 <= (mn+x)/r < 2n as required.
+     */
+    if (!carry) {
+        for (i = 0; i < len; i++)
+            if (x[len + i] != n[i])
+                break;
+    }
+    if (carry || i >= len || x[len + i] > n[i])
+        internal_sub(x+len, n, x+len, len);
+}
+
 static void internal_add_shifted(BignumInt *number,
 				 unsigned n, int shift)
 {
@@ -291,9 +717,9 @@ static void internal_mod(BignumInt *a, int alen,
 }
 
 /*
- * Compute (base ^ exp) % mod.
+ * Compute (base ^ exp) % mod, the pedestrian way.
  */
-Bignum modpow(Bignum base_in, Bignum exp, Bignum mod)
+Bignum modpow_simple(Bignum base_in, Bignum exp, Bignum mod)
 {
     BignumInt *a, *b, *n, *m;
     int mshift;
@@ -411,6 +837,155 @@ Bignum modpow(Bignum base_in, Bignum exp, Bignum mod)
     return result;
 }
 
+/*
+ * Compute (base ^ exp) % mod. Uses the Montgomery multiplication
+ * technique where possible, falling back to modpow_simple otherwise.
+ */
+Bignum modpow(Bignum base_in, Bignum exp, Bignum mod)
+{
+    BignumInt *a, *b, *x, *n, *mninv, *tmp;
+    int len, i, j;
+    Bignum base, base2, r, rn, inv, result;
+
+    /*
+     * The most significant word of mod needs to be non-zero. It
+     * should already be, but let's make sure.
+     */
+    assert(mod[mod[0]] != 0);
+
+    /*
+     * mod had better be odd, or we can't do Montgomery multiplication
+     * using a power of two at all.
+     */
+    if (!(mod[1] & 1))
+        return modpow_simple(base_in, exp, mod);
+
+    /*
+     * Make sure the base is smaller than the modulus, by reducing
+     * it modulo the modulus if not.
+     */
+    base = bigmod(base_in, mod);
+
+    /*
+     * Compute the inverse of n mod r, for monty_reduce. (In fact we
+     * want the inverse of _minus_ n mod r, but we'll sort that out
+     * below.)
+     */
+    len = mod[0];
+    r = bn_power_2(BIGNUM_INT_BITS * len);
+    inv = modinv(mod, r);
+
+    /*
+     * Multiply the base by r mod n, to get it into Montgomery
+     * representation.
+     */
+    base2 = modmul(base, r, mod);
+    freebn(base);
+    base = base2;
+
+    rn = bigmod(r, mod);               /* r mod n, i.e. Montgomerified 1 */
+
+    freebn(r);                         /* won't need this any more */
+
+    /*
+     * Set up internal arrays of the right lengths, in big-endian
+     * format, containing the base, the modulus, and the modulus's
+     * inverse.
+     */
+    n = snewn(len, BignumInt);
+    for (j = 0; j < len; j++)
+	n[len - 1 - j] = mod[j + 1];
+
+    mninv = snewn(len, BignumInt);
+    for (j = 0; j < len; j++)
+	mninv[len - 1 - j] = (j < inv[0] ? inv[j + 1] : 0);
+    freebn(inv);         /* we don't need this copy of it any more */
+    /* Now negate mninv mod r, so it's the inverse of -n rather than +n. */
+    x = snewn(len, BignumInt);
+    for (j = 0; j < len; j++)
+        x[j] = 0;
+    internal_sub(x, mninv, mninv, len);
+
+    /* x = snewn(len, BignumInt); */ /* already done above */
+    for (j = 0; j < len; j++)
+	x[len - 1 - j] = (j < base[0] ? base[j + 1] : 0);
+    freebn(base);        /* we don't need this copy of it any more */
+
+    a = snewn(2*len, BignumInt);
+    b = snewn(2*len, BignumInt);
+    for (j = 0; j < len; j++)
+	a[2*len - 1 - j] = (j < rn[0] ? rn[j + 1] : 0);
+    freebn(rn);
+
+    tmp = snewn(3*len, BignumInt);
+
+    /* Skip leading zero bits of exp. */
+    i = 0;
+    j = BIGNUM_INT_BITS-1;
+    while (i < (int)exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) {
+	j--;
+	if (j < 0) {
+	    i++;
+	    j = BIGNUM_INT_BITS-1;
+	}
+    }
+
+    /* Main computation */
+    while (i < (int)exp[0]) {
+	while (j >= 0) {
+	    internal_mul(a + len, a + len, b, len);
+            monty_reduce(b, n, mninv, tmp, len);
+	    if ((exp[exp[0] - i] & (1 << j)) != 0) {
+                internal_mul(b + len, x, a, len);
+                monty_reduce(a, n, mninv, tmp, len);
+	    } else {
+		BignumInt *t;
+		t = a;
+		a = b;
+		b = t;
+	    }
+	    j--;
+	}
+	i++;
+	j = BIGNUM_INT_BITS-1;
+    }
+
+    /*
+     * Final monty_reduce to get back from the adjusted Montgomery
+     * representation.
+     */
+    monty_reduce(a, n, mninv, tmp, len);
+
+    /* Copy result to buffer */
+    result = newbn(mod[0]);
+    for (i = 0; i < len; i++)
+	result[result[0] - i] = a[i + len];
+    while (result[0] > 1 && result[result[0]] == 0)
+	result[0]--;
+
+    /* Free temporary arrays */
+    for (i = 0; i < 3 * len; i++)
+	tmp[i] = 0;
+    sfree(tmp);
+    for (i = 0; i < 2 * len; i++)
+	a[i] = 0;
+    sfree(a);
+    for (i = 0; i < 2 * len; i++)
+	b[i] = 0;
+    sfree(b);
+    for (i = 0; i < len; i++)
+	mninv[i] = 0;
+    sfree(mninv);
+    for (i = 0; i < len; i++)
+	n[i] = 0;
+    sfree(n);
+    for (i = 0; i < len; i++)
+	x[i] = 0;
+    sfree(x);
+
+    return result;
+}
+
 /*
  * Compute (p * q) % mod.
  * The most significant word of mod MUST be non-zero.
@@ -824,6 +1399,69 @@ Bignum bigmul(Bignum a, Bignum b)
     return bigmuladd(a, b, NULL);
 }
 
+/*
+ * Simple addition.
+ */
+Bignum bigadd(Bignum a, Bignum b)
+{
+    int alen = a[0], blen = b[0];
+    int rlen = (alen > blen ? alen : blen) + 1;
+    int i, maxspot;
+    Bignum ret;
+    BignumDblInt carry;
+
+    ret = newbn(rlen);
+
+    carry = 0;
+    maxspot = 0;
+    for (i = 1; i <= rlen; i++) {
+        carry += (i <= (int)a[0] ? a[i] : 0);
+        carry += (i <= (int)b[0] ? b[i] : 0);
+        ret[i] = (BignumInt) carry & BIGNUM_INT_MASK;
+        carry >>= BIGNUM_INT_BITS;
+        if (ret[i] != 0 && i > maxspot)
+            maxspot = i;
+    }
+    ret[0] = maxspot;
+
+    return ret;
+}
+
+/*
+ * Subtraction. Returns a-b, or NULL if the result would come out
+ * negative (recall that this entire bignum module only handles
+ * positive numbers).
+ */
+Bignum bigsub(Bignum a, Bignum b)
+{
+    int alen = a[0], blen = b[0];
+    int rlen = (alen > blen ? alen : blen);
+    int i, maxspot;
+    Bignum ret;
+    BignumDblInt carry;
+
+    ret = newbn(rlen);
+
+    carry = 1;
+    maxspot = 0;
+    for (i = 1; i <= rlen; i++) {
+        carry += (i <= (int)a[0] ? a[i] : 0);
+        carry += (i <= (int)b[0] ? b[i] ^ BIGNUM_INT_MASK : BIGNUM_INT_MASK);
+        ret[i] = (BignumInt) carry & BIGNUM_INT_MASK;
+        carry >>= BIGNUM_INT_BITS;
+        if (ret[i] != 0 && i > maxspot)
+            maxspot = i;
+    }
+    ret[0] = maxspot;
+
+    if (!carry) {
+        freebn(ret);
+        return NULL;
+    }
+
+    return ret;
+}
+
 /*
  * Create a bignum which is the bitmask covering another one. That
  * is, the smallest integer which is >= N and is also one less than
@@ -1102,3 +1740,166 @@ char *bignum_decimal(Bignum x)
     sfree(workspace);
     return ret;
 }
+
+#ifdef TESTBN
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+/*
+ * gcc -g -O0 -DTESTBN -o testbn sshbn.c misc.c -I unix -I charset
+ *
+ * Then feed to this program's standard input the output of
+ * testdata/bignum.py .
+ */
+
+void modalfatalbox(char *p, ...)
+{
+    va_list ap;
+    fprintf(stderr, "FATAL ERROR: ");
+    va_start(ap, p);
+    vfprintf(stderr, p, ap);
+    va_end(ap);
+    fputc('\n', stderr);
+    exit(1);
+}
+
+#define fromxdigit(c) ( (c)>'9' ? ((c)&0xDF) - 'A' + 10 : (c) - '0' )
+
+int main(int argc, char **argv)
+{
+    char *buf;
+    int line = 0;
+    int passes = 0, fails = 0;
+
+    while ((buf = fgetline(stdin)) != NULL) {
+        int maxlen = strlen(buf);
+        unsigned char *data = snewn(maxlen, unsigned char);
+        unsigned char *ptrs[5], *q;
+        int ptrnum;
+        char *bufp = buf;
+
+        line++;
+
+        q = data;
+        ptrnum = 0;
+
+        while (*bufp && !isspace((unsigned char)*bufp))
+            bufp++;
+        if (bufp)
+            *bufp++ = '\0';
+
+        while (*bufp) {
+            char *start, *end;
+            int i;
+
+            while (*bufp && !isxdigit((unsigned char)*bufp))
+                bufp++;
+            start = bufp;
+
+            if (!*bufp)
+                break;
+
+            while (*bufp && isxdigit((unsigned char)*bufp))
+                bufp++;
+            end = bufp;
+
+            if (ptrnum >= lenof(ptrs))
+                break;
+            ptrs[ptrnum++] = q;
+            
+            for (i = -((end - start) & 1); i < end-start; i += 2) {
+                unsigned char val = (i < 0 ? 0 : fromxdigit(start[i]));
+                val = val * 16 + fromxdigit(start[i+1]);
+                *q++ = val;
+            }
+
+            ptrs[ptrnum] = q;
+        }
+
+        if (!strcmp(buf, "mul")) {
+            Bignum a, b, c, p;
+
+            if (ptrnum != 3) {
+                printf("%d: mul with %d parameters, expected 3\n", line);
+                exit(1);
+            }
+            a = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]);
+            b = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]);
+            c = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]);
+            p = bigmul(a, b);
+
+            if (bignum_cmp(c, p) == 0) {
+                passes++;
+            } else {
+                char *as = bignum_decimal(a);
+                char *bs = bignum_decimal(b);
+                char *cs = bignum_decimal(c);
+                char *ps = bignum_decimal(p);
+                
+                printf("%d: fail: %s * %s gave %s expected %s\n",
+                       line, as, bs, ps, cs);
+                fails++;
+
+                sfree(as);
+                sfree(bs);
+                sfree(cs);
+                sfree(ps);
+            }
+            freebn(a);
+            freebn(b);
+            freebn(c);
+            freebn(p);
+        } else if (!strcmp(buf, "pow")) {
+            Bignum base, expt, modulus, expected, answer;
+
+            if (ptrnum != 4) {
+                printf("%d: mul with %d parameters, expected 3\n", line);
+                exit(1);
+            }
+
+            base = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]);
+            expt = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]);
+            modulus = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]);
+            expected = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]);
+            answer = modpow(base, expt, modulus);
+
+            if (bignum_cmp(expected, answer) == 0) {
+                passes++;
+            } else {
+                char *as = bignum_decimal(base);
+                char *bs = bignum_decimal(expt);
+                char *cs = bignum_decimal(modulus);
+                char *ds = bignum_decimal(answer);
+                char *ps = bignum_decimal(expected);
+                
+                printf("%d: fail: %s ^ %s mod %s gave %s expected %s\n",
+                       line, as, bs, cs, ds, ps);
+                fails++;
+
+                sfree(as);
+                sfree(bs);
+                sfree(cs);
+                sfree(ds);
+                sfree(ps);
+            }
+            freebn(base);
+            freebn(expt);
+            freebn(modulus);
+            freebn(expected);
+            freebn(answer);
+        } else {
+            printf("%d: unrecognised test keyword: '%s'\n", line, buf);
+            exit(1);
+        }
+
+        sfree(buf);
+        sfree(data);
+    }
+
+    printf("passed %d failed %d total %d\n", passes, fails, passes+fails);
+    return fails != 0;
+}
+
+#endif

+ 81 - 5
putty/SSHRSA.C

@@ -114,9 +114,83 @@ static void sha512_mpint(SHA512_State * s, Bignum b)
 }
 
 /*
- * This function is a wrapper on modpow(). It has the same effect
- * as modpow(), but employs RSA blinding to protect against timing
- * attacks.
+ * Compute (base ^ exp) % mod, provided mod == p * q, with p,q
+ * distinct primes, and iqmp is the multiplicative inverse of q mod p.
+ * Uses Chinese Remainder Theorem to speed computation up over the
+ * obvious implementation of a single big modpow.
+ */
+Bignum crt_modpow(Bignum base, Bignum exp, Bignum mod,
+                  Bignum p, Bignum q, Bignum iqmp)
+{
+    Bignum pm1, qm1, pexp, qexp, presult, qresult, diff, multiplier, ret0, ret;
+
+    /*
+     * Reduce the exponent mod phi(p) and phi(q), to save time when
+     * exponentiating mod p and mod q respectively. Of course, since p
+     * and q are prime, phi(p) == p-1 and similarly for q.
+     */
+    pm1 = copybn(p);
+    decbn(pm1);
+    qm1 = copybn(q);
+    decbn(qm1);
+    pexp = bigmod(exp, pm1);
+    qexp = bigmod(exp, qm1);
+
+    /*
+     * Do the two modpows.
+     */
+    presult = modpow(base, pexp, p);
+    qresult = modpow(base, qexp, q);
+
+    /*
+     * Recombine the results. We want a value which is congruent to
+     * qresult mod q, and to presult mod p.
+     *
+     * We know that iqmp * q is congruent to 1 * mod p (by definition
+     * of iqmp) and to 0 mod q (obviously). So we start with qresult
+     * (which is congruent to qresult mod both primes), and add on
+     * (presult-qresult) * (iqmp * q) which adjusts it to be congruent
+     * to presult mod p without affecting its value mod q.
+     */
+    if (bignum_cmp(presult, qresult) < 0) {
+        /*
+         * Can't subtract presult from qresult without first adding on
+         * p.
+         */
+        Bignum tmp = presult;
+        presult = bigadd(presult, p);
+        freebn(tmp);
+    }
+    diff = bigsub(presult, qresult);
+    multiplier = bigmul(iqmp, q);
+    ret0 = bigmuladd(multiplier, diff, qresult);
+
+    /*
+     * Finally, reduce the result mod n.
+     */
+    ret = bigmod(ret0, mod);
+
+    /*
+     * Free all the intermediate results before returning.
+     */
+    freebn(pm1);
+    freebn(qm1);
+    freebn(pexp);
+    freebn(qexp);
+    freebn(presult);
+    freebn(qresult);
+    freebn(diff);
+    freebn(multiplier);
+    freebn(ret0);
+
+    return ret;
+}
+
+/*
+ * This function is a wrapper on modpow(). It has the same effect as
+ * modpow(), but employs RSA blinding to protect against timing
+ * attacks and also uses the Chinese Remainder Theorem (implemented
+ * above, in crt_modpow()) to speed up the main operation.
  */
 static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key)
 {
@@ -218,10 +292,12 @@ static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key)
      * _y^d_, and use the _public_ exponent to compute (y^d)^e = y
      * from it, which is much faster to do.
      */
-    random_encrypted = modpow(random, key->exponent, key->modulus);
+    random_encrypted = crt_modpow(random, key->exponent,
+                                  key->modulus, key->p, key->q, key->iqmp);
     random_inverse = modinv(random, key->modulus);
     input_blinded = modmul(input, random_encrypted, key->modulus);
-    ret_blinded = modpow(input_blinded, key->private_exponent, key->modulus);
+    ret_blinded = crt_modpow(input_blinded, key->private_exponent,
+                             key->modulus, key->p, key->q, key->iqmp);
     ret = modmul(ret_blinded, random_inverse, key->modulus);
 
     freebn(ret_blinded);

+ 17 - 0
putty/putty.h

@@ -470,6 +470,7 @@ struct config_tag {
     int sshprot;		       /* use v1 or v2 when both available */
     int ssh2_des_cbc;		       /* "des-cbc" unrecommended SSH-2 cipher */
     int ssh_no_userauth;	       /* bypass "ssh-userauth" (SSH-2 only) */
+    int ssh_show_banner;	       /* show USERAUTH_BANNERs (SSH-2 only) */
     int try_tis_auth;
     int try_ki_auth;
     int try_gssapi_auth;               /* attempt gssapi auth */
@@ -625,6 +626,7 @@ struct config_tag {
     FontSpec wideboldfont;
     int shadowboldoffset;
     int crhaslf;
+    char winclass[256];
 };
 
 /*
@@ -666,6 +668,10 @@ GLOBAL int default_port;
  * This is set TRUE by cmdline.c iff a session is loaded with "-load".
  */
 GLOBAL int loaded_session;
+/*
+ * This is set to the name of the loaded session.
+ */
+GLOBAL char *cmdline_session_name;
 
 struct RSAKey;			       /* be a little careful of scope */
 
@@ -1249,4 +1255,15 @@ void expire_timer_context(void *ctx);
 int run_timers(long now, long *next);
 void timer_change_notify(long next);
 
+/*
+ * Define no-op macros for the jump list functions, on platforms that
+ * don't support them. (This is a bit of a hack, and it'd be nicer to
+ * localise even the calls to those functions into the Windows front
+ * end, but it'll do for the moment.)
+ */
+#ifndef JUMPLIST_SUPPORTED
+#define add_session_to_jumplist(x) ((void)0)
+#define remove_session_from_jumplist(x) ((void)0)
+#endif
+
 #endif

+ 2 - 0
putty/windows/WINNET.C

@@ -882,10 +882,12 @@ static DWORD try_connect(Actual_Socket sock)
 	p_setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *) &b, sizeof(b));
     }
 
+#ifdef MPEXT
     {
 	int bufsize = 262144;
 	p_setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void *) &bufsize, sizeof(bufsize));
     }
+#endif
 
     /*
      * Bind to local address.

+ 8 - 0
putty/windows/WINNOJMP.C

@@ -0,0 +1,8 @@
+/*
+ * winnojmp.c: stub jump list functions for Windows executables that
+ * don't update the jump list.
+ */
+
+void add_session_to_jumplist(const char * const sessionname) {}
+void remove_session_from_jumplist(const char * const sessionname) {}
+void clear_jumplist(void) {}

+ 90 - 1
putty/windows/WINPGNTC.C

@@ -7,6 +7,10 @@
 
 #include "putty.h"
 
+#ifndef NO_SECURITY
+#include <aclapi.h>
+#endif
+
 #define AGENT_COPYDATA_ID 0x804e50ba   /* random goop */
 #define AGENT_MAX_MSGLEN  8192
 
@@ -66,6 +70,33 @@ DWORD WINAPI agent_query_thread(LPVOID param)
 
 #endif
 
+/*
+ * Dynamically load advapi32.dll for SID manipulation. In its absence,
+ * we degrade gracefully.
+ */
+#ifndef NO_SECURITY
+int advapi_initialised = FALSE;
+static HMODULE advapi;
+DECL_WINDOWS_FUNCTION(static, BOOL, OpenProcessToken,
+		      (HANDLE, DWORD, PHANDLE));
+DECL_WINDOWS_FUNCTION(static, BOOL, GetTokenInformation,
+		      (HANDLE, TOKEN_INFORMATION_CLASS,
+                       LPVOID, DWORD, PDWORD));
+DECL_WINDOWS_FUNCTION(static, BOOL, InitializeSecurityDescriptor,
+		      (PSECURITY_DESCRIPTOR, DWORD));
+DECL_WINDOWS_FUNCTION(static, BOOL, SetSecurityDescriptorOwner,
+		      (PSECURITY_DESCRIPTOR, PSID, BOOL));
+static int init_advapi(void)
+{
+    advapi = load_system32_dll("advapi32.dll");
+    return advapi &&
+        GET_WINDOWS_FUNCTION(advapi, OpenProcessToken) &&
+	GET_WINDOWS_FUNCTION(advapi, GetTokenInformation) &&
+	GET_WINDOWS_FUNCTION(advapi, InitializeSecurityDescriptor) &&
+	GET_WINDOWS_FUNCTION(advapi, SetSecurityDescriptorOwner);
+}
+#endif
+
 int agent_query(void *in, int inlen, void **out, int *outlen,
 		void (*callback)(void *, void *, int), void *callback_ctx)
 {
@@ -75,6 +106,10 @@ int agent_query(void *in, int inlen, void **out, int *outlen,
     unsigned char *p, *ret;
     int id, retlen;
     COPYDATASTRUCT cds;
+    SECURITY_ATTRIBUTES sa, *psa;
+    PSECURITY_DESCRIPTOR psd = NULL;
+    HANDLE proc, tok;
+    TOKEN_USER *user = NULL;
 
     *out = NULL;
     *outlen = 0;
@@ -83,7 +118,57 @@ int agent_query(void *in, int inlen, void **out, int *outlen,
     if (!hwnd)
 	return 1;		       /* *out == NULL, so failure */
     mapname = dupprintf("PageantRequest%08x", (unsigned)GetCurrentThreadId());
-    filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
+
+#ifndef NO_SECURITY
+    if (advapi_initialised || init_advapi()) {
+        /*
+         * Make the file mapping we create for communication with
+         * Pageant owned by the user SID rather than the default. This
+         * should make communication between processes with slightly
+         * different contexts more reliable: in particular, command
+         * prompts launched as administrator should still be able to
+         * run PSFTPs which refer back to the owning user's
+         * unprivileged Pageant.
+         */
+
+        if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE,
+                                GetCurrentProcessId())) != NULL) {
+            if (p_OpenProcessToken(proc, TOKEN_QUERY, &tok)) {
+                DWORD retlen;
+                p_GetTokenInformation(tok, TokenUser, NULL, 0, &retlen);
+                user = (TOKEN_USER *)LocalAlloc(LPTR, retlen);
+                if (!p_GetTokenInformation(tok, TokenUser,
+                                           user, retlen, &retlen)) {
+                    LocalFree(user);
+                    user = NULL;
+                }
+                CloseHandle(tok);
+            }
+            CloseHandle(proc);
+        }
+
+        psa = NULL;
+        if (user) {
+            psd = (PSECURITY_DESCRIPTOR)
+                LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
+            if (psd) {
+                if (p_InitializeSecurityDescriptor
+                    (psd, SECURITY_DESCRIPTOR_REVISION) &&
+                    p_SetSecurityDescriptorOwner(psd, user->User.Sid, FALSE)) {
+                    sa.nLength = sizeof(sa);
+                    sa.bInheritHandle = TRUE;
+                    sa.lpSecurityDescriptor = psd;
+                    psa = &sa;
+                } else {
+                    LocalFree(psd);
+                    psd = NULL;
+                }
+            }
+        }
+    }
+#endif /* NO_SECURITY */
+
+    filemap = CreateFileMapping(INVALID_HANDLE_VALUE, psa, PAGE_READWRITE,
 				0, AGENT_MAX_MSGLEN, mapname);
     if (filemap == NULL || filemap == INVALID_HANDLE_VALUE)
 	return 1;		       /* *out == NULL, so failure */
@@ -134,6 +219,10 @@ int agent_query(void *in, int inlen, void **out, int *outlen,
     }
     UnmapViewOfFile(p);
     CloseHandle(filemap);
+    if (psd)
+        LocalFree(psd);
+    if (user)
+        LocalFree(user);
 #ifdef MPEXT
     // fix memory leak
     sfree(mapname);

+ 173 - 0
putty/windows/WINSTORE.C

@@ -17,6 +17,8 @@
 #define CSIDL_LOCAL_APPDATA 0x001c
 #endif
 
+static const char *const reg_jumplist_key = PUTTY_REG_POS "\\Jumplist";
+static const char *const reg_jumplist_value = "Recent sessions";
 static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
 
 static const char hex[16] = "0123456789ABCDEF";
@@ -243,6 +245,8 @@ void del_settings(const char *sessionname)
     sfree(p);
 
     RegCloseKey(subkey1);
+
+    remove_session_from_jumplist(sessionname);
 }
 
 struct enumsettings {
@@ -603,6 +607,169 @@ void write_random_seed(void *data, int len)
     }
 }
 
+/*
+ * Internal function supporting the jump list registry code. All the
+ * functions to add, remove and read the list have substantially
+ * similar content, so this is a generalisation of all of them which
+ * transforms the list in the registry by prepending 'add' (if
+ * non-null), removing 'rem' from what's left (if non-null), and
+ * returning the resulting concatenated list of strings in 'out' (if
+ * non-null).
+ */
+static int transform_jumplist_registry
+    (const char *add, const char *rem, char **out)
+{
+    int ret;
+    HKEY pjumplist_key, psettings_tmp;
+    DWORD type;
+    int value_length;
+    char *old_value, *new_value;
+    char *piterator_old, *piterator_new, *piterator_tmp;
+
+    ret = RegCreateKeyEx(HKEY_CURRENT_USER, reg_jumplist_key, 0, NULL,
+                         REG_OPTION_NON_VOLATILE, (KEY_READ | KEY_WRITE), NULL,
+                         &pjumplist_key, NULL);
+    if (ret != ERROR_SUCCESS) {
+	return JUMPLISTREG_ERROR_KEYOPENCREATE_FAILURE;
+    }
+
+    /* Get current list of saved sessions in the registry. */
+    value_length = 200;
+    old_value = snewn(value_length, char);
+    ret = RegQueryValueEx(pjumplist_key, reg_jumplist_value, NULL, &type,
+                          old_value, &value_length);
+    /* When the passed buffer is too small, ERROR_MORE_DATA is
+     * returned and the required size is returned in the length
+     * argument. */
+    if (ret == ERROR_MORE_DATA) {
+        sfree(old_value);
+        old_value = snewn(value_length, char);
+        ret = RegQueryValueEx(pjumplist_key, reg_jumplist_value, NULL, &type,
+                              old_value, &value_length);
+    }
+
+    if (ret == ERROR_FILE_NOT_FOUND) {
+        /* Value doesn't exist yet. Start from an empty value. */
+        *old_value = '\0';
+        *(old_value + 1) = '\0';
+    } else if (ret != ERROR_SUCCESS) {
+        /* Some non-recoverable error occurred. */
+        sfree(old_value);
+        RegCloseKey(pjumplist_key);
+        return JUMPLISTREG_ERROR_VALUEREAD_FAILURE;
+    } else if (type != REG_MULTI_SZ) {
+        /* The value present in the registry has the wrong type: we
+         * try to delete it and start from an empty value. */
+        ret = RegDeleteValue(pjumplist_key, reg_jumplist_value);
+        if (ret != ERROR_SUCCESS) {
+            sfree(old_value);
+            RegCloseKey(pjumplist_key);
+            return JUMPLISTREG_ERROR_VALUEREAD_FAILURE;
+        }
+
+        *old_value = '\0';
+        *(old_value + 1) = '\0';
+    }
+
+    /* Check validity of registry data: REG_MULTI_SZ value must end
+     * with \0\0. */
+    piterator_tmp = old_value;
+    while (((piterator_tmp - old_value) < (value_length - 1)) &&
+           !(*piterator_tmp == '\0' && *(piterator_tmp+1) == '\0')) {
+        ++piterator_tmp;
+    }
+
+    if ((piterator_tmp - old_value) >= (value_length-1)) {
+        /* Invalid value. Start from an empty value. */
+        *old_value = '\0';
+        *(old_value + 1) = '\0';
+    }
+
+    /*
+     * Modify the list, if we're modifying.
+     */
+    if (add || rem) {
+        /* Walk through the existing list and construct the new list of
+         * saved sessions. */
+        new_value = snewn(value_length + (add ? strlen(add) + 1 : 0), char);
+        piterator_new = new_value;
+        piterator_old = old_value;
+
+        /* First add the new item to the beginning of the list. */
+        if (add) {
+            strcpy(piterator_new, add);
+            piterator_new += strlen(piterator_new) + 1;
+        }
+        /* Now add the existing list, taking care to leave out the removed
+         * item, if it was already in the existing list. */
+        while (*piterator_old != '\0') {
+            if (!rem || strcmp(piterator_old, rem) != 0) {
+                /* Check if this is a valid session, otherwise don't add. */
+                psettings_tmp = open_settings_r(piterator_old);
+                if (psettings_tmp != NULL) {
+                    close_settings_r(psettings_tmp);
+                    strcpy(piterator_new, piterator_old);
+                    piterator_new += strlen(piterator_new) + 1;
+                }
+            }
+            piterator_old += strlen(piterator_old) + 1;
+        }
+        *piterator_new = '\0';
+        ++piterator_new;
+
+        /* Save the new list to the registry. */
+        ret = RegSetValueEx(pjumplist_key, reg_jumplist_value, 0, REG_MULTI_SZ,
+                            new_value, piterator_new - new_value);
+
+        sfree(old_value);
+        old_value = new_value;
+    } else
+        ret = ERROR_SUCCESS;
+
+    /*
+     * Either return or free the result.
+     */
+    if (out)
+        *out = old_value;
+    else
+        sfree(old_value);
+
+    /* Clean up and return. */
+    RegCloseKey(pjumplist_key);
+
+    if (ret != ERROR_SUCCESS) {
+        return JUMPLISTREG_ERROR_VALUEWRITE_FAILURE;
+    } else {
+        return JUMPLISTREG_OK;
+    }
+}
+
+/* Adds a new entry to the jumplist entries in the registry. */
+int add_to_jumplist_registry(const char *item)
+{
+    return transform_jumplist_registry(item, item, NULL);
+}
+
+/* Removes an item from the jumplist entries in the registry. */
+int remove_from_jumplist_registry(const char *item)
+{
+    return transform_jumplist_registry(NULL, item, NULL);
+}
+
+/* Returns the jumplist entries from the registry. Caller must free
+ * the returned pointer. */
+char *get_jumplist_registry_entries (void)
+{
+    char *list_value;
+
+    if (transform_jumplist_registry(NULL,NULL,&list_value) != ERROR_SUCCESS) {
+	list_value = snewn(2, char);
+        *list_value = '\0';
+        *(list_value + 1) = '\0';
+    }
+    return list_value;
+}
+
 /*
  * Recursively delete a registry key and everything under it.
  */
@@ -634,6 +801,12 @@ void cleanup_all(void)
      */
     access_random_seed(DEL);
 
+    /* ------------------------------------------------------------
+     * Ask Windows to delete any jump list information associated
+     * with this installation of PuTTY.
+     */
+    clear_jumplist();
+
     /* ------------------------------------------------------------
      * Destroy all registry information associated with PuTTY.
      */

+ 46 - 2
putty/windows/WINSTUFF.H

@@ -98,9 +98,9 @@ struct FontSpec {
 #define STR1(x) #x
 #define STR(x) STR1(x)
 #define GET_WINDOWS_FUNCTION_PP(module, name) \
-    p_##name = module ? (t_##name) GetProcAddress(module, STR(name)) : NULL
+    (p_##name = module ? (t_##name) GetProcAddress(module, STR(name)) : NULL)
 #define GET_WINDOWS_FUNCTION(module, name) \
-    p_##name = module ? (t_##name) GetProcAddress(module, #name) : NULL
+    (p_##name = module ? (t_##name) GetProcAddress(module, #name) : NULL)
 
 /*
  * Global variables. Most modules declare these `extern', but
@@ -128,6 +128,14 @@ typedef struct terminal_tag Terminal;
 #define PUTTY_REG_GPARENT "Software"
 #define PUTTY_REG_GPARENT_CHILD "SimonTatham"
 
+/* Result values for the jumplist registry functions. */
+#define JUMPLISTREG_OK 0
+#define JUMPLISTREG_ERROR_INVALID_PARAMETER 1
+#define JUMPLISTREG_ERROR_KEYOPENCREATE_FAILURE 2
+#define JUMPLISTREG_ERROR_VALUEREAD_FAILURE 3
+#define JUMPLISTREG_ERROR_VALUEWRITE_FAILURE 4
+#define JUMPLISTREG_ERROR_INVALID_VALUE 5
+
 #define PUTTY_HELP_FILE "putty.hlp"
 #define PUTTY_CHM_FILE "putty.chm"
 #define PUTTY_HELP_CONTENTS "putty.cnt"
@@ -310,6 +318,7 @@ struct dlgparam {
     struct { unsigned char r, g, b, ok; } coloursel_result;   /* 0-255 */
     tree234 *privdata;		       /* stores per-control private data */
     int ended, endresult;	       /* has the dialog been ended? */
+    int fixed_pitch_fonts;             /* are we constrained to fixed fonts? */
 };
 
 /*
@@ -368,6 +377,10 @@ void fwdsetter(struct ctlpos *cp, int listid, char *stext, int sid,
 	       char *btext, int bid,
 	       char *r1text, int r1id, char *r2text, int r2id);
 
+void dlg_auto_set_fixed_pitch_flag(void *dlg);
+int dlg_get_fixed_pitch_flag(void *dlg);
+void dlg_set_fixed_pitch_flag(void *dlg, int flag);
+
 #define MAX_SHORTCUTS_PER_CTRL 16
 
 /*
@@ -506,4 +519,35 @@ void agent_schedule_callback(void (*callback)(void *, void *, int),
  */
 extern Backend serial_backend;
 
+/*
+ * Exports from winjump.c.
+ */
+#define JUMPLIST_SUPPORTED             /* suppress #defines in putty.h */
+void add_session_to_jumplist(const char * const sessionname);
+void remove_session_from_jumplist(const char * const sessionname);
+void clear_jumplist(void);
+
+/*
+ * Extra functions in winstore.c over and above the interface in
+ * storage.h.
+ *
+ * These functions manipulate the Registry section which mirrors the
+ * current Windows 7 jump list. (Because the real jump list storage is
+ * write-only, we need to keep another copy of whatever we put in it,
+ * so that we can put in a slightly modified version the next time.)
+ */
+
+/* Adds a saved session to the registry jump list mirror. 'item' is a
+ * string naming a saved session. */
+int add_to_jumplist_registry(const char *item);
+
+/* Removes an item from the registry jump list mirror. */
+int remove_from_jumplist_registry(const char *item);
+
+/* Returns the current jump list entries from the registry. Caller
+ * must free the returned pointer, which points to a contiguous
+ * sequence of NUL-terminated strings in memory, terminated with an
+ * empty one. */
+char *get_jumplist_registry_entries(void);
+
 #endif

+ 0 - 27
release/install.u3.bat

@@ -1,27 +0,0 @@
-@echo off
-set WINSCP_INI=%U3_APP_DATA_PATH%\winscp.ini
-set WINSCP3_INI=%U3_APP_DATA_PATH%\winscp3.ini
-
-set VER_403=%U3_APP_DATA_PATH%\ver.403
-set VER_406=%U3_APP_DATA_PATH%\ver.406
-
-if not "%U3_IS_UPGRADE%" == "true" goto NO_UPGRADE
-
-rem 403
-if not exist "%WINSCP3_INI%" goto NO_WINSCP3_INI
-
-copy "%WINSCP_INI%" + "%WINSCP3_INI%" "%WINSCP_INI%"
-del "%WINSCP3_INI%"
-
-:NO_WINSCP3_INI
-
-rem 406
-if exist "%VER_406%" goto SKIP_406_UPGRADE
-echo [Override\Configuration\Interface] >> "%WINSCP_INI%"
-echo PuttyRegistryStorageKey=Software%%5CPuTTY%%20for%%20U3-%U3_DEVICE_VENDOR_ID%-%U3_DEVICE_SERIAL% >> "%WINSCP_INI%"
-echo PuttyPath=%%25U3_HOST_EXEC_PATH%%25%%5C..%%5C..%%5CD7A496BD-33D0-448C-A2A8-6F9FF3130636%%5CExec%%5Cputty.exe >> "%WINSCP_INI%"
-:SKIP_406_UPGRADE
-
-:NO_UPGRADE
-
-echo. > "%VER_406%"

+ 0 - 4
release/u3.ini

@@ -1,4 +0,0 @@
-[Configuration\Interface]
-RandomSeedFile=%25U3_APP_DATA_PATH%25\winscp.rnd
-DDTemporaryDirectory=%25U3_HOST_EXEC_PATH%25\
-ConfirmClosingSession=0

+ 0 - 21
release/winscp.u3i

@@ -1,21 +0,0 @@
-<?xml version="1.0"?>
-<u3manifest version="1.0">
-  <application uuid="48b341d1-d411-4b5a-a82c-f3b5d65602fc" version="4.3.1">
-    <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>
-    <shortDescription>Freeware SFTP, FTP and SCP client for Windows</shortDescription>
-    <vendor url="http://winscp.net/">Martin Prikryl</vendor>
-    <options>
-      <minFreeSpace>6</minFreeSpace>
-      <upgrade appData="add" deviceExec="remove" />
-    </options>
-    <i18n />
-  </application>
-  <actions>
-    <hostCleanUp cmd="%U3_HOST_EXEC_PATH%\U3Action.exe">-hostCleanUp</hostCleanUp>
-    <appStop cmd="%U3_HOST_EXEC_PATH%\U3Action.exe">-appStop</appStop>
-    <appStart cmd="%U3_HOST_EXEC_PATH%\U3Action.exe">-appStart \"%U3_HOST_EXEC_PATH%\WinSCP.exe\" /ini=\"%U3_APP_DATA_PATH%\WinSCP.ini\"</appStart>
-    <deviceInstall cmd="%U3_HOST_EXEC_PATH%\U3Action.exe">-appStart -shell \"%U3_HOST_EXEC_PATH%\install.bat\"</deviceInstall>
-  </actions>
-</u3manifest>

+ 3 - 3
resource/TextsCore1.rc

@@ -337,14 +337,14 @@ BEGIN
   CORE_VARIABLE_STRINGS, "CORE_VARIABLE"
   PUTTY_BASED_ON, "SSH and SCP code based on PuTTY %s"
   PUTTY_VERSION, "0.60"
-  PUTTY_COPYRIGHT, "Copyright © 1997-2010 Simon Tatham"
+  PUTTY_COPYRIGHT, "Copyright © 1997-2011 Simon Tatham"
   PUTTY_URL, "http://www.chiark.greenend.org.uk/~sgtatham/putty/"
   FILEZILLA_BASED_ON, "FTP code based on FileZilla %s"
   FILEZILLA_VERSION, "2.2.32"
   FILEZILLA_COPYRIGHT, "Copyright © 2001-2007 Tim Kosse"
   FILEZILLA_URL, "http://filezilla.sourceforge.net/"
   OPENSSL_BASED_ON, "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s."
-  OPENSSL_COPYRIGHT, "Copyright © 1998-2010 The OpenSSL Project"
-  OPENSSL_VERSION, "1.0.0c"
+  OPENSSL_COPYRIGHT, "Copyright © 1998-2011 The OpenSSL Project"
+  OPENSSL_VERSION, "1.0.0d"
   OPENSSL_URL, "http://www.openssl.org/"
 END

+ 1 - 1
resource/TextsWin1.rc

@@ -387,7 +387,7 @@ BEGIN
         FIND_FILE_STOP, "&Stop"
 
         WIN_VARIABLE_STRINGS, "WIN_VARIABLE"
-        WINSCP_COPYRIGHT, "Copyright © 2000-2010 Martin Prikryl"
+        WINSCP_COPYRIGHT, "Copyright © 2000-2011 Martin Prikryl"
         HOMEPAGE_URL, "http://winscp.net/"
         HISTORY_URL, "http://winscp.net/eng/docs/history"
         REQUIREMENTS_URL, "http://winscp.net/eng/docs/requirements"

+ 3 - 3
windows/Setup.cpp

@@ -588,9 +588,9 @@ void __fastcall TemporaryDirectoryCleanup()
 //---------------------------------------------------------------------------
 AnsiString __fastcall VersionStrFromCompoundVersion(int Version)
 {
-  int MajorVer = Version / (1000*100*100);
-  int MinorVer = (Version % (1000*100*100)) / (1000*100);
-  int Release = (Version % (1000*100)) / (1000);
+  int MajorVer = Version / (10000*100*100);
+  int MinorVer = (Version % (10000*100*100)) / (10000*100);
+  int Release = (Version % (10000*100)) / (10000);
   AnsiString Result;
   if (Release > 0)
   {

+ 5 - 4
windows/WinConfiguration.cpp

@@ -1059,10 +1059,11 @@ bool __fastcall TWinConfiguration::GetDDExtInstalled()
     else
     {
       void * DragExtRef;
-      bool Result;
-      Result = (CoCreateInstance(CLSID_ShellExtension, NULL,
-        CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_IUnknown,
-        &DragExtRef) == S_OK);
+      int CreateResult =
+        CoCreateInstance(CLSID_ShellExtension, NULL,
+          CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_IUnknown,
+          &DragExtRef);
+      bool Result = (CreateResult == S_OK);
       FDDExtInstalled = (Result ? 1 : 0);
       if (Result)
       {