tauri_plugin_media_toolkit/
paths.rs1use std::fs::create_dir_all;
5use std::path::PathBuf;
6use tauri::{AppHandle, Manager, Runtime};
7
8use crate::error::Error;
9
10const MEDIA_CACHE_SUBDIR: &str = "media-cache";
12
13const MEDIA_OUTPUT_SUBDIR: &str = "media";
15
16pub fn get_media_cache_dir<R: Runtime>(app: &AppHandle<R>) -> Result<PathBuf, Error> {
26 let base_path = app
27 .path()
28 .app_cache_dir()
29 .map_err(|e| Error::InvalidPath(format!("Could not determine app cache directory: {e}")))?;
30
31 let full_path = base_path.join(MEDIA_CACHE_SUBDIR);
32
33 create_dir_all(&full_path).map_err(|e| {
34 Error::InvalidPath(format!(
35 "Could not create cache directory {}: {}",
36 full_path.display(),
37 e
38 ))
39 })?;
40
41 Ok(full_path)
42}
43
44pub fn get_media_output_dir<R: Runtime>(app: &AppHandle<R>) -> Result<PathBuf, Error> {
48 let base_path = app
49 .path()
50 .app_data_dir()
51 .map_err(|e| Error::InvalidPath(format!("Could not determine app data directory: {e}")))?;
52
53 let full_path = base_path.join(MEDIA_OUTPUT_SUBDIR);
54
55 create_dir_all(&full_path).map_err(|e| {
56 Error::InvalidPath(format!(
57 "Could not create output directory {}: {}",
58 full_path.display(),
59 e
60 ))
61 })?;
62
63 Ok(full_path)
64}
65
66pub fn validate_path(path: &str) -> Result<(), Error> {
68 let path_buf = PathBuf::from(path);
69
70 for component in path_buf.components() {
71 if let std::path::Component::ParentDir = component {
72 return Err(Error::InvalidPath(
73 "Path traversal not allowed (contains '..')".to_string(),
74 ));
75 }
76 }
77
78 Ok(())
79}
80
81pub fn cleanup_old_cache<R: Runtime>(app: &AppHandle<R>, max_age_hours: u64) -> Result<u64, Error> {
86 use std::time::{Duration, SystemTime};
87
88 let cache_dir = get_media_cache_dir(app)?;
89 let max_age = Duration::from_secs(max_age_hours * 3600);
90 let now = SystemTime::now();
91 let mut deleted_count = 0u64;
92
93 if let Ok(entries) = std::fs::read_dir(&cache_dir) {
94 for entry in entries.flatten() {
95 if let Ok(metadata) = entry.metadata() {
96 if let Ok(modified) = metadata.modified() {
97 if let Ok(age) = now.duration_since(modified) {
98 if age > max_age && metadata.is_file() {
99 if std::fs::remove_file(entry.path()).is_ok() {
100 deleted_count += 1;
101 }
102 }
103 }
104 }
105 }
106 }
107 }
108
109 Ok(deleted_count)
110}