use std::fs::File;
use std::io;
use std::path::Path;
use suppaftp::native_tls::TlsConnector;
use suppaftp::types::FileType;
use suppaftp::{Mode, NativeTlsConnector};
use super::{FtpError, FtpStream};
pub fn quit(mut ftp: Option<FtpStream>) {
if let Some(mut ftp) = ftp.take() {
match ftp.quit() {
Ok(_) => println!("OK"),
Err(err) => eprintln!("Failed to disconnect from remote: {err}"),
}
}
}
pub fn appe(ftp: &mut FtpStream, local: &Path, dest: &str) {
let mut reader = match File::open(local) {
Ok(r) => r,
Err(err) => {
eprintln!("Failed to open local file for read: {err}");
return;
}
};
match ftp.append_file(dest, &mut reader) {
Ok(_) => println!("OK"),
Err(err) => eprintln!("APPE error: {err}"),
}
}
pub fn cdup(ftp: &mut FtpStream) {
match ftp.cdup() {
Ok(_) => println!("OK"),
Err(err) => eprintln!("CDUP error: {err}"),
}
}
pub fn connect(remote: &str, secure: bool) -> Option<FtpStream> {
let mut stream: FtpStream = match FtpStream::connect(remote) {
Ok(c) => c,
Err(err) => {
eprintln!("Failed to connect to remote: {err}");
return None;
}
};
if secure {
let ctx = match TlsConnector::builder()
.danger_accept_invalid_certs(true)
.danger_accept_invalid_hostnames(true)
.build()
{
Ok(tls) => tls,
Err(err) => {
eprintln!("Failed to setup TLS stream: {err}");
return None;
}
};
let address: &str = remote.split(':').next().unwrap_or(remote);
stream = match stream.into_secure(NativeTlsConnector::from(ctx), address) {
Ok(s) => s,
Err(err) => {
eprintln!("Failed to setup TLS stream: {err}");
return None;
}
};
}
if let Err(err) = stream.transfer_type(FileType::Binary) {
eprintln!("Failed to set transfer type to binary: {err}");
}
println!("OK");
Some(stream)
}
pub fn cwd(ftp: &mut FtpStream, dir: &str) {
match ftp.cwd(dir) {
Ok(_) => println!("OK"),
Err(err) => eprintln!("CWD error: {err}"),
}
}
pub fn feat(ftp: &mut FtpStream) {
match ftp.feat() {
Ok(features) => {
for (feature, value) in features.iter() {
if let Some(value) = value {
println!("{feature}: {value}");
} else {
println!("{feature}");
}
}
}
Err(err) => eprintln!("FEAT error: {err}"),
}
}
pub fn opts(ftp: &mut FtpStream, opt: String, value: Option<String>) {
match ftp.opts(opt, value) {
Ok(()) => {
println!("OPTS OK");
}
Err(err) => eprintln!("OPTS error: {err}"),
}
}
pub fn list(ftp: &mut FtpStream, p: Option<&str>) {
match ftp.list(p) {
Ok(files) => {
files.iter().for_each(|f| println!("{f}"));
}
Err(err) => eprintln!("LIST error: {err}"),
}
}
pub fn mlst(ftp: &mut FtpStream, p: Option<&str>) {
match ftp.mlst(p) {
Ok(file) => {
println!("{file}");
}
Err(err) => eprintln!("MLST error: {err}"),
}
}
pub fn mlsd(ftp: &mut FtpStream, p: Option<&str>) {
match ftp.mlsd(p) {
Ok(files) => {
files.iter().for_each(|f| println!("{f}"));
}
Err(err) => eprintln!("MLSD error: {err}"),
}
}
pub fn login(ftp: &mut FtpStream) {
let username: String = match rpassword::prompt_password("Username: ") {
Ok(u) => u,
Err(err) => {
eprintln!("Could not read username: {err}");
return;
}
};
println!();
let password: String = match rpassword::prompt_password("Password: ") {
Ok(p) => p,
Err(err) => {
eprintln!("Could not read password: {err}");
return;
}
};
println!();
match ftp.login(username.as_str(), password.as_str()) {
Ok(_) => println!("OK"),
Err(err) => eprintln!("LOGIN error: {err}"),
}
}
pub fn mdtm(ftp: &mut FtpStream, f: &str) {
match ftp.mdtm(f) {
Ok(time) => println!("OK: {time}"),
Err(err) => eprintln!("MDTM error: {err}"),
}
}
pub fn mkdir(ftp: &mut FtpStream, f: &str) {
match ftp.mkdir(f) {
Ok(_) => println!("OK"),
Err(err) => eprintln!("MDTM error: {err}"),
}
}
pub fn set_mode(ftp: &mut FtpStream, mode: Mode) {
ftp.set_mode(mode);
println!("OK");
}
pub fn noop(ftp: &mut FtpStream) {
match ftp.noop() {
Ok(_) => println!("OK"),
Err(err) => eprintln!("NOOP error: {err}"),
}
}
pub fn put(ftp: &mut FtpStream, local: &Path, dest: &str) {
let mut reader = match File::open(local) {
Ok(r) => r,
Err(err) => {
eprintln!("Failed to open local file for read: {err}");
return;
}
};
match ftp.put_file(dest, &mut reader) {
Ok(_) => println!("OK"),
Err(err) => eprintln!("PUT error: {err}"),
}
}
pub fn pwd(ftp: &mut FtpStream) {
match ftp.pwd() {
Ok(p) => println!("OK: {p}"),
Err(err) => eprintln!("PWD error: {err}"),
}
}
pub fn rename(ftp: &mut FtpStream, src: &str, dest: &str) {
match ftp.rename(src, dest) {
Ok(_) => println!("OK"),
Err(err) => eprintln!("RENAME error: {err}"),
}
}
pub fn retr(ftp: &mut FtpStream, file: &str, dest: &Path) {
let mut dest: File = match File::create(dest) {
Ok(d) => d,
Err(err) => {
eprintln!("Failed to open destination file: {err}");
return;
}
};
match ftp.retr(file, move |reader| {
io::copy(reader, &mut dest)
.map(|_| ())
.map_err(FtpError::ConnectionError)
}) {
Ok(_) => println!("OK"),
Err(err) => eprintln!("RETR error: {err}"),
}
}
pub fn rm(ftp: &mut FtpStream, file: &str) {
match ftp.rm(file) {
Ok(_) => println!("OK"),
Err(err) => eprintln!("RM error: {err}"),
}
}
pub fn rmdir(ftp: &mut FtpStream, dir: &str) {
match ftp.rmdir(dir) {
Ok(_) => println!("OK"),
Err(err) => eprintln!("RMDIR error: {err}"),
}
}
pub fn size(ftp: &mut FtpStream, file: &str) {
match ftp.size(file) {
Ok(size) => println!("OK: {size}"),
Err(err) => eprintln!("SIZE error: {err}"),
}
}