#!/bin/sh # SOFTGIT: download an app and verify its SHA-256 checksum. # # curl -fsSL https://softgit.pro/get.sh | sh -s -- # # is the last part of the app page address: https://softgit.pro/p/ # The file is saved in the current folder and opened with the default app once it is verified # (set SHOWCASE_NO_OPEN=1 to skip opening). Works on macOS and Linux (POSIX sh, curl or wget). set -eu SITE="${SHOWCASE_URL:-https://softgit.pro}" SITE="${SITE%/}" SLUG="${1:-}" say() { printf '%s\n' "$*"; } die() { printf 'Error: %s\n' "$*" >&2; exit 1; } if [ -z "$SLUG" ]; then say "Usage: curl -fsSL $SITE/get.sh | sh -s -- " >&2 exit 2 fi case "$SLUG" in *[!A-Za-z0-9._-]*) die "invalid app name: $SLUG" ;; esac if command -v curl >/dev/null 2>&1; then fetch() { curl -fsSL "$1"; } fetch_to() { curl -fL --progress-bar -o "$2" "$1"; } elif command -v wget >/dev/null 2>&1; then fetch() { wget -qO- "$1"; } fetch_to() { wget -q -O "$2" "$1"; } else die "curl or wget is required" fi sha256_of() { if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | cut -d ' ' -f 1 elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | cut -d ' ' -f 1 elif command -v openssl >/dev/null 2>&1; then openssl dgst -sha256 "$1" | sed 's/^.*= *//' else return 1 fi } # Opens the verified file with the default app, in the background; never fails the script. open_file() { [ -z "${SHOWCASE_NO_OPEN:-}" ] || return 0 case "$(uname -s 2>/dev/null || echo unknown)" in Darwin) say "Opening $1 ..." open "$1" >/dev/null 2>&1 & ;; *) if [ -z "${DISPLAY:-}${WAYLAND_DISPLAY:-}" ]; then say "Note: no desktop session found, so the file was not opened." elif command -v xdg-open >/dev/null 2>&1; then say "Opening $1 ..." xdg-open "$1" >/dev/null 2>&1 & else say "Note: no file opener found (xdg-open), so the file was not opened." fi ;; esac return 0 } INFO=$(fetch "$SITE/api/download-info?slug=$SLUG") || die "app \"$SLUG\" was not found on $SITE (or the site could not be reached)" FILE_JSON=$(printf '%s' "$INFO" | tr -d '\r\n' | sed -n 's/.*"file":{\([^}]*\)}.*/\1/p') [ -n "$FILE_JSON" ] || die "\"$SLUG\" has no downloadable file on $SITE" field() { printf '%s' "$FILE_JSON" | sed -n "s/.*\"$1\":\"\([^\"]*\)\".*/\1/p"; } NAME=$(field name) URL=$(field url) SUM=$(field sha256 | tr 'ABCDEF' 'abcdef') case "$FILE_JSON" in *'"external":true'*) EXTERNAL=1 ;; *) EXTERNAL=0 ;; esac case "$URL" in /*) URL="$SITE$URL" ;; https://*|http://*) ;; *) die "no download address for \"$SLUG\"" ;; esac OUT=$(printf '%s' "${NAME##*/}" | tr -c 'A-Za-z0-9._+-' '_' | sed 's/^[.-]*//') [ -n "$OUT" ] || OUT="$SLUG.download" say "Downloading $OUT from $SITE ..." [ "$EXTERNAL" = 1 ] && say "This file is served by its official mirror (SourceForge), not hosted on $SITE." fetch_to "$URL" "./$OUT" || die "download failed" if [ -z "$SUM" ]; then say "WARNING: no SHA-256 checksum is published for this file, so it cannot be verified automatically." say "Saved: $(pwd)/$OUT" open_file "./$OUT" exit 0 fi ACTUAL=$(sha256_of "./$OUT") || die "no SHA-256 tool found (sha256sum, shasum or openssl). Expected checksum: $SUM" ACTUAL=$(printf '%s' "$ACTUAL" | tr 'ABCDEF' 'abcdef') if [ "$ACTUAL" = "$SUM" ]; then say "OK: checksum matches ($SUM)" say "Saved: $(pwd)/$OUT" open_file "./$OUT" else say "WARNING: checksum mismatch!" >&2 say " expected: $SUM" >&2 say " actual: $ACTUAL" >&2 say "Do not open this file. Delete it and try again, and please let us know: $SITE/security" >&2 exit 1 fi