kget/sftp/mod.rs
1//! SFTP (SSH File Transfer Protocol) download support.
2//!
3//! This module provides secure file downloads over SSH using SFTP.
4//!
5//! # Security
6//!
7//! SFTP provides encrypted file transfer, unlike plain FTP.
8//! Authentication is handled via SSH (password or key-based).
9//!
10//! # Example
11//!
12//! ```rust,no_run
13//! use kget::sftp::SftpDownloader;
14//! use kget::{ProxyConfig, Optimizer};
15//!
16//! let downloader = SftpDownloader::new(
17//! "sftp://user@server.com:22/path/to/file".to_string(),
18//! "local_file.txt".to_string(),
19//! false,
20//! ProxyConfig::default(),
21//! Optimizer::new(),
22//! );
23//!
24//! downloader.download().unwrap();
25//! ```
26
27use std::error::Error;
28use std::io::Read;
29use crate::config::ProxyConfig;
30use crate::optimization::Optimizer;
31
32/// SFTP file downloader using SSH.
33///
34/// Downloads files securely over SSH File Transfer Protocol.
35///
36/// # Note
37///
38/// Currently requires the SSH session to be established manually.
39/// For key-based authentication, configure `SftpConfig.key_path` in
40/// the application config.
41pub struct SftpDownloader {
42 url: String,
43 output: String,
44 quiet: bool,
45 #[allow(dead_code)]
46 proxy: ProxyConfig,
47 #[allow(dead_code)]
48 optimizer: Optimizer,
49}
50
51impl SftpDownloader {
52 /// Create a new SFTP downloader.
53 ///
54 /// # Arguments
55 ///
56 /// * `url` - SFTP URL (e.g., "sftp://user@host/path")
57 /// * `output` - Local path to save the file
58 /// * `quiet` - Suppress console output
59 /// * `proxy` - Proxy configuration
60 /// * `optimizer` - Optimizer instance
61 pub fn new(url: String, output: String, quiet: bool, proxy: ProxyConfig, optimizer: Optimizer) -> Self {
62 Self {
63 url,
64 output,
65 quiet,
66 proxy,
67 optimizer,
68 }
69 }
70
71 pub fn download(&self) -> Result<(), Box<dyn Error + Send + Sync>> {
72 let tcp = std::net::TcpStream::connect(&self.url)?;
73 let mut sess = ssh2::Session::new()?;
74 sess.set_tcp_stream(tcp);
75 sess.handshake()?;
76
77 let sftp = sess.sftp()?;
78 let mut remote_file = sftp.open(std::path::Path::new(&self.url))?;
79 let mut contents = Vec::new();
80 remote_file.read_to_end(&mut contents)?;
81
82 std::fs::write(&self.output, contents)?;
83
84 if !self.quiet {
85 println!("Downloaded {} to {}", self.url, self.output);
86 }
87 Ok(())
88 }
89}