use std::path::Path;
use crate::TailFinError;
pub fn parse_netscape_cookies(data: &str) -> Vec<(String, String)> {
let mut cookies = Vec::new();
for line in data.lines() {
let line = line.trim();
if line.is_empty() || line.starts_with('#') {
continue;
}
let parts: Vec<&str> = line.splitn(7, '\t').collect();
if parts.len() < 6 {
continue;
}
let name = parts[5].to_string();
let value = if parts.len() > 6 {
parts[6].to_string()
} else {
String::new()
};
cookies.push((name, value));
}
cookies
}
pub fn load_netscape_file(path: &Path) -> Result<Vec<(String, String)>, TailFinError> {
let data = std::fs::read_to_string(path)
.map_err(|e| TailFinError::Io(format!("Cannot read cookie file: {}", e)))?;
let cookies = parse_netscape_cookies(&data);
if cookies.is_empty() {
return Err(TailFinError::AuthRequired);
}
Ok(cookies)
}
pub fn write_netscape_file(path: &Path, cookies: &[serde_json::Value]) -> Result<(), TailFinError> {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)
.map_err(|e| TailFinError::Io(format!("Cannot create directory: {}", e)))?;
}
let mut lines = vec![
"# Netscape HTTP Cookie File".to_string(),
"# Exported by tail-fin".to_string(),
String::new(),
];
for cookie in cookies {
let domain = cookie.get("domain").and_then(|v| v.as_str()).unwrap_or("");
let flag = if domain.starts_with('.') {
"TRUE"
} else {
"FALSE"
};
let path_val = cookie.get("path").and_then(|v| v.as_str()).unwrap_or("/");
let secure = if cookie
.get("secure")
.and_then(|v| v.as_bool())
.unwrap_or(false)
{
"TRUE"
} else {
"FALSE"
};
let expires = cookie
.get("expires")
.and_then(|v| v.as_f64())
.map(|v| v as u64)
.unwrap_or(0);
let name = cookie.get("name").and_then(|v| v.as_str()).unwrap_or("");
let value = cookie.get("value").and_then(|v| v.as_str()).unwrap_or("");
lines.push(format!(
"{}\t{}\t{}\t{}\t{}\t{}\t{}",
domain, flag, path_val, secure, expires, name, value
));
}
std::fs::write(path, lines.join("\n"))
.map_err(|e| TailFinError::Io(format!("Cannot write cookie file: {}", e)))?;
Ok(())
}