1
1
//! FTP module.
2
2
use std:: borrow:: Cow ;
3
3
use std:: net:: SocketAddr ;
4
- use std:: str:: FromStr ;
5
4
use std:: string:: String ;
6
5
7
6
use chrono:: offset:: TimeZone ;
@@ -38,6 +37,7 @@ pub struct FtpStream {
38
37
reader : BufReader < DataStream > ,
39
38
#[ cfg( feature = "secure" ) ]
40
39
ssl_cfg : Option < ( ClientConfig , DNSName ) > ,
40
+ welcome_msg : Option < String > ,
41
41
}
42
42
43
43
impl FtpStream {
@@ -51,8 +51,10 @@ impl FtpStream {
51
51
reader : BufReader :: new ( DataStream :: Tcp ( stream) ) ,
52
52
#[ cfg( feature = "secure" ) ]
53
53
ssl_cfg : None ,
54
+ welcome_msg : None ,
54
55
} ;
55
- ftp_stream. read_response ( status:: READY ) . await ?;
56
+ let result = ftp_stream. read_response ( status:: READY ) . await ?;
57
+ ftp_stream. welcome_msg = Some ( result. 1 ) ;
56
58
57
59
Ok ( ftp_stream)
58
60
}
@@ -97,6 +99,7 @@ impl FtpStream {
97
99
let mut secured_ftp_tream = FtpStream {
98
100
reader : BufReader :: new ( DataStream :: Ssl ( stream) ) ,
99
101
ssl_cfg : Some ( ( config, domain) ) ,
102
+ welcome_msg : None ,
100
103
} ;
101
104
// Set protection buffer size
102
105
secured_ftp_tream. write_str ( "PBSZ 0\r \n " ) . await ?;
@@ -140,6 +143,7 @@ impl FtpStream {
140
143
let plain_ftp_stream = FtpStream {
141
144
reader : BufReader :: new ( DataStream :: Tcp ( self . reader . into_inner ( ) . into_tcp_stream ( ) ) ) ,
142
145
ssl_cfg : None ,
146
+ welcome_msg : None ,
143
147
} ;
144
148
Ok ( plain_ftp_stream)
145
149
}
@@ -187,6 +191,11 @@ impl FtpStream {
187
191
self . reader . get_ref ( ) . get_ref ( )
188
192
}
189
193
194
+ /// Get welcome message from the server on connect.
195
+ pub fn get_welcome_msg ( & self ) -> Option < & str > {
196
+ self . welcome_msg . as_deref ( )
197
+ }
198
+
190
199
/// Log in to the FTP server.
191
200
pub async fn login ( & mut self , user : & str , password : & str ) -> Result < ( ) > {
192
201
self . write_str ( format ! ( "USER {}\r \n " , user) ) . await ?;
@@ -268,8 +277,18 @@ impl FtpStream {
268
277
caps[ 6 ] . parse :: < u8 > ( ) . unwrap ( ) ,
269
278
) ;
270
279
let port = ( ( msb as u16 ) << 8 ) + lsb as u16 ;
271
- let addr = format ! ( "{}.{}.{}.{}:{}" , oct1, oct2, oct3, oct4, port) ;
272
- SocketAddr :: from_str ( & addr) . map_err ( FtpError :: InvalidAddress )
280
+
281
+ use std:: net:: { IpAddr , Ipv4Addr } ;
282
+
283
+ let ip = if ( oct1, oct2, oct3, oct4) == ( 0 , 0 , 0 , 0 ) {
284
+ self . get_ref ( )
285
+ . peer_addr ( )
286
+ . map_err ( FtpError :: ConnectionError ) ?
287
+ . ip ( )
288
+ } else {
289
+ IpAddr :: V4 ( Ipv4Addr :: new ( oct1, oct2, oct3, oct4) )
290
+ } ;
291
+ Ok ( SocketAddr :: new ( ip, port) )
273
292
} )
274
293
}
275
294
@@ -292,7 +311,9 @@ impl FtpStream {
292
311
pub async fn restart_from ( & mut self , offset : u64 ) -> Result < ( ) > {
293
312
let rest_command = format ! ( "REST {}\r \n " , offset. to_string( ) ) ;
294
313
self . write_str ( & rest_command) . await ?;
295
- self . read_response ( status:: REQUEST_FILE_PENDING ) . await . map ( |_| ( ) )
314
+ self . read_response ( status:: REQUEST_FILE_PENDING )
315
+ . await
316
+ . map ( |_| ( ) )
296
317
}
297
318
298
319
/// Retrieves the file name specified from the server.
@@ -302,11 +323,8 @@ impl FtpStream {
302
323
pub async fn get ( & mut self , file_name : & str ) -> Result < BufReader < DataStream > > {
303
324
let retr_command = format ! ( "RETR {}\r \n " , file_name) ;
304
325
let data_stream = BufReader :: new ( self . data_command ( & retr_command) . await ?) ;
305
- self . read_response_in ( & [
306
- status:: ABOUT_TO_SEND ,
307
- status:: ALREADY_OPEN
308
- ] )
309
- . await ?;
326
+ self . read_response_in ( & [ status:: ABOUT_TO_SEND , status:: ALREADY_OPEN ] )
327
+ . await ?;
310
328
Ok ( data_stream)
311
329
}
312
330
@@ -629,7 +647,7 @@ mod tests {
629
647
#[ tokio:: test]
630
648
async fn list_command_dos_newlines ( ) {
631
649
let data_stream = StreamReader :: new ( once ( Ok :: < _ , std:: io:: Error > (
632
- b"Hello\r \n World\r \n \r \n Be\r \n Happy\r \n " as & [ u8 ]
650
+ b"Hello\r \n World\r \n \r \n Be\r \n Happy\r \n " as & [ u8 ] ,
633
651
) ) ) ;
634
652
635
653
assert_eq ! (
@@ -643,7 +661,9 @@ mod tests {
643
661
644
662
#[ tokio:: test]
645
663
async fn list_command_unix_newlines ( ) {
646
- let data_stream = StreamReader :: new ( once ( Ok :: < _ , std:: io:: Error > ( b"Hello\n World\n \n Be\n Happy\n " as & [ u8 ] ) ) ) ;
664
+ let data_stream = StreamReader :: new ( once ( Ok :: < _ , std:: io:: Error > (
665
+ b"Hello\n World\n \n Be\n Happy\n " as & [ u8 ] ,
666
+ ) ) ) ;
647
667
648
668
assert_eq ! (
649
669
FtpStream :: get_lines_from_stream( data_stream) . await . unwrap( ) ,
0 commit comments