diff --git a/.codex/skills/linux-game-manager-dev/references/core-map.md b/.codex/skills/linux-game-manager-dev/references/core-map.md index fbf8fae..c95da65 100644 --- a/.codex/skills/linux-game-manager-dev/references/core-map.md +++ b/.codex/skills/linux-game-manager-dev/references/core-map.md @@ -1,6 +1,6 @@ # Linux Game Manager Core Map -Last refreshed: 2026-04-12 +Last refreshed: 2026-04-14 ## Top-Level Structure @@ -16,7 +16,7 @@ Last refreshed: 2026-04-12 - Installers: 42 (`.install/*.sh`) - Launcher definitions: 42 (`.launch/*.game`) -- Launcher runnable entries: 30 (`.launch/*.sh`, both symlinks and files) +- Launcher runnable entries: 31 (`.launch/*.sh`, both symlinks and files) - Update scripts: 5 (`.update/*.sh`) Regenerate this snapshot with: @@ -30,7 +30,8 @@ python3 .codex/skills/linux-game-manager-dev/scripts/audit_game_catalog.py 1. **Install flow** - `game_installer` builds menu from `.install/*.sh`. - Selected installer is sourced in the current shell. -- Shared downloads try `curl` first, fall back to `wget` when available, and reject obvious HTML error pages for unknown file types. +- Shared downloads try `curl` first, fall back to `wget` when available, validate archive payloads before install, and reject obvious HTML error pages for unknown file types. +- `download_named()` shares the same cache validation path as `download()`, so resolved asset URLs must still produce a valid payload for their file extension. - If `.launch/.game` exists and `.launch/.sh` does not, the manager creates a symlink using the repository root, even if the installer changed directories. 2. **Launch flow** diff --git a/linux-game-manager.sh b/linux-game-manager.sh index 4c0c76c..af6e374 100755 --- a/linux-game-manager.sh +++ b/linux-game-manager.sh @@ -556,44 +556,56 @@ download() { ui_msgbox "Linux Game Manager" "Linux Game Manager" "Could not download \"$i\"...\n\ndownload exit codes: ${downloadAttemptExitCodes}\nError details: ${downloadErrorLog}" exit 1 fi; } | ui_progressbox "Linux Game Manager" "Downloading \"$dest\" from \"$i\"" - local downloadError=0 - case "${dest##*.}" in - "pk3"|"zip") - unzip -tq "${cache}/${dest}" | ui_progressbox "Linux Game Manager" "Validating ${dest##*.} file" - downloadError=$? - ;; - "7z") - 7z t "${cache}/${dest}" | ui_progressbox "Linux Game Manager" "Validating 7z file" - downloadError=$? - ;; - "exe") - # Check if it's a valid Windows executable by looking at the MZ header - if ! hexdump -n 2 -v -e '/1 "%02X"' "${cache}/${dest}" | grep -q "4D5A"; then - downloadError=0 - fi - ;; - "wad") - if [[ "$(file -b --mime-type "${cache}/${dest}")" == "application/octet-stream" ]]; then - downloadError=0 - fi - ;; - *) - # Add HTML check for other file types - if file -b "${cache}/${dest}" | grep -q "HTML document" ; then - downloadError=1 - else - downloadError=0 - fi - ;; - esac - if [[ $downloadError -ne 0 ]]; then - rm -fv "${cache}/${dest}" - alert "Linux Game Manager" "Linux Game Manager" "Error downloading \"${dest}\". Installation cannot continue." - exit 1 - fi + validate_downloaded_cache_file "${dest}" done } +validate_downloaded_cache_file() { + local dest="$1" + local downloadError=0 + case "${dest##*.}" in + "pk3"|"zip") + if ! ( + set -o pipefail + unzip -tq "${cache}/${dest}" | ui_progressbox "Linux Game Manager" "Validating ${dest##*.} file" + ); then + downloadError=1 + fi + ;; + "7z") + if ! ( + set -o pipefail + 7z t "${cache}/${dest}" | ui_progressbox "Linux Game Manager" "Validating 7z file" + ); then + downloadError=1 + fi + ;; + "exe") + # Check if it's a valid Windows executable by looking at the MZ header + if ! hexdump -n 2 -v -e '/1 "%02X"' "${cache}/${dest}" | grep -q "4D5A"; then + downloadError=0 + fi + ;; + "wad") + if [[ "$(file -b --mime-type "${cache}/${dest}")" == "application/octet-stream" ]]; then + downloadError=0 + fi + ;; + *) + if file -b "${cache}/${dest}" | grep -q "HTML document" ; then + downloadError=1 + else + downloadError=0 + fi + ;; + esac + if [[ ${downloadError} -ne 0 ]]; then + rm -fv "${cache}/${dest}" + alert "Linux Game Manager" "Linux Game Manager" "Error downloading \"${dest}\". Installation cannot continue." + exit 1 + fi +} + download_named() { # Only needed if url breaks the name, e.g. downloads/?filename=1234 # Required arguments: filename url @@ -614,6 +626,7 @@ download_named() { ui_msgbox "Linux Game Manager" "Linux Game Manager" "Could not download \"$dest\"...\n\ndownload exit codes: ${downloadAttemptExitCodes}\nError details: ${downloadErrorLog}" exit 1 fi + validate_downloaded_cache_file "${dest}" } get_installer() {