Martin Prikryl 11 lat temu
rodzic
commit
0b94790954
61 zmienionych plików z 708 dodań i 227 usunięć
  1. 5 3
      deployment/WinSCPnet.nuspec
  2. 3 2
      deployment/winscpsetup.iss
  3. 1 1
      dotnet/properties/AssemblyInfo.cs
  4. 1 1
      libs/openssl/crypto/asn1/asn1_err.c
  5. 1 1
      libs/openssl/crypto/bio/bss_log.c
  6. 11 0
      libs/openssl/crypto/bn/bn.h
  7. 52 0
      libs/openssl/crypto/bn/bn_lib.c
  8. 3 3
      libs/openssl/crypto/buildinf.h
  9. 1 1
      libs/openssl/crypto/cryptlib.c
  10. 1 1
      libs/openssl/crypto/evp/bio_b64.c
  11. 88 0
      libs/openssl/crypto/modes/gcm128.c
  12. 3 3
      libs/openssl/crypto/opensslv.h
  13. 3 0
      libs/openssl/crypto/rand/md_rand.c
  14. 1 1
      libs/openssl/crypto/rand/rand_win.c
  15. 6 0
      libs/openssl/crypto/symhacks.h
  16. 2 4
      libs/openssl/crypto/x509/by_dir.c
  17. 2 3
      libs/openssl/crypto/x509/x509_vfy.c
  18. 7 0
      libs/openssl/e_os.h
  19. 18 8
      libs/openssl/ssl/d1_both.c
  20. 9 0
      libs/openssl/ssl/kssl.h
  21. 1 1
      libs/openssl/ssl/s23_clnt.c
  22. 2 2
      libs/openssl/ssl/s3_srvr.c
  23. 1 1
      libs/openssl/ssl/ssl.h
  24. 2 1
      libs/openssl/ssl/t1_enc.c
  25. 40 6
      libs/openssl/ssl/t1_lib.c
  26. 6 0
      libs/openssl/ssl/tls1.h
  27. 1 1
      source/Console.cbproj
  28. 1 1
      source/DragExt.cbproj
  29. 2 2
      source/DragExt64.rc
  30. 2 2
      source/WinSCP.cbproj
  31. 30 0
      source/core/Common.cpp
  32. 2 0
      source/core/Common.h
  33. 111 15
      source/core/FtpFileSystem.cpp
  34. 1 0
      source/core/FtpFileSystem.h
  35. 1 1
      source/core/Script.cpp
  36. 25 11
      source/filezilla/AsyncSslSocketLayer.cpp
  37. 2 0
      source/filezilla/AsyncSslSocketLayer.h
  38. 1 0
      source/filezilla/FileZillaIntf.cpp
  39. 2 0
      source/filezilla/FileZillaIntf.h
  40. 5 1
      source/forms/CustomScpExplorer.cpp
  41. 29 11
      source/forms/Login.cpp
  42. 2 0
      source/forms/Login.h
  43. 60 46
      source/forms/Preferences.cpp
  44. 2 0
      source/forms/Preferences.dfm
  45. 53 43
      source/forms/Progress.cpp
  46. 1 1
      source/forms/ScpCommander.cpp
  47. 2 1
      source/packages/my/PathLabel.pas
  48. 3 1
      source/putty/SSH.C
  49. 1 1
      source/resource/TextsCore.h
  50. 3 3
      source/resource/TextsCore1.rc
  51. 1 1
      source/resource/TextsWin1.rc
  52. 34 1
      source/windows/GUITools.cpp
  53. 1 0
      source/windows/GUITools.h
  54. 36 27
      source/windows/Setup.cpp
  55. 9 3
      source/windows/TerminalManager.cpp
  56. 1 0
      source/windows/TerminalManager.h
  57. 6 1
      source/windows/Tools.cpp
  58. 1 0
      source/windows/Tools.h
  59. 4 0
      source/windows/UserInterface.cpp
  60. 1 3
      source/windows/WinConfiguration.cpp
  61. 2 7
      source/windows/WinMain.cpp

+ 5 - 3
deployment/WinSCPnet.nuspec

@@ -1,12 +1,12 @@
 <?xml version="1.0"?>
 <package >
   <metadata>
-    <id>WinSCPnet</id>
+    <id>WinSCP</id>
     <version>$version$</version>
     <title>WinSCP .NET assembly</title>
     <authors>Martin Prikryl</authors>
     <owners>Martin Prikryl</owners>
-    <licenseUrl>http://winscp.net/eng/docs/library#license</licenseUrl>
+    <licenseUrl>http://www.mozilla.org/MPL/2.0/</licenseUrl>
     <projectUrl>http://winscp.net/eng/docs/library</projectUrl>
     <iconUrl>http://winscp.net/pad/winscp.png</iconUrl>
     <requireLicenseAcceptance>false</requireLicenseAcceptance>
@@ -15,7 +15,9 @@
     
 The library is primarily intended for advanced automation tasks that require conditional processing, loops or other control structures for which the basic scripting interface is too limited. The library is not a general purpose file transfer library. It particularly lacks support for interactive processing and as such it is not well suited for use in GUI applications.
 
-For documentation and examples of use, see project website.</description>
+For documentation and examples of use, see project website.
+
+The NuGet package includes the assembly itself and a required WinSCP executable. When installed, it adds the assembly as reference to your project and sets up WinSCP executable to be copied to project output directory, so that it can be found on run-time.</description>
     <copyright>Copyright © 2012-2014 Martin Prikryl</copyright>
     <tags>winscp sftp ftp ftps scp transfer</tags>
   </metadata>

+ 3 - 2
deployment/winscpsetup.iss

@@ -1416,9 +1416,10 @@ begin
     Log('Preparing intallation report');
 
     ReportData := Format(
-      'installed=%d&silent=%d&ver=%s&lang=%s&', [
+      'installed=%d&silent=%d&ver=%s&lang=%s&prevver=%s&', [
        Integer(InstallationDone), Integer(WizardSilent),
-       ExpandConstant('{#VersionOnly}'), ActiveLanguage]);
+       ExpandConstant('{#VersionOnly}'), ActiveLanguage,
+       PrevVersion]);
 
 #ifdef Chrome
     ReportData := ReportData +

+ 1 - 1
dotnet/properties/AssemblyInfo.cs

@@ -21,7 +21,7 @@ using System.Runtime.InteropServices;
 
 [assembly: AssemblyVersion("1.1.5.0")]
 [assembly: AssemblyFileVersion("1.1.5.0")]
-[assembly: AssemblyInformationalVersionAttribute("5.5.2.0")]
+[assembly: AssemblyInformationalVersionAttribute("5.5.3.0")]
 
 [assembly: CLSCompliant(true)]
 

+ 1 - 1
libs/openssl/crypto/asn1/asn1_err.c

@@ -305,7 +305,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
 {ERR_REASON(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE),"unknown public key type"},
 {ERR_REASON(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM),"unknown signature algorithm"},
 {ERR_REASON(ASN1_R_UNKNOWN_TAG)          ,"unknown tag"},
-{ERR_REASON(ASN1_R_UNKOWN_FORMAT)        ,"unkown format"},
+{ERR_REASON(ASN1_R_UNKOWN_FORMAT)        ,"unknown format"},
 {ERR_REASON(ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE),"unsupported any defined by type"},
 {ERR_REASON(ASN1_R_UNSUPPORTED_CIPHER)   ,"unsupported cipher"},
 {ERR_REASON(ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM),"unsupported encryption algorithm"},

+ 1 - 1
libs/openssl/crypto/bio/bss_log.c

@@ -245,7 +245,7 @@ static int MS_CALLBACK slg_puts(BIO *bp, const char *str)
 
 static void xopenlog(BIO* bp, char* name, int level)
 {
-	if (GetVersion() < 0x80000000)
+	if (check_winnt())
 		bp->ptr = RegisterEventSourceA(NULL,name);
 	else
 		bp->ptr = NULL;

+ 11 - 0
libs/openssl/crypto/bn/bn.h

@@ -538,6 +538,8 @@ BIGNUM *BN_mod_inverse(BIGNUM *ret,
 BIGNUM *BN_mod_sqrt(BIGNUM *ret,
 	const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx);
 
+void	BN_consttime_swap(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords);
+
 /* Deprecated versions */
 #ifndef OPENSSL_NO_DEPRECATED
 BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe,
@@ -774,11 +776,20 @@ int RAND_pseudo_bytes(unsigned char *buf,int num);
 
 #define bn_fix_top(a)		bn_check_top(a)
 
+#define bn_check_size(bn, bits) bn_wcheck_size(bn, ((bits+BN_BITS2-1))/BN_BITS2)
+#define bn_wcheck_size(bn, words) \
+	do { \
+		const BIGNUM *_bnum2 = (bn); \
+		assert(words <= (_bnum2)->dmax && words >= (_bnum2)->top); \
+	} while(0)
+
 #else /* !BN_DEBUG */
 
 #define bn_pollute(a)
 #define bn_check_top(a)
 #define bn_fix_top(a)		bn_correct_top(a)
+#define bn_check_size(bn, bits)
+#define bn_wcheck_size(bn, words)
 
 #endif
 

+ 52 - 0
libs/openssl/crypto/bn/bn_lib.c

@@ -824,3 +824,55 @@ int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b,
 		}
 	return bn_cmp_words(a,b,cl);
 	}
+
+/* 
+ * Constant-time conditional swap of a and b.  
+ * a and b are swapped if condition is not 0.  The code assumes that at most one bit of condition is set.
+ * nwords is the number of words to swap.  The code assumes that at least nwords are allocated in both a and b,
+ * and that no more than nwords are used by either a or b.
+ * a and b cannot be the same number
+ */
+void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)
+	{
+	BN_ULONG t;
+	int i;
+
+	bn_wcheck_size(a, nwords);
+	bn_wcheck_size(b, nwords);
+
+	assert(a != b);
+	assert((condition & (condition - 1)) == 0);
+	assert(sizeof(BN_ULONG) >= sizeof(int));
+
+	condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1;
+
+	t = (a->top^b->top) & condition;
+	a->top ^= t;
+	b->top ^= t;
+
+#define BN_CONSTTIME_SWAP(ind) \
+	do { \
+		t = (a->d[ind] ^ b->d[ind]) & condition; \
+		a->d[ind] ^= t; \
+		b->d[ind] ^= t; \
+	} while (0)
+
+
+	switch (nwords) {
+	default:
+		for (i = 10; i < nwords; i++) 
+			BN_CONSTTIME_SWAP(i);
+		/* Fallthrough */
+	case 10: BN_CONSTTIME_SWAP(9); /* Fallthrough */
+	case 9: BN_CONSTTIME_SWAP(8); /* Fallthrough */
+	case 8: BN_CONSTTIME_SWAP(7); /* Fallthrough */
+	case 7: BN_CONSTTIME_SWAP(6); /* Fallthrough */
+	case 6: BN_CONSTTIME_SWAP(5); /* Fallthrough */
+	case 5: BN_CONSTTIME_SWAP(4); /* Fallthrough */
+	case 4: BN_CONSTTIME_SWAP(3); /* Fallthrough */
+	case 3: BN_CONSTTIME_SWAP(2); /* Fallthrough */
+	case 2: BN_CONSTTIME_SWAP(1); /* Fallthrough */
+	case 1: BN_CONSTTIME_SWAP(0);
+	}
+#undef BN_CONSTTIME_SWAP
+}

+ 3 - 3
libs/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 "Fri Jan 10 14:05:30 2014"
+  #define DATE "Wed Apr  9 09:25:41 2014"
 #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 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 -D_timeb=timeb -D_ftime=ftime -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 "Fri Jan 10 14:05:30 2014"
+  #define DATE "Wed Apr  9 09:25:42 2014"
 #endif

+ 1 - 1
libs/openssl/crypto/cryptlib.c

@@ -889,7 +889,7 @@ void OPENSSL_showfatal (const char *fmta,...)
 
 #if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
     /* this -------------v--- guards NT-specific calls */
-    if (GetVersion() < 0x80000000 && OPENSSL_isservice() > 0)
+    if (check_winnt() && OPENSSL_isservice() > 0)
     {	HANDLE h = RegisterEventSource(0,_T("OPENSSL"));
 	const TCHAR *pmsg=buf;
 	ReportEvent(h,EVENTLOG_ERROR_TYPE,0,0,0,1,0,&pmsg,0);

+ 1 - 1
libs/openssl/crypto/evp/bio_b64.c

@@ -264,7 +264,7 @@ static int b64_read(BIO *b, char *out, int outl)
 				}
 
 			/* we fell off the end without starting */
-			if (j == i)
+			if ((j == i) && (num == 0))
 				{
 				/* Is this is one long chunk?, if so, keep on
 				 * reading until a new line. */

+ 88 - 0
libs/openssl/crypto/modes/gcm128.c

@@ -810,7 +810,11 @@ void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx,const unsigned char *iv,size_t len)
 		GCM_MUL(ctx,Yi);
 
 		if (is_endian.little)
+#ifdef BSWAP4
+			ctr = BSWAP4(ctx->Yi.d[3]);
+#else
 			ctr = GETU32(ctx->Yi.c+12);
+#endif
 		else
 			ctr = ctx->Yi.d[3];
 	}
@@ -818,7 +822,11 @@ void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx,const unsigned char *iv,size_t len)
 	(*ctx->block)(ctx->Yi.c,ctx->EK0.c,ctx->key);
 	++ctr;
 	if (is_endian.little)
+#ifdef BSWAP4
+		ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 		PUTU32(ctx->Yi.c+12,ctr);
+#endif
 	else
 		ctx->Yi.d[3] = ctr;
 }
@@ -913,7 +921,11 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
 	}
 
 	if (is_endian.little)
+#ifdef BSWAP4
+		ctr = BSWAP4(ctx->Yi.d[3]);
+#else
 		ctr = GETU32(ctx->Yi.c+12);
+#endif
 	else
 		ctr = ctx->Yi.d[3];
 
@@ -947,7 +959,11 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
+#ifdef BSWAP4
+				ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 				PUTU32(ctx->Yi.c+12,ctr);
+#endif
 			else
 				ctx->Yi.d[3] = ctr;
 			for (i=0; i<16/sizeof(size_t); ++i)
@@ -969,7 +985,11 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
+#ifdef BSWAP4
+				ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 				PUTU32(ctx->Yi.c+12,ctr);
+#endif
 			else
 				ctx->Yi.d[3] = ctr;
 			for (i=0; i<16/sizeof(size_t); ++i)
@@ -988,7 +1008,11 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
+#ifdef BSWAP4
+				ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 				PUTU32(ctx->Yi.c+12,ctr);
+#endif
 			else
 				ctx->Yi.d[3] = ctr;
 			for (i=0; i<16/sizeof(size_t); ++i)
@@ -1004,7 +1028,11 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
+#ifdef BSWAP4
+				ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 				PUTU32(ctx->Yi.c+12,ctr);
+#endif
 			else
 				ctx->Yi.d[3] = ctr;
 			while (len--) {
@@ -1022,7 +1050,11 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
+#ifdef BSWAP4
+				ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 				PUTU32(ctx->Yi.c+12,ctr);
+#endif
 			else
 				ctx->Yi.d[3] = ctr;
 		}
@@ -1066,7 +1098,11 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
 	}
 
 	if (is_endian.little)
+#ifdef BSWAP4
+		ctr = BSWAP4(ctx->Yi.d[3]);
+#else
 		ctr = GETU32(ctx->Yi.c+12);
+#endif
 	else
 		ctr = ctx->Yi.d[3];
 
@@ -1103,7 +1139,11 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
+#ifdef BSWAP4
+				ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 				PUTU32(ctx->Yi.c+12,ctr);
+#endif
 			else
 				ctx->Yi.d[3] = ctr;
 			for (i=0; i<16/sizeof(size_t); ++i)
@@ -1123,7 +1163,11 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
+#ifdef BSWAP4
+				ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 				PUTU32(ctx->Yi.c+12,ctr);
+#endif
 			else
 				ctx->Yi.d[3] = ctr;
 			for (i=0; i<16/sizeof(size_t); ++i)
@@ -1141,7 +1185,11 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
+#ifdef BSWAP4
+				ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 				PUTU32(ctx->Yi.c+12,ctr);
+#endif
 			else
 				ctx->Yi.d[3] = ctr;
 			for (i=0; i<16/sizeof(size_t); ++i) {
@@ -1159,7 +1207,11 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
+#ifdef BSWAP4
+				ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 				PUTU32(ctx->Yi.c+12,ctr);
+#endif
 			else
 				ctx->Yi.d[3] = ctr;
 			while (len--) {
@@ -1180,7 +1232,11 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
 			(*block)(ctx->Yi.c,ctx->EKi.c,key);
 			++ctr;
 			if (is_endian.little)
+#ifdef BSWAP4
+				ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 				PUTU32(ctx->Yi.c+12,ctr);
+#endif
 			else
 				ctx->Yi.d[3] = ctr;
 		}
@@ -1225,7 +1281,11 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
 	}
 
 	if (is_endian.little)
+#ifdef BSWAP4
+		ctr = BSWAP4(ctx->Yi.d[3]);
+#else
 		ctr = GETU32(ctx->Yi.c+12);
+#endif
 	else
 		ctr = ctx->Yi.d[3];
 
@@ -1247,7 +1307,11 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
 		(*stream)(in,out,GHASH_CHUNK/16,key,ctx->Yi.c);
 		ctr += GHASH_CHUNK/16;
 		if (is_endian.little)
+#ifdef BSWAP4
+			ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 			PUTU32(ctx->Yi.c+12,ctr);
+#endif
 		else
 			ctx->Yi.d[3] = ctr;
 		GHASH(ctx,out,GHASH_CHUNK);
@@ -1262,7 +1326,11 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
 		(*stream)(in,out,j,key,ctx->Yi.c);
 		ctr += (unsigned int)j;
 		if (is_endian.little)
+#ifdef BSWAP4
+			ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 			PUTU32(ctx->Yi.c+12,ctr);
+#endif
 		else
 			ctx->Yi.d[3] = ctr;
 		in  += i;
@@ -1282,7 +1350,11 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
 		(*ctx->block)(ctx->Yi.c,ctx->EKi.c,key);
 		++ctr;
 		if (is_endian.little)
+#ifdef BSWAP4
+			ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 			PUTU32(ctx->Yi.c+12,ctr);
+#endif
 		else
 			ctx->Yi.d[3] = ctr;
 		while (len--) {
@@ -1324,7 +1396,11 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
 	}
 
 	if (is_endian.little)
+#ifdef BSWAP4
+		ctr = BSWAP4(ctx->Yi.d[3]);
+#else
 		ctr = GETU32(ctx->Yi.c+12);
+#endif
 	else
 		ctr = ctx->Yi.d[3];
 
@@ -1349,7 +1425,11 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
 		(*stream)(in,out,GHASH_CHUNK/16,key,ctx->Yi.c);
 		ctr += GHASH_CHUNK/16;
 		if (is_endian.little)
+#ifdef BSWAP4
+			ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 			PUTU32(ctx->Yi.c+12,ctr);
+#endif
 		else
 			ctx->Yi.d[3] = ctr;
 		out += GHASH_CHUNK;
@@ -1375,7 +1455,11 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
 		(*stream)(in,out,j,key,ctx->Yi.c);
 		ctr += (unsigned int)j;
 		if (is_endian.little)
+#ifdef BSWAP4
+			ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 			PUTU32(ctx->Yi.c+12,ctr);
+#endif
 		else
 			ctx->Yi.d[3] = ctr;
 		out += i;
@@ -1386,7 +1470,11 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
 		(*ctx->block)(ctx->Yi.c,ctx->EKi.c,key);
 		++ctr;
 		if (is_endian.little)
+#ifdef BSWAP4
+			ctx->Yi.d[3] = BSWAP4(ctr);
+#else
 			PUTU32(ctx->Yi.c+12,ctr);
+#endif
 		else
 			ctx->Yi.d[3] = ctr;
 		while (len--) {

+ 3 - 3
libs/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	0x1000106fL
+#define OPENSSL_VERSION_NUMBER	0x1000107fL
 #ifdef OPENSSL_FIPS
-#define OPENSSL_VERSION_TEXT	"OpenSSL 1.0.1f-fips 6 Jan 2014"
+#define OPENSSL_VERSION_TEXT	"OpenSSL 1.0.1g-fips 7 Apr 2014"
 #else
-#define OPENSSL_VERSION_TEXT	"OpenSSL 1.0.1f 6 Jan 2014"
+#define OPENSSL_VERSION_TEXT	"OpenSSL 1.0.1g 7 Apr 2014"
 #endif
 #define OPENSSL_VERSION_PTEXT	" part of " OPENSSL_VERSION_TEXT
 

+ 3 - 0
libs/openssl/crypto/rand/md_rand.c

@@ -198,6 +198,9 @@ static void ssleay_rand_add(const void *buf, int num, double add)
 	EVP_MD_CTX m;
 	int do_not_lock;
 
+	if (!num)
+		return;
+
 	/*
 	 * (Based on the rand(3) manpage)
 	 *

+ 1 - 1
libs/openssl/crypto/rand/rand_win.c

@@ -750,7 +750,7 @@ static void readscreen(void)
   int		y;		/* y-coordinate of screen lines to grab */
   int		n = 16;		/* number of screen lines to grab at a time */
 
-  if (GetVersion() < 0x80000000 && OPENSSL_isservice()>0)
+  if (check_winnt() && OPENSSL_isservice()>0)
     return;
 
   /* Create a screen DC and a memory DC compatible to screen DC */

+ 6 - 0
libs/openssl/crypto/symhacks.h

@@ -204,6 +204,12 @@
 #define SSL_CTX_set_next_protos_advertised_cb	SSL_CTX_set_next_protos_adv_cb
 #undef SSL_CTX_set_next_proto_select_cb
 #define SSL_CTX_set_next_proto_select_cb	SSL_CTX_set_next_proto_sel_cb
+#undef ssl3_cbc_record_digest_supported
+#define ssl3_cbc_record_digest_supported        ssl3_cbc_record_digest_support
+#undef ssl_check_clienthello_tlsext_late
+#define ssl_check_clienthello_tlsext_late       ssl_check_clihello_tlsext_late
+#undef ssl_check_clienthello_tlsext_early
+#define ssl_check_clienthello_tlsext_early      ssl_check_clihello_tlsext_early
 
 /* Hack some long ENGINE names */
 #undef ENGINE_get_default_BN_mod_exp_crt

+ 2 - 4
libs/openssl/crypto/x509/by_dir.c

@@ -218,7 +218,7 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
 
 	s=dir;
 	p=s;
-	for (;;p++)
+	do
 		{
 		if ((*p == LIST_SEPARATOR_CHAR) || (*p == '\0'))
 			{
@@ -264,9 +264,7 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
 				return 0;
 				}
 			}
-		if (*p == '\0')
-			break;
-		}
+		} while (*p++ != '\0');
 	return 1;
 	}
 

+ 2 - 3
libs/openssl/crypto/x509/x509_vfy.c

@@ -1462,10 +1462,9 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
 	 * a certificate was revoked. This has since been changed since 
 	 * critical extension can change the meaning of CRL entries.
 	 */
-	if (crl->flags & EXFLAG_CRITICAL)
+	if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
+		&& (crl->flags & EXFLAG_CRITICAL))
 		{
-		if (ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
-			return 1;
 		ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
 		ok = ctx->verify_cb(0, ctx);
 		if(!ok)

+ 7 - 0
libs/openssl/e_os.h

@@ -368,6 +368,13 @@ static unsigned int _strlen31(const char *str)
 #    define DEFAULT_HOME  "C:"
 #  endif
 
+/* Avoid Windows 8 SDK GetVersion deprecated problems */
+#if defined(_MSC_VER) && _MSC_VER>=1800
+#  define check_winnt() (1)
+#else
+#  define check_winnt() (GetVersion() < 0x80000000)
+#endif 
+
 #else /* The non-microsoft world */
 
 #  ifdef OPENSSL_SYS_VMS

+ 18 - 8
libs/openssl/ssl/d1_both.c

@@ -1459,26 +1459,36 @@ dtls1_process_heartbeat(SSL *s)
 	unsigned int payload;
 	unsigned int padding = 16; /* Use minimum padding */
 
-	/* Read type and payload length first */
-	hbtype = *p++;
-	n2s(p, payload);
-	pl = p;
-
 	if (s->msg_callback)
 		s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
 			&s->s3->rrec.data[0], s->s3->rrec.length,
 			s, s->msg_callback_arg);
 
+	/* Read type and payload length first */
+	if (1 + 2 + 16 > s->s3->rrec.length)
+		return 0; /* silently discard */
+	hbtype = *p++;
+	n2s(p, payload);
+	if (1 + 2 + payload + 16 > s->s3->rrec.length)
+		return 0; /* silently discard per RFC 6520 sec. 4 */
+	pl = p;
+
 	if (hbtype == TLS1_HB_REQUEST)
 		{
 		unsigned char *buffer, *bp;
+		unsigned int write_length = 1 /* heartbeat type */ +
+					    2 /* heartbeat length */ +
+					    payload + padding;
 		int r;
 
+		if (write_length > SSL3_RT_MAX_PLAIN_LENGTH)
+			return 0;
+
 		/* Allocate memory for the response, size is 1 byte
 		 * message type, plus 2 bytes payload length, plus
 		 * payload, plus padding
 		 */
-		buffer = OPENSSL_malloc(1 + 2 + payload + padding);
+		buffer = OPENSSL_malloc(write_length);
 		bp = buffer;
 
 		/* Enter response type, length and copy payload */
@@ -1489,11 +1499,11 @@ dtls1_process_heartbeat(SSL *s)
 		/* Random padding */
 		RAND_pseudo_bytes(bp, padding);
 
-		r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);
+		r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length);
 
 		if (r >= 0 && s->msg_callback)
 			s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
-				buffer, 3 + payload + padding,
+				buffer, write_length,
 				s, s->msg_callback_arg);
 
 		OPENSSL_free(buffer);

+ 9 - 0
libs/openssl/ssl/kssl.h

@@ -70,6 +70,15 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <krb5.h>
+#ifdef OPENSSL_SYS_WIN32
+/* These can sometimes get redefined indirectly by krb5 header files
+ * after they get undefed in ossl_typ.h
+ */
+#undef X509_NAME
+#undef X509_EXTENSIONS
+#undef OCSP_REQUEST
+#undef OCSP_RESPONSE
+#endif
 
 #ifdef  __cplusplus
 extern "C" {

+ 1 - 1
libs/openssl/ssl/s23_clnt.c

@@ -283,7 +283,7 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, int len)
 		send_time = (s->mode & SSL_MODE_SEND_CLIENTHELLO_TIME) != 0;
 	if (send_time)
 		{
-		unsigned long Time = time(NULL);
+		unsigned long Time = (unsigned long)time(NULL);
 		unsigned char *p = result;
 		l2n(Time, p);
 		return RAND_pseudo_bytes(p, len-4);

+ 2 - 2
libs/openssl/ssl/s3_srvr.c

@@ -1830,7 +1830,7 @@ int ssl3_send_server_key_exchange(SSL *s)
 			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
 			goto f_err;
 			}
-		for (i=0; r[i] != NULL && i<4; i++)
+		for (i=0; i < 4 && r[i] != NULL; i++)
 			{
 			nr[i]=BN_num_bytes(r[i]);
 #ifndef OPENSSL_NO_SRP
@@ -1866,7 +1866,7 @@ int ssl3_send_server_key_exchange(SSL *s)
 		d=(unsigned char *)s->init_buf->data;
 		p= &(d[4]);
 
-		for (i=0; r[i] != NULL && i<4; i++)
+		for (i=0; i < 4 && r[i] != NULL; i++)
 			{
 #ifndef OPENSSL_NO_SRP
 			if ((i == 2) && (type & SSL_kSRP))

+ 1 - 1
libs/openssl/ssl/ssl.h

@@ -915,7 +915,7 @@ struct ssl_ctx_st
 	 */
 	unsigned int max_send_fragment;
 
-#ifndef OPENSSL_ENGINE
+#ifndef OPENSSL_NO_ENGINE
 	/* Engine to pass requests for client certs to
 	 */
 	ENGINE *client_cert_engine;

+ 2 - 1
libs/openssl/ssl/t1_enc.c

@@ -986,7 +986,8 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
 		}
 		else
 		{
-			EVP_MD_CTX_copy(&hmac,hash);
+			if (!EVP_MD_CTX_copy(&hmac,hash))
+				return -1;
 			mac_ctx = &hmac;
 		}
 

+ 40 - 6
libs/openssl/ssl/t1_lib.c

@@ -662,6 +662,36 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
                 }
 #endif
 
+#ifdef TLSEXT_TYPE_padding
+	/* Add padding to workaround bugs in F5 terminators.
+	 * See https://tools.ietf.org/html/draft-agl-tls-padding-03
+	 *
+	 * NB: because this code works out the length of all existing
+	 * extensions it MUST always appear last.
+	 */
+	{
+	int hlen = ret - (unsigned char *)s->init_buf->data;
+	/* The code in s23_clnt.c to build ClientHello messages includes the
+	 * 5-byte record header in the buffer, while the code in s3_clnt.c does
+	 * not. */
+	if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
+		hlen -= 5;
+	if (hlen > 0xff && hlen < 0x200)
+		{
+		hlen = 0x200 - hlen;
+		if (hlen >= 4)
+			hlen -= 4;
+		else
+			hlen = 0;
+
+		s2n(TLSEXT_TYPE_padding, ret);
+		s2n(hlen, ret);
+		memset(ret, 0, hlen);
+		ret += hlen;
+		}
+	}
+#endif
+
 	if ((extdatalen = ret-p-2)== 0) 
 		return p;
 
@@ -1261,7 +1291,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
 				}
 			}
 		else if (type == TLSEXT_TYPE_status_request &&
-		         s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
+		         s->version != DTLS1_VERSION)
 			{
 		
 			if (size < 5) 
@@ -2558,16 +2588,20 @@ tls1_process_heartbeat(SSL *s)
 	unsigned int payload;
 	unsigned int padding = 16; /* Use minimum padding */
 
-	/* Read type and payload length first */
-	hbtype = *p++;
-	n2s(p, payload);
-	pl = p;
-
 	if (s->msg_callback)
 		s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
 			&s->s3->rrec.data[0], s->s3->rrec.length,
 			s, s->msg_callback_arg);
 
+	/* Read type and payload length first */
+	if (1 + 2 + 16 > s->s3->rrec.length)
+		return 0; /* silently discard */
+	hbtype = *p++;
+	n2s(p, payload);
+	if (1 + 2 + payload + 16 > s->s3->rrec.length)
+		return 0; /* silently discard per RFC 6520 sec. 4 */
+	pl = p;
+
 	if (hbtype == TLS1_HB_REQUEST)
 		{
 		unsigned char *buffer, *bp;

+ 6 - 0
libs/openssl/ssl/tls1.h

@@ -230,6 +230,12 @@ extern "C" {
 /* ExtensionType value from RFC5620 */
 #define TLSEXT_TYPE_heartbeat	15
 
+/* ExtensionType value for TLS padding extension.
+ * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
+ * http://tools.ietf.org/html/draft-agl-tls-padding-03
+ */
+#define TLSEXT_TYPE_padding	21
+
 /* ExtensionType value from RFC4507 */
 #define TLSEXT_TYPE_session_ticket		35
 

+ 1 - 1
source/Console.cbproj

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

+ 1 - 1
source/DragExt.cbproj

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

+ 2 - 2
source/DragExt64.rc

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

+ 2 - 2
source/WinSCP.cbproj

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

+ 30 - 0
source/core/Common.cpp

@@ -1897,6 +1897,28 @@ UnicodeString __fastcall EncodeUrlString(UnicodeString S)
   return DoEncodeUrl(S, NonUrlChars());
 }
 //---------------------------------------------------------------------------
+UnicodeString __fastcall AppendUrlParams(UnicodeString AURL, UnicodeString Params)
+{
+  // see also TWebHelpSystem::ShowHelp
+  const wchar_t FragmentSeparator = L'#';
+  UnicodeString URL = ::CutToChar(AURL, FragmentSeparator, false);
+
+  if (URL.Pos(L"?") == 0)
+  {
+    URL += L"?";
+  }
+  else
+  {
+    URL += L"&";
+  }
+
+  URL += Params;
+
+  AddToList(URL, AURL, FragmentSeparator);
+
+  return URL;
+}
+//---------------------------------------------------------------------------
 UnicodeString __fastcall EscapeHotkey(const UnicodeString & Caption)
 {
   return ReplaceStr(Caption, L"&", L"&&");
@@ -1997,6 +2019,14 @@ bool __fastcall IsWin7()
   return CheckWin32Version(6, 1);
 }
 //---------------------------------------------------------------------------
+bool __fastcall IsWine()
+{
+  HMODULE NtDll = GetModuleHandle(L"ntdll.dll");
+  return
+    ALWAYS_TRUE(NtDll != NULL) &&
+    (GetProcAddress(NtDll, "wine_get_version") != NULL);
+}
+//---------------------------------------------------------------------------
 LCID __fastcall GetDefaultLCID()
 {
   return GetUserDefaultLCID();

+ 2 - 0
source/core/Common.h

@@ -86,6 +86,7 @@ bool __fastcall IsHex(wchar_t Ch);
 UnicodeString __fastcall DecodeUrlChars(UnicodeString S);
 UnicodeString __fastcall EncodeUrlChars(UnicodeString S, UnicodeString Ignore = L"");
 UnicodeString __fastcall EncodeUrlString(UnicodeString S);
+UnicodeString __fastcall AppendUrlParams(UnicodeString AURL, UnicodeString Params);
 bool __fastcall RecursiveDeleteFile(const UnicodeString FileName, bool ToRecycleBin);
 void __fastcall DeleteFileChecked(const UnicodeString & FileName);
 unsigned int __fastcall CancelAnswer(unsigned int Answers);
@@ -99,6 +100,7 @@ bool __fastcall CutToken(UnicodeString & Str, UnicodeString & Token,
 void __fastcall AddToList(UnicodeString & List, const UnicodeString & Value, const UnicodeString & Delimiter);
 bool __fastcall IsWinVista();
 bool __fastcall IsWin7();
+bool __fastcall IsWine();
 TLibModule * __fastcall FindModule(void * Instance);
 __int64 __fastcall Round(double Number);
 bool __fastcall TryRelativeStrToDateTime(UnicodeString S, TDateTime & DateTime);

+ 111 - 15
source/core/FtpFileSystem.cpp

@@ -3187,6 +3187,84 @@ UnicodeString __fastcall FormatValidityTime(const TFtpsCertificateData::TValidit
       (unsigned short)ValidityTime.Sec, 0));
 }
 //---------------------------------------------------------------------------
+bool __fastcall VerifyNameMask(UnicodeString Name, UnicodeString Mask)
+{
+  bool Result = true;
+  int Pos;
+  while (Result && (Pos = Mask.Pos(L"*")) > 0)
+  {
+    // Pos will typically be 1 here, so not actual comparison is done
+    Result = SameText(Mask.SubString(1, Pos - 1), Name.SubString(1, Pos - 1));
+    if (Result)
+    {
+      Mask.Delete(1, Pos); // including *
+      Name.Delete(1, Pos - 1);
+      // remove everything until the next dot
+      Pos = Name.Pos(L".");
+      if (Pos == 0)
+      {
+        Pos = Name.Length() + 1;
+      }
+      Name.Delete(1, Pos - 1);
+    }
+  }
+
+  if (Result)
+  {
+    Result = SameText(Mask, Name);
+  }
+
+  return Result;
+}
+//---------------------------------------------------------------------------
+bool __fastcall TFTPFileSystem::VerifyCertificateHostName(const TFtpsCertificateData & Data)
+{
+  UnicodeString HostName = FTerminal->SessionData->HostNameExpanded;
+
+  UnicodeString CommonName = Data.Subject.CommonName;
+  bool NoMask = CommonName.IsEmpty();
+  bool Result = !NoMask && VerifyNameMask(HostName, CommonName);
+  if (Result)
+  {
+    FTerminal->LogEvent(FORMAT("Certificate common name \"%s\" matches hostname", (CommonName)));
+  }
+  else
+  {
+    if (!NoMask && (FTerminal->Configuration->ActualLogProtocol >= 1))
+    {
+      FTerminal->LogEvent(FORMAT("Certificate common name \"%s\" does not match hostname", (CommonName)));
+    }
+    UnicodeString SubjectAltName = Data.SubjectAltName;
+    while (!Result && !SubjectAltName.IsEmpty())
+    {
+      UnicodeString Entry = CutToChar(SubjectAltName, L',', true);
+      UnicodeString EntryName = CutToChar(Entry, L':', true);
+      if (SameText(EntryName, L"DNS"))
+      {
+        NoMask = false;
+        Result = VerifyNameMask(HostName, Entry);
+        if (Result)
+        {
+          FTerminal->LogEvent(FORMAT("Certificate subject alternative name \"%s\" matches hostname", (Entry)));
+        }
+        else
+        {
+          if (FTerminal->Configuration->ActualLogProtocol >= 1)
+          {
+            FTerminal->LogEvent(FORMAT("Certificate subject alternative name \"%s\" does not match hostname", (Entry)));
+          }
+        }
+      }
+    }
+  }
+  if (!Result && NoMask)
+  {
+    FTerminal->LogEvent("Certificate has no common name nor subject alternative name, not verifying hostname");
+    Result = true;
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 bool __fastcall TFTPFileSystem::HandleAsynchRequestVerifyCertificate(
   const TFtpsCertificateData & Data, int & RequestResult)
 {
@@ -3199,11 +3277,14 @@ bool __fastcall TFTPFileSystem::HandleAsynchRequestVerifyCertificate(
     FSessionInfo.CertificateFingerprint =
       BytesToHex(RawByteString((const char*)Data.Hash, Data.HashLen), false, L':');
 
+    UnicodeString CertificateSubject = Data.Subject.Organization;
+    FTerminal->LogEvent(FORMAT(L"Verifying certificate for \"%s\" with fingerprint %s", (CertificateSubject, FSessionInfo.CertificateFingerprint)));
+
     int VerificationResultStr;
     switch (Data.VerificationResult)
     {
       case X509_V_OK:
-        VerificationResultStr = CERT_OK;
+        VerificationResultStr = -1;
         break;
       case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
         VerificationResultStr = CERT_ERR_UNABLE_TO_GET_ISSUER_CERT;
@@ -3267,10 +3348,15 @@ bool __fastcall TFTPFileSystem::HandleAsynchRequestVerifyCertificate(
         break;
     }
 
-    UnicodeString Summary = LoadStr(VerificationResultStr);
-    if (Data.VerificationResult != X509_V_OK)
+    UnicodeString Summary;
+    if (VerificationResultStr >= 0)
+    {
+      Summary = LoadStr(VerificationResultStr) + L" " + FMTLOAD(CERT_ERRDEPTH, (Data.VerificationDepth + 1));
+    }
+
+    if (!VerifyCertificateHostName(Data))
     {
-      Summary += L" " + FMTLOAD(CERT_ERRDEPTH, (Data.VerificationDepth + 1));
+      AddToList(Summary, FMTLOAD(CERT_NAME_MISMATCH, (FTerminal->SessionData->HostNameExpanded)), L"\n\n");
     }
 
     FSessionInfo.Certificate =
@@ -3284,21 +3370,30 @@ bool __fastcall TFTPFileSystem::HandleAsynchRequestVerifyCertificate(
 
     RequestResult = 0;
 
-    THierarchicalStorage * Storage =
-      FTerminal->Configuration->CreateScpStorage(false);
-    try
+    if (Summary.IsEmpty())
     {
-      Storage->AccessMode = smRead;
+      RequestResult = 1;
+    }
 
-      if (Storage->OpenSubKey(CertificateStorageKey, false) &&
-          Storage->ValueExists(FSessionInfo.CertificateFingerprint))
+    if (RequestResult == 0)
+    {
+      THierarchicalStorage * Storage =
+        FTerminal->Configuration->CreateScpStorage(false);
+      try
       {
-        RequestResult = 1;
+        Storage->AccessMode = smRead;
+
+        if (Storage->OpenSubKey(CertificateStorageKey, false) &&
+            Storage->ValueExists(FSessionInfo.CertificateFingerprint))
+        {
+          FTerminal->LogEvent(FORMAT(L"Certificate for \"%s\" matches cached fingerprint", (CertificateSubject)));
+          RequestResult = 1;
+        }
+      }
+      __finally
+      {
+        delete Storage;
       }
-    }
-    __finally
-    {
-      delete Storage;
     }
 
     if (RequestResult == 0)
@@ -3316,6 +3411,7 @@ bool __fastcall TFTPFileSystem::HandleAsynchRequestVerifyCertificate(
         }
         else if (ExpectedKey == FSessionInfo.CertificateFingerprint)
         {
+          FTerminal->LogEvent(FORMAT(L"Certificate for \"%s\" matches configured fingerprint", (CertificateSubject)));
           RequestResult = 1;
         }
       }

+ 1 - 0
source/core/FtpFileSystem.h

@@ -183,6 +183,7 @@ protected:
   void __fastcall SetLastCode(int Code);
   void __fastcall StoreLastResponse(const UnicodeString & Text);
   void __fastcall SetCPSLimit(TFileOperationProgressType * OperationProgress);
+  bool __fastcall VerifyCertificateHostName(const TFtpsCertificateData & Data);
 
   static bool __fastcall Unquote(UnicodeString & Str);
   static UnicodeString __fastcall ExtractStatusMessage(UnicodeString Status);

+ 1 - 1
source/core/Script.cpp

@@ -410,7 +410,7 @@ void __fastcall TScript::LogPendingLines(TTerminal * ATerminal)
   {
     // not using Log(), as we want to log to ATerminal, not Terminal,
     // what is different here, as we are called from TManagementScript::Connect()
-    ATerminal->Log->Add(llMessage, FORMAT(ScriptLogFormat, (L"Retrospectivelly logging previous script records:")));
+    ATerminal->Log->Add(llMessage, FORMAT(ScriptLogFormat, (L"Retrospectively logging previous script records:")));
 
     for (int Index = 0; Index < FPendingLogLines->Count; Index++)
     {

+ 25 - 11
source/filezilla/AsyncSslSocketLayer.cpp

@@ -1,4 +1,4 @@
-/*           CAsyncSslSocketLayer by Tim Kosse 
+/*           CAsyncSslSocketLayer by Tim Kosse
           mailto: [email protected])
                  Version 2.0 (2005-02-27)
 -------------------------------------------------------------
@@ -123,6 +123,7 @@ static char THIS_FILE[] = __FILE__;
 	if (!p##n) \
 		bError = true;
 #endif
+#include <openssl/x509v3.h>
 
 //The following functions from the SSL libraries are used:
 def(int, SSL_state, (const SSL *s));
@@ -1558,16 +1559,8 @@ void CAsyncSslSocketLayer::apps_ssl_info_callback(const SSL *s, int where, int r
 	if (where & SSL_CB_HANDSHAKE_DONE)
 	{
 		int error = pSSL_get_verify_result(pLayer->m_ssl);
-		if (error)
-		{
-			pLayer->DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_VERIFY_CERT, error);
-			pLayer->m_bBlocking = TRUE;
-			return;
-		}
-		pLayer->m_bSslEstablished = TRUE;
-		pLayer->PrintSessionInfo();
-		pLayer->DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_INFO, SSL_INFO_ESTABLISHED);
-		pLayer->TriggerEvents();
+		pLayer->DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_VERIFY_CERT, error);
+		pLayer->m_bBlocking = TRUE;
 	}
 }
 
@@ -1930,6 +1923,27 @@ BOOL CAsyncSslSocketLayer::GetPeerCertificateData(t_SslCertData &SslCertData, LP
 		return FALSE;
 	}
 
+	int subjectAltNamePos = X509_get_ext_by_NID(pX509, NID_subject_alt_name, -1);
+	if (subjectAltNamePos >= 0)
+	{
+		X509_EXTENSION * subjectAltNameExtension = X509_get_ext(pX509, subjectAltNamePos);
+		BIO * subjectAltNameBio = BIO_new(BIO_s_mem());
+
+		if (X509V3_EXT_print(subjectAltNameBio, subjectAltNameExtension, 0, 0) == 1)
+		{
+			USES_CONVERSION;
+			u_char *data;
+			int len = BIO_get_mem_data(subjectAltNameBio, &data);
+			char * buf = new char[len + 1];
+			memcpy(buf, data, len);
+			buf[len] = '\0';
+			_tcsncpy(SslCertData.subjectAltName, A2CT(buf), LENOF(SslCertData.subjectAltName));
+			SslCertData.subjectAltName[LENOF(SslCertData.subjectAltName) - 1] = '\0';
+		}
+
+		BIO_vfree(subjectAltNameBio);
+  }
+
 	unsigned int length = 20;
 	pX509_digest(pX509, pEVP_sha1(), SslCertData.hash, &length);
 

+ 2 - 0
source/filezilla/AsyncSslSocketLayer.h

@@ -126,6 +126,8 @@ struct t_SslCertData
 		int y,M,d,h,m,s;
 	} validFrom, validUntil;
 
+	TCHAR subjectAltName[10240];
+
 	unsigned char hash[20];
 
 	int verificationResult;

+ 1 - 0
source/filezilla/FileZillaIntf.cpp

@@ -375,6 +375,7 @@ bool __fastcall TFileZillaIntf::HandleMessage(WPARAM wParam, LPARAM lParam)
           CopyContact(Data.Issuer, AData->pCertData->issuer);
           CopyValidityTime(Data.ValidFrom, AData->pCertData->validFrom);
           CopyValidityTime(Data.ValidUntil, AData->pCertData->validUntil);
+          Data.SubjectAltName = AData->pCertData->subjectAltName;
           Data.Hash = AData->pCertData->hash;
           Data.VerificationResult = AData->pCertData->verificationResult;
           Data.VerificationDepth = AData->pCertData->verificationDepth;

+ 2 - 0
source/filezilla/FileZillaIntf.h

@@ -67,6 +67,8 @@ struct TFtpsCertificateData
   TValidityTime ValidFrom;
   TValidityTime ValidUntil;
 
+  const wchar_t * SubjectAltName;
+
   const unsigned char * Hash;
   static const size_t HashLen = 20;
 

+ 5 - 1
source/forms/CustomScpExplorer.cpp

@@ -2017,7 +2017,11 @@ bool __fastcall TCustomScpExplorerForm::ExecuteFileOperation(TFileOperation Oper
     else if (Operation == foDelete)
     {
       assert(FileList->Count);
-      bool Alternative = bool(Param);
+      // We deliberately do not toggle alternative flag (Param), but use OR,
+      // because the Param is set only when command is invoked using Shift-Del/F8 keyboard
+      // shortcut of CurrentDeleteAlternativeAction
+      bool Alternative =
+        bool(Param) || UseAlternativeFunction();
       bool Recycle;
       if (Side == osLocal)
       {

+ 29 - 11
source/forms/Login.cpp

@@ -291,10 +291,15 @@ TTreeNode * __fastcall TLoginDialog::AddSession(TSessionData * Data)
   TTreeNode * Parent = AddSessionPath(UnixExtractFilePath(Data->Name), true, Data->IsWorkspace);
   TTreeNode * Node = SessionTree->Items->AddChild(Parent, UnixExtractFileName(Data->Name));
   Node->Data = Data;
-  SetNodeImage(Node, GetSessionImageIndex(Data));
+  UpdateNodeImage(Node);
 
   return Node;
 }
+//---------------------------------------------------------------------------
+void __fastcall TLoginDialog::UpdateNodeImage(TTreeNode * Node)
+{
+  SetNodeImage(Node, GetSessionImageIndex(GetNodeSession(Node)));
+}
 //---------------------------------------------------------------------
 int __fastcall TLoginDialog::GetSessionImageIndex(TSessionData * Data)
 {
@@ -380,12 +385,17 @@ void __fastcall TLoginDialog::NewSite()
   LoadContents();
 }
 //---------------------------------------------------------------------------
-void __fastcall TLoginDialog::Default()
+void __fastcall TLoginDialog::ResetNewSiteData()
 {
   if (ALWAYS_TRUE(StoredSessions != NULL))
   {
     FNewSiteData->Assign(StoredSessions->DefaultSettings);
   }
+}
+//---------------------------------------------------------------------------
+void __fastcall TLoginDialog::Default()
+{
+  ResetNewSiteData();
 
   NewSite();
 }
@@ -588,12 +598,6 @@ void __fastcall TLoginDialog::UpdateControls()
     UpdateButtonVisibility(EditButton);
     UpdateButtonVisibility(EditCancelButton);
 
-    TAction * SaveButtonAction =
-      SupportsSplitButton() ? SaveSessionAction : SaveAsSessionAction;
-    if (SaveButton->Action != SaveButtonAction)
-    {
-      SaveButton->Action = SaveButtonAction;
-    }
     SaveAsSessionMenuItem->Visible = FEditing;
   }
 }
@@ -649,6 +653,19 @@ void __fastcall TLoginDialog::FormShow(TObject * /*Sender*/)
     // Explicit call is needed, as we get here during csRecreating phase,
     // when SessionTreeChange is not triggered, see initial method comment
     LoadContents();
+
+    if (FLocaleChanging)
+    {
+      TTreeNode * Node = SessionTree->Items->GetFirstNode();
+      while (Node != NULL)
+      {
+        if (IsSiteNode(Node))
+        {
+          UpdateNodeImage(Node);
+        }
+        Node = Node->GetNext();
+      }
+    }
   }
   UpdateControls();
 }
@@ -879,6 +896,8 @@ void __fastcall TLoginDialog::SaveAsSession(bool ForceDialog)
     LoadContents();
 
     UpdateControls();
+
+    ResetNewSiteData();
   }
 }
 //---------------------------------------------------------------------------
@@ -2414,8 +2433,7 @@ void __fastcall TLoginDialog::PortNumberEditChange(TObject * Sender)
 //---------------------------------------------------------------------------
 UnicodeString __fastcall TLoginDialog::ImportExportIniFilePath()
 {
-  UnicodeString PersonalDirectory;
-  ::SpecialFolderLocation(CSIDL_PERSONAL, PersonalDirectory);
+  UnicodeString PersonalDirectory = GetPersonalFolder();
   UnicodeString FileName = IncludeTrailingBackslash(PersonalDirectory) +
     ExtractFileName(ExpandEnvironmentVariables(Configuration->IniFileStorageName));
   return FileName;
@@ -2745,7 +2763,7 @@ void __fastcall TLoginDialog::CancelEditing()
 {
   FEditing = false;
   // reset back the color
-  SetNodeImage(SessionTree->Selected, GetSessionImageIndex(GetNodeSession(SessionTree->Selected)));
+  UpdateNodeImage(SessionTree->Selected);
 }
 //---------------------------------------------------------------------------
 void __fastcall TLoginDialog::CloneToNewSite()

+ 2 - 0
source/forms/Login.h

@@ -329,6 +329,7 @@ private:
   bool __fastcall CanLogin();
   bool __fastcall IsCloneToNewSiteDefault();
   bool __fastcall IsDefaultResult(TModalResult Result);
+  void __fastcall UpdateNodeImage(TTreeNode * Node);
   int __fastcall GetSessionImageIndex(TSessionData * Data);
   void __fastcall SetNodeImage(TTreeNode * Node, int ImageIndex);
   void __fastcall CancelEditing();
@@ -336,6 +337,7 @@ private:
   bool __fastcall IsEditable();
   TSessionData * __fastcall CloneSelectedSession();
   void __fastcall CloneToNewSite();
+  void __fastcall ResetNewSiteData();
 
 protected:
   void __fastcall Default();

+ 60 - 46
source/forms/Preferences.cpp

@@ -105,10 +105,13 @@ __fastcall TPreferencesDialog::~TPreferencesDialog()
   SAFE_DESTROY(FEditorScrollOnDragOver);
   SAFE_DESTROY(FCopyParamScrollOnDragOver);
   SAFE_DESTROY(FCustomCommandsScrollOnDragOver);
-  delete FEditorFont;
+  SAFE_DESTROY(FEditorFont);
   delete FCustomCommandList;
+  FCustomCommandList = NULL;
   delete FCopyParamList;
+  FCopyParamList = NULL;
   delete FEditorList;
+  FEditorList = NULL;
 }
 //---------------------------------------------------------------------
 bool __fastcall TPreferencesDialog::Execute(TPreferencesDialogData * DialogData)
@@ -1188,29 +1191,32 @@ void __fastcall TPreferencesDialog::IconButtonClick(TObject *Sender)
 void __fastcall TPreferencesDialog::CustomCommandsViewData(TObject * /*Sender*/,
       TListItem * Item)
 {
-  assert(FCustomCommandList != NULL);
-  int Index = Item->Index;
-  assert(Index >= 0 && Index <= FCustomCommandList->Count);
-  const TCustomCommandType * Command = FCustomCommandList->Commands[Index];
-  UnicodeString Caption = StripHotkey(Command->Name);
-  if (Command->ShortCut != 0)
-  {
-    Caption = FORMAT(L"%s (%s)", (Caption, ShortCutToText(Command->ShortCut)));
-  }
-  Item->Caption = Caption;
-  assert(!Item->SubItems->Count);
-  Item->SubItems->Add(Command->Command);
-  int Params = Command->Params;
-  Item->SubItems->Add(LoadStr(
-    FLAGSET(Params, ccLocal) ? CUSTOM_COMMAND_LOCAL : CUSTOM_COMMAND_REMOTE));
-  UnicodeString ParamsStr;
-  #define ADDPARAM(PARAM, STR) \
-    if (FLAGSET(Params, PARAM)) \
-      ParamsStr += (ParamsStr.IsEmpty() ? L"" : L"/") + LoadStr(STR);
-  ADDPARAM(ccApplyToDirectories, CUSTOM_COMMAND_DIRECTORIES);
-  ADDPARAM(ccRecursive, CUSTOM_COMMAND_RECURSE);
-  #undef ADDPARAM
-  Item->SubItems->Add(ParamsStr);
+  // WORKAROUND We get here on Wine after destructor is called
+  if (FCustomCommandList != NULL)
+  {
+    int Index = Item->Index;
+    assert(Index >= 0 && Index <= FCustomCommandList->Count);
+    const TCustomCommandType * Command = FCustomCommandList->Commands[Index];
+    UnicodeString Caption = StripHotkey(Command->Name);
+    if (Command->ShortCut != 0)
+    {
+      Caption = FORMAT(L"%s (%s)", (Caption, ShortCutToText(Command->ShortCut)));
+    }
+    Item->Caption = Caption;
+    assert(!Item->SubItems->Count);
+    Item->SubItems->Add(Command->Command);
+    int Params = Command->Params;
+    Item->SubItems->Add(LoadStr(
+      FLAGSET(Params, ccLocal) ? CUSTOM_COMMAND_LOCAL : CUSTOM_COMMAND_REMOTE));
+    UnicodeString ParamsStr;
+    #define ADDPARAM(PARAM, STR) \
+      if (FLAGSET(Params, PARAM)) \
+        ParamsStr += (ParamsStr.IsEmpty() ? L"" : L"/") + LoadStr(STR);
+    ADDPARAM(ccApplyToDirectories, CUSTOM_COMMAND_DIRECTORIES);
+    ADDPARAM(ccRecursive, CUSTOM_COMMAND_RECURSE);
+    #undef ADDPARAM
+    Item->SubItems->Add(ParamsStr);
+  }
 }
 //---------------------------------------------------------------------------
 void __fastcall TPreferencesDialog::ListViewSelectItem(
@@ -1642,14 +1648,18 @@ void __fastcall TPreferencesDialog::UpdateEditorListView()
 void __fastcall TPreferencesDialog::EditorListView3Data(TObject * /*Sender*/,
   TListItem * Item)
 {
-  int Index = Item->Index;
-  assert(Index >= 0 && Index <= FEditorList->Count);
-  const TEditorPreferences * Editor = FEditorList->Editors[Index];
-  Item->Caption = Editor->Name;
-  Item->SubItems->Add(Editor->Data->FileMask.Masks);
-  if (Editor->Data->Editor == edExternal)
+  // WORKAROUND We get here on Wine after destructor is called
+  if (FEditorList != NULL)
   {
-    Item->SubItems->Add(BooleanToStr(Editor->Data->ExternalEditorText));
+    int Index = Item->Index;
+    assert(Index >= 0 && Index <= FEditorList->Count);
+    const TEditorPreferences * Editor = FEditorList->Editors[Index];
+    Item->Caption = Editor->Name;
+    Item->SubItems->Add(Editor->Data->FileMask.Masks);
+    if (Editor->Data->Editor == edExternal)
+    {
+      Item->SubItems->Add(BooleanToStr(Editor->Data->ExternalEditorText));
+    }
   }
 }
 //---------------------------------------------------------------------------
@@ -1822,23 +1832,27 @@ void __fastcall TPreferencesDialog::UpdateCopyParamListView()
 void __fastcall TPreferencesDialog::CopyParamListViewData(TObject * /*Sender*/,
   TListItem * Item)
 {
-  UnicodeString Name;
-  UnicodeString Rule;
-
-  int Index = Item->Index;
-  if (Index == 0)
-  {
-    Name = StripHotkey(LoadStr(COPY_PARAM_DEFAULT));
-  }
-  else
+  // WORKAROUND We get here on Wine after destructor is called
+  if (FCopyParamList != NULL)
   {
-    assert(Index >= 1 && Index <= 1 + FCopyParamList->Count);
-    Name = StripHotkey(FCopyParamList->Names[Index - 1]);
-    Rule = BooleanToStr(FCopyParamList->Rules[Index - 1] != NULL);
-  }
+    UnicodeString Name;
+    UnicodeString Rule;
+
+    int Index = Item->Index;
+    if (Index == 0)
+    {
+      Name = StripHotkey(LoadStr(COPY_PARAM_DEFAULT));
+    }
+    else
+    {
+      assert(Index >= 1 && Index <= 1 + FCopyParamList->Count);
+      Name = StripHotkey(FCopyParamList->Names[Index - 1]);
+      Rule = BooleanToStr(FCopyParamList->Rules[Index - 1] != NULL);
+    }
 
-  Item->Caption = Name;
-  Item->SubItems->Add(Rule);
+    Item->Caption = Name;
+    Item->SubItems->Add(Rule);
+  }
 }
 //---------------------------------------------------------------------------
 void __fastcall TPreferencesDialog::HelpButtonClick(TObject * /*Sender*/)

+ 2 - 0
source/forms/Preferences.dfm

@@ -2952,6 +2952,8 @@ object PreferencesDialog: TPreferencesDialog
       end
       object PanelLocalSheet: TTabSheet
         Tag = 22
+        HelpType = htKeyword
+        HelpKeyword = 'ui_pref_panels_local'
         Caption = 'Local'
         ImageIndex = 20
         TabVisible = False

+ 53 - 43
source/forms/Progress.cpp

@@ -118,53 +118,62 @@ void __fastcall TProgressForm::UpdateControls()
   if (FData.Operation != FLastOperation)
   {
     bool AVisible;
-    THandle ShellModule;
 
-    try
+    // Wine does have static text "Searching" instead of actual animations
+    if (!IsWine())
     {
-      AVisible = true;
-      switch (FData.Operation) {
-        case foCopy:
-        case foMove:
-        case foRemoteMove:
-        case foRemoteCopy:
-          if (FData.Count == 1) Animate->CommonAVI = aviCopyFile;
-            else Animate->CommonAVI = aviCopyFiles;
-          break;
-
-        case foDelete:
-          Animate->CommonAVI = (DeleteToRecycleBin ? aviRecycleFile : aviDeleteFile);
-          break;
-
-        case foSetProperties:
-        case foGetProperties:
-          ShellModule = SafeLoadLibrary(L"shell32.dll");
-          if (!ShellModule)
-          {
-            Abort();
-          }
-          // workaround, VCL is not able to set both ResId and ResHandle otherwise
-          Animate->Active = false;
-          Animate->ResHandle = 0;
-          Animate->ComponentState << csLoading;
-          Animate->ResId = 165;
-          Animate->ResHandle = ShellModule;
-          Animate->ComponentState >> csLoading;
-          Animate->Active = true;
-          break;
-
-        default:
-          assert(FData.Operation == foCustomCommand ||
-            FData.Operation == foCalculateSize ||
-            FData.Operation == foCalculateChecksum);
-          Animate->CommonAVI = aviNone;
-          AVisible = false;
+      try
+      {
+        THandle ShellModule;
+        AVisible = true;
+        switch (FData.Operation) {
+          case foCopy:
+          case foMove:
+          case foRemoteMove:
+          case foRemoteCopy:
+            if (FData.Count == 1) Animate->CommonAVI = aviCopyFile;
+              else Animate->CommonAVI = aviCopyFiles;
+            break;
+
+          case foDelete:
+            Animate->CommonAVI = (DeleteToRecycleBin ? aviRecycleFile : aviDeleteFile);
+            break;
+
+          case foSetProperties:
+          case foGetProperties:
+            ShellModule = SafeLoadLibrary(L"shell32.dll");
+            if (!ShellModule)
+            {
+              Abort();
+            }
+            // workaround, VCL is not able to set both ResId and ResHandle otherwise
+            Animate->Active = false;
+            Animate->ResHandle = 0;
+            Animate->ComponentState << csLoading;
+            Animate->ResId = 165;
+            Animate->ResHandle = ShellModule;
+            Animate->ComponentState >> csLoading;
+            Animate->Active = true;
+            break;
+
+          default:
+            assert(FData.Operation == foCustomCommand ||
+              FData.Operation == foCalculateSize ||
+              FData.Operation == foCalculateChecksum);
+            Animate->CommonAVI = aviNone;
+            AVisible = false;
+        }
       }
+      catch (...)
+      {
+        AVisible = false;
+      };
     }
-    catch (...)
+    else
     {
+      Animate->CommonAVI = aviNone;
       AVisible = false;
-    };
+    }
 
     int Delta = 0;
     if (AVisible && !Animate->Visible) Delta = Animate->Height;
@@ -173,7 +182,6 @@ void __fastcall TProgressForm::UpdateControls()
 
     MainPanel->Top = MainPanel->Top + Delta;
     TransferPanel->Top = TransferPanel->Top + Delta;
-    SpeedPanel->Top = SpeedPanel->Top + Delta;
     Animate->Visible = AVisible;
     Animate->Active = AVisible;
 
@@ -181,7 +189,9 @@ void __fastcall TProgressForm::UpdateControls()
       else
     if (!TransferOperation && TransferPanel->Visible) Delta += -TransferPanel->Height;
     TransferPanel->Visible = TransferOperation;
-    SpeedPanel->Visible = TransferOperation;
+    // when animation is hidden for transfers (on wine) speed panel does not fit,
+    // so we hide it (temporary solution before window redesign)
+    SpeedPanel->Visible = TransferOperation && AVisible;
 
     ClientHeight = ClientHeight + Delta;
 

+ 1 - 1
source/forms/ScpCommander.cpp

@@ -1774,7 +1774,7 @@ void __fastcall TScpCommanderForm::LocalPathComboUpdateDrives()
     Strings->Clear();
     FLocalPathComboBoxPaths->Clear();
     Strings->Add(LoadStr(SPECIAL_FOLDER_MY_DOCUMENTS));
-    FLocalPathComboBoxPaths->AddObject(DriveInfo->SpecialFolder[CSIDL_PERSONAL]->Location,
+    FLocalPathComboBoxPaths->AddObject(GetPersonalFolder(),
       (TObject *)DriveInfo->SpecialFolder[CSIDL_PERSONAL]->ImageIndex);
     Strings->Add(LoadStr(SPECIAL_FOLDER_DESKTOP));
     FLocalPathComboBoxPaths->AddObject(DriveInfo->SpecialFolder[CSIDL_DESKTOP]->Location,

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

@@ -531,6 +531,7 @@ begin
     end;
 
     FDisplayPath := FDisplayPath + Separator;
+    S := S + Separator;
 
     WidthMask := Canvas.TextWidth(FDisplayMask);
     if WidthMask > Width div 3 then
@@ -582,7 +583,7 @@ begin
     (WidthPath + WidthMask > Width);
 
   if not ShowHint then Hint := ''
-    else Hint := S + Separator + Mask;
+    else Hint := S + Mask;
 
   Str := FDisplayPath + FDisplayMask;
   if not Enabled then

+ 3 - 1
source/putty/SSH.C

@@ -2563,7 +2563,9 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
     if (conf_get_int(ssh->conf, CONF_sshbug_rsapad2) == FORCE_ON ||
 	(conf_get_int(ssh->conf, CONF_sshbug_rsapad2) == AUTO &&
 	 (wc_match("OpenSSH_2.[5-9]*", imp) ||
-	  wc_match("OpenSSH_3.[0-2]*", imp)))) {
+ 	  wc_match("OpenSSH_3.[0-2]*", imp) ||
+ 	  wc_match("mod_sftp/0.[0-8]*", imp) ||
+ 	  wc_match("mod_sftp/0.9.[0-8]", imp)))) {
 	/*
 	 * These versions have the SSH-2 RSA padding bug.
 	 */

+ 1 - 1
source/resource/TextsCore.h

@@ -210,7 +210,6 @@
 #define CERT_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 284
 #define CERT_ERR_UNKNOWN        285
 #define CERT_ERRDEPTH           286
-#define CERT_OK                 287
 #define MASK_ERROR              288
 #define FTP_CANNOT_OPEN_ACTIVE_CONNECTION2 289
 #define DELETE_LOCAL_FILE_ERROR 290
@@ -224,6 +223,7 @@
 #define REPORT_ERROR            298
 #define TLS_CERT_DECODE_ERROR   299
 #define FIND_FILE_ERROR         700
+#define CERT_NAME_MISMATCH      701
 
 #define CORE_CONFIRMATION_STRINGS 300
 #define CONFIRM_PROLONG_TIMEOUT3 301

+ 3 - 3
source/resource/TextsCore1.rc

@@ -174,8 +174,7 @@ BEGIN
   CERT_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, "Unable to get local issuer certificate."
   CERT_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, "Unable to verify the first certificate."
   CERT_ERR_UNKNOWN, "Unknown certificate verification error."
-  CERT_ERRDEPTH, "The error occured at a depth of %d in the certificate chain."
-  CERT_OK, "The certificate seems to be valid."
+  CERT_ERRDEPTH, "The error occurred at a depth of %d in the certificate chain."
   MASK_ERROR, "Mask is invalid near '%s'."
   FTP_CANNOT_OPEN_ACTIVE_CONNECTION2, "The server cannot open connection in active mode. If you are behind a NAT router, you may need to specify an external IP address. Alternatively, consider switching to passive mode."
   DELETE_LOCAL_FILE_ERROR, "Error deleting file '%s'."
@@ -189,6 +188,7 @@ BEGIN
   REPORT_ERROR, "%s\n\nPlease help us improving WinSCP by reporting the error on WinSCP support forum."
   TLS_CERT_DECODE_ERROR, "Error decoding TLS/SSL certificate (%s)."
   FIND_FILE_ERROR, "Error retrieving file list for \"%s\"."
+  CERT_NAME_MISMATCH, "Certificate was not issued for this server. You might be connecting to a server that is pretending to be \"%s\"."
 
   CORE_CONFIRMATION_STRINGS, "CORE_CONFIRMATION"
   CONFIRM_PROLONG_TIMEOUT3, "Host is not communicating for %d seconds.\n\nWait for another %0:d seconds?"
@@ -372,7 +372,7 @@ BEGIN
   FILEZILLA_URL, "http://filezilla-project.org/"
   OPENSSL_BASED_ON, "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s."
   OPENSSL_COPYRIGHT, "Copyright © 1998-2014 The OpenSSL Project"
-  OPENSSL_VERSION, "1.0.1f"
+  OPENSSL_VERSION, "1.0.1g"
   OPENSSL_URL, "http://www.openssl.org/"
   PUTTY_LICENSE_URL, "http://www.chiark.greenend.org.uk/~sgtatham/putty/licence.html"
   MAIN_MSG_TAG, "**"

+ 1 - 1
source/resource/TextsWin1.rc

@@ -139,7 +139,7 @@ BEGIN
         BOOKMARK_INFO_TIP, "Local: %s\nRemote: %s"
         CUSTOM_COMMAND_TOUCH, "&Touch"
         CUSTOM_COMMAND_EXECUTE, "&Execute"
-        ERROR_LIST_COUNT, "%d error(s) occured during last operation. Do you want to see it/them?"
+        ERROR_LIST_COUNT, "%d error(s) occurred during last operation. Do you want to see it/them?"
         ERROR_LIST_NUMBER, "Error %d of %d:\n%s"
         NO_NEW_VERSION, "You have the latest version."
         NEW_VERSION4, "New version %s was released."

+ 34 - 1
source/windows/GUITools.cpp

@@ -259,6 +259,39 @@ bool __fastcall SpecialFolderLocation(int PathID, UnicodeString & Path)
   return false;
 }
 //---------------------------------------------------------------------------
+UnicodeString __fastcall GetPersonalFolder()
+{
+  UnicodeString Result;
+  SpecialFolderLocation(CSIDL_PERSONAL, Result);
+
+  if (IsWine())
+  {
+    UnicodeString WineHostHome = GetEnvironmentVariable(L"WINE_HOST_HOME");
+    if (!WineHostHome.IsEmpty())
+    {
+      UnicodeString WineHome = L"Z:" + ToUnixPath(WineHostHome);
+      if (DirectoryExists(WineHome))
+      {
+        Result = WineHome;
+      }
+    }
+    else
+    {
+      // Should we use WinAPI GetUserName() instead?
+      UnicodeString UserName = GetEnvironmentVariable(L"USERNAME");
+      if (!UserName.IsEmpty())
+      {
+        UnicodeString WineHome = L"Z:\\home\\" + UserName;
+        if (DirectoryExists(WineHome))
+        {
+          Result = WineHome;
+        }
+      }
+    }
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 UnicodeString __fastcall ItemsFormatString(const UnicodeString SingleItemFormat,
   const UnicodeString MultiItemsFormat, int Count, const UnicodeString FirstItem)
 {
@@ -311,7 +344,7 @@ UnicodeString __fastcall UniqTempDir(const UnicodeString BaseDir, const UnicodeS
     {
       TempDir += IncludeTrailingBackslash(FormatDateTime(L"nnzzz", Now()));
     };
-  }
+    }
   while (!Mask && DirectoryExists(TempDir));
 
   return TempDir;

+ 1 - 0
source/windows/GUITools.h

@@ -30,6 +30,7 @@ bool __fastcall ExecuteShellAndWait(HWND Handle, const UnicodeString Command,
 void __fastcall OpenSessionInPutty(const UnicodeString PuttyPath,
   TSessionData * SessionData, UnicodeString UserName, UnicodeString Password);
 bool __fastcall SpecialFolderLocation(int PathID, UnicodeString & Path);
+UnicodeString __fastcall GetPersonalFolder();
 UnicodeString __fastcall ItemsFormatString(const UnicodeString SingleItemFormat,
   const UnicodeString MultiItemsFormat, int Count, const UnicodeString FirstItem);
 UnicodeString __fastcall ItemsFormatString(const UnicodeString SingleItemFormat,

+ 36 - 27
source/windows/Setup.cpp

@@ -763,6 +763,37 @@ UnicodeString __fastcall GetUsageData()
   return Configuration->Usage->Serialize();
 }
 //---------------------------------------------------------------------------
+static UnicodeString __fastcall WantBetaUrl(UnicodeString URL, bool Force)
+{
+  bool Beta;
+  if (WinConfiguration->IsBeta)
+  {
+    Beta = true;
+  }
+  else
+  {
+    switch (WinConfiguration->Updates.BetaVersions)
+    {
+      case asAuto:
+        Beta = WinConfiguration->AnyBetaInVersionHistory;
+        break;
+
+      case asOn:
+        Beta = true;
+        break;
+
+      default:
+        Beta = false;
+        break;
+    }
+  }
+  if (Beta || Force)
+  {
+    URL = AppendUrlParams(URL, FORMAT(L"beta=%d", (Beta ? 1 : 0)));
+  }
+  return URL;
+}
+//---------------------------------------------------------------------------
 void __fastcall QueryUpdates()
 {
   bool Complete = false;
@@ -784,32 +815,7 @@ void __fastcall QueryUpdates()
       UnicodeString URL = LoadStr(UPDATES_URL) +
         FORMAT(L"?v=%s&lang=%s", (CurrentVersionStr,
           IntToHex(__int64(GUIConfiguration->Locale), 4)));
-      bool Beta;
-      if (WinConfiguration->IsBeta)
-      {
-        Beta = true;
-      }
-      else
-      {
-        switch (Updates.BetaVersions)
-        {
-          case asAuto:
-            Beta = WinConfiguration->AnyBetaInVersionHistory;
-            break;
-
-          case asOn:
-            Beta = true;
-            break;
-
-          default:
-            Beta = false;
-            break;
-        }
-      }
-      if (Beta)
-      {
-        URL += L"&beta=1";
-      }
+      URL = WantBetaUrl(URL, false);
       URL += L"&dotnet=" + Updates.DotNetVersion;
       URL += L"&console=" + Updates.ConsoleVersion;
       UnicodeString Proxy;
@@ -1099,7 +1105,10 @@ void __fastcall CheckForUpdates(bool CachedResults)
           if (New)
           {
             Configuration->Usage->Inc(L"UpdateDownloadOpens");
-            OpenBrowser(LoadStr(UPGRADE_URL));
+            UnicodeString UpgradeUrl = LoadStr(UPGRADE_URL);
+            UpgradeUrl = WantBetaUrl(UpgradeUrl, true);
+            UpgradeUrl = AppendUrlParams(UpgradeUrl, FORMAT(L"to=%s", (VersionStrFromCompoundVersion(Updates.Results.Version))));
+            OpenBrowser(UpgradeUrl);
           }
           break;
 

+ 9 - 3
source/windows/TerminalManager.cpp

@@ -650,7 +650,11 @@ void __fastcall TTerminalManager::UpdateAppTitle()
     }
 
     UnicodeString QueueProgressTitle;
-    if (!FProgressTitle.IsEmpty() && !ForegroundTask())
+    if (!FForegroundProgressTitle.IsEmpty())
+    {
+      NewTitle = FForegroundProgressTitle + L" - " + NewTitle;
+    }
+    else if (!FProgressTitle.IsEmpty() && !ForegroundTask())
     {
       NewTitle = FProgressTitle + L" - " + NewTitle;
     }
@@ -1013,9 +1017,10 @@ void __fastcall TTerminalManager::TerminalReadDirectoryProgress(
       ScpExplorer->LockWindow();
     }
     FDirectoryReadingStart = Now();
-    if (!FProgressTitle.IsEmpty())
+    if (!FProgressTitle.IsEmpty() || !FForegroundProgressTitle.IsEmpty())
     {
       FProgressTitle = L"";
+      FForegroundProgressTitle = L"";
       UpdateAppTitle();
     }
 
@@ -1040,6 +1045,7 @@ void __fastcall TTerminalManager::TerminalReadDirectoryProgress(
       }
 
       FProgressTitle = L"";
+      FForegroundProgressTitle = L"";
       UpdateAppTitle();
     }
   }
@@ -1055,7 +1061,7 @@ void __fastcall TTerminalManager::TerminalReadDirectoryProgress(
 
     if ((Now() - FDirectoryReadingStart) >= DirectoryReadingProgressDelay)
     {
-      FProgressTitle = FMTLOAD(DIRECTORY_READING_PROGRESS, (Progress));
+      FForegroundProgressTitle = FMTLOAD(DIRECTORY_READING_PROGRESS, (Progress));
       UpdateAppTitle();
     }
   }

+ 1 - 0
source/windows/TerminalManager.h

@@ -91,6 +91,7 @@ private:
   TList * FQueues;
   TStrings * FTerminationMessages;
   UnicodeString FProgressTitle;
+  UnicodeString FForegroundProgressTitle;
   TDateTime FDirectoryReadingStart;
   TAuthenticateForm * FAuthenticateForm;
   TCriticalSection * FQueueSection;

+ 6 - 1
source/windows/Tools.cpp

@@ -276,11 +276,16 @@ bool __fastcall ExecuteShellAndWait(const UnicodeString Command)
     &Application->ProcessMessages);
 }
 //---------------------------------------------------------------------------
-bool __fastcall OpenInNewWindow()
+bool __fastcall UseAlternativeFunction()
 {
   return FLAGSET(GetAsyncKeyState(VK_SHIFT), 0x8000);
 }
 //---------------------------------------------------------------------------
+bool __fastcall OpenInNewWindow()
+{
+  return UseAlternativeFunction();
+}
+//---------------------------------------------------------------------------
 void __fastcall ExecuteNewInstance(const UnicodeString & Param)
 {
   UnicodeString Arg = Param;

+ 1 - 0
source/windows/Tools.h

@@ -11,6 +11,7 @@
 void __fastcall CenterFormOn(TForm * Form, TControl * CenterOn);
 bool __fastcall ExecuteShellAndWait(const UnicodeString Path, const UnicodeString Params);
 bool __fastcall ExecuteShellAndWait(const UnicodeString Command);
+bool __fastcall UseAlternativeFunction();
 bool __fastcall OpenInNewWindow();
 void __fastcall ExecuteNewInstance(const UnicodeString & Param);
 IShellLink * __fastcall CreateDesktopShortCut(const UnicodeString &Name,

+ 4 - 0
source/windows/UserInterface.cpp

@@ -23,6 +23,7 @@
 #include "Custom.h"
 #include "HelpWin.h"
 #include <Math.hpp>
+#include <GUITools.h>
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
 //---------------------------------------------------------------------------
@@ -273,6 +274,9 @@ void __fastcall ConfigureInterface()
   {
     TBXSetTheme(WinConfiguration->Theme);
   }
+  // Has any effect on Wine only
+  // (otherwise initial UserDocumentDirectory is equivalent to GetPersonalFolder())
+  UserDocumentDirectory = GetPersonalFolder();
 }
 //---------------------------------------------------------------------------
 // dummy function to force linking of TBXOfficeXPTheme.pas

+ 1 - 3
source/windows/WinConfiguration.cpp

@@ -552,9 +552,7 @@ void __fastcall TWinConfiguration::Default()
     PixelsPerInchToolbarValue;
   FScpExplorer.SessionsTabs = true;
   FScpExplorer.StatusBar = true;
-  UnicodeString PersonalFolder;
-  ::SpecialFolderLocation(CSIDL_PERSONAL, PersonalFolder);
-  FScpExplorer.LastLocalTargetDirectory = PersonalFolder;
+  FScpExplorer.LastLocalTargetDirectory = GetPersonalFolder();
   FScpExplorer.ViewStyle = 0; /* vsIcon */
   FScpExplorer.ShowFullAddress = true;
   FScpExplorer.DriveView = true;

+ 2 - 7
source/windows/WinMain.cpp

@@ -110,7 +110,7 @@ void __fastcall Download(TTerminal * Terminal, const UnicodeString FileName,
     UnicodeString LocalDirectory = ExpandFileName(Terminal->SessionData->LocalDirectory);
     if (LocalDirectory.IsEmpty())
     {
-      ::SpecialFolderLocation(CSIDL_PERSONAL, LocalDirectory);
+      LocalDirectory = GetPersonalFolder();
     }
     TargetDirectory = IncludeTrailingBackslash(LocalDirectory);
 
@@ -321,12 +321,7 @@ void __fastcall UpdateStaticUsage()
   UnicodeString ExeName = ExpandFileName(Application->ExeName);
   bool InProgramFiles = AnsiSameText(ExeName.SubString(1, ProgramsFolder.Length()), ProgramsFolder);
   Configuration->Usage->Set(L"InProgramFiles", InProgramFiles);
-
-  HMODULE NtDll = GetModuleHandle(L"ntdll.dll");
-  bool Wine =
-    ALWAYS_TRUE(NtDll != NULL) &&
-    (GetProcAddress(NtDll, "wine_get_version") != NULL);
-  Configuration->Usage->Set(L"Wine", Wine);
+  Configuration->Usage->Set(L"Wine", IsWine());
 
   WinConfiguration->UpdateStaticUsage();