Skip to content

Commit

Permalink
feat: FEAT and OPTS commands (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
veeso committed Sep 7, 2023
1 parent 7a3f9e4 commit 5bf40b4
Show file tree
Hide file tree
Showing 27 changed files with 336 additions and 115 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

- [Changelog](#changelog)
- [5.2.0](#520)
- [5.1.2](#512)
- [5.1.1](#511)
- [5.1.0](#510)
Expand All @@ -26,6 +27,14 @@

---

## 5.2.0

Released on 07/09/2023

- Implemented [RFC 2389](https://www.rfc-editor.org/rfc/rfc2389)
- Added `FEAT` command
- Added `OPTS` command

## 5.1.2

Released on 14/06/2023
Expand Down
6 changes: 2 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
[workspace]
members = [
"suppaftp",
"suppaftp-cli"
]
members = ["suppaftp", "suppaftp-cli"]
resolver = "2"
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</p>

<p align="center">Developed by <a href="https://veeso.github.io/">veeso</a> and <a href="https://github.com/mattnenterprise">Matt McCoy</a></p>
<p align="center">Current version: 5.1.2 (14/06/2023)</p>
<p align="center">Current version: 5.2.0 (07/09/2023)</p>

<p align="center">
<a href="https://opensource.org/licenses/MIT"
Expand Down Expand Up @@ -110,6 +110,7 @@ SuppaFTP is the main FTP/FTPS client library for Rust, with both support for syn
- EPRT
- Some extra features, such as the **LIST** command output parser
- Implementation of [RFC 2428](https://www.rfc-editor.org/rfc/rfc2428.html)
- Implementationb of [RFC 2389](https://www.rfc-editor.org/rfc/rfc2389)
- Removed deprecated statements ⚰️
- Better error handling 🐛
- Added test units keeping an eye on code coverage 👀
Expand All @@ -121,7 +122,7 @@ SuppaFTP is the main FTP/FTPS client library for Rust, with both support for syn
To get started, first add **suppaftp** to your dependencies:

```toml
suppaftp = "^5.1.0"
suppaftp = "^5.2.0"
```

### Features
Expand All @@ -131,9 +132,9 @@ suppaftp = "^5.1.0"
If you want to enable **support for FTPS**, you must enable the `native-tls` or `rustls` feature in your cargo dependencies, based on the TLS provider you prefer.

```toml
suppaftp = { version = "^5.1.0", features = ["native-tls"] }
suppaftp = { version = "^5.2.0", features = ["native-tls"] }
# or
suppaftp = { version = "^5.1.0", features = ["rustls"] }
suppaftp = { version = "^5.2.0", features = ["rustls"] }
```

> 💡 If you don't know what to choose, `native-tls` should be preferred for compatibility reasons.
Expand All @@ -144,7 +145,7 @@ suppaftp = { version = "^5.1.0", features = ["rustls"] }
If you want to enable **async** support, you must enable `async` feature in your cargo dependencies.

```toml
suppaftp = { version = "^5.1.0", features = ["async"] }
suppaftp = { version = "^5.2.0", features = ["async"] }
```

> ⚠️ If you want to enable both **native-tls** and **async** you must use the **async-native-tls** feature ⚠️
Expand Down
2 changes: 2 additions & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
group_imports = "StdExternalCrate"
imports_granularity = "Module"
6 changes: 3 additions & 3 deletions suppaftp-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
authors = ["Christian Visintin <christian.visintin1997@gmail.com>"]
authors = ["Christian Visintin <christian.visintin@veeso.dev>"]
categories = ["command-line-utilities"]
description = "FTP command line client, based on suppaftp"
edition = "2021"
Expand All @@ -10,7 +10,7 @@ license = "MIT"
name = "suppaftp-cli"
readme = "../README.md"
repository = "https://github.com/veeso/suppaftp"
version = "5.0.0"
version = "5.2.0"

[[bin]]
name = "suppaftp"
Expand All @@ -21,4 +21,4 @@ argh = "^0.1"
env_logger = "^0.10"
log = "^0.4"
rpassword = "^7.2"
suppaftp = { path = "../suppaftp", version = "^5.0", features = [ "native-tls" ] }
suppaftp = { path = "../suppaftp", version = "^5.2", features = ["native-tls"] }
29 changes: 27 additions & 2 deletions suppaftp-cli/src/actions.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use super::{FtpError, FtpStream};

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() {
Expand Down Expand Up @@ -83,6 +84,30 @@ pub fn cwd(ftp: &mut FtpStream, dir: &str) {
}
}

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) => {
Expand Down
2 changes: 2 additions & 0 deletions suppaftp-cli/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ pub struct Args {
pub verbose: bool,
#[argh(switch, short = 'V', description = "print version")]
pub version: bool,
#[argh(positional, description = "host to connect to")]
pub host: Option<String>,
}
14 changes: 14 additions & 0 deletions suppaftp-cli/src/command.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
use std::path::PathBuf;
use std::str::FromStr;

use suppaftp::Mode;

pub enum Command {
Appe(PathBuf, String),
Cdup,
Connect(String, bool),
Cwd(String),
Feat,
Help,
List(Option<String>),
Login,
Mdtm(String),
Mkdir(String),
Mode(Mode),
Noop,
Opts(String, Option<String>),
Put(PathBuf, String),
Pwd,
Quit,
Expand Down Expand Up @@ -56,6 +59,7 @@ impl FromStr for Command {
Some(p) => Ok(Self::Cwd(p.to_string())),
None => Err("Missing `dir` field"),
},
"FEAT" => Ok(Self::Feat),
"HELP" => Ok(Self::Help),
"LIST" => match args.next() {
Some(dir) => Ok(Self::List(Some(dir.to_string()))),
Expand All @@ -78,6 +82,16 @@ impl FromStr for Command {
None => Err("Missing `mode` field"),
},
"NOOP" => Ok(Self::Noop),
"OPTS" => {
let feature_name = match args.next() {
Some(s) => s.to_string(),
None => return Err("Missing `feature-name` field"),
};
match args.collect::<Vec<&str>>().join(" ") {
s if s.is_empty() => Ok(Self::Opts(feature_name, None)),
s => Ok(Self::Opts(feature_name, Some(s.to_string()))),
}
}
"PUT" => {
let local: PathBuf = match args.next() {
Some(l) => PathBuf::from(l),
Expand Down
20 changes: 15 additions & 5 deletions suppaftp-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ mod actions;
mod args;
mod command;

use std::io;
use std::io::Write;
use std::str::FromStr;

use actions::*;
use args::Args;
use command::Command;

use env_logger::Builder as LogBuilder;
use log::LevelFilter;
use std::io;
use std::io::Write;
use std::str::FromStr;
use suppaftp::{FtpError, NativeTlsFtpStream as FtpStream};

const APP_VERSION: &str = env!("CARGO_PKG_VERSION");
Expand All @@ -29,12 +29,14 @@ fn usage() {
println!("CONNECT <addr:port> Connect to remote host");
println!("CONNECT+S <addr:port> Connect to remote host using FTPS");
println!("CWD <dir> Change working directory");
println!("FEAT Get supported features on the server");
println!("HELP Print this help");
println!("LIST [dir] List files. If directory is not provided, current directory is used");
println!("LOGIN Login to remote");
println!("MDTM <file> Get modification time for `file`");
println!("MODE <PASSIVE|EXTPASSIVE|ACTIVE> Set mode");
println!("NOOP Ping server");
println!("OPTS <feature-name> [feature-value] Set a feature on the server (e.g. OPTS UTF8 ON)");
println!("PUT <file> <dest> Upload local file `file` to `dest`");
println!("PWD Print working directory");
println!("QUIT Quit suppaftp");
Expand Down Expand Up @@ -70,7 +72,7 @@ fn main() {
// init logger
LogBuilder::new()
.filter_level(if args.debug {
LevelFilter::Debug
LevelFilter::Trace
} else if args.verbose {
LevelFilter::Info
} else {
Expand All @@ -79,6 +81,12 @@ fn main() {
.init();
// Main loop
let mut ftp: Option<FtpStream> = None;

// connect if host is specified
if let Some(host) = args.host {
perform(&mut ftp, Command::Connect(host, false));
}

loop {
match input() {
Command::Quit => {
Expand Down Expand Up @@ -124,11 +132,13 @@ fn perform_connected(ftp: &mut FtpStream, command: Command) {
}
Command::Cwd(dir) => cwd(ftp, dir.as_str()),
Command::List(p) => list(ftp, p.as_deref()),
Command::Feat => feat(ftp),
Command::Login => login(ftp),
Command::Mdtm(p) => mdtm(ftp, p.as_str()),
Command::Mkdir(p) => mkdir(ftp, p.as_str()),
Command::Mode(m) => set_mode(ftp, m),
Command::Noop => noop(ftp),
Command::Opts(feature, values) => opts(ftp, feature, values),
Command::Put(src, dest) => put(ftp, src.as_path(), dest.as_str()),
Command::Pwd => pwd(ftp),
Command::Rename(src, dest) => rename(ftp, src.as_str(), dest.as_str()),
Expand Down
12 changes: 6 additions & 6 deletions suppaftp/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "suppaftp"
version = "5.1.2"
version = "5.2.0"
authors = [
"Christian Visintin <christian.visintin1997@gmail.com>",
"Christian Visintin <christian.visintin@veeso.dev>",
"Matt McCoy <mattnenterprise@yahoo.com>",
]
edition = "2021"
Expand All @@ -27,14 +27,14 @@ path = "src/lib.rs"

[dependencies]
chrono = { version = "^0.4", default-features = false, features = ["clock"] }
lazy-regex = "^2.4"
lazy-regex = "^3"
log = "^0.4"
thiserror = "^1"
# async
async-std = { version = "^1.10", optional = true }
async-native-tls-crate = { package = "async-native-tls", version = "^0.4", optional = true }
async-trait = { version = "0.1.64", optional = true }
async-tls = { version = "^0.11", optional = true }
async-tls = { version = "^0.12", optional = true }
pin-project = { version = "^1", optional = true }
# secure
native-tls-crate = { package = "native-tls", version = "^0.2", optional = true }
Expand All @@ -45,8 +45,8 @@ async-attributes = "1.1.2"
env_logger = "^0.10"
pretty_assertions = "^1.0.0"
rand = "^0.8.4"
serial_test = "^1.0"
webpki-roots = "0.22.5"
serial_test = "^2.0"
webpki-roots = "0.25"

[features]
default = []
Expand Down
3 changes: 2 additions & 1 deletion suppaftp/src/async_ftp/data_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
//!
//! This module exposes the async data stream implementation where bytes must be written to/read from

use std::pin::Pin;

#[cfg(any(feature = "async", feature = "async-secure"))]
use async_std::io::{Read, Result, Write};
#[cfg(any(feature = "async", feature = "async-secure"))]
use async_std::net::TcpStream;
use pin_project::pin_project;
use std::pin::Pin;

use super::AsyncTlsStream;

Expand Down
Loading

0 comments on commit 5bf40b4

Please sign in to comment.