use crate::LockerResult;
use crate::SmartLockerError;
use colored::Colorize;
use copypasta::{ClipboardContext, ClipboardProvider};
use directories::UserDirs;
use std::env;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
pub fn ensure_dir_exists(path: &PathBuf) -> LockerResult<()> {
if !path.exists() {
fs::create_dir_all(path).map_err(|e| {
SmartLockerError::FileSystemError(format!("Error creating folder {:?}: {}", path, e))
})?;
println!("✅ Directory created: {:?}", path);
}
Ok(())
}
pub fn get_locker_dir() -> LockerResult<PathBuf> {
if let Some((_, value)) = env::vars()
.filter(|(key, _)| key.starts_with("SMART_LOCKER_TEST_DIR_"))
.last()
{
return Ok(PathBuf::from(value));
}
if let Ok(test_dir) = env::var("SMART_LOCKER_TEST_DIR") {
Ok(PathBuf::from(test_dir))
} else {
let user_dirs = UserDirs::new().ok_or_else(|| {
SmartLockerError::FileSystemError("Unable to access user directory".to_string())
})?;
Ok(user_dirs.home_dir().join(".locker"))
}
}
pub fn is_this_secret(file_path: &Path, silent: bool) -> (bool, Option<String>) {
if file_path.extension().and_then(|ext| ext.to_str()) == Some("slock") {
if let Some(secret_name) = file_path.file_stem().and_then(|stem| stem.to_str()) {
return (true, Some(secret_name.to_string()));
} else if !silent {
println!(
"{}",
format!("⚠️ Invalid secret file name '{}'.", file_path.display()).yellow()
);
}
(false, None)
} else {
if !silent {
println!(
"{}",
format!(
"⚠️ The file '{}' is not a valid secret file.",
file_path.display()
)
.yellow()
);
}
(false, None)
}
}
pub fn copy_to_clipboard(content: &str) -> Result<(), String> {
println!("Attempting to copy to clipboard...");
if cfg!(target_os = "windows") {
let mut ctx = ClipboardContext::new()
.map_err(|_| "Unable to access the clipboard on Windows".to_string())?;
ctx.set_contents(content.to_string())
.map_err(|_| "Failed to copy content to the clipboard on Windows".to_string())?;
println!("✅ Content copied to clipboard on Windows.");
Ok(())
} else if cfg!(target_os = "linux") {
if is_wsl() {
Command::new("clip.exe")
.stdin(std::process::Stdio::piped())
.spawn()
.and_then(|mut child| {
if let Some(stdin) = child.stdin.as_mut() {
use std::io::Write;
stdin.write_all(content.as_bytes())?;
}
child.wait() })
.map_err(|_| "Failed to copy content to clipboard on WSL".to_string())?;
println!("✅ Content copied to clipboard on WSL.");
Ok(())
} else {
if Command::new("xclip").output().is_ok() {
Command::new("xclip")
.arg("-selection")
.arg("clipboard")
.stdin(std::process::Stdio::piped())
.spawn()
.and_then(|mut child| {
if let Some(stdin) = child.stdin.as_mut() {
use std::io::Write;
stdin.write_all(content.as_bytes())?;
}
child.wait()
})
.map_err(|_| "Failed to copy content to clipboard using xclip".to_string())?;
println!("✅ Content copied to clipboard using xclip.");
Ok(())
} else if Command::new("xsel").output().is_ok() {
Command::new("xsel")
.arg("--clipboard")
.arg("--input")
.stdin(std::process::Stdio::piped())
.spawn()
.and_then(|mut child| {
if let Some(stdin) = child.stdin.as_mut() {
use std::io::Write;
stdin.write_all(content.as_bytes())?;
}
child.wait()
})
.map_err(|_| "Failed to copy content to clipboard using xsel".to_string())?;
println!("✅ Content copied to clipboard using xsel.");
Ok(())
} else {
Err("No clipboard utility (xclip or xsel) found on Linux".to_string())
}
}
} else {
Err("Unsupported operating system".to_string())
}
}
fn is_wsl() -> bool {
if let Ok(output) = Command::new("uname").arg("-r").output() {
if let Ok(stdout) = String::from_utf8(output.stdout) {
return stdout.to_lowercase().contains("microsoft");
}
}
false
}