From 1b04860c943bbd8e8ef963353c2b26c8a9a04eb6 Mon Sep 17 00:00:00 2001 From: NimBold Date: Mon, 15 Jun 2026 14:24:34 +0330 Subject: [PATCH] fix: resolve P3 audit findings --- src-tauri/Cargo.toml | 3 +- src-tauri/src/db.rs | 4 +- src-tauri/src/extension_server.rs | 15 ++-- src-tauri/src/lib.rs | 13 ++- src-tauri/src/scheduler.rs | 2 +- src/App.css | 114 +-------------------------- src/components/AddDownloadsModal.tsx | 2 +- src/components/DownloadTable.tsx | 3 +- src/components/Sidebar.tsx | 5 +- 9 files changed, 27 insertions(+), 134 deletions(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 45aec7c..a177ad4 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -52,6 +52,7 @@ tokio-tungstenite = "0.29.0" futures-util = { version = "0.3.32", features = ["sink"] } rusqlite = { version = "0.40.1", features = ["bundled"] } chrono = "0.4.38" +url = "2" +[target.'cfg(target_os = "macos")'.dependencies] cocoa = "0.25" objc = "0.2.7" -url = "2" diff --git a/src-tauri/src/db.rs b/src-tauri/src/db.rs index 924c89a..e6b1099 100644 --- a/src-tauri/src/db.rs +++ b/src-tauri/src/db.rs @@ -1,6 +1,6 @@ use rusqlite::{Connection, Result, params}; use tokio::sync::Mutex; -use std::path::PathBuf; + use tauri::Manager; pub struct DbState { @@ -8,7 +8,7 @@ pub struct DbState { } pub fn init_db(app_handle: &tauri::AppHandle) -> Result { - let app_dir = app_handle.path().app_data_dir().unwrap_or_else(|_| PathBuf::from(".")); + let app_dir = app_handle.path().app_data_dir().expect("Cannot get app data dir"); if !app_dir.exists() { let _ = std::fs::create_dir_all(&app_dir); } diff --git a/src-tauri/src/extension_server.rs b/src-tauri/src/extension_server.rs index cae826c..32157af 100644 --- a/src-tauri/src/extension_server.rs +++ b/src-tauri/src/extension_server.rs @@ -81,16 +81,11 @@ pub async fn start_server( .layer(cors) .with_state(state); - let mut listener = None; - for port in EXTENSION_SERVER_PORT..=(EXTENSION_SERVER_PORT + 10) { - if let Ok(l) = tokio::net::TcpListener::bind(("127.0.0.1", port)).await { - listener = Some((l, port)); - break; - } - } - - let (listener, bound_port) = listener.ok_or_else(|| "Failed to bind extension server to any port".to_string())?; - println!("Browser extension server bound to 127.0.0.1:{}", bound_port); + let listener = tokio::net::TcpListener::bind(("127.0.0.1", EXTENSION_SERVER_PORT)) + .await + .map_err(|e| format!("Failed to bind extension server to port {}: {}", EXTENSION_SERVER_PORT, e))?; + + println!("Browser extension server bound to 127.0.0.1:{}", EXTENSION_SERVER_PORT); axum::serve(listener, app) .await diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 347ff68..695d90f 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -837,9 +837,13 @@ pub(crate) async fn start_media_download_internal( let stdout = child.stdout.take().ok_or("Failed to capture stdout")?; // yt-dlp parsing regex - let pct_re = Regex::new(r"\[download\]\s+(\d+(?:\.\d+)?)%").unwrap(); - let spd_re = Regex::new(r"at\s+([^\s]+)").unwrap(); - let eta_re = Regex::new(r"ETA\s+([^\s]+)").unwrap(); + static PCT_RE: std::sync::OnceLock = std::sync::OnceLock::new(); + static SPD_RE: std::sync::OnceLock = std::sync::OnceLock::new(); + static ETA_RE: std::sync::OnceLock = std::sync::OnceLock::new(); + + let pct_re = PCT_RE.get_or_init(|| Regex::new(r"\[download\]\s+(\d+(?:\.\d+)?)%").unwrap()); + let spd_re = SPD_RE.get_or_init(|| Regex::new(r"at\s+([^\s]+)").unwrap()); + let eta_re = ETA_RE.get_or_init(|| Regex::new(r"ETA\s+([^\s]+)").unwrap()); let _keep_alive = config_path; let mut reader = BufReader::new(stdout).lines(); @@ -1195,7 +1199,8 @@ fn toggle_tray_icon(app_handle: tauri::AppHandle, show: bool) -> Result<(), Stri let show_i = MenuItem::with_id(&app_handle, "show", "Show Firelink", true, None::<&str>).map_err(|e| e.to_string())?; let menu = Menu::with_items(&app_handle, &[&show_i, &quit_i]).map_err(|e| e.to_string())?; - let tray_icon = tauri::image::Image::from_bytes(include_bytes!("../icons/trayTemplate.png")).unwrap(); + let tray_icon = tauri::image::Image::from_bytes(include_bytes!("../icons/trayTemplate.png")) + .map_err(|e| e.to_string())?; let _tray = TrayIconBuilder::with_id("main") .icon(tray_icon) .icon_as_template(true) diff --git a/src-tauri/src/scheduler.rs b/src-tauri/src/scheduler.rs index e5b947d..d5da9f4 100644 --- a/src-tauri/src/scheduler.rs +++ b/src-tauri/src/scheduler.rs @@ -6,7 +6,7 @@ use std::time::Duration; pub fn spawn_scheduler(app_handle: tauri::AppHandle) { tauri::async_runtime::spawn(async move { - let mut interval = tokio::time::interval(Duration::from_secs(10)); + let mut interval = tokio::time::interval(Duration::from_secs(1)); loop { interval.tick().await; diff --git a/src/App.css b/src/App.css index 246295d..a00db89 100644 --- a/src/App.css +++ b/src/App.css @@ -1,113 +1 @@ -.logo.vite:hover { - filter: drop-shadow(0 0 2em #747bff); -} - -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafb); -} -:root { - font-family: Inter, Avenir, Helvetica, Arial, sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - - color: #0f0f0f; - background-color: #f6f6f6; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -.container { - margin: 0; - padding-top: 10vh; - display: flex; - flex-direction: column; - justify-content: center; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: 0.75s; -} - -.logo.tauri:hover { - filter: drop-shadow(0 0 2em #24c8db); -} - -.row { - display: flex; - justify-content: center; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -h1 { - text-align: center; -} - -input, -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - color: #0f0f0f; - background-color: #ffffff; - transition: border-color 0.25s; - box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); -} - -button { - cursor: pointer; -} - -button:hover { - border-color: #396cd8; -} -button:active { - border-color: #396cd8; - background-color: #e8e8e8; -} - -input, -button { - outline: none; -} - - -@media (prefers-color-scheme: dark) { - :root { - color: #f6f6f6; - background-color: #2f2f2f; - } - - a:hover { - color: #24c8db; - } - - input, - button { - color: #ffffff; - background-color: #0f0f0f98; - } - button:active { - background-color: #0f0f0f69; - } -} +/* Boilerplate styles cleared */ diff --git a/src/components/AddDownloadsModal.tsx b/src/components/AddDownloadsModal.tsx index a07e6ed..036050a 100644 --- a/src/components/AddDownloadsModal.tsx +++ b/src/components/AddDownloadsModal.tsx @@ -531,7 +531,7 @@ export const AddDownloadsModal = () => { let newName = finalFile; let exists = true; - while (exists) { + while (exists && count < 1000) { newName = `${base} (${count})${ext}`; const storeHas = useDownloadStore.getState().downloads.some(d => { const dest = d.destination || useSettingsStore.getState().defaultDownloadPath || '~/Downloads'; diff --git a/src/components/DownloadTable.tsx b/src/components/DownloadTable.tsx index 37baca1..eca7f82 100644 --- a/src/components/DownloadTable.tsx +++ b/src/components/DownloadTable.tsx @@ -57,7 +57,8 @@ export const DownloadTable: React.FC = ({ filter }) => { } else if (dir === '~') { resolvedDir = await homeDir(); } - return resolvedDir + '/' + file; + const separator = resolvedDir.endsWith('/') ? '' : '/'; + return resolvedDir + separator + file; }; const filteredDownloads = downloads.filter((d: DownloadItem) => { diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 7efd5cf..b16fe7e 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -247,7 +247,10 @@ export const Sidebar: React.FC = (props) => { {contextMenu && (
e.stopPropagation()} >