summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog.txt11
-rw-r--r--FreeFileSync/Source/afs/native.cpp1
-rw-r--r--FreeFileSync/Source/base/synchronization.cpp16
-rw-r--r--FreeFileSync/Source/ui/progress_indicator.cpp21
-rw-r--r--FreeFileSync/Source/ui/sync_cfg.cpp4
-rw-r--r--FreeFileSync/Source/version/version.h2
-rw-r--r--zen/open_ssl.cpp36
-rw-r--r--zen/resolve_path.cpp11
-rw-r--r--zen/resolve_path.h7
9 files changed, 60 insertions, 49 deletions
diff --git a/Changelog.txt b/Changelog.txt
index 5b48fa6c..b6984b1d 100644
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -1,4 +1,13 @@
-FreeFileSync 11.13 [2021-08-07]
+FreeFileSync 11.14 [2021-09-20]
+-------------------------------
+Authenticate (S)FTP connections using OpenSSL 3.0
+Fixed E_NOINTERFACE error after synchronization
+Preempt crashes due to Nahimic Sonic Studio 3
+Hide main window when minimizing progress window (macOS)
+Avoid second dock icon when minimizing progress window (macOS)
+
+
+FreeFileSync 11.13 [2021-08-17]
-------------------------------
Manage default filter settings via GUI
Support arbitrary location for local app installation (macOS)
diff --git a/FreeFileSync/Source/afs/native.cpp b/FreeFileSync/Source/afs/native.cpp
index e4285d66..2551234a 100644
--- a/FreeFileSync/Source/afs/native.cpp
+++ b/FreeFileSync/Source/afs/native.cpp
@@ -732,6 +732,7 @@ bool fff::acceptsItemPathPhraseNative(const Zstring& itemPathPhrase) //noexcept
AbstractPath fff::createItemPathNative(const Zstring& itemPathPhrase) //noexcept
{
+ warn_static("reevaluate")
//TODO: get volume by name hangs for idle HDD! => run createItemPathNative during getFolderStatusNonBlocking() but getResolvedFilePath currently not thread-safe!
const Zstring& itemPath = getResolvedFilePath(itemPathPhrase);
return createItemPathNativeNoFormatting(itemPath);
diff --git a/FreeFileSync/Source/base/synchronization.cpp b/FreeFileSync/Source/base/synchronization.cpp
index 1a7aa58c..41a0eeab 100644
--- a/FreeFileSync/Source/base/synchronization.cpp
+++ b/FreeFileSync/Source/base/synchronization.cpp
@@ -256,15 +256,13 @@ void SyncStatistics::processFolder(const FolderPair& folder)
}
-/*
- DeletionPolicy::permanent: deletion frees space
- DeletionPolicy::recycler: won't free space until recycler is full, but then frees space
- DeletionPolicy::versioning: depends on whether versioning folder is on a different volume
--> if deleted item is a followed symlink, no space is freed
--> created/updated/deleted item may be on a different volume than base directory: consider symlinks, junctions!
-
-=> generally assume deletion frees space; may avoid false-positive disk space warnings for recycler and versioning
-*/
+/* DeletionPolicy::permanent: deletion frees space
+ DeletionPolicy::recycler: won't free space until recycler is full, but then frees space
+ DeletionPolicy::versioning: depends on whether versioning folder is on a different volume
+ -> if deleted item is a followed symlink, no space is freed
+ -> created/updated/deleted item may be on a different volume than base directory: consider symlinks, junctions!
+
+ => generally assume deletion frees space; may avoid false-positive disk space warnings for recycler and versioning */
class MinimumDiskSpaceNeeded
{
public:
diff --git a/FreeFileSync/Source/ui/progress_indicator.cpp b/FreeFileSync/Source/ui/progress_indicator.cpp
index ad67effd..b772009d 100644
--- a/FreeFileSync/Source/ui/progress_indicator.cpp
+++ b/FreeFileSync/Source/ui/progress_indicator.cpp
@@ -1558,8 +1558,7 @@ void SyncProgressDialogImpl<TopLevelDialog>::onPause(wxCommandEvent& event)
template <class TopLevelDialog>
void SyncProgressDialogImpl<TopLevelDialog>::onIconize(wxIconizeEvent& event)
{
- /*
- propagate progress dialog minimize/maximize to parent
+ /* propagate progress dialog minimize/maximize to parent
-----------------------------------------------------
Fedora/Debian/Ubuntu:
- wxDialog cannot be minimized
@@ -1573,15 +1572,13 @@ void SyncProgressDialogImpl<TopLevelDialog>::onIconize(wxIconizeEvent& event)
- probably the same issues with stray iconize events like Fedora/Debian/Ubuntu
- minimize button is always shown, even if wxMINIMIZE_BOX is omitted!
=> nothing to do
- Mac OS X:
- - wxDialog can be minimized and automatically minimizes parent
- - no iconize events seen by wxWidgets!
- => nothing to do
+ macOS:
+ - wxDialog can be minimized but does not also minimize parent
+ => propagate event to parent
Windows:
- wxDialog can be minimized but does not also minimize parent
- iconize events only seen for manual minimize
- => propagate event to parent
- */
+ => propagate event to parent */
event.Skip();
}
@@ -1651,10 +1648,14 @@ SyncProgressDialog* SyncProgressDialog::create(wxSize dlgSize, bool dlgMaximize,
{
if (parentWindow) //sync from GUI
{
- //due to usual "wxBugs", wxDialog on OS X does not float on its parent; wxFrame OTOH does => hack!
- //https://groups.google.com/forum/#!topic/wx-users/J5SjjLaBOQE
+#if 0 //macOS; update 08-2021: Bug seems to be fixed!?
+ //due to usual "wxBugs", wxDialog on OS X does not float on its parent; wxFrame OTOH does => hack! https://groups.google.com/forum/#!topic/wx-users/J5SjjLaBOQE
+ return new SyncProgressDialogImpl<wxFrame>(wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT,
+ dlgSize, dlgMaximize, userRequestAbort, syncStat, parentWindow, showProgress, autoCloseDialog, jobNames, syncStartTime, ignoreErrors, autoRetryCount, postSyncAction);
+#else //GNOME bug: wxDialog seems to ignore wxMAXIMIZE_BOX | wxMINIMIZE_BOX! :( wxFrame OTOH has them, but adds an extra taskbar entry
return new SyncProgressDialogImpl<wxDialog>(wxDEFAULT_DIALOG_STYLE | wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxRESIZE_BORDER,
dlgSize, dlgMaximize, userRequestAbort, syncStat, parentWindow, showProgress, autoCloseDialog, jobNames, syncStartTime, ignoreErrors, autoRetryCount, postSyncAction);
+#endif
}
else //FFS batch job
{
diff --git a/FreeFileSync/Source/ui/sync_cfg.cpp b/FreeFileSync/Source/ui/sync_cfg.cpp
index d7e36f8e..81359450 100644
--- a/FreeFileSync/Source/ui/sync_cfg.cpp
+++ b/FreeFileSync/Source/ui/sync_cfg.cpp
@@ -46,7 +46,9 @@ void initBitmapRadioButtons(const std::vector<std::pair<ToggleButton*, std::stri
auto generateSelectImage = [physicalLeft](wxButton& btn, const std::string& imgName, bool selected)
{
- wxImage imgTxt = createImageFromText(btn.GetLabel(), btn.GetFont(), btn.GetForegroundColour());
+ wxImage imgTxt = createImageFromText(btn.GetLabel(), btn.GetFont(),
+ selected ? *wxBLACK : //accessibility: always set both foreground AND background colors! see renderSelectedButton()
+ btn.GetForegroundColour());
wxImage imgIco = mirrorIfRtl(loadImage(imgName, -1 /*maxWidth*/, getDefaultMenuIconSize()));
diff --git a/FreeFileSync/Source/version/version.h b/FreeFileSync/Source/version/version.h
index 692ce6bc..6c2e91e9 100644
--- a/FreeFileSync/Source/version/version.h
+++ b/FreeFileSync/Source/version/version.h
@@ -3,7 +3,7 @@
namespace fff
{
-const char ffsVersion[] = "11.13"; //internal linkage!
+const char ffsVersion[] = "11.14"; //internal linkage!
const char FFS_VERSION_SEPARATOR = '.';
}
diff --git a/zen/open_ssl.cpp b/zen/open_ssl.cpp
index 7c94263a..e875351c 100644
--- a/zen/open_ssl.cpp
+++ b/zen/open_ssl.cpp
@@ -179,9 +179,9 @@ std::shared_ptr<EVP_PKEY> streamToKey(const std::string& keyStream, RsaStreamTyp
//================================================================================
-using EvpToBioFunc = int (*)(BIO* bio, EVP_PKEY* evp);
+using EvpToBioFunc = int (*)(BIO* bio, const EVP_PKEY* evp);
-std::string evpKeyToStream(EVP_PKEY* evp, EvpToBioFunc evpToBio, const char* functionName) //throw SysError
+std::string evpKeyToStream(const EVP_PKEY* evp, EvpToBioFunc evpToBio, const char* functionName) //throw SysError
{
BIO* bio = ::BIO_new(BIO_s_mem());
if (!bio)
@@ -205,16 +205,16 @@ std::string evpKeyToStream(EVP_PKEY* evp, EvpToBioFunc evpToBio, const char* fun
}
-using RsaToBioFunc = int (*)(BIO* bp, RSA* x);
+using RsaToBioFunc = int (*)(BIO* bp, const RSA* x);
-std::string evpKeyToStream(EVP_PKEY* evp, RsaToBioFunc rsaToBio, const char* functionName) //throw SysError
+std::string evpKeyToStream(const EVP_PKEY* evp, RsaToBioFunc rsaToBio, const char* functionName) //throw SysError
{
BIO* bio = ::BIO_new(BIO_s_mem());
if (!bio)
throw SysError(formatLastOpenSSLError("BIO_new"));
ZEN_ON_SCOPE_EXIT(::BIO_free_all(bio));
- RSA* rsa = ::EVP_PKEY_get0_RSA(evp); //unowned reference!
+ const RSA* rsa = ::EVP_PKEY_get0_RSA(evp); //unowned reference!
if (!rsa)
throw SysError(formatLastOpenSSLError("EVP_PKEY_get0_RSA"));
@@ -236,33 +236,33 @@ std::string evpKeyToStream(EVP_PKEY* evp, RsaToBioFunc rsaToBio, const char* fun
//fix OpenSSL API inconsistencies:
-int PEM_write_bio_PrivateKey2(BIO* bio, EVP_PKEY* key)
+int PEM_write_bio_PrivateKey2(BIO* bio, const EVP_PKEY* key)
{
return ::PEM_write_bio_PrivateKey(bio, //BIO* bp
- key, //EVP_PKEY* x
+ key, //const EVP_PKEY* x
nullptr, //const EVP_CIPHER* enc
- nullptr, //unsigned char* kstr
+ nullptr, //const unsigned char* kstr
0, //int klen
nullptr, //pem_password_cb* cb
nullptr); //void* u
}
-int PEM_write_bio_RSAPrivateKey2(BIO* bio, RSA* rsa)
+int PEM_write_bio_RSAPrivateKey2(BIO* bio, const RSA* rsa)
{
return ::PEM_write_bio_RSAPrivateKey(bio, //BIO* bp
- rsa, //RSA* x
+ rsa, //const RSA* x
nullptr, //const EVP_CIPHER* enc
- nullptr, //unsigned char* kstr
+ nullptr, //const unsigned char* kstr
0, //int klen
nullptr, //pem_password_cb* cb
nullptr); //void* u
}
-int PEM_write_bio_RSAPublicKey2(BIO* bio, RSA* rsa) { return ::PEM_write_bio_RSAPublicKey(bio, rsa); }
+int PEM_write_bio_RSAPublicKey2(BIO* bio, const RSA* rsa) { return ::PEM_write_bio_RSAPublicKey(bio, rsa); }
//--------------------------------------------------------------------------------
-std::string keyToStream(EVP_PKEY* evp, RsaStreamType streamType, bool publicKey) //throw SysError
+std::string keyToStream(const EVP_PKEY* evp, RsaStreamType streamType, bool publicKey) //throw SysError
{
switch (streamType)
{
@@ -571,15 +571,15 @@ public:
if (sslError == SSL_ERROR_ZERO_RETURN)
return 0; //EOF + close_notify alert
-#if OPENSSL_VERSION_NUMBER == 0x1010105fL //OpenSSL 1.1.1e
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L /*OpenSSL 3.0.0*/ || \
+ OPENSSL_VERSION_NUMBER == 0x1010105fL /*OpenSSL 1.1.1e*/
const auto ec = ::ERR_peek_last_error();
if (sslError == SSL_ERROR_SSL && ERR_GET_REASON(ec) == SSL_R_UNEXPECTED_EOF_WHILE_READING) //EOF: only expected for HTTP/1.0
- return 0;
-#else //obsolete handling, at least in OpenSSL 1.1.1e (but valid again with OpenSSL 1.1.1f!)
- //https://github.com/openssl/openssl/issues/10880#issuecomment-575746226
+#else //obsolete handling: https://github.com/openssl/openssl/issues/10880#issuecomment-575746226
if ((sslError == SSL_ERROR_SYSCALL && ::ERR_peek_last_error() == 0)) //EOF: only expected for HTTP/1.0
- return 0;
#endif
+ return 0;
+
throw SysError(formatLastOpenSSLError("SSL_read_ex") + L' ' + getSslErrorLiteral(sslError));
}
assert(bytesReceived > 0); //SSL_read_ex() considers EOF an error!
diff --git a/zen/resolve_path.cpp b/zen/resolve_path.cpp
index 0e714528..4eab76ee 100644
--- a/zen/resolve_path.cpp
+++ b/zen/resolve_path.cpp
@@ -41,10 +41,14 @@ std::optional<Zstring> getEnvironmentVar(const Zstring& name)
Zstring resolveRelativePath(const Zstring& relativePath)
{
- assert(runningOnMainThread()); //GetFullPathName() is documented to NOT be thread-safe!
+ assert(runningOnMainThread());
/* MSDN: "Multithreaded applications and shared library code should not use the GetFullPathName function
- and should avoid using relative path names.
- The current directory state written by the SetCurrentDirectory function is stored as a global variable in each process, */
+ and should avoid using relative path names. The current directory state written by the
+ SetCurrentDirectory function is stored as a global variable in each process,
+ therefore multithreaded applications cannot reliably use this value without possible data corruption from other threads, [...]"
+
+ => Just plain wrong, there is no data corruption. What MSDN really means: GetFullPathName() is *perfectly* thread-safe, but depends
+ on the current directory, which is a process-scope global: https://devblogs.microsoft.com/oldnewthing/20210816-00/?p=105562 */
if (relativePath.empty())
return relativePath;
@@ -268,7 +272,6 @@ Zstring zen::getResolvedFilePath(const Zstring& pathPhrase) //noexcept
- \\?\-prefix requires absolute names
- Volume Shadow Copy: volume name needs to be part of each file path
- file icon buffer (at least for extensions that are actually read from disk, like "exe")
- - Use of relative path names is not thread safe! (e.g. SHFileOperation)
WINDOWS/LINUX:
- detection of dependent directories, e.g. "\" and "C:\test" */
path = resolveRelativePath(path);
diff --git a/zen/resolve_path.h b/zen/resolve_path.h
index f2c427f1..4a5fc8fe 100644
--- a/zen/resolve_path.h
+++ b/zen/resolve_path.h
@@ -13,15 +13,12 @@
namespace zen
{
-/*
- - expand macros
+/* - expand macros
- trim whitespace
- expand volume path by name
- convert relative paths into absolute
- => may block for slow USB sticks and idle HDDs
- => not thread-safe, see ::GetFullPathName()!
-*/
+ => may block for slow USB sticks and idle HDDs */
Zstring getResolvedFilePath(const Zstring& pathPhrase); //noexcept
//macro substitution only
bgstack15