Skip to main content

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}