Removed progress callback (not a priority atm)

This commit is contained in:
ChristianVisintin
2020-11-29 12:35:51 +01:00
parent e84e4ab2b1
commit 840a2685bf
3 changed files with 75 additions and 131 deletions

View File

@@ -23,17 +23,14 @@
* *
*/ */
use std::path::{Path, PathBuf};
use std::fs::File; use std::fs::File;
use std::path::{Path, PathBuf};
use crate::fs::FsEntry; use crate::fs::FsEntry;
// Transfers // Transfers
pub mod sftp_transfer; pub mod sftp_transfer;
// Types
pub type ProgressCallback = dyn Fn(usize, usize);
/// ## FileTransferProtocol /// ## FileTransferProtocol
/// ///
/// This enum defines the different transfer protocol available in TermSCP /// This enum defines the different transfer protocol available in TermSCP
@@ -65,7 +62,9 @@ pub enum FileTransferError {
impl std::fmt::Display for FileTransferError { impl std::fmt::Display for FileTransferError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let err: String = match self { let err: String = match self {
FileTransferError::AuthenticationFailed => String::from("Authentication failed: bad credentials"), FileTransferError::AuthenticationFailed => {
String::from("Authentication failed: bad credentials")
}
FileTransferError::BadAddress => String::from("Bad address syntax"), FileTransferError::BadAddress => String::from("Bad address syntax"),
FileTransferError::ConnectionError => String::from("Connection error"), FileTransferError::ConnectionError => String::from("Connection error"),
FileTransferError::DirStatFailed => String::from("Could not stat directory"), FileTransferError::DirStatFailed => String::from("Could not stat directory"),
@@ -82,71 +81,75 @@ impl std::fmt::Display for FileTransferError {
} }
/// ## FileTransfer /// ## FileTransfer
/// ///
/// File transfer trait must be implemented by all the file transfers and defines the method used by a generic file transfer /// File transfer trait must be implemented by all the file transfers and defines the method used by a generic file transfer
pub trait FileTransfer { pub trait FileTransfer {
/// ### connect /// ### connect
/// ///
/// Connect to the remote server /// Connect to the remote server
fn connect(&mut self, address: String, port: u16, username: Option<String>, password: Option<String>) -> Result<(), FileTransferError>; fn connect(
&mut self,
address: String,
port: u16,
username: Option<String>,
password: Option<String>,
) -> Result<(), FileTransferError>;
/// ### disconnect /// ### disconnect
/// ///
/// Disconnect from the remote server /// Disconnect from the remote server
fn disconnect(&mut self) -> Result<(), FileTransferError>; fn disconnect(&mut self) -> Result<(), FileTransferError>;
/// ### is_connected /// ### is_connected
/// ///
/// Indicates whether the client is connected to remote /// Indicates whether the client is connected to remote
fn is_connected(&self) -> bool; fn is_connected(&self) -> bool;
/// ### pwd /// ### pwd
/// ///
/// Print working directory /// Print working directory
fn pwd(&self) -> Result<PathBuf, FileTransferError>; fn pwd(&self) -> Result<PathBuf, FileTransferError>;
/// ### change_dir /// ### change_dir
/// ///
/// Change working directory /// Change working directory
fn change_dir(&mut self, dir: &Path) -> Result<PathBuf, FileTransferError>; fn change_dir(&mut self, dir: &Path) -> Result<PathBuf, FileTransferError>;
/// ### list_dir /// ### list_dir
/// ///
/// List directory entries /// List directory entries
fn list_dir(&self, path: &Path) -> Result<Vec<FsEntry>, FileTransferError>; fn list_dir(&self, path: &Path) -> Result<Vec<FsEntry>, FileTransferError>;
/// ### mkdir /// ### mkdir
/// ///
/// Make directory /// Make directory
fn mkdir(&self, dir: &Path) -> Result<(), FileTransferError>; fn mkdir(&self, dir: &Path) -> Result<(), FileTransferError>;
/// ### remove /// ### remove
/// ///
/// Remove a file or a directory /// Remove a file or a directory
fn remove(&self, file: &FsEntry) -> Result<(), FileTransferError>; fn remove(&self, file: &FsEntry) -> Result<(), FileTransferError>;
/// ### rename /// ### rename
/// ///
/// Rename file or a directory /// Rename file or a directory
fn rename(&self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError>; fn rename(&self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError>;
/// ### send_file /// ### send_file
/// ///
/// Send file to remote /// Send file to remote
/// File name is referred to the name of the file as it will be saved /// File name is referred to the name of the file as it will be saved
/// Data contains the file data /// Data contains the file data
fn send_file(&self, file_name: &Path, file: &mut File, prog_cb: Option<Box<ProgressCallback>>) -> Result<(), FileTransferError>; fn send_file(&self, file_name: &Path, file: &mut File) -> Result<(), FileTransferError>;
/// ### recv_file /// ### recv_file
/// ///
/// Receive file from remote with provided name /// Receive file from remote with provided name
fn recv_file(&self, file_name: &Path, dest_file: &mut File, prog_cb: Option<Box<ProgressCallback>>) -> Result<(), FileTransferError>; fn recv_file(&self, file_name: &Path, dest_file: &mut File) -> Result<(), FileTransferError>;
} }

View File

@@ -27,7 +27,7 @@
extern crate ssh2; extern crate ssh2;
// Locals // Locals
use super::{FileTransfer, FileTransferError, ProgressCallback}; use super::{FileTransfer, FileTransferError};
use crate::fs::{FsDirectory, FsEntry, FsFile}; use crate::fs::{FsDirectory, FsEntry, FsFile};
// Includes // Includes
@@ -178,7 +178,7 @@ impl FileTransfer for SftpFileTransfer {
} }
/// ### is_connected /// ### is_connected
/// ///
/// Indicates whether the client is connected to remote /// Indicates whether the client is connected to remote
fn is_connected(&self) -> bool { fn is_connected(&self) -> bool {
self.session.is_some() self.session.is_some()
@@ -369,7 +369,7 @@ impl FileTransfer for SftpFileTransfer {
} }
/// ### rename /// ### rename
/// ///
/// Rename file or a directory /// Rename file or a directory
fn rename(&self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError> { fn rename(&self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError> {
match self.sftp.as_ref() { match self.sftp.as_ref() {
@@ -380,11 +380,11 @@ impl FileTransfer for SftpFileTransfer {
// Get abs path of entry // Get abs path of entry
let abs_src: PathBuf = match file { let abs_src: PathBuf = match file {
FsEntry::Directory(dir) => dir.abs_path.clone(), FsEntry::Directory(dir) => dir.abs_path.clone(),
FsEntry::File(file) => file.abs_path.clone() FsEntry::File(file) => file.abs_path.clone(),
}; };
match sftp.rename(abs_src.as_path(), abs_dst.as_path(), None) { match sftp.rename(abs_src.as_path(), abs_dst.as_path(), None) {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(_) => Err(FileTransferError::FileCreateDenied) Err(_) => Err(FileTransferError::FileCreateDenied),
} }
} }
} }
@@ -395,18 +395,13 @@ impl FileTransfer for SftpFileTransfer {
/// Send file to remote /// Send file to remote
/// File name is referred to the name of the file as it will be saved /// File name is referred to the name of the file as it will be saved
/// Data contains the file data /// Data contains the file data
fn send_file( fn send_file(&self, file_name: &Path, file: &mut File) -> Result<(), FileTransferError> {
&self,
file_name: &Path,
file: &mut File,
prog_cb: Option<Box<ProgressCallback>>,
) -> Result<(), FileTransferError> {
match self.sftp.as_ref() { match self.sftp.as_ref() {
None => Err(FileTransferError::UninitializedSession), None => Err(FileTransferError::UninitializedSession),
Some(sftp) => { Some(sftp) => {
let remote_path: PathBuf = self.get_abs_path(file_name); let remote_path: PathBuf = self.get_abs_path(file_name);
// Get file size // Get file size
let file_size: usize = file.seek(std::io::SeekFrom::End(0)).unwrap_or(0) as usize; //let file_size: usize = file.seek(std::io::SeekFrom::End(0)).unwrap_or(0) as usize;
// rewind // rewind
if let Err(err) = file.seek(std::io::SeekFrom::Start(0)) { if let Err(err) = file.seek(std::io::SeekFrom::Start(0)) {
return Err(FileTransferError::IoErr(err)); return Err(FileTransferError::IoErr(err));
@@ -414,13 +409,13 @@ impl FileTransfer for SftpFileTransfer {
// Open remote file // Open remote file
match sftp.create(remote_path.as_path()) { match sftp.create(remote_path.as_path()) {
Ok(mut rhnd) => { Ok(mut rhnd) => {
let mut total_bytes_written: usize = 0; //let mut total_bytes_written: usize = 0;
loop { loop {
// Read till you can // Read till you can
let mut buffer: [u8; 8192] = [0; 8192]; let mut buffer: [u8; 8192] = [0; 8192];
match file.read(&mut buffer) { match file.read(&mut buffer) {
Ok(bytes_read) => { Ok(bytes_read) => {
total_bytes_written += bytes_read; //total_bytes_written += bytes_read;
if bytes_read == 0 { if bytes_read == 0 {
break; break;
} else { } else {
@@ -428,10 +423,6 @@ impl FileTransfer for SftpFileTransfer {
if let Err(err) = rhnd.write(&buffer) { if let Err(err) = rhnd.write(&buffer) {
return Err(FileTransferError::IoErr(err)); return Err(FileTransferError::IoErr(err));
} }
// Call callback
if let Some(ref cb) = prog_cb {
cb(total_bytes_written, file_size);
}
} }
} }
Err(err) => return Err(FileTransferError::IoErr(err)), Err(err) => return Err(FileTransferError::IoErr(err)),
@@ -448,12 +439,7 @@ impl FileTransfer for SftpFileTransfer {
/// ### recv_file /// ### recv_file
/// ///
/// Receive file from remote with provided name /// Receive file from remote with provided name
fn recv_file( fn recv_file(&self, file_name: &Path, dest_file: &mut File) -> Result<(), FileTransferError> {
&self,
file_name: &Path,
dest_file: &mut File,
prog_cb: Option<Box<ProgressCallback>>,
) -> Result<(), FileTransferError> {
match self.sftp.as_ref() { match self.sftp.as_ref() {
None => Err(FileTransferError::UninitializedSession), None => Err(FileTransferError::UninitializedSession),
Some(sftp) => { Some(sftp) => {
@@ -465,20 +451,19 @@ impl FileTransfer for SftpFileTransfer {
// Open remote file // Open remote file
match sftp.open(remote_path.as_path()) { match sftp.open(remote_path.as_path()) {
Ok(mut rhnd) => { Ok(mut rhnd) => {
let file_size: usize = // let file_size: usize = rhnd.seek(std::io::SeekFrom::End(0)).unwrap_or(0) as usize;
rhnd.seek(std::io::SeekFrom::End(0)).unwrap_or(0) as usize;
// rewind // rewind
if let Err(err) = rhnd.seek(std::io::SeekFrom::Start(0)) { if let Err(err) = rhnd.seek(std::io::SeekFrom::Start(0)) {
return Err(FileTransferError::IoErr(err)); return Err(FileTransferError::IoErr(err));
}; };
// Write local file // Write local file
let mut total_bytes_written: usize = 0; // let mut total_bytes_written: usize = 0;
loop { loop {
// Read till you can // Read till you can
let mut buffer: [u8; 8192] = [0; 8192]; let mut buffer: [u8; 8192] = [0; 8192];
match rhnd.read(&mut buffer) { match rhnd.read(&mut buffer) {
Ok(bytes_read) => { Ok(bytes_read) => {
total_bytes_written += bytes_read; // total_bytes_written += bytes_read;
if bytes_read == 0 { if bytes_read == 0 {
break; break;
} else { } else {
@@ -486,10 +471,6 @@ impl FileTransfer for SftpFileTransfer {
if let Err(err) = dest_file.write(&buffer) { if let Err(err) = dest_file.write(&buffer) {
return Err(FileTransferError::IoErr(err)); return Err(FileTransferError::IoErr(err));
} }
// Call callback
if let Some(ref cb) = prog_cb {
cb(total_bytes_written, file_size);
}
} }
} }
Err(err) => return Err(FileTransferError::IoErr(err)), Err(err) => return Err(FileTransferError::IoErr(err)),
@@ -696,11 +677,7 @@ mod tests {
.unwrap(); .unwrap();
// Receive file // Receive file
assert!(client assert!(client
.recv_file( .recv_file(PathBuf::from("readme.txt").as_path(), &mut dst_file_hnd)
PathBuf::from("readme.txt").as_path(),
&mut dst_file_hnd,
Some(Box::new(progress_callback))
)
.is_ok()); .is_ok());
// Disconnect // Disconnect
assert!(client.disconnect().is_ok()); assert!(client.disconnect().is_ok());
@@ -730,11 +707,7 @@ mod tests {
.unwrap(); .unwrap();
// Receive file // Receive file
assert!(client assert!(client
.recv_file( .recv_file(PathBuf::from("omar.txt").as_path(), &mut dst_file_hnd)
PathBuf::from("omar.txt").as_path(),
&mut dst_file_hnd,
Some(Box::new(progress_callback))
)
.is_err()); .is_err());
// Disconnect // Disconnect
assert!(client.disconnect().is_ok()); assert!(client.disconnect().is_ok());
@@ -767,11 +740,7 @@ mod tests {
let mut dst_file_hnd: File = OpenOptions::new().read(true).open(dst_file.path()).unwrap(); let mut dst_file_hnd: File = OpenOptions::new().read(true).open(dst_file.path()).unwrap();
// Receive file // Receive file
assert!(client assert!(client
.recv_file( .recv_file(PathBuf::from("readme.txt").as_path(), &mut dst_file_hnd)
PathBuf::from("readme.txt").as_path(),
&mut dst_file_hnd,
Some(Box::new(progress_callback))
)
.is_err()); .is_err());
// Disconnect // Disconnect
assert!(client.disconnect().is_ok()); assert!(client.disconnect().is_ok());
@@ -794,8 +763,4 @@ mod tests {
assert!(client.disconnect().is_ok()); assert!(client.disconnect().is_ok());
} }
*/ */
fn progress_callback(it: usize, max: usize) {
assert!(it <= max);
}
} }

View File

@@ -34,7 +34,7 @@ use crate::filetransfer::FileTransferProtocol;
// File transfer // File transfer
use crate::filetransfer::sftp_transfer::SftpFileTransfer; use crate::filetransfer::sftp_transfer::SftpFileTransfer;
use crate::filetransfer::{FileTransfer, ProgressCallback}; use crate::filetransfer::FileTransfer;
use crate::fs::FsEntry; use crate::fs::FsEntry;
// Includes // Includes
@@ -55,9 +55,6 @@ use tui::{
}; };
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
// Holder for current upload progress
static mut UPLOAD_PROGRESS: f64 = 0.0; // VERY VERY BAD CODING
// Types // Types
type DialogCallback = fn(&mut FileTransferActivity); type DialogCallback = fn(&mut FileTransferActivity);
type OnInputSubmitCallback = fn(&mut FileTransferActivity, String); type OnInputSubmitCallback = fn(&mut FileTransferActivity, String);
@@ -315,22 +312,15 @@ impl FileTransferActivity {
FsEntry::Directory(dir) => dir.name.clone(), FsEntry::Directory(dir) => dir.name.clone(),
FsEntry::File(file) => file.name.clone(), FsEntry::File(file) => file.name.clone(),
}; };
self.input_mode = InputMode::Popup(PopupType::Progress(format!( self.input_mode =
"Uploading \"{}\"...", InputMode::Popup(PopupType::Wait(format!("Uploading \"{}\"...", file_name)));
file_name // Draw
))); self.draw();
// Get remote path
let remote_path: PathBuf = match dst_name { let remote_path: PathBuf = match dst_name {
Some(s) => PathBuf::from(s.as_str()), Some(s) => PathBuf::from(s.as_str()),
None => PathBuf::from(file_name.as_str()), None => PathBuf::from(file_name.as_str()),
}; };
let prog_cb: Box<ProgressCallback> = Box::new(|c, sz| {
// Progress callback
let percentage: f64 = ((c as f64) * 100.0) / (sz as f64);
unsafe {
UPLOAD_PROGRESS = percentage;
}
// FIXME: can't draw here...
});
// Match entry // Match entry
match entry { match entry {
FsEntry::File(file) => { FsEntry::File(file) => {
@@ -343,31 +333,26 @@ impl FileTransferActivity {
.local .local
.open_file_read(file.abs_path.as_path()) .open_file_read(file.abs_path.as_path())
{ {
Ok(mut f) => { Ok(mut f) => match self.client.send_file(remote_path.as_path(), &mut f) {
match self Ok(_) => self.log(
.client LogLevel::Info,
.send_file(remote_path.as_path(), &mut f, Some(prog_cb)) format!(
{ "Saved file \"{}\" to \"{}\"",
Ok(_) => self.log( file.abs_path.display(),
LogLevel::Info, remote_path.display()
format!( )
"Saved file \"{}\" to \"{}\"", .as_ref(),
file.abs_path.display(), ),
remote_path.display() Err(err) => self.log(
) LogLevel::Error,
.as_ref(), format!(
), "Failed to upload file \"{}\": {}",
Err(err) => self.log( file.abs_path.display(),
LogLevel::Error, err
format!( )
"Failed to upload file \"{}\": {}", .as_ref(),
file.abs_path.display(), ),
err },
)
.as_ref(),
),
}
}
Err(err) => { Err(err) => {
// Report error // Report error
self.log( self.log(
@@ -441,18 +426,10 @@ impl FileTransferActivity {
FsEntry::Directory(dir) => dir.name.clone(), FsEntry::Directory(dir) => dir.name.clone(),
FsEntry::File(file) => file.name.clone(), FsEntry::File(file) => file.name.clone(),
}; };
self.input_mode = InputMode::Popup(PopupType::Progress(format!( self.input_mode =
"Downloading \"{}\"...", InputMode::Popup(PopupType::Wait(format!("Downloading \"{}\"...", file_name)));
file_name // Draw
))); self.draw();
let prog_cb: Box<ProgressCallback> = Box::new(|c, sz| {
// Progress callback
let percentage: f64 = ((c as f64) * 100.0) / (sz as f64);
unsafe {
UPLOAD_PROGRESS = percentage;
}
// FIXME: can't draw here...
});
// Match entry // Match entry
match entry { match entry {
FsEntry::File(file) => { FsEntry::File(file) => {
@@ -473,11 +450,10 @@ impl FileTransferActivity {
{ {
Ok(mut local_file) => { Ok(mut local_file) => {
// Download file from remote // Download file from remote
match self.client.recv_file( match self
file.abs_path.as_path(), .client
&mut local_file, .recv_file(file.abs_path.as_path(), &mut local_file)
Some(prog_cb), {
) {
Ok(_) => self.log( Ok(_) => self.log(
LogLevel::Info, LogLevel::Info,
format!( format!(