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 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}