ftp_rs/
lib.rs

1//! ftp is an FTP client written in Rust.
2//!
3//! ### Usage
4//!
5//! Here is a basic usage example:
6//!
7//! ```rust,no_run
8//! use ftp_rs::FtpClient;
9//! async {
10//!   let mut ftp_client = FtpClient::connect("192.168.32.204:21").await.unwrap_or_else(|err|
11//!       panic!("{}", err)
12//!   );
13//!   let _ = ftp_client.quit();
14//! };
15//! ```
16//!
17//! ### FTPS
18//!
19//! The client supports FTPS on demand. To enable it the client should be
20//! compiled with feature `openssl` enabled what requires
21//! [openssl](https://crates.io/crates/openssl) dependency.
22//!
23//! The client uses explicit mode for connecting FTPS what means you should
24//! connect the server as usually and then switch to the secure mode (TLS is used).
25//! For better security it's the good practice to switch to the secure mode
26//! before authentication.
27//!
28//! ### FTPS Usage
29//!
30//! ```rust,no_run
31//! use std::convert::TryFrom;
32//! use std::path::Path;
33//! use ftp_rs::FtpClient;
34//! use tokio_rustls::rustls::{ClientConfig, RootCertStore, ServerName};
35//!
36//! async {
37//!   let ftp_client = FtpClient::connect("192.168.32.204:21").await.unwrap();
38//!   
39//!   let mut root_store = RootCertStore::empty();
40//!   // root_store.add_pem_file(...);
41//!   let conf = ClientConfig::builder().with_safe_defaults().with_root_certificates(root_store).with_no_client_auth();
42//!   let domain = ServerName::try_from("www.cert-domain.com").expect("invalid DNS name");
43//!
44//!   // Switch to the secure mode
45//!   let mut ftp_client = ftp_client.into_secure(conf, domain).await.unwrap();
46//!   ftp_client.login("anonymous", "anonymous").await.unwrap();
47//!   // Do other secret stuff
48//!   // Switch back to the insecure mode (if required)
49//!   let mut ftp_client = ftp_client.into_insecure().await.unwrap();
50//!   // Do all public stuff
51//!   let _ = ftp_client.quit().await;
52//! };
53//! ```
54//!
55
56mod connection;
57mod ftp_client;
58pub mod ftp_reply;
59pub mod types;
60pub mod cmd;
61
62pub use self::connection::Connection;
63pub use self::ftp_client::FtpClient;
64pub use self::types::FtpError;
65
66pub const REPLY_CODE_LEN: usize = 3;
67
68pub const MODES: &'static str = "AEILNTCFRPSBC";
69
70pub trait StringExt {
71    fn substring(&self, start_index: usize, end_index: usize) -> &str;
72}
73
74impl StringExt for str {
75    fn substring(&self, start_index: usize, end_index: usize) -> &str {
76        if end_index <= start_index {
77            return "";
78        }
79
80        let mut indices = self.char_indices();
81
82        let obtain_index = |(index, _char)| index;
83        let str_len = self.len();
84
85        unsafe {
86            self.slice_unchecked(
87                indices.nth(start_index).map_or(str_len, &obtain_index),
88                indices
89                    .nth(end_index - start_index - 1)
90                    .map_or(str_len, &obtain_index),
91            )
92        }
93    }
94}