Fix macos appinfo
This commit is contained in:
parent
e3315c9372
commit
7d32a732b0
|
@ -73,6 +73,17 @@ version = "1.0.93"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
|
||||
|
||||
[[package]]
|
||||
name = "apple-bundle"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a9a3a9da7ba0220d2ee5a02b6be5e0dbc73d9e9e74d8ffb5f1a7d32275e7282"
|
||||
dependencies = [
|
||||
"plist",
|
||||
"serde",
|
||||
"serde_plain",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arboard"
|
||||
version = "3.4.1"
|
||||
|
@ -709,6 +720,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"aes",
|
||||
"anyhow",
|
||||
"apple-bundle",
|
||||
"arboard",
|
||||
"async-stream",
|
||||
"base64",
|
||||
|
@ -737,6 +749,7 @@ dependencies = [
|
|||
"scopeguard",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"serde",
|
||||
"sha2",
|
||||
"ssh-encoding",
|
||||
"ssh-key",
|
||||
|
@ -1950,6 +1963,19 @@ version = "0.3.31"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||
|
||||
[[package]]
|
||||
name = "plist"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"indexmap",
|
||||
"quick-xml 0.32.0",
|
||||
"serde",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.16.8"
|
||||
|
@ -2033,6 +2059,15 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.36.2"
|
||||
|
@ -2293,24 +2328,33 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.214"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
|
||||
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.214"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
|
||||
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_plain"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.19"
|
||||
|
@ -2858,7 +2902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quick-xml",
|
||||
"quick-xml 0.36.2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
|
|
|
@ -61,7 +61,6 @@ pkcs8 = { version = "=0.10.2", features = ["alloc", "encryption", "pem"] }
|
|||
rsa = "=0.9.6"
|
||||
ed25519 = { version = "=2.2.3", features = ["pkcs8"] }
|
||||
sysinfo = { version = "0.32.0", features = ["windows"] }
|
||||
icns = "0.3.1"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
widestring = { version = "=1.1.0", optional = true }
|
||||
|
@ -85,6 +84,9 @@ keytar = "=0.1.6"
|
|||
core-foundation = { version = "=0.10.0", optional = true }
|
||||
security-framework = { version = "=3.0.0", optional = true }
|
||||
security-framework-sys = { version = "=2.12.0", optional = true }
|
||||
icns = "0.3.1"
|
||||
apple-bundle = "0.1.4"
|
||||
serde = { version = "1.0.215", features = ["derive", "serde_derive"] }
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
gio = { version = "=0.19.5", optional = true }
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use apple_bundle::plist;
|
||||
use base64::prelude::BASE64_STANDARD;
|
||||
use icns::{IconFamily, IconType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sysinfo::{Pid, System};
|
||||
use std::{fs::File, io::{BufReader, BufWriter}, process::Command};
|
||||
use base64::prelude::*;
|
||||
|
@ -21,32 +23,37 @@ pub fn get_info(pid: usize) -> Result<ApplicationInfo, anyhow::Error> {
|
|||
if proc.is_none() {
|
||||
break;
|
||||
}
|
||||
|
||||
println!("checking parent: {:?} {:?}", ppid, proc.unwrap().name());
|
||||
|
||||
let parent_info = get_info_for_pid(ppid.as_u32() as usize)?;
|
||||
if parent_info.is_installed_app {
|
||||
println!("Parent app installed, returning parent app");
|
||||
return Ok(parent_info);
|
||||
}
|
||||
|
||||
if let Ok(new_ppid) = get_parent_pid(ppid) {
|
||||
println!("Found parent using sysinfo");
|
||||
ppid = new_ppid;
|
||||
} else {
|
||||
if let Ok(new_ppid) = get_parent_fallback(ppid) {
|
||||
println!("Found parent using fallback");
|
||||
ppid = new_ppid;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ppid = get_parent(ppid)?;
|
||||
}
|
||||
|
||||
println!("No app found, returning initial app");
|
||||
Ok(app_info)
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Default)]
|
||||
pub struct InfoPlist {
|
||||
#[serde(
|
||||
rename = "CFBundleName",
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub bundle_name: Option<String>,
|
||||
#[serde(
|
||||
rename = "CFBundleDisplayName",
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub bundle_display_name: Option<String>,
|
||||
#[serde(
|
||||
rename = "CFBundleIconFile",
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub bundle_icon_file: Option<String>,
|
||||
}
|
||||
|
||||
fn get_info_for_pid(pid: usize) -> Result<ApplicationInfo, anyhow::Error> {
|
||||
let sys = System::new_all();
|
||||
// get with pid
|
||||
|
@ -54,22 +61,30 @@ fn get_info_for_pid(pid: usize) -> Result<ApplicationInfo, anyhow::Error> {
|
|||
let executable_path = proc.unwrap().exe().ok_or(anyhow::anyhow!("Executable path not found"))?.to_str().unwrap().to_string();
|
||||
let process_name = proc.ok_or(anyhow::anyhow!("Process not found"))?.name();
|
||||
|
||||
println!("executable_path: {:?}", executable_path);
|
||||
|
||||
// if path stars with /Applications/
|
||||
if executable_path.starts_with("/Applications/") {
|
||||
let application_name = executable_path.split("/").last().ok_or(anyhow::anyhow!("App name not found"))?;
|
||||
let package_name = executable_path.split("/").nth(2).ok_or(anyhow::anyhow!("Package name not found"))?;
|
||||
|
||||
let info_plist_path = format!("/Applications/{}/Contents/Info.plist", package_name);
|
||||
let info_plist = std::fs::read(info_plist_path).map_err(|e| anyhow::anyhow!("Error reading Info.plist: {:?}", e))?;
|
||||
let info_plist: InfoPlist = plist::from_bytes(&info_plist).map_err(|e| anyhow::anyhow!("Error parsing Info.plist: {:?}", e))?;
|
||||
let application_name = info_plist.bundle_display_name.unwrap_or(application_name.to_string());
|
||||
let icon_name = info_plist.bundle_icon_file.unwrap_or("AppIcon.icns".to_string());
|
||||
let icon_name = if icon_name.ends_with(".icns") {
|
||||
icon_name
|
||||
} else {
|
||||
format!("{}.icns", icon_name)
|
||||
};
|
||||
let icon = get_icon(package_name, &icon_name).ok();
|
||||
return Ok(ApplicationInfo {
|
||||
name: application_name.to_string(),
|
||||
name: application_name,
|
||||
path: Some(executable_path.clone()),
|
||||
icon: get_icon(package_name).ok(),
|
||||
icon,
|
||||
is_installed_app: true,
|
||||
});
|
||||
} else {
|
||||
return Ok(ApplicationInfo {
|
||||
name: process_name.to_str().unwrap().to_string(),
|
||||
name: process_name.to_str().unwrap_or_else(|| "unknown process").to_string(),
|
||||
path: None,
|
||||
icon: None,
|
||||
is_installed_app: false,
|
||||
|
@ -77,11 +92,11 @@ fn get_info_for_pid(pid: usize) -> Result<ApplicationInfo, anyhow::Error> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_icon(package_name: &str) -> Result<String, anyhow::Error> {
|
||||
let icon_path = format!("/Applications/{}/Contents/Resources/AppIcon.icns", package_name);
|
||||
fn get_icon(package_name: &str, icon_name: &str) -> Result<String, anyhow::Error> {
|
||||
let icon_path = format!("/Applications/{}/Contents/Resources/{}", package_name, icon_name);
|
||||
let file = BufReader::new(File::open(icon_path)?);
|
||||
let icon_family = IconFamily::read(file)?;
|
||||
let image = icon_family.get_icon_with_type(IconType::RGBA32_128x128)?;
|
||||
let image = icon_family.get_icon_with_type(IconType::RGBA32_128x128).unwrap();
|
||||
let mut buffer = Vec::new();
|
||||
let file = BufWriter::new(&mut buffer);
|
||||
image.write_png(file)?;
|
||||
|
@ -109,4 +124,8 @@ fn get_parent_fallback(pid: Pid) -> Result<Pid, anyhow::Error> {
|
|||
let parent_pid = output.lines().nth(1).ok_or(anyhow::anyhow!("Line not found"))?.split_whitespace().nth(0).ok_or(anyhow::anyhow!("Column not found"))?;
|
||||
let parent_pid = parent_pid.parse::<usize>()?;
|
||||
Ok(Pid::from(parent_pid))
|
||||
}
|
||||
|
||||
fn get_parent(pid: Pid) -> Result<Pid, anyhow::Error> {
|
||||
get_parent_pid(pid).or_else(|_| get_parent_fallback(pid))
|
||||
}
|
Loading…
Reference in New Issue