diff options
author | elfmz <fenix1905@tut.by> | 2021-09-27 23:26:48 +0300 |
---|---|---|
committer | elfmz <fenix1905@tut.by> | 2021-09-27 23:26:48 +0300 |
commit | 99b0f77b7aec0803a89d3fbc80770f691bfc5206 (patch) | |
tree | f8e078aec0ebb9788393048a035975c68feeeed1 /NetRocks | |
parent | 7d8ea233f5d00425e979cdaf5d07f475a63c7c42 (diff) |
NetRocks: ability to navigate to existing parent dir if current one inaccessible just after connected; increase default SSH timeout to 20 seconds
Diffstat (limited to 'NetRocks')
-rw-r--r-- | NetRocks/CMakeLists.txt | 2 | ||||
-rw-r--r-- | NetRocks/configs/plug/eng.lng | 3 | ||||
-rw-r--r-- | NetRocks/configs/plug/rus.lng | 3 | ||||
-rw-r--r-- | NetRocks/src/Location.cpp | 12 | ||||
-rw-r--r-- | NetRocks/src/Location.h | 3 | ||||
-rw-r--r-- | NetRocks/src/NetRocks.cpp | 2 | ||||
-rw-r--r-- | NetRocks/src/Op/OpCheckDirectory.cpp | 64 | ||||
-rw-r--r-- | NetRocks/src/Op/OpCheckDirectory.h | 13 | ||||
-rw-r--r-- | NetRocks/src/Op/OpEnumDirectory.cpp | 4 | ||||
-rw-r--r-- | NetRocks/src/Op/OpGetMode.cpp | 43 | ||||
-rw-r--r-- | NetRocks/src/Op/OpGetMode.h | 13 | ||||
-rw-r--r-- | NetRocks/src/Op/OpXfer.cpp | 2 | ||||
-rw-r--r-- | NetRocks/src/PluginImpl.cpp | 48 | ||||
-rw-r--r-- | NetRocks/src/PluginImpl.h | 4 | ||||
-rw-r--r-- | NetRocks/src/Protocol/SSH/ProtocolSCP.cpp | 2 | ||||
-rw-r--r-- | NetRocks/src/Protocol/SSH/SSHConnection.cpp | 2 | ||||
-rw-r--r-- | NetRocks/src/UI/Activities/WhatOnError.cpp | 34 | ||||
-rw-r--r-- | NetRocks/src/UI/Activities/WhatOnError.h | 25 | ||||
-rw-r--r-- | NetRocks/src/UI/Defs.h | 7 | ||||
-rw-r--r-- | NetRocks/src/UI/Settings/ConfigureProtocolSFTPSCP.cpp | 4 | ||||
-rw-r--r-- | NetRocks/src/lng.h | 3 |
21 files changed, 183 insertions, 110 deletions
diff --git a/NetRocks/CMakeLists.txt b/NetRocks/CMakeLists.txt index 9bd7a7de..d1d9033b 100644 --- a/NetRocks/CMakeLists.txt +++ b/NetRocks/CMakeLists.txt @@ -41,7 +41,7 @@ src/Op/Utils/Enumer.cpp src/Op/Utils/IOBuffer.cpp src/Op/OpBase.cpp src/Op/OpConnect.cpp -src/Op/OpGetMode.cpp +src/Op/OpCheckDirectory.cpp src/Op/OpChangeMode.cpp src/Op/OpEnumDirectory.cpp src/Op/OpXfer.cpp diff --git a/NetRocks/configs/plug/eng.lng b/NetRocks/configs/plug/eng.lng index ea0b81d9..af93c7ff 100644 --- a/NetRocks/configs/plug/eng.lng +++ b/NetRocks/configs/plug/eng.lng @@ -8,6 +8,8 @@ "&Skip" "Error" +"Go&Up" + "NetRocks options" "Enable desktop ¬ifications" "<&ENTER> to execute files remotely when possible" @@ -156,6 +158,7 @@ "Upload error" "Crossload error" "Query information error" +"Check directory error" "Enum directory error" "Make directory error" "Rename error" diff --git a/NetRocks/configs/plug/rus.lng b/NetRocks/configs/plug/rus.lng index e271d8c8..052c8bcb 100644 --- a/NetRocks/configs/plug/rus.lng +++ b/NetRocks/configs/plug/rus.lng @@ -8,6 +8,8 @@ "&Пропустить" "Ошибка" +"В&ыше" + "Настройки NetRocks" "Включить уведомления рабочего стола" "<&ENTER> исполняет файлы на сервере если возможно" @@ -156,6 +158,7 @@ "Ошибка закачивания" "Ошибка перекачивания" "Ошибка опроса" +"Ошибка проверки директории" "Ошибка сканирования директории" "Ошибка создания директории" "Ошибка переименование" diff --git a/NetRocks/src/Location.cpp b/NetRocks/src/Location.cpp index df875464..083cdb72 100644 --- a/NetRocks/src/Location.cpp +++ b/NetRocks/src/Location.cpp @@ -15,7 +15,7 @@ sftp://server//etc/dir/file sftp://user@server:port/dir/in/home/file */ -bool Location::FromString(const std::string standalone_config, const std::string &str) +bool Location::FromString(const std::string &standalone_config, const std::string &str) { server.clear(); @@ -74,8 +74,7 @@ bool Location::FromString(const std::string standalone_config, const std::string path.absolute = !str.empty() && str[str.size() - 1] == '/'; } else { - path.absolute = directory[0] == '/'; - StrExplode(path.components, directory, "/"); + PathFromString(directory); } #if 0 @@ -87,6 +86,13 @@ bool Location::FromString(const std::string standalone_config, const std::string return true; } +bool Location::PathFromString(const std::string &directory) +{ + path.absolute = directory[0] == '/'; + path.components.clear(); + StrExplode(path.components, directory, "/"); +} + std::string Location::ToString(bool with_server) const { std::string out; diff --git a/NetRocks/src/Location.h b/NetRocks/src/Location.h index e05c80be..f20397c9 100644 --- a/NetRocks/src/Location.h +++ b/NetRocks/src/Location.h @@ -24,6 +24,7 @@ struct Location void ResetToHome(); } path; - bool FromString(const std::string standalone_config, const std::string &str); + bool PathFromString(const std::string &directory); + bool FromString(const std::string &standalone_config, const std::string &str); std::string ToString(bool with_server) const; }; diff --git a/NetRocks/src/NetRocks.cpp b/NetRocks/src/NetRocks.cpp index 65054b69..f3fb8403 100644 --- a/NetRocks/src/NetRocks.cpp +++ b/NetRocks/src/NetRocks.cpp @@ -66,7 +66,7 @@ SHAREDSYMBOL HANDLE WINAPI _export OpenFilePluginW(const wchar_t *Name, const un } } - return new PluginImpl(Name, true); + return new PluginImpl(Name, true, OpMode); } diff --git a/NetRocks/src/Op/OpCheckDirectory.cpp b/NetRocks/src/Op/OpCheckDirectory.cpp new file mode 100644 index 00000000..9740d1f7 --- /dev/null +++ b/NetRocks/src/Op/OpCheckDirectory.cpp @@ -0,0 +1,64 @@ +#include "OpCheckDirectory.h" +#include "../UI/Activities/SimpleOperationProgress.h" + +OpCheckDirectory::OpCheckDirectory(int op_mode, std::shared_ptr<IHost> &base_host, const std::string &path, std::shared_ptr<WhatOnErrorState> &wea_state) + : + OpBase(op_mode, base_host, path, wea_state), + _final_path(path) +{ +} + +bool OpCheckDirectory::Do(std::string &final_path) +{ + _succeed = false; + + if (!StartThread()) { + ; + + } else if (IS_SILENT(_op_mode)) { + WaitThread(); + + } else if (!WaitThread(1000)) { + SimpleOperationProgress p(SimpleOperationProgress::K_GETMODE, _base_dir, _state); + p.Show(); + WaitThread(); + } + + if (!_succeed) + return false; + + final_path.swap(_final_path); + return true; +} + + +void OpCheckDirectory::Process() +{ + WhatOnErrorWrap<WEK_CHECKDIR>(_wea_state, _state, _base_host.get(), _final_path, + [&] () mutable + { + auto mode = _base_host->GetMode(_final_path); + if (!S_ISDIR(mode)) { + fprintf(stderr, "NetRocks: not dir mode=0%o: '%s'\n", mode, _final_path.c_str()); + throw std::runtime_error("Not a directory"); + } + _succeed = true; + } + , + [this] (bool &recovery) mutable + { + if (_op_mode != 0 || _final_path.empty()) { + recovery = false; + } + + if (recovery) { + size_t p = _final_path.rfind('/'); + if (p != std::string::npos) { + _final_path.resize(p); + } + } + } + , + _op_mode == 0 && !_final_path.empty() + ); +} diff --git a/NetRocks/src/Op/OpCheckDirectory.h b/NetRocks/src/Op/OpCheckDirectory.h new file mode 100644 index 00000000..d6db442c --- /dev/null +++ b/NetRocks/src/Op/OpCheckDirectory.h @@ -0,0 +1,13 @@ +#pragma once +#include "OpBase.h" + +class OpCheckDirectory : protected OpBase +{ + std::string _final_path; + volatile bool _succeed; + virtual void Process(); + +public: + OpCheckDirectory(int op_mode, std::shared_ptr<IHost> &base_host, const std::string &path, std::shared_ptr<WhatOnErrorState> &wea_state); + bool Do(std::string &final_path); +}; diff --git a/NetRocks/src/Op/OpEnumDirectory.cpp b/NetRocks/src/Op/OpEnumDirectory.cpp index 50e12bec..6b50135a 100644 --- a/NetRocks/src/Op/OpEnumDirectory.cpp +++ b/NetRocks/src/Op/OpEnumDirectory.cpp @@ -1,3 +1,4 @@ +#include <assert.h> #include <utils.h> #include "OpEnumDirectory.h" #include "../UI/Activities/Confirm.h" @@ -62,8 +63,9 @@ void OpEnumDirectory::Process() } } , - [this] () mutable + [this] (bool &recovery) mutable { + recovery = false; _result.Shrink(_initial_result_count); std::unique_lock<std::mutex> locker(_state.mtx); _state.stats.count_complete = _initial_count_complete; diff --git a/NetRocks/src/Op/OpGetMode.cpp b/NetRocks/src/Op/OpGetMode.cpp deleted file mode 100644 index 97a39a12..00000000 --- a/NetRocks/src/Op/OpGetMode.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "OpGetMode.h" -#include "../UI/Activities/SimpleOperationProgress.h" - -OpGetMode::OpGetMode(int op_mode, std::shared_ptr<IHost> &base_host, const std::string &path, std::shared_ptr<WhatOnErrorState> &wea_state) - : - OpBase(op_mode, base_host, path, wea_state) -{ -} - -bool OpGetMode::Do(mode_t &result) -{ - _succeed = false; - - if (!StartThread()) { - ; - - } else if (IS_SILENT(_op_mode)) { - WaitThread(); - - } else if (!WaitThread(1000)) { - SimpleOperationProgress p(SimpleOperationProgress::K_GETMODE, _base_dir, _state); - p.Show(); - WaitThread(); - } - - if (!_succeed) - return false; - - result = _result; - return true; -} - - -void OpGetMode::Process() -{ - WhatOnErrorWrap<WEK_QUERYINFO>(_wea_state, _state, _base_host.get(), _base_dir, - [&] () mutable - { - _result = _base_host->GetMode(_base_dir); - _succeed = true; - } - ); -} diff --git a/NetRocks/src/Op/OpGetMode.h b/NetRocks/src/Op/OpGetMode.h deleted file mode 100644 index 013d7ca5..00000000 --- a/NetRocks/src/Op/OpGetMode.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "OpBase.h" - -class OpGetMode : protected OpBase -{ - volatile mode_t _result = 0; - volatile bool _succeed; - virtual void Process(); - -public: - OpGetMode(int op_mode, std::shared_ptr<IHost> &base_host, const std::string &path, std::shared_ptr<WhatOnErrorState> &wea_state); - bool Do(mode_t &result); -}; diff --git a/NetRocks/src/Op/OpXfer.cpp b/NetRocks/src/Op/OpXfer.cpp index fe28b664..b743c249 100644 --- a/NetRocks/src/Op/OpXfer.cpp +++ b/NetRocks/src/Op/OpXfer.cpp @@ -555,7 +555,7 @@ bool OpXfer::FileCopyLoop(const std::string &path_src, const std::string &path_d _io_buf.Desire(bufsize_optimal); if (g_netrocks_verbosity > 0 && _io_buf.Size() != prev_bufsize) { - fprintf(stderr, "NetRocks: IO buffer size changed to %lu\n", _io_buf.Size()); + fprintf(stderr, "NetRocks: IO buffer size changed to %lu\n", (unsigned long)_io_buf.Size()); } } diff --git a/NetRocks/src/PluginImpl.cpp b/NetRocks/src/PluginImpl.cpp index 06b3f6d4..fbc6312d 100644 --- a/NetRocks/src/PluginImpl.cpp +++ b/NetRocks/src/PluginImpl.cpp @@ -13,9 +13,9 @@ #include "UI/Settings/SiteConnectionEditor.h" #include "UI/Activities/Confirm.h" #include "Op/OpConnect.h" -#include "Op/OpGetMode.h" #include "Op/OpXfer.h" #include "Op/OpRemove.h" +#include "Op/OpCheckDirectory.h" #include "Op/OpMakeDirectory.h" #include "Op/OpEnumDirectory.h" #include "Op/OpExecute.h" @@ -72,7 +72,7 @@ public: } g_all_netrocks; -PluginImpl::PluginImpl(const wchar_t *path, bool path_is_standalone_config) +PluginImpl::PluginImpl(const wchar_t *path, bool path_is_standalone_config, int OpMode) { _cur_dir[0] = _panel_title[0] = _format[0] = 0; @@ -96,6 +96,7 @@ PluginImpl::PluginImpl(const wchar_t *path, bool path_is_standalone_config) if (!_remote) { throw std::runtime_error(G.GetMsgMB(MCouldNotConnect)); } + ValidateLocationDirectory(OpMode); } else if (!_sites_cfg_location.Change(Wide2MB(path))) { throw std::runtime_error(G.GetMsgMB(MWrongPath)); @@ -346,7 +347,7 @@ int PluginImpl::SetDirectoryInternal(const wchar_t *Dir, int OpMode) } _wea_state = std::make_shared<WhatOnErrorState>(); - return TRUE; + return ValidateLocationDirectory(OpMode) ? TRUE : FALSE; } @@ -376,25 +377,34 @@ int PluginImpl::SetDirectoryInternal(const wchar_t *Dir, int OpMode) return TRUE; } + if (ValidateLocationDirectory(OpMode)) { + return TRUE; + } + + _location.path = saved_path; + return FALSE; +} + +bool PluginImpl::ValidateLocationDirectory(int OpMode) +{ const std::string &dir = _location.ToString(false); - fprintf(stderr, "NetRocks::SetDirectoryInternal - dir: '%s'\n", dir.c_str()); - if (!dir.empty()) { - mode_t mode = 0; - if (!OpGetMode(OpMode, _remote, dir, _wea_state).Do(mode)) { - fprintf(stderr, "NetRocks::SetDirectoryInternal - can't get mode: '%s'\n", dir.c_str()); - _location.path = saved_path; - return FALSE; - } - - if (!S_ISDIR(mode)) { - fprintf(stderr, "NetRocks::SetDirectoryInternal - not dir mode=0x%x: '%s'\n", mode, dir.c_str()); - _location.path = saved_path; - return FALSE; - } + fprintf(stderr, "NetRocks::ValidateLocationDirectory - dir: '%s'\n", dir.c_str()); + if (dir.empty()) { + return true; } - fprintf(stderr, "NetRocks::SetDirectoryInternal('%ls', %d) OK: '%s'\n", Dir, OpMode, dir.c_str()); - return TRUE; + std::string final_dir; + if (!OpCheckDirectory(OpMode, _remote, dir, _wea_state).Do(final_dir)) { + fprintf(stderr, "NetRocks::ValidateLocationDirectory - failed\n"); + return false; + } + + if (dir != final_dir) { + fprintf(stderr, "NetRocks::ValidateLocationDirectory - final_dir: '%s'\n", final_dir.c_str()); + _location.PathFromString(final_dir); + } + + return true; } void PluginImpl::GetOpenPluginInfo(struct OpenPluginInfo *Info) diff --git a/NetRocks/src/PluginImpl.h b/NetRocks/src/PluginImpl.h index 2fec917e..2701884e 100644 --- a/NetRocks/src/PluginImpl.h +++ b/NetRocks/src/PluginImpl.h @@ -56,8 +56,10 @@ class PluginImpl void DismissRemoteHost(); std::string CurrentConnectionPoolId(); + bool ValidateLocationDirectory(int OpMode); + public: - PluginImpl(const wchar_t *path = nullptr, bool path_is_standalone_config = false); + PluginImpl(const wchar_t *path = nullptr, bool path_is_standalone_config = false, int OpMode = 0); virtual ~PluginImpl(); static void sOnExiting(); diff --git a/NetRocks/src/Protocol/SSH/ProtocolSCP.cpp b/NetRocks/src/Protocol/SSH/ProtocolSCP.cpp index 9e8c4815..e7ad21f3 100644 --- a/NetRocks/src/Protocol/SSH/ProtocolSCP.cpp +++ b/NetRocks/src/Protocol/SSH/ProtocolSCP.cpp @@ -497,7 +497,7 @@ public: SCPDirectoryEnumer(std::shared_ptr<SSHConnection> &conn, std::string path) : _conn(conn) { - std::string command_line = "stat --format=\"%n %f %s %X %Y %Z %U %G\" "; + std::string command_line = "stat --format=\"%n %f %s %X %Y %Z %U %G\""; command_line+= QuotedArg(path); command_line+= "/.* "; command_line+= QuotedArg(path); diff --git a/NetRocks/src/Protocol/SSH/SSHConnection.cpp b/NetRocks/src/Protocol/SSH/SSHConnection.cpp index ca93b787..30ac4f51 100644 --- a/NetRocks/src/Protocol/SSH/SSHConnection.cpp +++ b/NetRocks/src/Protocol/SSH/SSHConnection.cpp @@ -150,7 +150,7 @@ SSHConnection::SSHConnection(const std::string &host, unsigned int port, const s } int retries = std::max(protocol_options.GetInt("ConnectRetries", 2), 1); - long timeout = std::max(protocol_options.GetInt("ConnectTimeout", 10), 1); + long timeout = std::max(protocol_options.GetInt("ConnectTimeout", 20), 1); ssh_options_set(ssh, SSH_OPTIONS_TIMEOUT, &timeout); diff --git a/NetRocks/src/UI/Activities/WhatOnError.cpp b/NetRocks/src/UI/Activities/WhatOnError.cpp index cd584f6d..522b9f1a 100644 --- a/NetRocks/src/UI/Activities/WhatOnError.cpp +++ b/NetRocks/src/UI/Activities/WhatOnError.cpp @@ -1,3 +1,4 @@ +#include <assert.h> #include <utils.h> #include "WhatOnError.h" #include "../../Globals.h" @@ -18,7 +19,7 @@ 6 29 38 60 */ -WhatOnError::WhatOnError(WhatOnErrorKind wek, const std::string &error, const std::string &object, const std::string &site) +WhatOnError::WhatOnError(WhatOnErrorKind wek, const std::string &error, const std::string &object, const std::string &site, bool may_recovery) { int title_lng; switch (wek) { @@ -26,6 +27,7 @@ WhatOnError::WhatOnError(WhatOnErrorKind wek, const std::string &error, const st case WEK_UPLOAD: title_lng = MErrorUploadTitle; break; case WEK_CROSSLOAD: title_lng = MErrorCrossloadTitle; break; case WEK_QUERYINFO: title_lng = MErrorQueryInfoTitle; break; + case WEK_CHECKDIR: title_lng = MErrorCheckDirTitle; break; case WEK_ENUMDIR: title_lng = MErrorEnumDirTitle; break; case WEK_MAKEDIR: title_lng = MErrorMakeDirTitle; break; case WEK_RENAME: title_lng = MErrorRenameTitle; break; @@ -67,9 +69,14 @@ WhatOnError::WhatOnError(WhatOnErrorKind wek, const std::string &error, const st _di.AddAtLine(DI_TEXT, 4,63, DIF_BOXCOLOR | DIF_SEPARATOR); _di.NextLine(); - _i_retry = _di.AddAtLine(DI_BUTTON, 5,20, DIF_CENTERGROUP, MRetry); - _i_skip = _di.AddAtLine(DI_BUTTON, 21,40, DIF_CENTERGROUP, MSkip); - _di.AddAtLine(DI_BUTTON, 41,60, DIF_CENTERGROUP, MCancel); + int left = 5; + if (may_recovery && wek == WEK_CHECKDIR) { + _i_recovery = _di.AddAtLine(DI_BUTTON, left, left + 15, DIF_CENTERGROUP, MRecoveryDir); + left+= 16; + } + _i_retry = _di.AddAtLine(DI_BUTTON, left, left + 15, DIF_CENTERGROUP, MRetry); + _i_skip = _di.AddAtLine(DI_BUTTON, left + 16, left + 30, DIF_CENTERGROUP, MSkip); + _di.AddAtLine(DI_BUTTON, left + 31, left + 45, DIF_CENTERGROUP, MCancel); SetFocusedDialogControl(_i_retry); SetDefaultDialogControl(_i_retry); @@ -86,7 +93,10 @@ WhatOnErrorAction WhatOnError::Ask(WhatOnErrorAction &default_wea) WhatOnErrorAction out = WEA_CANCEL; - if (r == _i_retry) { + if (_i_recovery != -1 && r == _i_recovery) { + out = WEA_RECOVERY; + + } else if (r == _i_retry) { out = WEA_RETRY; } else if (r == _i_skip) { @@ -103,14 +113,17 @@ WhatOnErrorAction WhatOnError::Ask(WhatOnErrorAction &default_wea) ////////////////////////////////////// -WhatOnErrorAction WhatOnErrorState::Query(ProgressState &progress_state, WhatOnErrorKind wek, const std::string &error, const std::string &object, const std::string &site) +WhatOnErrorAction WhatOnErrorState::Query(ProgressState &progress_state, WhatOnErrorKind wek, const std::string &error, const std::string &object, const std::string &site, bool may_recovery) { std::unique_lock<std::mutex> locker(_mtx); auto wea = _default_weas[wek].emplace(error, WEA_ASK).first->second; locker.unlock(); + if (wea == WEA_RECOVERY && !may_recovery) { + wea = WEA_ASK; + } if (wea != WEA_ASK) { - if (wea == WEA_RETRY) { + if (wea == WEA_RETRY || wea == WEA_RECOVERY) { for (unsigned int sleep_usec = _auto_retry_delay * 1000000; sleep_usec; ) { unsigned int sleep_usec_portion = (sleep_usec > 100000) ? 100000 : sleep_usec; usleep(sleep_usec_portion); @@ -131,7 +144,7 @@ WhatOnErrorAction WhatOnErrorState::Query(ProgressState &progress_state, WhatOnE ++_showing_ui; - auto out = WhatOnError(wek, error, object, site).Ask(wea); + auto out = WhatOnError(wek, error, object, site, may_recovery).Ask(wea); --_showing_ui; locker.lock(); _default_weas[wek][error] = wea; @@ -160,9 +173,6 @@ void WhatOnErrorState::ResetAutoActions() _has_any_autoaction = false; } - -void WhatOnErrorWrap_DummyOnRetry() +void WhatOnErrorWrap_DummyOnRetry(bool &recovery) { } - - diff --git a/NetRocks/src/UI/Activities/WhatOnError.h b/NetRocks/src/UI/Activities/WhatOnError.h index ed1f14c2..c83f9b9a 100644 --- a/NetRocks/src/UI/Activities/WhatOnError.h +++ b/NetRocks/src/UI/Activities/WhatOnError.h @@ -11,10 +11,10 @@ class WhatOnError : protected BaseDialog { - int _i_remember = -1, _i_retry = -1, _i_skip = -1; + int _i_remember = -1, _i_recovery = -1, _i_retry = -1, _i_skip = -1; public: - WhatOnError(WhatOnErrorKind wek, const std::string &error, const std::string &object, const std::string &site); + WhatOnError(WhatOnErrorKind wek, const std::string &error, const std::string &object, const std::string &site, bool may_recovery = false); WhatOnErrorAction Ask(WhatOnErrorAction &default_wea); }; @@ -28,7 +28,7 @@ class WhatOnErrorState std::mutex _mtx; public: - WhatOnErrorAction Query(ProgressState &progress_state, WhatOnErrorKind wek, const std::string &error, const std::string &object, const std::string &site); + WhatOnErrorAction Query(ProgressState &progress_state, WhatOnErrorKind wek, const std::string &error, const std::string &object, const std::string &site, bool may_recovery = false); void ResetAutoRetryDelay(); bool IsShowingUIRightNow() const { return _showing_ui != 0; }; @@ -37,12 +37,12 @@ class WhatOnErrorState void ResetAutoActions(); }; -void WhatOnErrorWrap_DummyOnRetry(); +void WhatOnErrorWrap_DummyOnRetry(bool &recovery); //void (IT::*METH)(...) -template <WhatOnErrorKind WEK, class FN, class FN_ON_RETRY = void(*)()> +template <WhatOnErrorKind WEK, class FN, class FN_ON_RETRY = void(*)(bool &)> static void WhatOnErrorWrap(std::shared_ptr<WhatOnErrorState> &wea_state, - ProgressState &progress_state, IHost *indicted, const std::string &object, FN fn, FN_ON_RETRY fn_on_retry = WhatOnErrorWrap_DummyOnRetry) + ProgressState &progress_state, IHost *indicted, const std::string &object, FN fn, FN_ON_RETRY fn_on_retry = WhatOnErrorWrap_DummyOnRetry, bool may_recovery = false) { for (;;) try { fn(); @@ -53,15 +53,22 @@ template <WhatOnErrorKind WEK, class FN, class FN_ON_RETRY = void(*)()> throw; } catch (std::exception &ex) { - switch (wea_state->Query(progress_state, WEK, ex.what(), object, indicted->SiteName())) { + auto wea = wea_state->Query(progress_state, WEK, ex.what(), object, indicted->SiteName(), may_recovery); + switch (wea) { case WEA_SKIP: { std::unique_lock<std::mutex> locker(progress_state.mtx); progress_state.stats.count_skips++; } return; - case WEA_RETRY: { + case WEA_RETRY: indicted->ReInitialize(); - fn_on_retry(); + + case WEA_RECOVERY: { + bool recovery = (wea == WEA_RECOVERY); + fn_on_retry(recovery); + if (!recovery && wea == WEA_RECOVERY) { + may_recovery = false; + } std::unique_lock<std::mutex> locker(progress_state.mtx); if (progress_state.aborting) throw AbortError(); diff --git a/NetRocks/src/UI/Defs.h b/NetRocks/src/UI/Defs.h index d595613a..559d02dd 100644 --- a/NetRocks/src/UI/Defs.h +++ b/NetRocks/src/UI/Defs.h @@ -36,6 +36,7 @@ enum WhatOnErrorKind WEK_UPLOAD, WEK_CROSSLOAD, WEK_QUERYINFO, + WEK_CHECKDIR, WEK_ENUMDIR, WEK_MAKEDIR, WEK_RENAME, @@ -47,12 +48,16 @@ enum WhatOnErrorKind WEKS_COUNT }; + + enum WhatOnErrorAction { WEA_CANCEL = 0, // meaningful as dialog result WEA_ASK = 0, // meaningful as default action WEA_SKIP, - WEA_RETRY + WEA_RETRY, + + WEA_RECOVERY, // for directory validation - allows traversing to first valid parent directory }; struct ProgressStateStats diff --git a/NetRocks/src/UI/Settings/ConfigureProtocolSFTPSCP.cpp b/NetRocks/src/UI/Settings/ConfigureProtocolSFTPSCP.cpp index 8cbf2b80..3b1047be 100644 --- a/NetRocks/src/UI/Settings/ConfigureProtocolSFTPSCP.cpp +++ b/NetRocks/src/UI/Settings/ConfigureProtocolSFTPSCP.cpp @@ -156,7 +156,7 @@ public: _di.NextLine(); _di.AddAtLine(DI_TEXT, 5,50, 0, MSFTPConnectTimeout); - _i_connect_timeout = _di.AddAtLine(DI_FIXEDIT, 51,53, DIF_MASKEDIT, "10", "999"); + _i_connect_timeout = _di.AddAtLine(DI_FIXEDIT, 51,53, DIF_MASKEDIT, "20", "999"); _di.NextLine(); _i_tcp_nodelay = _di.AddAtLine(DI_CHECKBOX, 5,60, 0, MSFTPTCPNodelay); @@ -210,7 +210,7 @@ public: SetCheckedDialogControl(_i_use_openssh_configs, sc.GetInt("UseOpenSSHConfigs", 0) != 0); LongLongToDialogControl(_i_connect_retries, std::max((int)1, sc.GetInt("ConnectRetries", 2))); - LongLongToDialogControl(_i_connect_timeout, std::max((int)1, sc.GetInt("ConnectTimeout", 10))); + LongLongToDialogControl(_i_connect_timeout, std::max((int)1, sc.GetInt("ConnectTimeout", 20))); if (_i_use_custom_subsystem != -1) { SetCheckedDialogControl(_i_use_custom_subsystem, sc.GetInt("UseCustomSubsystem", 0) != 0); diff --git a/NetRocks/src/lng.h b/NetRocks/src/lng.h index 0dee08c9..ef2af91a 100644 --- a/NetRocks/src/lng.h +++ b/NetRocks/src/lng.h @@ -10,6 +10,8 @@ enum LanguageID MSkip, MError, + MRecoveryDir, + MPluginOptionsTitle, MEnableDesktopNotifications, MEnterExecRemotely, @@ -158,6 +160,7 @@ enum LanguageID MErrorUploadTitle, MErrorCrossloadTitle, MErrorQueryInfoTitle, + MErrorCheckDirTitle, MErrorEnumDirTitle, MErrorMakeDirTitle, MErrorRenameTitle, |