From cdf303a847157b5f384329c620ad6ed66b78bc2f Mon Sep 17 00:00:00 2001 From: veeso Date: Sat, 15 Mar 2025 16:46:57 +0100 Subject: [PATCH] fix: fixed a crash when the local directory specified in the auth form does not exist fix #319 --- CHANGELOG.md | 2 ++ src/activity_manager.rs | 16 +++++++++++++--- src/filetransfer/host_bridge_builder.rs | 18 +++++++++++------- src/filetransfer/remotefs_builder.rs | 20 +++++++++++--------- src/ui/activities/filetransfer/mod.rs | 10 +++++----- src/ui/context.rs | 4 ++++ 6 files changed, 46 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d360d0..a59d468 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,8 @@ Released on ?? +- [issue 319](https://github.com/veeso/termscp/issues/319): fixed a crash when the local directory specified in the auth form does not exist +- [issue 327](https://github.com/veeso/termscp/issues/327): fixed a panic when trying to go up from local directory on localhost in the auth form - Dependencies: - `argh` to `0.1.13` - `bytesize` to `2` diff --git a/src/activity_manager.rs b/src/activity_manager.rs index 89f7af2..913d7d1 100644 --- a/src/activity_manager.rs +++ b/src/activity_manager.rs @@ -342,7 +342,7 @@ impl ActivityManager { fn run_filetransfer(&mut self) -> Option { info!("Starting FileTransferActivity"); // Get context - let ctx: Context = match self.context.take() { + let mut ctx: Context = match self.context.take() { Some(ctx) => ctx, None => { error!("Failed to start FileTransferActivity: context is None"); @@ -367,8 +367,18 @@ impl ActivityManager { } }; - let mut activity: FileTransferActivity = - FileTransferActivity::new(host_bridge_params, remote_params, self.ticks); + // try to setup activity + let mut activity = + match FileTransferActivity::new(host_bridge_params, remote_params, self.ticks) { + Ok(activity) => activity, + Err(err) => { + error!("Failed to start FileTransferActivity: {}", err); + ctx.set_error(err); + self.context = Some(ctx); + // Return to authentication + return Some(NextActivity::Authentication); + } + }; // Prepare result let result: Option; // Create activity diff --git a/src/filetransfer/host_bridge_builder.rs b/src/filetransfer/host_bridge_builder.rs index 885f0d9..5ce30de 100644 --- a/src/filetransfer/host_bridge_builder.rs +++ b/src/filetransfer/host_bridge_builder.rs @@ -7,15 +7,19 @@ pub struct HostBridgeBuilder; impl HostBridgeBuilder { /// Build Host Bridge from parms /// - /// if protocol and parameters are inconsistent, the function will panic. - pub fn build(params: HostBridgeParams, config_client: &ConfigClient) -> Box { + /// if protocol and parameters are inconsistent, the function will return an error. + pub fn build( + params: HostBridgeParams, + config_client: &ConfigClient, + ) -> Result, String> { match params { - HostBridgeParams::Localhost(path) => { - Box::new(Localhost::new(path).expect("Failed to create Localhost")) + HostBridgeParams::Localhost(path) => Localhost::new(path) + .map(|host| Box::new(host) as Box) + .map_err(|e| e.to_string()), + HostBridgeParams::Remote(protocol, params) => { + RemoteFsBuilder::build(protocol, params, config_client) + .map(|host| Box::new(RemoteBridged::from(host)) as Box) } - HostBridgeParams::Remote(protocol, params) => Box::new(RemoteBridged::from( - RemoteFsBuilder::build(protocol, params, config_client), - )), } } } diff --git a/src/filetransfer/remotefs_builder.rs b/src/filetransfer/remotefs_builder.rs index 3a4fdc5..ec162de 100644 --- a/src/filetransfer/remotefs_builder.rs +++ b/src/filetransfer/remotefs_builder.rs @@ -37,33 +37,35 @@ impl RemoteFsBuilder { protocol: FileTransferProtocol, params: ProtocolParams, config_client: &ConfigClient, - ) -> Box { + ) -> Result, String> { match (protocol, params) { (FileTransferProtocol::AwsS3, ProtocolParams::AwsS3(params)) => { - Box::new(Self::aws_s3_client(params)) + Ok(Box::new(Self::aws_s3_client(params))) } (FileTransferProtocol::Ftp(secure), ProtocolParams::Generic(params)) => { - Box::new(Self::ftp_client(params, secure)) + Ok(Box::new(Self::ftp_client(params, secure))) } (FileTransferProtocol::Kube, ProtocolParams::Kube(params)) => { - Box::new(Self::kube_client(params)) + Ok(Box::new(Self::kube_client(params))) } (FileTransferProtocol::Scp, ProtocolParams::Generic(params)) => { - Box::new(Self::scp_client(params, config_client)) + Ok(Box::new(Self::scp_client(params, config_client))) } (FileTransferProtocol::Sftp, ProtocolParams::Generic(params)) => { - Box::new(Self::sftp_client(params, config_client)) + Ok(Box::new(Self::sftp_client(params, config_client))) } #[cfg(smb)] (FileTransferProtocol::Smb, ProtocolParams::Smb(params)) => { - Box::new(Self::smb_client(params)) + Ok(Box::new(Self::smb_client(params))) } (FileTransferProtocol::WebDAV, ProtocolParams::WebDAV(params)) => { - Box::new(Self::webdav_client(params)) + Ok(Box::new(Self::webdav_client(params))) } (protocol, params) => { error!("Invalid params for protocol '{:?}'", protocol); - panic!("Invalid protocol '{protocol:?}' with parameters of type {params:?}") + Err(format!( + "Invalid protocol '{protocol:?}' with parameters of type {params:?}", + )) } } } diff --git a/src/ui/activities/filetransfer/mod.rs b/src/ui/activities/filetransfer/mod.rs index 314f941..991f012 100644 --- a/src/ui/activities/filetransfer/mod.rs +++ b/src/ui/activities/filetransfer/mod.rs @@ -243,14 +243,14 @@ impl FileTransferActivity { host_bridge_params: HostBridgeParams, remote_params: &FileTransferParams, ticks: Duration, - ) -> Self { + ) -> Result { // Get config client let config_client: ConfigClient = Self::init_config_client(); // init host bridge - let host_bridge = HostBridgeBuilder::build(host_bridge_params, &config_client); + let host_bridge = HostBridgeBuilder::build(host_bridge_params, &config_client)?; let host_bridge_connected = host_bridge.is_localhost(); let enable_fs_watcher = host_bridge.is_localhost(); - Self { + Ok(Self { exit_reason: None, context: None, app: Application::init( @@ -264,7 +264,7 @@ impl FileTransferActivity { remote_params.protocol, remote_params.params.clone(), &config_client, - ), + )?, browser: Browser::new(&config_client), log_records: VecDeque::with_capacity(256), // 256 events is enough I guess walkdir: WalkdirStates::default(), @@ -280,7 +280,7 @@ impl FileTransferActivity { }, host_bridge_connected, remote_connected: false, - } + }) } fn host_bridge(&self) -> &FileExplorer { diff --git a/src/ui/context.rs b/src/ui/context.rs index 1ee3ff5..baecbf6 100644 --- a/src/ui/context.rs +++ b/src/ui/context.rs @@ -108,6 +108,10 @@ impl Context { pub fn error(&mut self) -> Option { self.error.take() } + + pub fn set_error(&mut self, error: String) { + self.error = Some(error); + } } impl Drop for Context {