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 crate::config::ProxyConfig;
28use crate::optimization::Optimizer;
29use std::error::Error;
30use std::io::Read;
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(
62        url: String,
63        output: String,
64        quiet: bool,
65        proxy: ProxyConfig,
66        optimizer: Optimizer,
67    ) -> Self {
68        Self {
69            url,
70            output,
71            quiet,
72            proxy,
73            optimizer,
74        }
75    }
76
77    pub fn download(&self) -> Result<(), Box<dyn Error + Send + Sync>> {
78        let tcp = std::net::TcpStream::connect(&self.url)?;
79        let mut sess = ssh2::Session::new()?;
80        sess.set_tcp_stream(tcp);
81        sess.handshake()?;
82
83        let sftp = sess.sftp()?;
84        let mut remote_file = sftp.open(std::path::Path::new(&self.url))?;
85        let mut contents = Vec::new();
86        remote_file.read_to_end(&mut contents)?;
87
88        std::fs::write(&self.output, contents)?;
89
90        if !self.quiet {
91            println!("Downloaded {} to {}", self.url, self.output);
92        }
93        Ok(())
94    }
95}