diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fa32e9a..fe9581d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -106,13 +106,17 @@ jobs: - name: Install dependencies (macOS) if: matrix.platform == 'macos-latest' run: | - brew install apache-arrow create-dmg libomp + brew extract --version=24.0.0 apache-arrow homebrew/core --force + brew install apache-arrow@24.0.0 create-dmg libomp - name: Install dependencies (Linux) if: matrix.platform == 'ubuntu-latest' || matrix.platform == 'ubuntu-24.04-arm' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgirepository1.0-dev libwebkit2gtk-4.1-dev libappindicator3-dev patchelf librsvg2-dev libfuse2 + wget https://apache.jfrog.io/artifactory/arrow/ubuntu/apache-arrow-apt-source-latest-noble.deb + sudo apt-get install -y ./apache-arrow-apt-source-latest-noble.deb + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libgirepository1.0-dev libwebkit2gtk-4.1-dev libappindicator3-dev patchelf librsvg2-dev libfuse2 libarrow-dev - name: Install frontend dependencies run: npm ci diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c98c608..16bb881 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["staticlib", "cdylib", "rlib"] tauri-build = { version = "2", features = [] } [features] -default = [] +default = ["icebug-analytics"] icebug-analytics = ["dep:icebug"] [dependencies] diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 2663eab..274ded4 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -214,31 +214,48 @@ fn scan_for_databases(dir: &Path, base_dir: &Path) -> Vec { for entry in WalkDir::new(dir).into_iter().filter_map(|e| e.ok()) { let path = entry.path(); if path.is_file() { - if let Some(ext) = path.extension() { - if ext == "lbdb" { - let name = path - .file_stem() - .unwrap_or_default() - .to_string_lossy() - .to_string(); - let relative_path = path - .strip_prefix(base_dir) - .unwrap_or(path) - .to_string_lossy() - .to_string(); - databases.push(DatabaseInfo { - id: 0, // assigned later - name, - path: path.to_string_lossy().to_string(), - relative_path, - }); - } + let abs_path = path.to_string_lossy().to_string(); + // Let Database::new() validate by magic bytes — no extension whitelist. + // A quick probe to skip obviously non-DB files without a full open. + if !is_lbug_file_fast(&abs_path) { + continue; } + let name = path + .file_stem() + .unwrap_or_default() + .to_string_lossy() + .to_string(); + let relative_path = path + .strip_prefix(base_dir) + .unwrap_or(path) + .to_string_lossy() + .to_string(); + databases.push(DatabaseInfo { + id: 0, // assigned later + name, + path: abs_path, + relative_path, + }); } } databases } +/// Quick check that a file starts with Lbug's magic bytes, without a full database open. +/// The Lbug magic is the 4-byte sequence `b"LBUG"` at offset 0. +fn is_lbug_file_fast(path: &str) -> bool { + use std::io::Read; + let mut file = match std::fs::File::open(path) { + Ok(f) => f, + Err(_) => return false, + }; + let mut magic = [0u8; 4]; + if file.read_exact(&mut magic).is_err() { + return false; + } + &magic == b"LBUG" +} + fn get_all_databases(state: &AppState) -> Vec { let scanned = scan_for_databases(&state.data_dir, &state.data_dir); let custom = state.custom_databases.lock().unwrap(); @@ -264,9 +281,7 @@ fn database_info_from_path(file_path: &str) -> Result { return Err("File not found".to_string()); } - if abs_path.extension().and_then(|e| e.to_str()) != Some("lbdb") { - return Err("Only .lbdb files are supported".to_string()); - } + // Extension check removed: Database::new() validates by magic bytes and returns a clear error let abs_path_str = abs_path.to_string_lossy().to_string(); let name = abs_path @@ -1318,6 +1333,20 @@ fn collect_edge_graph(conn: &Connection, limit: usize) -> Result stem.to_string_lossy().to_string(), + None => name.clone(), + }; files.push(DirEntry { - name: name.trim_end_matches(".lbdb").to_string(), + name: trimmed, path: entry_path.to_string_lossy().to_string(), entry_type: "file".to_string(), });