From fc3ee9ba8f4e6d69adc666d75fa8ea4e059210f8 Mon Sep 17 00:00:00 2001 From: lashman Date: Fri, 27 Feb 2026 18:08:24 +0200 Subject: [PATCH] Add comprehensive AppImage metadata extraction design document Covers all metadata sources from Type 1/2 ELF headers through desktop entries to AppStream XML, with schema, parser, and UI display plans. --- .../2026-02-27-appimage-metadata-design.md | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 docs/plans/2026-02-27-appimage-metadata-design.md diff --git a/docs/plans/2026-02-27-appimage-metadata-design.md b/docs/plans/2026-02-27-appimage-metadata-design.md new file mode 100644 index 0000000..012a39e --- /dev/null +++ b/docs/plans/2026-02-27-appimage-metadata-design.md @@ -0,0 +1,183 @@ +# AppImage Comprehensive Metadata Extraction and Display + +## Goal + +Extract ALL available metadata from AppImage files - from the oldest Type 1 format to the newest Type 2 with AppStream XML - and display it comprehensively in the overview tab of the detail view. + +## Background: All AppImage Metadata Sources + +### 1. ELF Binary Header (Type 1 and Type 2) +- Magic bytes at offset 8: `AI\x01` (Type 1) or `AI\x02` (Type 2) +- Architecture from `e_machine` at offset 18 + +### 2. Type 1: ISO 9660 Volume Descriptor +- Update info at fixed offset 33651 (512 bytes) + +### 3. Type 2: ELF Sections +- `.upd_info` (1024 bytes) - update transport (zsync, GitHub releases, etc.) +- `.sha256_sig` (1024 bytes) - GPG digital signature +- `.sig_key` (8192 bytes) - public key for signature verification + +### 4. Desktop Entry File (.desktop) +Standard freedesktop fields: +- `Name`, `GenericName`, `Comment`, `Icon`, `Exec`, `Categories` +- `Keywords`, `MimeType`, `StartupWMClass`, `Terminal` +- `Actions` with `[Desktop Action ]` sections +- AppImage-specific: `X-AppImage-Version`, `X-AppImage-Name`, `X-AppImage-Arch` + +### 5. AppStream / AppData XML (richest source) +Located at `usr/share/metainfo/*.xml` or `usr/share/appdata/*.xml`: +- `` - reverse-DNS identifier +- `` - localized app name +- `` - one-line description +- `` - full rich-text description +- `` - developer/organization +- `` - SPDX license +- `` - umbrella project (GNOME, KDE, etc.) +- `` - homepage, bugtracker, donation, help, vcs-browser, contribute +- `` - search terms +- `` - menu categories +- `` - screenshot URLs with captions +- `` - version history with dates and changelogs +- `` - age rating +- `` - MIME types, binaries, D-Bus interfaces +- `` - theme colors + +### 6. Icons (already handled) +- `.DirIcon`, root-level PNG/SVG, `usr/share/icons/` hierarchy + +### 7. Digital Signatures (Type 2) +- GPG signature in `.sha256_sig` ELF section +- Verifiable with embedded public key + +## Approach + +Parse everything at analysis time and store in the database (Approach A). This matches the existing architecture where `run_background_analysis()` populates the DB and the UI reads from `AppImageRecord`. + +## Database Schema (Migration v9) + +16 new columns on `appimages`: + +| Column | Type | Default | Description | +|--------|------|---------|-------------| +| `appstream_id` | TEXT | NULL | Reverse-DNS ID (e.g. `org.kde.krita`) | +| `appstream_description` | TEXT | NULL | Rich description (paragraphs joined with newlines) | +| `generic_name` | TEXT | NULL | Generic descriptor ("Web Browser") | +| `license` | TEXT | NULL | SPDX license expression | +| `homepage_url` | TEXT | NULL | Project website | +| `bugtracker_url` | TEXT | NULL | Bug reporting URL | +| `donation_url` | TEXT | NULL | Donation page | +| `help_url` | TEXT | NULL | Documentation URL | +| `vcs_url` | TEXT | NULL | Source code URL | +| `keywords` | TEXT | NULL | Comma-separated keywords | +| `mime_types` | TEXT | NULL | Semicolon-separated MIME types | +| `content_rating` | TEXT | NULL | Summarized OARS rating | +| `project_group` | TEXT | NULL | Umbrella project | +| `release_history` | TEXT | NULL | JSON array of recent releases | +| `desktop_actions` | TEXT | NULL | JSON array of desktop actions | +| `has_signature` | INTEGER | 0 | Whether AppImage has GPG signature | + +## New Module: AppStream XML Parser + +**File:** `src/core/appstream.rs` + +Uses `quick-xml` crate (pure Rust, lightweight). + +Key types: +``` +AppStreamMetadata + id: Option + name: Option + summary: Option + description: Option + developer: Option + project_license: Option + project_group: Option + urls: HashMap + keywords: Vec + categories: Vec + content_rating_summary: Option + releases: Vec + mime_types: Vec + +ReleaseInfo + version: String + date: Option + description: Option +``` + +Parser function: `parse_appstream_file(path: &Path) -> Option` +- Walks XML events, extracts all fields +- Strips HTML from `` (joins `

` with newlines, `

  • ` with bullets) +- Caps releases at 10 most recent +- Summarizes OARS content rating into a single label + +## Extended Desktop Entry Parsing + +Update `DesktopEntryFields` in `inspector.rs`: +- Add `generic_name`, `keywords`, `mime_types`, `terminal`, `actions`, `x_appimage_name` +- Parse `[Desktop Action ]` sections for action names and exec commands + +## Inspector + Analysis Pipeline + +1. `AppImageMetadata` struct gains all new fields +2. `inspect_appimage()` looks for AppStream XML after extraction, parses it, merges into metadata (AppStream takes priority for overlapping fields) +3. `run_background_analysis()` stores new fields via `db.update_appstream_metadata()` +4. Signature detection: read ELF `.sha256_sig` section, check if non-empty + +## Overview Tab UI Layout + +Groups in order (each only shown when data exists): + +### About (new) +- App ID, Generic name, Developer, License, Project group + +### Description (new) +- Full multi-paragraph AppStream description + +### Links (new) +- Homepage, Bug tracker, Source code, Documentation, Donate +- Each row clickable via `gtk::UriLauncher` + +### Updates (existing, unchanged) + +### Release History (new) +- Recent releases with version, date, description +- Uses `adw::ExpanderRow` for entries with descriptions + +### Usage (existing, unchanged) + +### Capabilities (new) +- Keywords, MIME types, Content rating, Desktop actions + +### File Information (existing, extended) +- Add "Signature: Signed / Not signed" row + +## Dependencies + +Add to `Cargo.toml`: +```toml +quick-xml = "0.37" +``` + +## Files Modified + +| File | Changes | +|------|---------| +| `Cargo.toml` | Add `quick-xml` | +| `src/core/mod.rs` | Add `pub mod appstream;` | +| `src/core/appstream.rs` | **New** - AppStream XML parser | +| `src/core/database.rs` | Migration v9, new columns, `update_appstream_metadata()` | +| `src/core/inspector.rs` | Extended desktop parsing, AppStream integration, signature detection | +| `src/core/analysis.rs` | Store new metadata fields | +| `src/ui/detail_view.rs` | Redesigned overview tab with all new groups | + +## Verification + +1. `cargo build` compiles without errors +2. AppImages with AppStream XML show full metadata (developer, license, URLs, releases) +3. AppImages without AppStream XML still show desktop entry fields (graceful degradation) +4. URL links open in browser +5. Release history is scrollable/expandable +6. Empty groups are hidden +7. Re-scanning an app picks up newly available metadata