FTP client for Rust

Overview

rust-ftp

FTP client for Rust

Number of Crate Downloads Crate Version Crate License Build Status Coverage Status

Documentation


Installation

FTPS support is achieved through rust-native-tls and is disabled by default. To enable it secure should be activated in Cargo.toml.

[dependencies]
ftp = { version = "<version>", features = ["secure"] }

Usage

extern crate ftp;

use std::str;
use std::io::Cursor;
use ftp::FtpStream;

fn main() {
    // Create a connection to an FTP server and authenticate to it.
    let mut ftp_stream = FtpStream::connect("127.0.0.1:21").unwrap();
    let _ = ftp_stream.login("username", "password").unwrap();

    // Get the current directory that the client will be reading from and writing to.
    println!("Current directory: {}", ftp_stream.pwd().unwrap());

    // Change into a new directory, relative to the one we are currently in.
    let _ = ftp_stream.cwd("test_data").unwrap();

    // Retrieve (GET) a file from the FTP server in the current working directory.
    let remote_file = ftp_stream.simple_retr("ftpext-charter.txt").unwrap();
    println!("Read file with contents\n{}\n", str::from_utf8(&remote_file.into_inner()).unwrap());

    // Store (PUT) a file from the client to the current working directory of the server.
    let mut reader = Cursor::new("Hello from the Rust \"ftp\" crate!".as_bytes());
    let _ = ftp_stream.put("greeting.txt", &mut reader);
    println!("Successfully wrote greeting.txt");

    // Terminate the connection to the server.
    let _ = ftp_stream.quit();
}

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Development environment

All you need to develop rust-ftp and run the tests is Rust and Docker. The tests folder contains a Dockerfile that installs and configures the vsftpd server.

To create the Docker image:

docker build -t ftp-server tests

To start the FTP server that is tested against:

tests/ftp-server.sh

This script runs the ftp-server image in detached mode and starts the vsftpd daemon. It binds ports 21 (FTP) as well as the range 65000-65010 for passive connections.

Once you have an instance running, to run tests type:

cargo test

The following commands can be useful:

# List running containers of ftp-server image
# (to include stopped containers use -a option)
docker ps --filter ancestor=ftp-server

# To stop and remove a container
docker stop container_name
docker rm container_name

# To remove the image
docker rmi ftp-server
Comments
  • FTPS support

    FTPS support

    Hello,

    implemented FTPS support using Private Protection mode what means both commands and data are secured with TLS. FTPS is a feature which is disabled be default because it introduces openssl dependency. To enable it feature secure should be activated in toml or directly in the build command cargo build/test/doc --features "secure".

    Also I introduce DataStream struct in the PR which abstracts FtpStream for the underlying stream (TCP or SSL over TCP).

    And I added a feature debug_output which on activation prints all commands and responses to STDOUT. Very usefull when debugging.

    opened by workanator 11
  • Custom Error Type

    Custom Error Type

    Hi

    It would be nice if this library would use a custom error type for all results, instead of mixing io::Error and Strings. This would play well together with the From<Error> trait.

    http://blog.burntsushi.net/rust-error-handling/

    opened by dbrgn 11
  • Question: Do get/retr methods return BufRead

    Question: Do get/retr methods return BufRead

    I've tried get and retr and neither seem to return a BufRead

    I ask because i'm trying to use read_line https://doc.rust-lang.org/beta/std/io/trait.BufRead.html#method.read_line

        let mut ftp_stream = FtpStream::connect(("ftp.arin.net", 21)).unwrap();
        ftp_stream.login("anonymous", "").unwrap();
        println!("current dir: {}", ftp_stream.pwd().unwrap());
    
        ftp_stream.cwd("pub/stats/arin").unwrap();
    
        let stream = ftp_stream.get("delegated-arin-extended-latest").unwrap();
    
        let mut buf = Vec::new();
    
        let num_bytes = stream.read_line(&mut buf);
        println!("got line: {}", str::from_utf8(&buf).unwrap());
    
        let num_bytes = stream.read_line(&mut buf);
        println!("got line: {}", str::from_utf8(&buf).unwrap());
    
    error[E0599]: no method named `read_line` found for type `std::io::BufReader<ftp::data_stream::DataStream>` in the current scope
    
    opened by jacktuck 8
  • implement list

    implement list

    cf: https://github.com/mattnenterprise/rust-ftp/issues/10

    This is work in progress. I need to add nlst as well. But if you have feedback aleady it's great. Maybe I should rename list() to ls(), also.

    opened by little-dude 7
  • Rename FTPStream to FtpStream

    Rename FTPStream to FtpStream

    This is the smallest change, so that's why I'm starting with this one. We will need to update the crate's version number to account for this breaking change.

    opened by matt2xu 7
  • cannot log in ftp.hq.nasa.gov

    cannot log in ftp.hq.nasa.gov

    I was trying to connect anonymously to ftp.hq.nasa.gov but I'm getting an "Invalid response". I suspect there is something wrong in read_response:

    // nasa.rs
    extern crate ftp;
    
    use std::str;
    use ftp::FTPStream;
    
    fn main() {
        let mut ftp_stream = match FTPStream::connect("198.116.65.45".to_string(), 21) {
            Ok(s) => s,
            Err(e) => panic!("{}", e)
        };
    }
    

    Here is a capture: ftp_failure.pcapng.zip

    opened by little-dude 7
  • Unify the library's interface and tidy up some code

    Unify the library's interface and tidy up some code

    I realize that this is a fairly controversial and large pull request. I've been using rust-ftp a fair bit lately and have found the code a bit confusing to navigate at times. It is evident that you, Matt, were improving your Rust skills as you wrote the library and I can see you've become a lot more comfortable with error handling in particular as you progressed. Because of the library's earlier roots, some code was implemented with an unnecessarily large amount of Result unwrapping, by way of match. One of the big things I set out to do here is make the implementation of each method more consistent.

    Another thing I wanted to set out to do here was introduce a custom error type, FtpError, so that the library only ever returns that one error type in its interface. This allows for much simpler usage, as a user could now chain operations together using Result.and_then() without having to do much intermediate error type inspection and conversion.

    You'll also see that I have changed the return types of the messier secure() and secure_with_ssl() methods, which had previously returned a tuple containing a (hopefully) modified FtpStream and an io::Result<()> in the case of error.

    If you'd like for me to elaborate on any of the choices I made or would like to discuss the impact or desirability of any of these changes, please don't hesitate to let me know. Since this refactoring is so substantial, I understand if there are parts you disagree with. If you feel that the changes I made are generally not in the spirit of your own intentions, you can reject this PR and I will create my own distinct version of the library.

    opened by arcrose 6
  • Persist custom ssl

    Persist custom ssl

    This PR addresses #48. The idea here is we supply a version of FtpStream that is created when the "secure" feature flag is set which contains an IntoSsl + Clone. By having a copy of an IntoSsl in the struct, we can use it in data_command, so that users can supply their own configurations that will work in all uses.

    Let me know if this works for your use cases @mattnenterprise

    opened by arcrose 5
  • RETR and TYPE

    RETR and TYPE

    Hello,

    the current implementation of RETR (FtpStream::get) is not correct because it does not read response lines after the data stream is read and closed and using the simple implementation (FtpStream::simple_retr) is not a good idea when files for downloading are big. In the PR I added a new function FtpStream::retr which takes an additional argument reader which is a closure which operates the data stream and inside retr all repsonses and dropping of the data stream are handled correctly.

    In the PR I also added TYPE (FtpStream::transfer_type) function which is very important when the binary file should be transfered.

    opened by workanator 5
  • Replace isize

    Replace isize

    Both status codes and ports don't have anything to do with the pointer size.

    Therefore I converted the type for port numbers to an u16 and the type for status codes to i16.

    According to https://en.wikipedia.org/wiki/List_of_FTP_server_return_codes, the return codes are between 100 and 10068. An i16 should be suitable here.

    An alternative would be to use i32 instead, the default for integer literals where the type cannot be derived properly. Also, an i32 is probably faster on a 32 bit platform (although that really shouldn't matter in this case). So let me know if I should change it :)

    opened by dbrgn 5
  • Status of rust-ftp

    Status of rust-ftp

    Hi,

    I wonder what the current status is given that there are a bunch of PRs being open that fixes some fairly important issues (such as version of openssl) is this crate still being supported or not?

    opened by emoon 4
  • Large download example

    Large download example

    Would be nice to have an example of how to properly download/upload a large file, avoiding the control stream timeout (null command)... I'm relatively new to rust and just trying to get a grasp of this.

    opened by tracker1 0
  • Depends on old winapi:

    Depends on old winapi: "the following packages contain code that will be rejected by a future version of rust"

    Hey there, thanks for the great library!

    On compiling with ftp 3.0.1 I get the following error:

    
    ❯ cargo b -r --future-incompat-report
        Finished release [optimized] target(s) in 0.13s
    warning: the following packages contain code that will be rejected by a future version of Rust: winapi v0.2.8
    note: 
    To solve this problem, you can try the following approaches:
    
    
    - Some affected dependencies have newer versions available.
    You may want to consider updating them to a newer version to see if the issue has been fixed.
    
    winapi v0.2.8 has the following newer versions available: 0.3.0, 0.3.1, 0.3.2, 0.3.3, 0.3.4, 0.3.5, 0.3.6, 0.3.7, 0.3.8, 0.3.9
    
    
    - If the issue is not solved by updating the dependencies, a fix has to be
    implemented by those dependencies. You can help with that by notifying the
    maintainers of this problem (e.g. by creating a bug report) or by proposing a
    fix to the maintainers (e.g. by creating a pull request):
    
      - [email protected]
      - Repository: https://github.com/retep998/winapi-rs
      - Detailed warning command: `cargo report future-incompatibilities --id 14 --package [email protected]`
    
    - If waiting for an upstream fix is not an option, you can use the `[patch]`
    section in `Cargo.toml` to use your own version of the dependency. For more
    information, see:
    https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section
    
    note: this report can be shown with `cargo report future-incompatibilities --id 14`
    

    It seems like winapi is required by the following sequence:

    ftp v3.0.1
    └── regex v0.1.80
        └── thread_local v0.2.7
            └── thread-id v2.0.0
                └── kernel32-sys v0.2.2
                    └── winapi v0.2.8
    

    Is there any chance to update these? Maybe a regex update might already suffice, or we might need to pass it down.

    opened by Christoph-AK 0
  • FTP connection fails when connecting to IIS server

    FTP connection fails when connecting to IIS server

    When connecting to an IIS ftp server we stumble upon the following error message:

    FTP - quit: InvalidResponse("Expected code [221], got response: 150 Opening BINARY mode data connection.")

    opened by SergenN 0
  • Cargo audit failed

    Cargo audit failed

    Cargo audit failed

    cargo check
    cargo audit
        Fetching advisory database from `https://github.com/RustSec/advisory-db.git`
          Loaded 433 security advisories (from /home/balrog/.cargo/advisory-db)
        Updating crates.io index
        Scanning Cargo.lock for vulnerabilities (57 crate dependencies)
    Crate:     time
    Version:   0.1.44
    Title:     Potential segfault in the time crate
    Date:      2020-11-18
    ID:        RUSTSEC-2020-0071
    URL:       https://rustsec.org/advisories/RUSTSEC-2020-0071
    Solution:  Upgrade to >=0.2.23
    Dependency tree:
    time 0.1.44
    └── chrono 0.4.20
        └── ftp 3.0.1
    
    error: 1 vulnerability found!
    
    opened by balroggg 0
  • Update chrono to pass audit

    Update chrono to pass audit

    Update chrono dependency and reduce its features to pass audit.

    cargo audit
        Fetching advisory database from `https://github.com/RustSec/advisory-db.git`
          Loaded 433 security advisories (from /home/balrog/.cargo/advisory-db)
        Updating crates.io index
        Scanning Cargo.lock for vulnerabilities (55 crate dependencies)
    
    opened by balroggg 1
  • Upgrade `regex` package versions to `>=1.5.5` (security vulnerabilities)

    Upgrade `regex` package versions to `>=1.5.5` (security vulnerabilities)

    Im not sure if that is the right place but when I run cargo audit on the duckscript repo I get this error:

    https://github.com/sagiegurari/duckscript

    $ cargo audit
        Fetching advisory database from `https://github.com/RustSec/advisory-db.git`
          Loaded 416 security advisories (from /Users/john/.cargo/advisory-db)
        Updating crates.io index
        Scanning Cargo.lock for vulnerabilities (124 crate dependencies)
    Crate:     regex
    Version:   0.1.80
    Title:     Regexes with large repetitions on empty sub-expressions take a very long time to parse
    Date:      2022-03-08
    ID:        RUSTSEC-2022-0013
    URL:       https://rustsec.org/advisories/RUSTSEC-2022-0013
    Solution:  Upgrade to >=1.5.5
    Dependency tree:
    regex 0.1.80
    └── ftp 3.0.1
        └── duckscriptsdk 0.8.12
            └── duckscript_cli 0.8.12
    
    Crate:     thread_local
    Version:   0.2.7
    Title:     Data race in `Iter` and `IterMut`
    Date:      2022-01-23
    ID:        RUSTSEC-2022-0006
    URL:       https://rustsec.org/advisories/RUSTSEC-2022-0006
    Solution:  Upgrade to >=1.1.4
    Dependency tree:
    thread_local 0.2.7
    └── regex 0.1.80
        └── ftp 3.0.1
            └── duckscriptsdk 0.8.12
                └── duckscript_cli 0.8.12
    
    error: 2 vulnerabilities found!
    

    So I'm not sure if that's the rust-ftp that has an old regex version or duckscript if its duckscript I will move my issue there.

    opened by John15321 0
Owner
Matt McCoy
Matt McCoy
NNTP client for Rust

rust-nntp NNTP Client for Rust Usage extern crate nntp; use nntp::{Article, NNTPStream}; fn main() { let mut nntp_stream = match NNTPStream::connec

Matt McCoy 13 Jan 22, 2022
POP3 client for Rust

rust-pop3 POP3 Client for Rust This client has SSL support. SSL is configured using an SSLContext that is passed into the connect method of a POP3Stre

Matt McCoy 26 Dec 19, 2022
A STOMP client in Rust. Compatible with RabbitMQ, ActiveMQ.

stomp-rs stomp-rs provides a full STOMP 1.2 client implementation for the Rust programming language. This allows programs written in Rust to interact

Zack Slayton 84 Dec 4, 2022
Rust client for NATS, the cloud native messaging system.

A Rust client for the NATS messaging system. Status Motivation Rust may be the most interesting new language the NATS ecosystem has seen. We believe t

NATS - The Cloud Native Messaging System 651 Jan 3, 2023
rqbit - bittorrent client in Rust

rqbit - bittorrent client in Rust

Igor Katson 177 Jan 2, 2023
Simple project to test grpc between ruby (client) and rust (server)

grpc-example Simple project to test grpc between ruby (client) and rust (server). Usage To simplify a lot this project uses docker and docker compose

Bruno Arueira 2 Oct 14, 2021
A rust client and structures to interact with the Clever-Cloud API.

Clever-Cloud Software Development Kit - Rust edition This crate provides structures and client to interact with the Clever-Cloud API. Status This crat

Clever Cloud 6 Jun 3, 2022
Third party Google DNS client for rust.

google-dns-rs Documentation Install Add the following line to your Cargo.toml file: google-dns-rs = "0.3.0" Usage use google_dns_rs::api::{Dns, DoH, R

Eduardo Stuart 2 Nov 13, 2021
A ddns client written in Rust.

ddns-rs ready for use with one cloudflare A/AAAA record ?? A ddns client written in Rust. Features get public ip cloudflare (A or AAAA record) toml co

Ric Li 1 Oct 25, 2022
Rust client for apache iotdb.

Apache IoTDB Apache IoTDB (Database for Internet of Things) is an IoT native database with high performance for data management and analysis, deployab

Mark Liu 7 Aug 4, 2022
Rust client for Kubernetes

Rust client for Kubernetes API.

null 244 Dec 17, 2022
A Rust based DNS client, server, and resolver

Trust-DNS A Rust based DNS client, server, and Resolver, built to be safe and secure from the ground up. This repo consists of multiple crates: Librar

Benjamin Fry 2.7k Dec 30, 2022
An online version of the popular game four in a row, written in Rust on the server side and Flutter + Dart on the client.

Four in a Row - Server An online version of the popular game four in a row, written in Rust on the server side and Flutter + Dart on the client. Downl

Filippo Orrù 8 Sep 16, 2022
A minimalist socket-based client/server in Rust to illustrate a tutorial

The basics of unix sockets This repository serves as a reference for this tutorial blogpost How to run Install Rust and Cargo, and then do: cargo run

Emmanuel Bosquet 4 Dec 4, 2022
Rust Verbio SpeechCenter Client

The CLI client allows you to launch a single file to the server. It also allows you to use either a grammar or a language model.

Verbio Technologies 3 Sep 16, 2022
Fast Discord RPC Client written in Rust

Discord RPC Client Examples Big image, small image, details and one button discordrpc -c 942151169185316874 -d 'untypeable nickname' --button-1-text '

Oskar 10 Jan 1, 2023
Rust client for Apache Kafka

Kafka Rust Client Project Status This project is starting to be maintained by John Ward, the current status is that I am bringing the project up to da

Kafka Rust 900 Dec 26, 2022
This is a UPnP client library for Rust.

UPnP Client This is a UPNP client library for Rust. Usage Add this to your Cargo.toml: [dependencies] upnp-client = "0.1" Example This example will pr

Tsiry Sandratraina 7 Feb 20, 2023
Socket.io client written in Rust

Rust-socketio-client An implementation of a socket.io client written in the rust programming language. This implementation currently supports revision

Hand of Midas 4 May 9, 2023