Stop executing AppImages during analysis, add screenshot lightbox and favicons

- fuse.rs: Replace Command::new(appimage_path) with 256KB binary scan for
  runtime detection - prevents apps like Affinity from launching on tile click
- fuse.rs: Read only 12 bytes for Type 2 magic check instead of entire file
- security.rs: Use find_squashfs_offset_for() instead of executing AppImages
  with --appimage-offset flag
- updater.rs: Read only first 1MB for update info instead of entire file
- detail_view.rs: Click screenshots to open in lightbox dialog
- detail_view.rs: Fetch favicons from Google favicon service for link rows
This commit is contained in:
lashman
2026-02-27 18:58:12 +02:00
parent 8362e066f7
commit 65a1ea78fe
4 changed files with 150 additions and 51 deletions

View File

@@ -171,36 +171,37 @@ pub fn determine_app_fuse_status(
}
/// Check if the AppImage uses the new type2-runtime with statically linked FUSE.
/// The new runtime embeds FUSE support and doesn't need system libfuse.
/// Scans the first 256KB of the binary for runtime signatures instead of executing
/// the AppImage (which can hang for apps with custom AppRun scripts like Affinity).
fn has_static_runtime(appimage_path: &Path) -> bool {
// The new type2-runtime responds to --appimage-version with a version string
// containing "type2-runtime" or a recent date
let output = Command::new(appimage_path)
.arg("--appimage-version")
.env("APPIMAGE_EXTRACT_AND_RUN", "1")
.output();
if let Ok(output) = output {
let stdout = String::from_utf8_lossy(&output.stdout).to_lowercase();
let stderr = String::from_utf8_lossy(&output.stderr).to_lowercase();
let combined = format!("{}{}", stdout, stderr);
// New runtime identifies itself
return combined.contains("type2-runtime")
|| combined.contains("static")
|| combined.contains("libfuse3");
}
false
use std::io::Read;
let mut file = match std::fs::File::open(appimage_path) {
Ok(f) => f,
Err(_) => return false,
};
// The runtime signature is in the ELF binary header area, well within first 256KB
let mut buf = vec![0u8; 256 * 1024];
let n = match file.read(&mut buf) {
Ok(n) => n,
Err(_) => return false,
};
let data = &buf[..n];
let haystack = String::from_utf8_lossy(data).to_lowercase();
haystack.contains("type2-runtime")
|| haystack.contains("libfuse3")
}
/// Check if --appimage-extract-and-run is supported.
fn supports_extract_and_run(appimage_path: &Path) -> bool {
// Virtually all Type 2 AppImages support this flag
// We check by looking at the appimage type (offset 8 in the file)
if let Ok(data) = std::fs::read(appimage_path) {
if data.len() > 11 {
// Check for AppImage Type 2 magic at offset 8
return data[8] == 0x41 && data[9] == 0x49 && data[10] == 0x02;
}
// Check for AppImage Type 2 magic at offset 8 - only need to read 12 bytes
use std::io::Read;
let mut file = match std::fs::File::open(appimage_path) {
Ok(f) => f,
Err(_) => return false,
};
let mut header = [0u8; 12];
if file.read_exact(&mut header).is_ok() {
return header[8] == 0x41 && header[9] == 0x49 && header[10] == 0x02;
}
false
}