chore: fix download path

This commit is contained in:
michel
2025-10-26 01:15:17 +02:00
committed by Michel de Graaf
parent f196c86328
commit 436bc0fe1a
4 changed files with 52 additions and 44 deletions
+3
View File
@@ -187,6 +187,7 @@ impl Client {
filename: String,
username: String,
size: u64,
download_directory: String,
) -> Result<crate::types::DownloadResult> {
use crate::types::{DownloadResult, DownloadStatus};
use std::time::{Duration, Instant};
@@ -201,6 +202,7 @@ impl Client {
filename: filename.clone(),
token,
size,
download_directory,
};
let mut context = self.context.lock().unwrap();
@@ -436,6 +438,7 @@ impl Client {
filename: transfer.filename,
token: transfer.token,
size: transfer.size,
download_directory: "~/Downloads/".to_string(),
},
);
}
+6 -6
View File
@@ -22,28 +22,28 @@ fn main() {
file.name,
file.username,
file.size,
"~/Downloads".to_string(),
) {
Ok(download_result) => {
println!(
"Download result: {:?}",
download_result
"Download result: {download_result:?}"
);
}
Err(e) => {
eprintln!("Failed to download: {}", e);
eprintln!("Failed to download: {e}");
}
}
} else {
eprint!("No results")
eprint!("No results");
}
}
Err(e) => {
eprintln!("Failed to search: {}", e);
eprintln!("Failed to search: {e}");
}
}
}
Err(e) => {
eprintln!("Failed to login: {}", e);
eprintln!("Failed to login: {e}");
}
}
}
+42 -38
View File
@@ -1,11 +1,12 @@
use crate::client::ClientContext;
use crate::message::server::MessageFactory;
use crate::trace;
use std::env;
use std::fs::{self, File};
use std::io::{self, BufWriter, Read, Write};
use std::net::TcpStream;
use std::net::ToSocketAddrs;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use std::time::Duration;
@@ -21,6 +22,14 @@ struct FileManager;
#[allow(dead_code)]
impl FileManager {
fn expand_path(mut path: &str) -> String {
if path.starts_with('~') {
let home = env::var("HOME").expect("HOME not set");
format!("{}{}", home, &path[1..])
} else {
path.to_string()
}
}
fn create_download_paths(
output_path: Option<String>,
username: &str,
@@ -28,9 +37,9 @@ impl FileManager {
) -> DownloadPaths {
let final_path = match output_path {
Some(path) if !path.is_empty() => path,
_ => format!("/tmp/{}_{}.mp3", username, token),
_ => format!("/tmp/{username}_{token}.mp3"),
};
let incomplete_path = format!("{}.incomplete", final_path);
let incomplete_path = format!("{final_path}.incomplete");
DownloadPaths {
final_path,
@@ -63,22 +72,31 @@ impl FileManager {
fn extract_filename_from_path(full_path: &str) -> String {
// Split on both forward slashes and backslashes to handle Windows and Unix paths
full_path.split(['/', '\\']).next_back().unwrap_or(full_path).to_string()
full_path
.split(['/', '\\'])
.next_back()
.unwrap_or(full_path)
.to_string()
}
fn create_download_path_from_filename(
output_directory: Option<&str>,
remote_username: &str,
token: u32,
filename: Option<&str>
filename: Option<&str>,
) -> String {
let base_dir = output_directory.unwrap_or("/tmp");
let mut expanded_base_dir = FileManager::expand_path(base_dir);
if expanded_base_dir.ends_with('/') {
expanded_base_dir.pop();
}
if let Some(filename) = filename {
let clean_filename = Self::extract_filename_from_path(filename);
format!("{}/{}", base_dir, clean_filename)
format!("{expanded_base_dir}/{clean_filename}")
} else {
format!("{}/{}_{}.mp3", base_dir, remote_username, token)
format!("{expanded_base_dir}/{remote_username}_{token}")
}
}
}
@@ -118,13 +136,9 @@ impl StreamProcessor {
Ok(false)
}
fn process_data_chunk(
&mut self,
data: &[u8],
) -> Result<(), io::Error> {
fn process_data_chunk(&mut self, data: &[u8]) {
self.buffer.extend_from_slice(data);
self.total_bytes += data.len();
Ok(())
}
fn should_continue(&self, expected_size: Option<usize>) -> bool {
@@ -148,7 +162,7 @@ pub struct DownloadPeer {
#[allow(dead_code)]
impl DownloadPeer {
#[allow(dead_code)]
#[must_use]
pub fn new(
username: String,
host: String,
@@ -211,10 +225,6 @@ impl DownloadPeer {
);
stream.write_all(&message.get_buffer())?;
stream.flush()?;
// stream
// .write_all(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])?;
// stream.flush()?;
//
} else {
stream.write_all(
&MessageFactory::build_pierce_firewall_message(self.token)
@@ -236,7 +246,7 @@ impl DownloadPeer {
self,
client_context: Arc<Mutex<ClientContext>>,
mut expected_size: Option<usize>,
output_path: Option<String>,
mut download_path: Option<String>,
) -> Result<(usize, String), io::Error> {
let mut stream = self.establish_connection()?;
trace!("[download_peer:{}] connected", self.username);
@@ -294,6 +304,8 @@ impl DownloadPeer {
download.filename
);
expected_size = Some(download.size as usize);
download_path =
Some(download.download_directory.clone());
}
None => {
trace!(
@@ -304,18 +316,15 @@ impl DownloadPeer {
}
}
continue; // Skip this data chunk
continue;
}
processor.process_data_chunk(data)?;
processor.process_data_chunk(data);
if !processor.should_continue(expected_size) {
break;
}
}
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => {
continue;
}
Err(e) => {
return Err(e);
}
@@ -326,8 +335,7 @@ impl DownloadPeer {
self.username
);
// Now determine the final file path using download info
let output_directory = output_path.as_ref().map(|path| {
let output_directory = download_path.as_ref().map(|path| {
if Path::new(path).is_dir() {
path.as_str()
} else if let Some(parent) = Path::new(path).parent() {
@@ -339,35 +347,31 @@ impl DownloadPeer {
let filename = download_info.as_ref().map(|d| d.filename.as_str());
let final_path = if let Some(output_path) = &output_path {
let final_path = if let Some(output_path) = &download_path {
if Path::new(output_path).is_dir() || output_path.ends_with('/') {
// output_path is a directory, append filename
FileManager::create_download_path_from_filename(
Some(output_path),
&self.username,
self.token,
filename
filename,
)
} else {
// output_path is a full file path, use it directly
output_path.clone()
}
} else {
// No output path provided, use default logic
FileManager::create_download_path_from_filename(
output_directory,
&self.username,
self.token,
filename
filename,
)
};
// Create directory if needed
if let Some(parent) = Path::new(&final_path).parent() {
fs::create_dir_all(parent)?;
}
// Write the buffer to the final file
fs::write(&final_path, &processor.buffer)?;
trace!(
@@ -527,7 +531,7 @@ mod tests {
let download_peer = DownloadPeer::new(
"remote_user".to_string(),
"127.0.0.1".to_string(),
port as u32,
u32::from(port),
42,
false,
"test_user".to_string(),
@@ -574,7 +578,7 @@ mod tests {
#[test]
fn test_file_manager_create_paths_with_empty_string() {
let paths = FileManager::create_download_paths(
Some("".to_string()),
Some(String::new()),
"user",
789,
);
@@ -705,7 +709,7 @@ mod tests {
Some("/downloads"),
"remote_user",
123,
Some("song.mp3")
Some("song.mp3"),
);
assert_eq!(path, "/downloads/song.mp3");
@@ -714,7 +718,7 @@ mod tests {
Some("/downloads"),
"remote_user",
123,
Some("/remote/path/to/song.mp3")
Some("/remote/path/to/song.mp3"),
);
assert_eq!(path, "/downloads/song.mp3");
@@ -723,7 +727,7 @@ mod tests {
Some("/downloads"),
"remote_user",
123,
None
None,
);
assert_eq!(path, "/downloads/remote_user_123.mp3");
@@ -732,7 +736,7 @@ mod tests {
None,
"remote_user",
123,
Some("song.mp3")
Some("song.mp3"),
);
assert_eq!(path, "/tmp/song.mp3");
}
+1
View File
@@ -87,6 +87,7 @@ pub struct Download {
pub filename: String,
pub token: u32,
pub size: u64,
pub download_directory: String,
}
#[derive(Debug, Clone)]