From ca250bf14979d359a82d5baf11ae9587d5605594 Mon Sep 17 00:00:00 2001 From: B Stack Date: Tue, 17 Sep 2019 08:06:14 -0400 Subject: add upstream 10.16 --- Bugs.txt | 175 ++++++--- Changelog.txt | 22 ++ FreeFileSync/Build/Resources/Icons.zip | Bin 288396 -> 338833 bytes FreeFileSync/Build/Resources/Languages/german.lng | 120 +++--- FreeFileSync/Build/Resources/cacert.pem | 35 +- FreeFileSync/Source/afs/abstract.h | 1 + FreeFileSync/Source/afs/ftp.cpp | 429 ++++++++++++---------- FreeFileSync/Source/afs/gdrive.cpp | 129 +++---- FreeFileSync/Source/afs/libcurl/curl_wrap.h | 9 +- FreeFileSync/Source/afs/sftp.cpp | 109 +++--- FreeFileSync/Source/base/db_file.cpp | 22 +- FreeFileSync/Source/base/dir_lock.cpp | 48 ++- FreeFileSync/Source/base/dir_lock.h | 10 +- FreeFileSync/Source/base/lock_holder.h | 11 +- FreeFileSync/Source/base/parallel_scan.cpp | 4 +- FreeFileSync/Source/base/resolve_path.cpp | 3 +- FreeFileSync/Source/base/synchronization.cpp | 2 +- FreeFileSync/Source/ui/gui_generated.cpp | 117 +++++- FreeFileSync/Source/ui/gui_generated.h | 41 +++ FreeFileSync/Source/ui/main_dlg.cpp | 1 + FreeFileSync/Source/ui/progress_indicator.cpp | 82 +++-- FreeFileSync/Source/ui/small_dlgs.cpp | 60 ++- FreeFileSync/Source/ui/small_dlgs.h | 2 + FreeFileSync/Source/version/version.h | 2 +- wx+/dc.h | 25 +- wx+/graph.cpp | 16 +- wx+/graph.h | 8 +- zen/http.cpp | 97 ++++- zen/http.h | 1 + zen/json.h | 101 ++--- zen/shell_execute.h | 2 +- zen/zlib_wrap.cpp | 44 ++- zen/zlib_wrap.h | 33 +- zenXml/zenxml/parser.h | 46 +-- 34 files changed, 1113 insertions(+), 694 deletions(-) diff --git a/Bugs.txt b/Bugs.txt index 1cec865e..551614a0 100755 --- a/Bugs.txt +++ b/Bugs.txt @@ -2,22 +2,72 @@ When manually compiling FreeFileSync, you should also fix the following bugs in ---------------- -| libssh2 Bugs | +| libcurl Bugs | ---------------- __________________________________________________________________________________________________________ -Amazons SFTP server returns legitimate package sizes of ~100kb! -https://freefilesync.org/forum/viewtopic.php?t=5999 +/lib/setopt.c +https://github.com/curl/curl/pull/4321 -/src/sftp.c: +- if ((arg < CURLFTPMETHOD_DEFAULT) || (arg > CURLFTPMETHOD_SINGLECWD)) ++ if ((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST)) -- #define LIBSSH2_SFTP_PACKET_MAXLEN 80000 -+ #define LIBSSH2_SFTP_PACKET_MAXLEN 160000 __________________________________________________________________________________________________________ +https://github.com/curl/curl/pull/4331 +/include/curl/curl.h + + CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ ++ CURLFTPMETHOD_FULLPATH, //AKA "CURLFTPMETHOD_NOCWD_BUT_THIS_TIME_FOR_REAL" + + +/lib/ftp.h + + FTPFILE_SINGLECWD = 3 /* make one CWD, then SIZE / RETR / STOR on the + file */ ++ FTPFILE_FULLPATH = 4 //AKA "FTPFILE_NOCWD_BUT_THIS_TIME_FOR_REAL" + + +/lib/ftp.c + +- if ((data->set.ftp_filemethod == FTPFILE_NOCWD) && ++ if ((data->set.ftp_filemethod == FTPFILE_NOCWD || ++ data->set.ftp_filemethod == FTPFILE_FULLPATH) && + + ++ if (data->set.ftp_filemethod == FTPFILE_FULLPATH) ++ { ++ //no CWDs happened => remember old working dir ++ //ftpc->prevmethod = ++ //ftpc->prevpath = ++ } ++ else ++ { + /* now store a copy of the directory we are in */ + free(ftpc->prevpath); + + [...] + + else + { + ftpc->prevpath = NULL; /* no path */ + free(path); + } + } + ++ } + + + switch (data->set.ftp_filemethod) + { + case FTPFILE_NOCWD: ++ case FTPFILE_FULLPATH: + + ++ if (data->set.ftp_filemethod == FTPFILE_FULLPATH) ++ ftpc->cwddone = TRUE; ++ else + if (ftpc->prevpath) ----------------- -| libcurl Bugs | ----------------- __________________________________________________________________________________________________________ https://github.com/curl/curl/issues/1455 @@ -51,63 +101,53 @@ Replace with: } if (skipIp) + __________________________________________________________________________________________________________ +/lib/ftp.c +https://github.com/curl/curl/pull/4332 -"wrong dir listing because libcurl remembers wrong CWD": https://github.com/curl/curl/issues/1782 +- else if (conn->bits.reuse && ftpc->entrypath) ++ else if (conn->bits.reuse && ftpc->entrypath && ++ !(ftpc->dirdepth && ftpc->dirs[0][0] == '/')) //no need to go to entrypath when we have an absolute path -=> "fixed" by adding only the "if (data->set.ftp_filemethod == FTPFILE_NOCWD)" below: https://github.com/curl/curl/issues/1811 -=> this is NOT enough! consider what happens for a reused connection that first used CURLFTPMETHOD_MULTICWD, now CURLFTPMETHOD_NOCWD: - - the code in ftp_state_cwd() will issue a CWD sequence that ends with "ftpc->cwdcount == 1"!!! See "if (++ftpc->cwdcount <= ftpc->dirdepth)" - => this skips the previous "fix" in https://github.com/curl/curl/issues/1718 with - if ((conn->data->set.ftp_filemethod == FTPFILE_NOCWD) && !ftpc->cwdcount) +__________________________________________________________________________________________________________ +/lib/ftp.c +https://github.com/curl/curl/pull/4348 -/lib/ftp.c: - if (ftpc->prevpath) - { -+ if (data->set.ftp_filemethod == FTPFILE_NOCWD) -+ { -+ /* -+ CURLFTPMETHOD_NOCWD -+ if the connection is used for the first time, *no* CWD takes place -+ if the connection is reused, ftp_state_cwd() issues a single "CWD ftpc->entrypath" before the operation -+ in both cases ftp_done() sets ftpc->prevpath to "" after a successfull FTP operation -+ ergo: "" corresponds to ftpc->entrypath, so we only ever need CWD if ftpc->prevpath != "" -+ => avoid needless "CWD /" and reduce folder traversal time with CURLFTPMETHOD_NOCWD by 15-20% -+ */ -+ if (strcmp(ftpc->prevpath, "") == 0) -+ { -+ infof(data, "Request has same path (\"%s\") as previous transfer\n", ftpc->prevpath); -+ ftpc->cwddone = TRUE; -+ } -+ } -+ else -+ { - /* prevpath is "raw" so we convert the input path before we compare the - strings */ - size_t dlen; - char* path; - CURLcode result = - Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, FALSE); - if (result) - { - freedirs(ftpc); - return result; - } - - dlen -= ftpc->file?strlen(ftpc->file):0; - if ((dlen == strlen(ftpc->prevpath)) && - !strncmp(path, ftpc->prevpath, dlen) && -- (ftpc->prevmethod == data->set.ftp_filemethod)) -+ true) //(ftpc->prevmethod == data->set.ftp_filemethod)) - { - infof(data, "Request has same path as previous transfer\n"); - ftpc->cwddone = TRUE; - } - free(path); -+ } - } +- size_t n = strlen(inpath); +- /* Check if path does not end with /, as then we cut off the file part */ +- if (inpath[n - 1] != '/') +- { +- /* chop off the file part if format is dir/dir/file */ +- slashPos = strrchr(inpath, '/'); +- n = slashPos - inpath; +- } + ++ /* chop off the file part if format is dir/file ++ otherwise remove the trailing slash for dir/dir/ ++ and full paths like %2f/ except for / */ ++ size_t n = strrchr(inpath, '/') - inpath; ++ if(n == 0) ++ ++n; +__________________________________________________________________________________________________________ + +/lib/vtls/openssl.c +https://github.com/curl/curl/issues/4329 + + case SSL_ERROR_ZERO_RETURN: /* no more data */ +- /* close_notify alert */ +- connclose(conn, "TLS close_notify"); +__________________________________________________________________________________________________________ + + +---------------- +| libssh2 Bugs | +---------------- +__________________________________________________________________________________________________________ +move the following constants from src/sftp.h to include/libssh2_sftp.h: + #define MAX_SFTP_OUTGOING_SIZE 30000 + #define MAX_SFTP_READ_SIZE 30000 __________________________________________________________________________________________________________ @@ -215,3 +255,16 @@ Backspace not working in filter dialog: http://www.freefilesync.org/forum/viewto +// g_source_attach(source, NULL); +// } __________________________________________________________________________________________________________ + +wxWidgets/GTK2 on some Linux systems incorrectly detects high DPI: https://freefilesync.org/forum/viewtopic.php?t=6114 +=> hack away high-DPI support for GTK2 (= pretend GTK2 has device independent pixels, which it clearly has not!) + +/include/wx/window.h: + + #include "wx/gtk/window.h" +- #ifdef __WXGTK3__ ++ //#ifdef __WXGTK3__ + #define wxHAVE_DPI_INDEPENDENT_PIXELS +- #endif ++ //#endif +__________________________________________________________________________________________________________ diff --git a/Changelog.txt b/Changelog.txt index 74415e95..9d1713f4 100755 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,3 +1,25 @@ +FreeFileSync 10.16 [2019-09-16] +------------------------------- +Redesigned progress indicator graphs +Avoid needless HTTP delay prior to Google Drive upload +Skip redundant CWDs during FTP metadata updates +Fixed MLSD 501 syntax error on Serv-U FTP server +Check FTP server status using home directory instead of root +Avoid redundant TYPE changes during FTP directory listing +Access FTP files by full path and avoid CWDs +Support FTP home paths with non-ASCII chars +Workaround libcurl bug failing to buffer FTP TLS authentication +Skip redundant FTP SIZE check before downloading file +Use ISO 8601 week of the year definition for %week% macro +Show login prompt for disconnected NAS share +Force icon resolution to 96 DPI in GTK2 build (Linux) +Detect missing full disk access permission (macOS) +Fixed accessibility issue due to graph color inconsistency +Use short naming convention when deleting abandoned folder lock +Detect endless folder lock recursion on buggy file systems +Fixed Google Drive parsing error for invalid file time + + FreeFileSync 10.15 [2019-08-15] ------------------------------- Redesigned progress indicator stats diff --git a/FreeFileSync/Build/Resources/Icons.zip b/FreeFileSync/Build/Resources/Icons.zip index af35c0b3..3c78d303 100755 Binary files a/FreeFileSync/Build/Resources/Icons.zip and b/FreeFileSync/Build/Resources/Icons.zip differ diff --git a/FreeFileSync/Build/Resources/Languages/german.lng b/FreeFileSync/Build/Resources/Languages/german.lng index 45c61939..47ae6f4e 100755 --- a/FreeFileSync/Build/Resources/Languages/german.lng +++ b/FreeFileSync/Build/Resources/Languages/german.lng @@ -387,12 +387,12 @@ Tatsächlich: %y bytes Database file is corrupted: Die Datenbankdatei ist beschädigt: -The database files do not yet contain information about the last synchronization. -Die Datenbankdateien beinhalten noch keine Informationen zur letzten Synchronisation. - Loading file %x... Lade Datei %x... +The database files do not yet contain information about the last synchronization. +Die Datenbankdateien beinhalten noch keine Informationen zur letzten Synchronisation. + Saving file %x... Speichere Datei %x... @@ -477,6 +477,27 @@ Tatsächlich: %y bytes Update attributes on right Aktualisiere Attribute des rechten Elements +Error parsing file %x, row %y, column %z. +Fehler beim Auswerten der Datei %x, Zeile %y, Spalte %z. + +Services +Dienste + +Show All +Alle einblenden + +Hide Others +Andere ausblenden + +Hide %x +%x ausblenden + +Quit %x +%x beenden + +Cannot set directory locks for the following folders: +Die Verzeichnissperren können für die folgenden Ordner nicht gesetzt werden: + Errors: Fehler: @@ -501,27 +522,6 @@ Tatsächlich: %y bytes Cleaning up log files: Bereinige Protokolldateien: -Error parsing file %x, row %y, column %z. -Fehler beim Auswerten der Datei %x, Zeile %y, Spalte %z. - -Services -Dienste - -Show All -Alle einblenden - -Hide Others -Andere ausblenden - -Hide %x -%x ausblenden - -Quit %x -%x beenden - -Cannot set directory locks for the following folders: -Die Verzeichnissperren können für die folgenden Ordner nicht gesetzt werden: - 1 thread %x threads @@ -1441,6 +1441,21 @@ Dadurch wird ein konsistenter Datenstand auch bei schweren Fehlern garantiert. Highlight configurations that have not been run for more than the following number of days: Konfigurationen hervorheben, die seit mehr als die folgende Anzahl an Tagen nicht mehr ausgeführt wurden: +FreeFileSync requires access rights to avoid "Operation not permitted" errors when synchronizing your data (e.g. Mail, Messages, Calendars). +FreeFileSync benötigt Zugriffsrechte, um "Operation nicht erlaubt" Fehler bei der Synchronisation deiner Daten (z.B. E-Mail, Nachrichten, Kalender) zu vermeiden. + +Locate the FreeFileSync app +Die FreeFileSync App finden + +Open Security && Privacy +Systemeinstellungen/Sicherheit öffnen + +Click the lock to allow changes. +Das Schloss anklicken und Änderungen erlauben. + +Drag FreeFileSync into the panel. +FreeFileSync in das Fenster ziehen. + Synchronization Settings Synchronisationseinstellungen @@ -1465,6 +1480,9 @@ Dadurch wird ein konsistenter Datenstand auch bei schweren Fehlern garantiert. Highlight Configurations Konfigurationen hervorheben +Grant Full Disk Access +Festplattenvollzugriff gewähren + Info Info @@ -1525,33 +1543,6 @@ Dadurch wird ein konsistenter Datenstand auch bei schweren Fehlern garantiert. &Execute &Ausführen - -1 directory -%x directories - - -1 Verzeichnis -%x Verzeichnisse - - - -1 file -%x files - - -1 Datei -%x Dateien - - - -Showing %y of 1 row -Showing %y of %x rows - - -Zeige %y von 1 Zeile -Zeige %y von %x Zeilen - - Set direction: Setze Richtung: @@ -1690,6 +1681,33 @@ Dadurch wird ein konsistenter Datenstand auch bei schweren Fehlern garantiert. All files are in sync Alle Dateien sind synchron + +1 directory +%x directories + + +1 Verzeichnis +%x Verzeichnisse + + + +1 file +%x files + + +1 Datei +%x Dateien + + + +Showing %y of 1 row +Showing %y of %x rows + + +Zeige %y von 1 Zeile +Zeige %y von %x Zeilen + + Cannot find %x %x wurde nicht gefunden. diff --git a/FreeFileSync/Build/Resources/cacert.pem b/FreeFileSync/Build/Resources/cacert.pem index 8e92f772..65be2181 100755 --- a/FreeFileSync/Build/Resources/cacert.pem +++ b/FreeFileSync/Build/Resources/cacert.pem @@ -1,7 +1,7 @@ ## ## Bundle of CA Root Certificates ## -## Certificate data from Mozilla as of: Wed May 15 03:12:09 2019 GMT +## Certificate data from Mozilla as of: Wed Aug 28 03:12:10 2019 GMT ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates @@ -14,7 +14,7 @@ ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.27. -## SHA256: 61eaa79ac46d923f2f74dfe401189424e96fa8736102b47ba2cdb4ea19af2cc8 +## SHA256: fffa309937c3be940649293f749b8207fabc6eb224e50e4bb3f2c5e44e0d6a6b ## @@ -2613,37 +2613,6 @@ kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su -----END CERTIFICATE----- -Certinomis - Root CA -==================== ------BEGIN CERTIFICATE----- -MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK -Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg -LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx -EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD -ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos -P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo -d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap -z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00 -8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x -RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE -6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t -FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV -PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH -i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj -YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I -6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF -AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV -WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw -Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX -lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ -y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9 -Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng -DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi -I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM -cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr -hkIGuUE= ------END CERTIFICATE----- - OISTE WISeKey Global Root GB CA =============================== -----BEGIN CERTIFICATE----- diff --git a/FreeFileSync/Source/afs/abstract.h b/FreeFileSync/Source/afs/abstract.h index 535d4114..85916fcd 100644 --- a/FreeFileSync/Source/afs/abstract.h +++ b/FreeFileSync/Source/afs/abstract.h @@ -468,6 +468,7 @@ AbstractFileSystem::FinalizeResult AbstractFileSystem::OutputStream::finalize() replaceCpy(replaceCpy(_("Unexpected size of data stream.\nExpected: %x bytes\nActual: %y bytes"), L"%x", numberTo(*bytesExpected_)), L"%y", numberTo(bytesWrittenTotal_))); + warn_static("somehow indicate that this is about source, and not the file name presented") const FinalizeResult result = outStream_->finalize(); //throw FileError, X finalizeSucceeded_ = true; diff --git a/FreeFileSync/Source/afs/ftp.cpp b/FreeFileSync/Source/afs/ftp.cpp index 4901168d..af3605e4 100644 --- a/FreeFileSync/Source/afs/ftp.cpp +++ b/FreeFileSync/Source/afs/ftp.cpp @@ -25,6 +25,10 @@ namespace { Zstring concatenateFtpFolderPathPhrase(const FtpLoginInfo& login, const AfsPath& afsPath); //noexcept +/* + Extensions to FTP: https://tools.ietf.org/html/rfc3659 +*/ + const std::chrono::seconds FTP_SESSION_MAX_IDLE_TIME (20); const std::chrono::seconds FTP_SESSION_CLEANUP_INTERVAL(4); const int FTP_STREAM_BUFFER_SIZE = 512 * 1024; //unit: [byte] @@ -224,7 +228,7 @@ public: template //expects non-empty range! std::string readRange(Function acceptChar) //throw SysError { - auto itEnd = std::find_if(it_, line_.end(), std::not_fn(acceptChar)); + auto itEnd = std::find_if_not(it_, line_.end(), acceptChar); std::string output(it_, itEnd); if (output.empty()) throw SysError(L"Expected char range not found."); @@ -241,37 +245,52 @@ private: //---------------------------------------------------------------------------------------------------------------- -std::wstring tryFormatFtpErrorCode(int ec) //https://en.wikipedia.org/wiki/List_of_FTP_server_return_codes +std::wstring formatFtpStatusCode(int sc) { - if (ec == 400) return L"The command was not accepted but the error condition is temporary."; - if (ec == 421) return L"Service not available, closing control connection."; - if (ec == 425) return L"Cannot open data connection."; - if (ec == 426) return L"Connection closed; transfer aborted."; - if (ec == 430) return L"Invalid username or password."; - if (ec == 431) return L"Need some unavailable resource to process security."; - if (ec == 434) return L"Requested host unavailable."; - if (ec == 450) return L"Requested file action not taken."; - if (ec == 451) return L"Local error in processing."; - if (ec == 452) return L"Insufficient storage space in system. File unavailable, e.g. file busy."; - if (ec == 500) return L"Syntax error, command unrecognized or command line too long."; - if (ec == 501) return L"Syntax error in parameters or arguments."; - if (ec == 502) return L"Command not implemented."; - if (ec == 503) return L"Bad sequence of commands."; - if (ec == 504) return L"Command not implemented for that parameter."; - if (ec == 521) return L"Data connection cannot be opened with this PROT setting."; - if (ec == 522) return L"Server does not support the requested network protocol."; - if (ec == 530) return L"User not logged in."; - if (ec == 532) return L"Need account for storing files."; - if (ec == 533) return L"Command protection level denied for policy reasons."; - if (ec == 534) return L"Could not connect to server; issue regarding SSL."; - if (ec == 535) return L"Failed security check."; - if (ec == 536) return L"Requested PROT level not supported by mechanism."; - if (ec == 537) return L"Command protection level not supported by security mechanism."; - if (ec == 550) return L"File unavailable, e.g. file not found, no access."; - if (ec == 551) return L"Requested action aborted. Page type unknown."; - if (ec == 552) return L"Requested file action aborted. Exceeded storage allocation."; - if (ec == 553) return L"File name not allowed."; - return L""; + const wchar_t* statusText = [&] //https://en.wikipedia.org/wiki/List_of_FTP_server_return_codes + { + switch (sc) + { + //*INDENT-OFF* + case 400: return L"The command was not accepted but the error condition is temporary."; + case 421: return L"Service not available, closing control connection."; + case 425: return L"Cannot open data connection."; + case 426: return L"Connection closed; transfer aborted."; + case 430: return L"Invalid username or password."; + case 431: return L"Need some unavailable resource to process security."; + case 434: return L"Requested host unavailable."; + case 450: return L"Requested file action not taken."; + case 451: return L"Local error in processing."; + case 452: return L"Insufficient storage space in system. File unavailable, e.g. file busy."; + + case 500: return L"Syntax error, command unrecognized or command line too long."; + case 501: return L"Syntax error in parameters or arguments."; + case 502: return L"Command not implemented."; + case 503: return L"Bad sequence of commands."; + case 504: return L"Command not implemented for that parameter."; + case 521: return L"Data connection cannot be opened with this PROT setting."; + case 522: return L"Server does not support the requested network protocol."; + case 530: return L"User not logged in."; + case 532: return L"Need account for storing files."; + case 533: return L"Command protection level denied for policy reasons."; + case 534: return L"Could not connect to server; issue regarding SSL."; + case 535: return L"Failed security check."; + case 536: return L"Requested PROT level not supported by mechanism."; + case 537: return L"Command protection level not supported by security mechanism."; + case 550: return L"File unavailable, e.g. file not found, no access."; + case 551: return L"Requested action aborted. Page type unknown."; + case 552: return L"Requested file action aborted. Exceeded storage allocation."; + case 553: return L"File name not allowed."; + + default: return L""; + //*INDENT-ON* + } + }(); + + if (strLength(statusText) == 0) + return trimCpy(replaceCpy(L"FTP status %x.", L"%x", numberTo(sc))); + else + return trimCpy(replaceCpy(L"FTP status %x: ", L"%x", numberTo(sc)) + statusText); } //================================================================================================================ @@ -309,7 +328,7 @@ public: }; //returns server response (header data) - std::string perform(const AfsPath* afsPath /*optional, use last-used path if null*/, bool isDir, + std::string perform(const AfsPath& afsPath, bool isDir, curl_ftpmethod pathMethod, const std::vector