6 Commits

Author SHA1 Message Date
Christian Visintin
4bebec369f fix: Issues with update checks (#363)
Some checks failed
Linux / build (push) Has been cancelled
MacOS / build (push) Has been cancelled
Windows / build (push) Has been cancelled
Removed error popup message if failed to check for updates.
Prevent long timeouts when checking for updates if the network is down or the DNS is not working.

closes #354
2025-10-02 21:27:51 +02:00
Christian Visintin
05c8613279 fix: Report a message while calculating total size of files to transfer. (#362)
* fix: Report a message while calculating total size of files to transfer.

Currently, in case of huge transfers the app may look frozen while calculating the transfer size. We should at least report to the user we are actually doing something.

closes #361

* ci: windows runner
2025-10-02 20:58:26 +02:00
veeso
205d2813ad perf: Migrated to libssh.org on Linux and MacOS for better ssh agent support.
Some checks failed
Linux / build (push) Has been cancelled
MacOS / build (push) Has been cancelled
Windows / build (push) Has been cancelled
closes #337
2025-09-20 18:13:20 +02:00
veeso
86660a0cc9 fix: SMB support for MacOS with vendored build of libsmbclient.
closes #334
2025-09-20 18:07:26 +02:00
veeso
3c79e812eb build: 0.19 deps 2025-09-06 16:40:01 +02:00
moshyfawn
0287e7706a fix: typo in file open error message (#349)
Some checks failed
Install.sh / build (push) Has been cancelled
Linux / build (push) Has been cancelled
MacOS / build (push) Has been cancelled
Windows / build (push) Has been cancelled
Close inactive issues / close-issues (push) Has been cancelled
2025-06-13 22:50:06 +02:00
27 changed files with 666 additions and 532 deletions

View File

@@ -4,7 +4,7 @@ on:
workflow_dispatch:
env:
TERMSCP_VERSION: "0.18.0"
TERMSCP_VERSION: "0.19.0"
jobs:
build-binaries:
@@ -29,8 +29,45 @@ jobs:
with:
toolchain: stable
targets: ${{ matrix.platform.target }}
- name: Install dependencies
run: |
brew update
brew install \
bison \
cpanminus \
cups \
flex \
gettext \
gmp \
gnutls \
icu4c \
jansson \
libarchive \
libbsd \
libunistring \
libgit2 \
libtirpc \
openldap \
pkg-config \
zlib
brew link --force bison
brew link --force cups
brew link --force flex
brew link --force gettext
brew link --force gmp
brew link --force gnutls
brew link --force icu4c
brew link --force jansson
brew link --force libarchive
brew link --force libbsd
brew link --force libgit2
brew link --force libtirpc
brew link --force libunistring
brew link --force openldap
brew link --force zlib
cpanm Parse::Yapp::Driver
- name: Build release
run: cargo build --release --target ${{ matrix.platform.target }}
run: cargo build --release --features smb-vendored --target ${{ matrix.platform.target }}
- name: Prepare artifact files
run: |
mkdir -p .artifact

View File

@@ -22,6 +22,13 @@ jobs:
with:
toolchain: stable
components: rustfmt, clippy
- name: Install dependencies
run: |
brew update
brew install \
pkg-config \
samba
brew link --force samba
- name: Build
run: cargo build
- name: Run tests

View File

@@ -15,7 +15,7 @@ env:
jobs:
build:
runs-on: windows-2019
runs-on: windows-latest
steps:
- uses: actions/checkout@v2

View File

@@ -1,6 +1,7 @@
# Changelog
- [Changelog](#changelog)
- [0.19.0](#0190)
- [0.18.0](#0180)
- [0.17.0](#0170)
- [0.16.1](#0161)
@@ -41,6 +42,18 @@
---
## 0.19.0
Released on 20/09/2025
- [Issue 356](https://github.com/veeso/termscp/issues/356): Fixed SSH auth issue not trying with the password if any RSA key was found.
- [Issue 334](https://github.com/veeso/termscp/issues/334): SMB support for MacOS with vendored build of libsmbclient.
- [Issue 337](https://github.com/veeso/termscp/issues/337): Migrated to libssh.org on Linux and MacOS for better ssh agent support.
- [Issue 361](https://github.com/veeso/termscp/issues/361): Report a message while calculating total size of files to transfer.
- [Issue 354](https://github.com/veeso/termscp/issues/354):
- Removed error popup message if failed to check for updates.
- Prevent long timeouts when checking for updates if the network is down or the DNS is not working.
## 0.18.0
Released on 10/06/2025

990
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,8 +10,8 @@ license = "MIT"
name = "termscp"
readme = "README.md"
repository = "https://github.com/veeso/termscp"
version = "0.18.0"
rust-version = "1.85.1"
version = "0.19.0"
rust-version = "1.87.0"
[package.metadata.rpm]
package = "termscp"
@@ -60,6 +60,7 @@ regex = "^1"
remotefs = "^0.3"
remotefs-aws-s3 = "0.4"
remotefs-kube = "0.4"
remotefs-smb = { version = "^0.3", optional = true }
remotefs-webdav = "^0.2"
rpassword = "^7"
self_update = { version = "^0.42", default-features = false, features = [
@@ -71,11 +72,11 @@ self_update = { version = "^0.42", default-features = false, features = [
] }
serde = { version = "^1", features = ["derive"] }
simplelog = "^0.12"
ssh2-config = "^0.5"
ssh2-config = "^0.6"
tempfile = "3"
thiserror = "2"
tokio = { version = "1.44", features = ["rt"] }
toml = "^0.8"
toml = "^0.9"
tui-realm-stdlib = "3"
tuirealm = "3"
tui-term = "0.2"
@@ -84,17 +85,20 @@ version-compare = "^0.2"
whoami = "^1.6"
wildmatch = "^2"
[target."cfg(not(target_os = \"macos\"))".dependencies]
remotefs-smb = { version = "^0.3", optional = true }
[target."cfg(target_family = \"unix\")".dependencies]
remotefs-ftp = { version = "^0.2", features = ["vendored", "native-tls"] }
remotefs-ssh = { version = "^0.6", features = ["ssh2-vendored"] }
remotefs-ftp = { version = "^0.3", features = [
"native-tls-vendored",
"native-tls",
] }
remotefs-ssh = { version = "^0.7", default-features = false, features = [
"find",
"libssh-vendored",
] }
uzers = "0.12"
[target."cfg(target_family = \"windows\")".dependencies]
remotefs-ftp = { version = "^0.2", features = ["native-tls"] }
remotefs-ssh = { version = "^0.6" }
remotefs-ftp = { version = "^0.3", features = ["native-tls"] }
remotefs-ssh = { version = "^0.7" }
[dev-dependencies]
pretty_assertions = "^1"

View File

@@ -71,7 +71,7 @@
</p>
<p align="center">Developed by <a href="https://veeso.me/" target="_blank">@veeso</a></p>
<p align="center">Current version: 0.18.0 10/06/2025</p>
<p align="center">Current version: 0.19.0 10/06/2025</p>
<p align="center">
<a href="https://opensource.org/licenses/MIT"

View File

@@ -10,8 +10,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
posix: { target_family = "unix" },
win: { target_family = "windows" },
// exclusive features
smb: { all(feature = "smb", not( macos )) },
smb_unix: { all(unix, feature = "smb", not(macos)) },
smb: { feature = "smb" },
smb_unix: { all(unix, feature = "smb") },
smb_windows: { all(windows, feature = "smb") }
}

View File

@@ -71,7 +71,7 @@
</p>
<p align="center">Entwickelt von <a href="https://veeso.me/" target="_blank">@veeso</a></p>
<p align="center">Aktuelle Version: 0.18.0 10/06/2025</p>
<p align="center">Aktuelle Version: 0.19.0 10/06/2025</p>
<p align="center">
<a href="https://opensource.org/licenses/MIT"

View File

@@ -71,7 +71,7 @@
</p>
<p align="center">Desarrollado por <a href="https://veeso.me/" target="_blank">@veeso</a></p>
<p align="center">Versión actual: 0.18.0 10/06/2025</p>
<p align="center">Versión actual: 0.19.0 10/06/2025</p>
<p align="center">
<a href="https://opensource.org/licenses/MIT"

View File

@@ -71,7 +71,7 @@
</p>
<p align="center">Développé par <a href="https://veeso.me/" target="_blank">@veeso</a></p>
<p align="center">Version actuelle: 0.18.0 10/06/2025</p>
<p align="center">Version actuelle: 0.19.0 10/06/2025</p>
<p align="center">
<a href="https://opensource.org/licenses/MIT"

View File

@@ -71,7 +71,7 @@
</p>
<p align="center">Sviluppato da <a href="https://veeso.me/" target="_blank">@veeso</a></p>
<p align="center">Versione corrente: 0.18.0 10/06/2025</p>
<p align="center">Versione corrente: 0.19.0 10/06/2025</p>
<p align="center">
<a href="https://opensource.org/licenses/MIT"

View File

@@ -71,7 +71,7 @@
</p>
<p align="center">Desenvolvido por <a href="https://veeso.me/" target="_blank">@veeso</a></p>
<p align="center">Versão atual: 0.18.0 10/06/2025</p>
<p align="center">Versão atual: 0.19.0 10/06/2025</p>
<p align="center">
<a href="https://opensource.org/licenses/MIT"

View File

@@ -71,7 +71,7 @@
</p>
<p align="center"><a href="https://veeso.me/" target="_blank">@veeso</a> 开发</p>
<p align="center">当前版本: 0.18.0 10/06/2025</p>
<p align="center">当前版本: 0.19.0 10/06/2025</p>
<p align="center">
<a href="https://opensource.org/licenses/MIT"

View File

@@ -8,7 +8,7 @@
# -f, -y, --force, --yes
# Skip the confirmation prompt during installation
TERMSCP_VERSION="0.18.0"
TERMSCP_VERSION="0.19.0"
GITHUB_URL="https://github.com/veeso/termscp/releases/download/v${TERMSCP_VERSION}"
DEB_URL_AMD64="${GITHUB_URL}/termscp_${TERMSCP_VERSION}_amd64.deb"
DEB_URL_AARCH64="${GITHUB_URL}/termscp_${TERMSCP_VERSION}_arm64.deb"

View File

@@ -35,7 +35,7 @@
<span translate="getStarted.windows.moderation">Consider that Chocolatey moderation can take up to a few weeks
since last release, so if the latest version is not available yet,
you can install it downloading the ZIP file from</span>
<a href="https://github.com/veeso/termscp/releases/latest/download/termscp.0.18.0.nupkg"
<a href="https://github.com/veeso/termscp/releases/latest/download/termscp.0.19.0.nupkg"
target="_blank">Github</a>
<span translate="getStarted.windows.then">and then, from the ZIP directory, install it via</span>
</p>
@@ -74,7 +74,7 @@
On Debian based distros, you can install termscp using the Deb
package via:
</p>
<pre><span class="function">wget</span> -O termscp.deb <span class="string">https://github.com/veeso/termscp/releases/latest/download/termscp_0.18.0_amd64.deb</span>
<pre><span class="function">wget</span> -O termscp.deb <span class="string">https://github.com/veeso/termscp/releases/latest/download/termscp_0.19.0_amd64.deb</span>
sudo <span class="function">dpkg</span> -i <span class="string">termscp.deb</span></pre>
</div>
<h3>

View File

@@ -12,7 +12,7 @@
</button>
<div class="p-4 my-4 text-sm text-green-800 rounded-lg bg-green-50">
<p class="text-lg">
<span translate="intro.versionAlert">termscp 0.18.0 is NOW out! Download it from</span>&nbsp;
<span translate="intro.versionAlert">termscp 0.19.0 is NOW out! Download it from</span>&nbsp;
<a href="/get-started.html" translate="intro.here">here!</a>
</p>
</div>

View File

@@ -12,7 +12,7 @@
"intro": {
"caption": "A feature rich terminal UI file transfer and explorer with support for SCP/SFTP/FTP/Kube/S3/WebDAV",
"getStarted": "Get started →",
"versionAlert": "termscp 0.18.0 is NOW out! Download it from",
"versionAlert": "termscp 0.19.0 is NOW out! Download it from",
"here": "here",
"features": {
"handy": {

View File

@@ -12,7 +12,7 @@
"intro": {
"caption": "Un explorador y transferencia de archivos de terminal rico en funciones, con apoyo para SCP/SFTP/FTP/Kube/S3/WebDAV",
"getStarted": "Para iniciar →",
"versionAlert": "termscp 0.18.0 ya está disponible! Descárgalo desde",
"versionAlert": "termscp 0.19.0 ya está disponible! Descárgalo desde",
"here": "aquì",
"features": {
"handy": {

View File

@@ -12,7 +12,7 @@
"intro": {
"caption": "Un file transfer et navigateur de terminal riche en fonctionnalités avec support pour SCP/SFTP/FTP/Kube/S3/WebDAV",
"getStarted": "Pour commencer →",
"versionAlert": "termscp 0.18.0 est maintenant sorti! Télécharge-le depuis",
"versionAlert": "termscp 0.19.0 est maintenant sorti! Télécharge-le depuis",
"here": "ici",
"features": {
"handy": {

View File

@@ -12,7 +12,7 @@
"intro": {
"caption": "Un file transfer ed explorer ricco di funzionalità con supporto per SFTP/SCP/FTP/S3",
"getStarted": "Installa termscp →",
"versionAlert": "termscp 0.18.0 è ORA disponbile! Scaricalo da",
"versionAlert": "termscp 0.19.0 è ORA disponbile! Scaricalo da",
"here": "qui",
"features": {
"handy": {

View File

@@ -12,7 +12,7 @@
"intro": {
"caption": "功能丰富的终端 UI 文件传输和浏览器,支持 SCP/SFTP/FTP/Kube/S3/WebDAV",
"getStarted": "开始 →",
"versionAlert": "termscp 0.18.0 现已发布! 从下载",
"versionAlert": "termscp 0.19.0 现已发布! 从下载",
"here": "这里",
"features": {
"handy": {

View File

@@ -13,6 +13,10 @@ use remotefs_kube::KubeMultiPodFs as KubeFs;
use remotefs_smb::SmbOptions;
#[cfg(smb)]
use remotefs_smb::{SmbCredentials, SmbFs};
#[cfg(windows)]
use remotefs_ssh::LibSsh2Session as SshSession;
#[cfg(unix)]
use remotefs_ssh::LibSshSession as SshSession;
use remotefs_ssh::{ScpFs, SftpFs, SshAgentIdentity, SshConfigParseRule, SshOpts};
use remotefs_webdav::WebDAVFs;
@@ -138,12 +142,18 @@ impl RemoteFsBuilder {
}
/// Build scp client
fn scp_client(params: GenericProtocolParams, config_client: &ConfigClient) -> ScpFs {
fn scp_client(
params: GenericProtocolParams,
config_client: &ConfigClient,
) -> ScpFs<SshSession> {
Self::build_ssh_opts(params, config_client).into()
}
/// Build sftp client
fn sftp_client(params: GenericProtocolParams, config_client: &ConfigClient) -> SftpFs {
fn sftp_client(
params: GenericProtocolParams,
config_client: &ConfigClient,
) -> SftpFs<SshSession> {
Self::build_ssh_opts(params, config_client).into()
}

View File

@@ -2,6 +2,8 @@
//!
//! Automatic update module. This module is used to upgrade the current version of termscp to the latest available on Github
use std::net::ToSocketAddrs as _;
use self_update::backends::github::Update as GithubUpdater;
pub use self_update::errors::Error as UpdateError;
use self_update::update::Release as UpdRelease;
@@ -67,6 +69,9 @@ impl Update {
/// otherwise if no version is available, return None
/// In case of error returns Error with the error description
pub fn is_new_version_available() -> Result<Option<Release>, UpdateError> {
// check if api.github.com is reachable before doing anything
Self::check_github_api_reachable()?;
info!("Checking whether a new version is available...");
GithubUpdater::configure()
// Set default options
@@ -83,6 +88,27 @@ impl Update {
.map(Self::check_version)
}
/// Check if api.github.com is reachable
/// This is useful to avoid long timeouts when the network is down
/// or the DNS is not working
fn check_github_api_reachable() -> Result<(), UpdateError> {
let Some(socket_addr) = ("api.github.com", 443)
.to_socket_addrs()
.ok()
.and_then(|mut i| i.next())
else {
error!("Could not resolve api.github.com");
return Err(UpdateError::Network(
"Could not resolve api.github.com".into(),
));
};
// just try to open a connection to api.github.com with a timeout of 5 seconds with tcp
std::net::TcpStream::connect_timeout(&socket_addr, std::time::Duration::from_secs(5))
.map(|_| ())
.map_err(|e| UpdateError::Network(format!("Could not reach api.github.com: {e}")))
}
/// In case received version is newer than current one, version as Some is returned; otherwise None
fn check_version(r: Release) -> Option<Release> {
debug!("got version from GitHub: {}", r.version);
@@ -212,4 +238,9 @@ mod test {
assert!(!Update::is_new_version_higher("0.9.9", "0.10.1"));
assert!(!Update::is_new_version_higher("0.10.9", "0.11.0"));
}
#[test]
fn test_should_check_whether_github_api_is_reachable() {
assert!(Update::check_github_api_reachable().is_ok());
}
}

View File

@@ -223,10 +223,7 @@ impl AuthActivity {
}
Err(err) => {
// Report error
error!("Failed to get latest version: {}", err);
self.mount_error(
format!("Could not check for new updates: {err}").as_str(),
);
error!("Failed to get latest version: {err}",);
}
}
} else {

View File

@@ -186,7 +186,7 @@ impl FileTransferActivity {
Ok(_) => self.log(LogLevel::Info, format!("Opened file `{}`", p.display())),
Err(err) => self.log(
LogLevel::Error,
format!("Failed to open filoe `{}`: {}", p.display(), err),
format!("Failed to open file `{}`: {}", p.display(), err),
),
}
// NOTE: clear screen in order to prevent crap on stderr

View File

@@ -1260,7 +1260,10 @@ impl FileTransferActivity {
/// Get total size of transfer for host_bridgehost
fn get_total_transfer_size_host(&mut self, entry: &File) -> usize {
if entry.is_dir() {
// mount message to tell we are calculating size
self.mount_blocking_wait("Calculating transfer size…");
let sz = if entry.is_dir() {
// List dir
match self.host_bridge.list_dir(entry.path()) {
Ok(files) => files
@@ -1281,12 +1284,18 @@ impl FileTransferActivity {
}
} else {
entry.metadata.size as usize
}
};
self.umount_wait();
sz
}
/// Get total size of transfer for remote host
fn get_total_transfer_size_remote(&mut self, entry: &File) -> usize {
if entry.is_dir() {
// mount message to tell we are calculating size
self.mount_blocking_wait("Calculating transfer size…");
let sz = if entry.is_dir() {
// List directory
match self.client.list_dir(entry.path()) {
Ok(files) => files
@@ -1307,7 +1316,11 @@ impl FileTransferActivity {
}
} else {
entry.metadata.size as usize
}
};
self.umount_wait();
sz
}
// file changed