ftp_get/
ftp-get.rs

1extern crate url;
2extern crate protocol_ftp_client;
3
4use std::io::prelude::*;
5use url::Url;
6use std::net::TcpStream;
7use std::env;
8use std::string::String;
9use std::fs::File;
10
11use protocol_ftp_client::*;
12
13fn get_reply(stream:&mut TcpStream, rx_buff: &mut [u8], receiver: FtpReceiver) -> FtpTransmitter {
14  let mut opt_transmitter = None;
15  let mut opt_receiver = Some(receiver);
16  let mut total_size = 0;
17  while opt_receiver.is_some() {
18    let sz = stream.read(rx_buff).unwrap();
19    total_size = total_size + sz;
20    let ftp_receiver = opt_receiver.take().unwrap();
21    match ftp_receiver.try_advance(&rx_buff[0 .. total_size]) {
22      Ok(transmitter)   => { opt_transmitter = Some(transmitter) }
23      Err(mut receiver) => {
24        match receiver.take_error() {
25          Some(FtpError::NotEnoughData) => { opt_receiver = Some(receiver) }
26          Some(e)  => { panic!(format!("Got unexpected error {}", e )) }
27          _ => {panic!("no advance nor error?")}
28        };
29      }
30    }
31  }
32  opt_transmitter.unwrap()
33}
34
35fn main() {
36  let url = env::args().nth(1).unwrap();
37  println!("url: {}", url);
38  let ftp_url = Url::parse(&url).unwrap();
39  assert!(ftp_url.scheme() == "ftp");
40
41  let mut username = ftp_url.username();
42  if username == "" { username = "anonymous" };
43
44  let password = match ftp_url.password() {
45    Some(value) => value,
46    None        => "unspecified",
47  };
48
49  assert!(ftp_url.path() != "");
50
51  let host = ftp_url.host().unwrap();
52  let port:u16 = ftp_url.port().or(Some(21)).unwrap();
53  let filename = ftp_url.path_segments().unwrap().last().unwrap();
54  let remote_path = ftp_url.path_segments().unwrap()
55    .take_while(|part| part.to_string() != filename.to_string())
56    .fold(String::new(), |mut acc, part| { acc.push_str("/"); acc.push_str(part); acc } );
57
58  println!("start dowloading {} at {}...", filename, remote_path);
59
60  let mut tx_buff:[u8; 1024] = [0; 1024];
61  let mut tx_count = 0;
62  let mut rx_buff:[u8; 1024] = [0; 1024];
63
64  let host_port = format!("{}:{}", host, port);
65  let mut stream = TcpStream::connect(host_port.as_str()).unwrap();
66  let mut ftp_receiver = FtpReceiver::new();
67
68  let mut transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
69  println!("connected to {}:{}", host, port);
70
71  ftp_receiver = transmitter.send_login(&mut tx_buff, &mut tx_count, username);
72  let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
73  println!("login sent...");
74
75  transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
76  println!("expecting password...");
77
78  ftp_receiver = transmitter.send_password(&mut tx_buff, &mut tx_count, password);
79  let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
80  println!("password sent...");
81
82  transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
83  println!("logged in...");
84
85  ftp_receiver = transmitter.send_system_req(&mut tx_buff, &mut tx_count);
86  let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
87  transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
88  {
89    let (system, subtype) = transmitter.get_system().clone();
90    println!("remote system {} / {}", system, subtype);
91  }
92
93  ftp_receiver = transmitter.send_cwd_req(&mut tx_buff, &mut tx_count, &remote_path);
94  let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
95  transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
96  println!("cwd to {}", remote_path);
97
98  ftp_receiver = transmitter.send_pwd_req(&mut tx_buff, &mut tx_count);
99  let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
100  transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
101  println!("changed remote directory is {}", transmitter.get_wd());
102
103  ftp_receiver = transmitter.send_type_req(&mut tx_buff, &mut tx_count, DataMode::Binary);
104  let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
105  transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
106  println!("switched to binary mode");
107
108  let mut data_stream = {
109    ftp_receiver = transmitter.send_pasv_req(&mut tx_buff, &mut tx_count);
110    let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
111    transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
112    let (addr, port) = transmitter.take_endpoint().clone();
113    println!("confirmed passive connection on {}:{}", addr, port);
114    TcpStream::connect((addr, port)).unwrap()
115  };
116  println!("passive connection opened");
117
118  ftp_receiver = transmitter.send_get_req(&mut tx_buff, &mut tx_count, ftp_url.path());
119
120  let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
121  transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
122  println!("starting downloading file {}", filename);
123
124  let mut local_file = File::create(filename).unwrap();
125  let mut eof = false;
126  let mut data_in =  [0; 40960];
127  while !eof {
128    let count = data_stream.read(&mut data_in).unwrap();
129    // println!("got {} bytes", count);
130    eof = count == 0;
131    if !eof { let _ = local_file.write(&data_in[0 .. count]).unwrap(); };
132  }
133  local_file.flush().unwrap();
134  println!("");
135
136  println!("got file {}", filename);
137  let _ = get_reply(&mut stream, &mut rx_buff, transmitter.to_receiver());
138  println!("Success ... ");
139
140}