From d439e8c5d539adb0382b4f1f6365aafb96947fbd Mon Sep 17 00:00:00 2001 From: Allen Houchins Date: Thu, 9 Jul 2026 10:05:19 -0500 Subject: [PATCH] Fix osascript is-running checks across FMA custom scripts (#48638, #48225) osascript -e '... is running' exits 0 whether it prints true or false, so gating on the command's exit status misclassifies a fully-quit app as running. In scripts with relaunch logic (Zoom, Google Chrome) this launched the app after every patch even when the user had nothing open; in the rest it caused needless quit attempts and misleading logs. Same fix as #42951 applied to the generated helpers and #49030 applied to GitHub Desktop: capture osascript output and compare it to "true". Covers the 15 remaining custom scripts and regenerates the 13 affected darwin manifests (script-ref-only diffs, except google-chrome which also picked up the upstream 150.0.7871.115 version bump). --- .../inputs/homebrew/scripts/1password_install.sh | 4 +++- .../inputs/homebrew/scripts/adobe-cc-install.sh | 3 ++- .../inputs/homebrew/scripts/adobe-cc-uninstall.sh | 3 ++- .../inputs/homebrew/scripts/cleanmymac-uninstall.sh | 4 +++- .../inputs/homebrew/scripts/expressvpn-install.sh | 4 +++- .../inputs/homebrew/scripts/google_chrome_install.sh | 3 ++- .../inputs/homebrew/scripts/gpg-suite-uninstall.sh | 4 +++- .../inputs/homebrew/scripts/grammarly-desktop-install.sh | 4 +++- .../inputs/homebrew/scripts/logitune-install.sh | 3 ++- .../inputs/homebrew/scripts/microsoft-edge-install.sh | 4 +++- .../inputs/homebrew/scripts/microsoft_word_uninstall.sh | 4 +++- ee/maintained-apps/inputs/homebrew/scripts/p4v-install.sh | 3 ++- .../inputs/homebrew/scripts/p4v-uninstall.sh | 3 ++- .../inputs/homebrew/scripts/slack_install.sh | 4 +++- .../inputs/homebrew/scripts/zoom_install.sh | 3 ++- ee/maintained-apps/outputs/1password/darwin.json | 6 +++--- .../outputs/adobe-creative-cloud/darwin.json | 8 ++++---- ee/maintained-apps/outputs/cleanmymac/darwin.json | 4 ++-- ee/maintained-apps/outputs/expressvpn/darwin.json | 4 ++-- ee/maintained-apps/outputs/google-chrome/darwin.json | 8 ++++---- ee/maintained-apps/outputs/gpg-suite/darwin.json | 4 ++-- ee/maintained-apps/outputs/grammarly-desktop/darwin.json | 4 ++-- ee/maintained-apps/outputs/logitune/darwin.json | 6 +++--- ee/maintained-apps/outputs/microsoft-edge/darwin.json | 6 +++--- ee/maintained-apps/outputs/microsoft-word/darwin.json | 4 ++-- ee/maintained-apps/outputs/p4v/darwin.json | 8 ++++---- ee/maintained-apps/outputs/slack/darwin.json | 4 ++-- ee/maintained-apps/outputs/zoom/darwin.json | 6 +++--- 28 files changed, 74 insertions(+), 51 deletions(-) diff --git a/ee/maintained-apps/inputs/homebrew/scripts/1password_install.sh b/ee/maintained-apps/inputs/homebrew/scripts/1password_install.sh index a97958c6cba..346979455f2 100755 --- a/ee/maintained-apps/inputs/homebrew/scripts/1password_install.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/1password_install.sh @@ -5,7 +5,9 @@ quit_application() { local timeout_duration=10 # check if the application is running - if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then + local app_running + app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null) + if [[ "$app_running" != "true" ]]; then return fi diff --git a/ee/maintained-apps/inputs/homebrew/scripts/adobe-cc-install.sh b/ee/maintained-apps/inputs/homebrew/scripts/adobe-cc-install.sh index 9830264e322..d669fbd4c7b 100644 --- a/ee/maintained-apps/inputs/homebrew/scripts/adobe-cc-install.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/adobe-cc-install.sh @@ -3,7 +3,8 @@ quit_application() { bundle_id="$1" timeout_duration=10 - if ! osascript -e "application id \"$bundle_id\" is running" >/dev/null 2>&1; then return; fi + app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null) + if [ "$app_running" != "true" ]; then return; fi console_user="$(stat -f "%Su" /dev/console 2>/dev/null || true)" if [ "$(id -u)" -eq 0 ] && [ "$console_user" = "root" ]; then echo "Skipping quit for '$bundle_id'." diff --git a/ee/maintained-apps/inputs/homebrew/scripts/adobe-cc-uninstall.sh b/ee/maintained-apps/inputs/homebrew/scripts/adobe-cc-uninstall.sh index 0373234ea65..53565af7e92 100644 --- a/ee/maintained-apps/inputs/homebrew/scripts/adobe-cc-uninstall.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/adobe-cc-uninstall.sh @@ -3,7 +3,8 @@ quit_app() { b="$1" # try a friendly quit if a GUI user is active - if osascript -e "application id \"$b\" is running" >/dev/null 2>&1; then + app_running=$(osascript -e "application id \"$b\" is running" 2>/dev/null) + if [ "$app_running" = "true" ]; then cu="$(stat -f "%Su" /dev/console 2>/dev/null || true)" if [ "$(id -u)" -ne 0 ] || [ "$cu" != "root" ]; then i=0 diff --git a/ee/maintained-apps/inputs/homebrew/scripts/cleanmymac-uninstall.sh b/ee/maintained-apps/inputs/homebrew/scripts/cleanmymac-uninstall.sh index 5feeec0f936..b05e74ebb36 100755 --- a/ee/maintained-apps/inputs/homebrew/scripts/cleanmymac-uninstall.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/cleanmymac-uninstall.sh @@ -11,7 +11,9 @@ quit_application() { local timeout_duration=10 # check if the application is running - if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then + local app_running + app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null) + if [[ "$app_running" != "true" ]]; then return fi diff --git a/ee/maintained-apps/inputs/homebrew/scripts/expressvpn-install.sh b/ee/maintained-apps/inputs/homebrew/scripts/expressvpn-install.sh index f7e7d755e75..d76066c2e65 100755 --- a/ee/maintained-apps/inputs/homebrew/scripts/expressvpn-install.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/expressvpn-install.sh @@ -11,7 +11,9 @@ quit_application() { local timeout_duration=10 # check if the application is running - if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then + local app_running + app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null) + if [[ "$app_running" != "true" ]]; then return fi diff --git a/ee/maintained-apps/inputs/homebrew/scripts/google_chrome_install.sh b/ee/maintained-apps/inputs/homebrew/scripts/google_chrome_install.sh index ec75e33b39e..77898ea5c15 100644 --- a/ee/maintained-apps/inputs/homebrew/scripts/google_chrome_install.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/google_chrome_install.sh @@ -48,7 +48,8 @@ CONSOLE_USER=$(stat -f "%Su" /dev/console 2>/dev/null || echo "") # Check if Chrome is running (only check once) CHROME_WAS_RUNNING=false -if osascript -e "application id \"com.google.Chrome\" is running" 2>/dev/null; then +CHROME_RUNNING=$(osascript -e "application id \"com.google.Chrome\" is running" 2>/dev/null) +if [[ "$CHROME_RUNNING" == "true" ]]; then CHROME_WAS_RUNNING=true quit_application 'com.google.Chrome' "$CONSOLE_USER" fi diff --git a/ee/maintained-apps/inputs/homebrew/scripts/gpg-suite-uninstall.sh b/ee/maintained-apps/inputs/homebrew/scripts/gpg-suite-uninstall.sh index e5b6c0a7fea..6c6c6981346 100644 --- a/ee/maintained-apps/inputs/homebrew/scripts/gpg-suite-uninstall.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/gpg-suite-uninstall.sh @@ -34,7 +34,9 @@ quit_application() { local timeout_duration=10 # check if the application is running - if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then + local app_running + app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null) + if [[ "$app_running" != "true" ]]; then return fi diff --git a/ee/maintained-apps/inputs/homebrew/scripts/grammarly-desktop-install.sh b/ee/maintained-apps/inputs/homebrew/scripts/grammarly-desktop-install.sh index bdd41483d0e..a6de8a18893 100755 --- a/ee/maintained-apps/inputs/homebrew/scripts/grammarly-desktop-install.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/grammarly-desktop-install.sh @@ -11,7 +11,9 @@ quit_application() { local timeout_duration=10 # check if the application is running - if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then + local app_running + app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null) + if [[ "$app_running" != "true" ]]; then return fi diff --git a/ee/maintained-apps/inputs/homebrew/scripts/logitune-install.sh b/ee/maintained-apps/inputs/homebrew/scripts/logitune-install.sh index 03c9684c514..c4a836658a6 100644 --- a/ee/maintained-apps/inputs/homebrew/scripts/logitune-install.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/logitune-install.sh @@ -36,7 +36,8 @@ CONSOLE_USER=$(stat -f "%Su" /dev/console 2>/dev/null || echo "") # Quit Logi Tune gracefully before the PKG's preinstall force-kills it. The # PKG's default RUNAPP choice relaunches the app for logged-in console users # after installation, so no relaunch step is needed here. -if osascript -e "application id \"com.logitech.logitune\" is running" 2>/dev/null; then +LOGITUNE_RUNNING=$(osascript -e "application id \"com.logitech.logitune\" is running" 2>/dev/null) +if [[ "$LOGITUNE_RUNNING" == "true" ]]; then quit_application 'com.logitech.logitune' "$CONSOLE_USER" fi diff --git a/ee/maintained-apps/inputs/homebrew/scripts/microsoft-edge-install.sh b/ee/maintained-apps/inputs/homebrew/scripts/microsoft-edge-install.sh index d5f0610f1c6..0b676e08b36 100755 --- a/ee/maintained-apps/inputs/homebrew/scripts/microsoft-edge-install.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/microsoft-edge-install.sh @@ -11,7 +11,9 @@ quit_application() { local timeout_duration=10 # check if the application is running - if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then + local app_running + app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null) + if [[ "$app_running" != "true" ]]; then return fi diff --git a/ee/maintained-apps/inputs/homebrew/scripts/microsoft_word_uninstall.sh b/ee/maintained-apps/inputs/homebrew/scripts/microsoft_word_uninstall.sh index f42f0bf7cb5..80ae5ec7fce 100644 --- a/ee/maintained-apps/inputs/homebrew/scripts/microsoft_word_uninstall.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/microsoft_word_uninstall.sh @@ -34,7 +34,9 @@ quit_application() { local timeout_duration=10 # check if the application is running - if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then + local app_running + app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null) + if [[ "$app_running" != "true" ]]; then return fi diff --git a/ee/maintained-apps/inputs/homebrew/scripts/p4v-install.sh b/ee/maintained-apps/inputs/homebrew/scripts/p4v-install.sh index 9e123bc539a..a92b01f9d6c 100644 --- a/ee/maintained-apps/inputs/homebrew/scripts/p4v-install.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/p4v-install.sh @@ -3,7 +3,8 @@ quit_application() { local bundle_id="$1" local timeout_duration=10 - if ! osascript -e "application id \"$bundle_id\" is running" >/dev/null 2>&1; then return; fi + local app_running; app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null) + if [[ "$app_running" != "true" ]]; then return; fi local console_user; console_user=$(stat -f "%Su" /dev/console) if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then echo "Skipping quit for '$bundle_id'."; return; fi echo "Quitting '$bundle_id'..." diff --git a/ee/maintained-apps/inputs/homebrew/scripts/p4v-uninstall.sh b/ee/maintained-apps/inputs/homebrew/scripts/p4v-uninstall.sh index 22ce85bce7b..59d9ffc7242 100644 --- a/ee/maintained-apps/inputs/homebrew/scripts/p4v-uninstall.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/p4v-uninstall.sh @@ -3,7 +3,8 @@ quit_application() { local bundle_id="$1" local timeout_duration=10 - if ! osascript -e "application id \"$bundle_id\" is running" >/dev/null 2>&1; then return; fi + local app_running; app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null) + if [[ "$app_running" != "true" ]]; then return; fi local console_user; console_user=$(stat -f "%Su" /dev/console) if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then return; fi SECONDS=0 diff --git a/ee/maintained-apps/inputs/homebrew/scripts/slack_install.sh b/ee/maintained-apps/inputs/homebrew/scripts/slack_install.sh index 89a00a0c15f..8d744b4e655 100755 --- a/ee/maintained-apps/inputs/homebrew/scripts/slack_install.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/slack_install.sh @@ -5,7 +5,9 @@ quit_application() { local timeout_duration=10 # check if the application is running - if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then + local app_running + app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null) + if [[ "$app_running" != "true" ]]; then return fi diff --git a/ee/maintained-apps/inputs/homebrew/scripts/zoom_install.sh b/ee/maintained-apps/inputs/homebrew/scripts/zoom_install.sh index 91b6afaa937..9d1a032aa83 100755 --- a/ee/maintained-apps/inputs/homebrew/scripts/zoom_install.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/zoom_install.sh @@ -48,7 +48,8 @@ CONSOLE_USER=$(stat -f "%Su" /dev/console 2>/dev/null || echo "") # Check if Zoom is running ZOOM_WAS_RUNNING=false -if osascript -e "application id \"us.zoom.xos\" is running" 2>/dev/null; then +ZOOM_RUNNING=$(osascript -e "application id \"us.zoom.xos\" is running" 2>/dev/null) +if [[ "$ZOOM_RUNNING" == "true" ]]; then ZOOM_WAS_RUNNING=true quit_application 'us.zoom.xos' "$CONSOLE_USER" fi diff --git a/ee/maintained-apps/outputs/1password/darwin.json b/ee/maintained-apps/outputs/1password/darwin.json index e72de6ea755..9f146c95532 100644 --- a/ee/maintained-apps/outputs/1password/darwin.json +++ b/ee/maintained-apps/outputs/1password/darwin.json @@ -7,7 +7,7 @@ "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.1password.1password' AND version_compare(bundle_short_version, '8.12.26') < 0);" }, "installer_url": "https://downloads.1password.com/mac/1Password.pkg", - "install_script_ref": "ef2a17ff", + "install_script_ref": "1d854c01", "uninstall_script_ref": "c927cf5a", "sha256": "no_check", "default_categories": [ @@ -16,7 +16,7 @@ } ], "refs": { - "c927cf5a": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nquit_application 'com.1password.1password'\nsudo rm -rf \"$APPDIR/1Password.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.1password*'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.agilebits'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.1password.1password-launcher'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.1password.browser-support'\ntrash $LOGGED_IN_USER '~/Library/Application Support/1Password'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Arc/User Data/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.1password.1password.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CrashReporter/1Password*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Beta/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Canary/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Dev/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Beta/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Canary/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Dev/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Mozilla/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Vivaldi/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Containers/2BUA8C4S2C.com.1password.browser-helper'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.1password.1password*'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.1password.browser-support'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/2BUA8C4S2C.com.1password'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/2BUA8C4S2C.com.agilebits'\ntrash $LOGGED_IN_USER '~/Library/Logs/1Password'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.1password.1password.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/group.com.1password.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.1password.1password.savedState'\n", - "ef2a17ff": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\nquit_application 'com.1password.1password'\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\n" + "1d854c01": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\nquit_application 'com.1password.1password'\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\n", + "c927cf5a": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nquit_application 'com.1password.1password'\nsudo rm -rf \"$APPDIR/1Password.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.1password*'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.agilebits'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.1password.1password-launcher'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.1password.browser-support'\ntrash $LOGGED_IN_USER '~/Library/Application Support/1Password'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Arc/User Data/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.1password.1password.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CrashReporter/1Password*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Beta/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Canary/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Dev/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Beta/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Canary/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Dev/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Mozilla/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Vivaldi/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Containers/2BUA8C4S2C.com.1password.browser-helper'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.1password.1password*'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.1password.browser-support'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/2BUA8C4S2C.com.1password'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/2BUA8C4S2C.com.agilebits'\ntrash $LOGGED_IN_USER '~/Library/Logs/1Password'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.1password.1password.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/group.com.1password.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.1password.1password.savedState'\n" } } diff --git a/ee/maintained-apps/outputs/adobe-creative-cloud/darwin.json b/ee/maintained-apps/outputs/adobe-creative-cloud/darwin.json index 04f0fbbdd8f..aaabb01093b 100644 --- a/ee/maintained-apps/outputs/adobe-creative-cloud/darwin.json +++ b/ee/maintained-apps/outputs/adobe-creative-cloud/darwin.json @@ -7,8 +7,8 @@ "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.adobe.acc.AdobeCreativeCloud' AND version_compare(bundle_short_version, '6.10.0.252.3') < 0);" }, "installer_url": "https://ccmdls.adobe.com/AdobeProducts/StandaloneBuilds/ACCC/ESD/6.10.0/252.3/macarm64/ACCCx6_10_0_252_3.dmg", - "install_script_ref": "a331ea84", - "uninstall_script_ref": "e002ddef", + "install_script_ref": "2aa2127c", + "uninstall_script_ref": "05acae65", "sha256": "d02fc307e32b583c0552fbbca87cfe40b098f2fc707a12b033dff726091a21d6", "default_categories": [ "Productivity" @@ -16,7 +16,7 @@ } ], "refs": { - "a331ea84": "#!/bin/bash\n\nquit_application() {\n bundle_id=\"$1\"\n timeout_duration=10\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" >/dev/null 2>&1; then return; fi\n console_user=\"$(stat -f \"%Su\" /dev/console 2>/dev/null || true)\"\n if [ \"$(id -u)\" -eq 0 ] && [ \"$console_user\" = \"root\" ]; then\n echo \"Skipping quit for '$bundle_id'.\"\n return\n fi\n echo \"Quitting '$bundle_id'...\"\n i=0\n while [ \"$i\" -lt \"$timeout_duration\" ]; do\n osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1 || true\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"'$bundle_id' quit successfully.\"\n return\n fi\n i=$((i+1))\n sleep 1\n done\n echo \"'$bundle_id' did not quit.\"\n}\n\n[ -n \"$INSTALLER_PATH\" ] && [ -f \"$INSTALLER_PATH\" ] || { echo \"missing installer\"; exit 1; }\n\nquit_application \"com.adobe.acc.AdobeCreativeCloud\"\n\n# Mount to a known path to avoid space-in-volume issues\nMOUNT_POINT=\"$(mktemp -d \"/tmp/adobe_cc.XXXXXX\")\"\nif ! hdiutil attach -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" >/dev/null 2>&1; then\n rmdir \"$MOUNT_POINT\" >/dev/null 2>&1 || true\n echo \"failed to mount dmg\"\n exit 1\nfi\n\n# Find the installer app (handles Install.app or variants like *Install*.app)\nINSTALL_APP=\"$(/usr/bin/find \"$MOUNT_POINT\" -maxdepth 5 -type d \\( -name \"Install.app\" -o -iname \"*Install*.app\" \\) -print -quit)\"\n\nif [ -z \"$INSTALL_APP\" ] || [ ! -d \"$INSTALL_APP\" ]; then\n hdiutil detach \"$MOUNT_POINT\" >/dev/null 2>&1 || true\n rmdir \"$MOUNT_POINT\" >/dev/null 2>&1 || true\n echo \"Install.app not found\"\n exit 1\nfi\n\n# Prefer Contents/MacOS/Install, fall back to first executable in MacOS\nBIN=\"$INSTALL_APP/Contents/MacOS/Install\"\nif [ ! -x \"$BIN\" ]; then\n BIN=\"$(/usr/bin/find \"$INSTALL_APP/Contents/MacOS\" -type f -perm +111 -print -quit 2>/dev/null)\"\nfi\n[ -n \"$BIN\" ] && [ -x \"$BIN\" ] || { hdiutil detach \"$MOUNT_POINT\" >/dev/null 2>&1 || true; rmdir \"$MOUNT_POINT\" >/dev/null 2>&1 || true; echo \"installer binary not found\"; exit 1; }\n\n# Try silent, fall back to normal if needed\n\"$BIN\" --mode=silent >/dev/null 2>&1 || \"$BIN\" >/dev/null 2>&1\n\nhdiutil detach \"$MOUNT_POINT\" >/dev/null 2>&1 || true\nrmdir \"$MOUNT_POINT\" >/dev/null 2>&1 || true\n\necho \"adobe creative cloud installed\"\n", - "e002ddef": "#!/bin/bash\n\nquit_app() {\n b=\"$1\"\n # try a friendly quit if a GUI user is active\n if osascript -e \"application id \\\"$b\\\" is running\" >/dev/null 2>&1; then\n cu=\"$(stat -f \"%Su\" /dev/console 2>/dev/null || true)\"\n if [ \"$(id -u)\" -ne 0 ] || [ \"$cu\" != \"root\" ]; then\n i=0\n while [ \"$i\" -lt 10 ]; do\n osascript -e \"tell application id \\\"$b\\\" to quit\" >/dev/null 2>&1 || true\n if ! pgrep -f \"$b\" >/dev/null 2>&1; then break; fi\n i=$((i+1))\n sleep 1\n done\n fi\n fi\n # hard stop fallback\n pkill -f \"$b\" >/dev/null 2>&1 || true\n}\n\nBUNDLE_ID=\"com.adobe.acc.AdobeCreativeCloud\"\nquit_app \"$BUNDLE_ID\"\n\n# Try the official Adobe Creative Cloud Uninstaller.app first\nUNINST_APP=\"\"\nfor p in \\\n \"/Applications/Utilities/Adobe Creative Cloud/Utils/Creative Cloud Uninstaller.app\" \\\n \"/Applications/Adobe Creative Cloud/Utils/Creative Cloud Uninstaller.app\" \\\n \"/Applications/Utilities/Adobe Creative Cloud/Creative Cloud Uninstaller.app\"\ndo\n [ -d \"$p\" ] && { UNINST_APP=\"$p\"; break; }\ndone\n[ -z \"$UNINST_APP\" ] && UNINST_APP=\"$(/usr/bin/find /Applications /Applications/Utilities -maxdepth 5 -type d -iname '*creative*cloud*uninstaller*.app' -print -quit 2>/dev/null)\"\n\nif [ -n \"$UNINST_APP\" ] && [ -d \"$UNINST_APP\" ]; then\n BIN=\"$(/usr/bin/find \"$UNINST_APP/Contents/MacOS\" -maxdepth 1 -type f -perm -111 -print -quit 2>/dev/null)\"\n [ -n \"$BIN\" ] && { \"$BIN\" -uninstall --force >/dev/null 2>&1 || \"$BIN\" >/dev/null 2>&1 || true; }\nfi\n\n# Remove app bundles\nrm -rf \"/Applications/Adobe Creative Cloud.app\" \\\n \"/Applications/Creative Cloud.app\" \\\n \"/Applications/Utilities/Adobe Creative Cloud/ACC/Creative Cloud.app\" >/dev/null 2>&1 || true\n\n# System support files\nrm -rf \"/Library/Application Support/Adobe/Creative Cloud\" \\\n \"/Library/Application Support/Adobe/Adobe Desktop Common\" >/dev/null 2>&1 || true\nrm -f \"/Library/Preferences/com.adobe.acc.AdobeCreativeCloud.plist\" >/dev/null 2>&1 || true\nrm -f /var/db/receipts/com.adobe.acc*.bom /var/db/receipts/com.adobe.acc*.plist >/dev/null 2>&1 || true\n\n# Per-user cleanup\nfor udir in /Users/* /var/root; do\n [ -d \"$udir/Library\" ] || continue\n rm -rf \"$udir/Library/Application Support/Adobe/Creative Cloud\" \\\n \"$udir/Library/Caches/com.adobe.acc.AdobeCreativeCloud\" \\\n \"$udir/Library/Logs/Adobe/Creative Cloud\" >/dev/null 2>&1 || true\n rm -f \"$udir/Library/Preferences/com.adobe.acc.AdobeCreativeCloud.plist\" >/dev/null 2>&1 || true\ndone\n\necho \"adobe creative cloud uninstalled\"\n" + "05acae65": "#!/bin/bash\n\nquit_app() {\n b=\"$1\"\n # try a friendly quit if a GUI user is active\n app_running=$(osascript -e \"application id \\\"$b\\\" is running\" 2>/dev/null)\n if [ \"$app_running\" = \"true\" ]; then\n cu=\"$(stat -f \"%Su\" /dev/console 2>/dev/null || true)\"\n if [ \"$(id -u)\" -ne 0 ] || [ \"$cu\" != \"root\" ]; then\n i=0\n while [ \"$i\" -lt 10 ]; do\n osascript -e \"tell application id \\\"$b\\\" to quit\" >/dev/null 2>&1 || true\n if ! pgrep -f \"$b\" >/dev/null 2>&1; then break; fi\n i=$((i+1))\n sleep 1\n done\n fi\n fi\n # hard stop fallback\n pkill -f \"$b\" >/dev/null 2>&1 || true\n}\n\nBUNDLE_ID=\"com.adobe.acc.AdobeCreativeCloud\"\nquit_app \"$BUNDLE_ID\"\n\n# Try the official Adobe Creative Cloud Uninstaller.app first\nUNINST_APP=\"\"\nfor p in \\\n \"/Applications/Utilities/Adobe Creative Cloud/Utils/Creative Cloud Uninstaller.app\" \\\n \"/Applications/Adobe Creative Cloud/Utils/Creative Cloud Uninstaller.app\" \\\n \"/Applications/Utilities/Adobe Creative Cloud/Creative Cloud Uninstaller.app\"\ndo\n [ -d \"$p\" ] && { UNINST_APP=\"$p\"; break; }\ndone\n[ -z \"$UNINST_APP\" ] && UNINST_APP=\"$(/usr/bin/find /Applications /Applications/Utilities -maxdepth 5 -type d -iname '*creative*cloud*uninstaller*.app' -print -quit 2>/dev/null)\"\n\nif [ -n \"$UNINST_APP\" ] && [ -d \"$UNINST_APP\" ]; then\n BIN=\"$(/usr/bin/find \"$UNINST_APP/Contents/MacOS\" -maxdepth 1 -type f -perm -111 -print -quit 2>/dev/null)\"\n [ -n \"$BIN\" ] && { \"$BIN\" -uninstall --force >/dev/null 2>&1 || \"$BIN\" >/dev/null 2>&1 || true; }\nfi\n\n# Remove app bundles\nrm -rf \"/Applications/Adobe Creative Cloud.app\" \\\n \"/Applications/Creative Cloud.app\" \\\n \"/Applications/Utilities/Adobe Creative Cloud/ACC/Creative Cloud.app\" >/dev/null 2>&1 || true\n\n# System support files\nrm -rf \"/Library/Application Support/Adobe/Creative Cloud\" \\\n \"/Library/Application Support/Adobe/Adobe Desktop Common\" >/dev/null 2>&1 || true\nrm -f \"/Library/Preferences/com.adobe.acc.AdobeCreativeCloud.plist\" >/dev/null 2>&1 || true\nrm -f /var/db/receipts/com.adobe.acc*.bom /var/db/receipts/com.adobe.acc*.plist >/dev/null 2>&1 || true\n\n# Per-user cleanup\nfor udir in /Users/* /var/root; do\n [ -d \"$udir/Library\" ] || continue\n rm -rf \"$udir/Library/Application Support/Adobe/Creative Cloud\" \\\n \"$udir/Library/Caches/com.adobe.acc.AdobeCreativeCloud\" \\\n \"$udir/Library/Logs/Adobe/Creative Cloud\" >/dev/null 2>&1 || true\n rm -f \"$udir/Library/Preferences/com.adobe.acc.AdobeCreativeCloud.plist\" >/dev/null 2>&1 || true\ndone\n\necho \"adobe creative cloud uninstalled\"\n", + "2aa2127c": "#!/bin/bash\n\nquit_application() {\n bundle_id=\"$1\"\n timeout_duration=10\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [ \"$app_running\" != \"true\" ]; then return; fi\n console_user=\"$(stat -f \"%Su\" /dev/console 2>/dev/null || true)\"\n if [ \"$(id -u)\" -eq 0 ] && [ \"$console_user\" = \"root\" ]; then\n echo \"Skipping quit for '$bundle_id'.\"\n return\n fi\n echo \"Quitting '$bundle_id'...\"\n i=0\n while [ \"$i\" -lt \"$timeout_duration\" ]; do\n osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1 || true\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"'$bundle_id' quit successfully.\"\n return\n fi\n i=$((i+1))\n sleep 1\n done\n echo \"'$bundle_id' did not quit.\"\n}\n\n[ -n \"$INSTALLER_PATH\" ] && [ -f \"$INSTALLER_PATH\" ] || { echo \"missing installer\"; exit 1; }\n\nquit_application \"com.adobe.acc.AdobeCreativeCloud\"\n\n# Mount to a known path to avoid space-in-volume issues\nMOUNT_POINT=\"$(mktemp -d \"/tmp/adobe_cc.XXXXXX\")\"\nif ! hdiutil attach -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" >/dev/null 2>&1; then\n rmdir \"$MOUNT_POINT\" >/dev/null 2>&1 || true\n echo \"failed to mount dmg\"\n exit 1\nfi\n\n# Find the installer app (handles Install.app or variants like *Install*.app)\nINSTALL_APP=\"$(/usr/bin/find \"$MOUNT_POINT\" -maxdepth 5 -type d \\( -name \"Install.app\" -o -iname \"*Install*.app\" \\) -print -quit)\"\n\nif [ -z \"$INSTALL_APP\" ] || [ ! -d \"$INSTALL_APP\" ]; then\n hdiutil detach \"$MOUNT_POINT\" >/dev/null 2>&1 || true\n rmdir \"$MOUNT_POINT\" >/dev/null 2>&1 || true\n echo \"Install.app not found\"\n exit 1\nfi\n\n# Prefer Contents/MacOS/Install, fall back to first executable in MacOS\nBIN=\"$INSTALL_APP/Contents/MacOS/Install\"\nif [ ! -x \"$BIN\" ]; then\n BIN=\"$(/usr/bin/find \"$INSTALL_APP/Contents/MacOS\" -type f -perm +111 -print -quit 2>/dev/null)\"\nfi\n[ -n \"$BIN\" ] && [ -x \"$BIN\" ] || { hdiutil detach \"$MOUNT_POINT\" >/dev/null 2>&1 || true; rmdir \"$MOUNT_POINT\" >/dev/null 2>&1 || true; echo \"installer binary not found\"; exit 1; }\n\n# Try silent, fall back to normal if needed\n\"$BIN\" --mode=silent >/dev/null 2>&1 || \"$BIN\" >/dev/null 2>&1\n\nhdiutil detach \"$MOUNT_POINT\" >/dev/null 2>&1 || true\nrmdir \"$MOUNT_POINT\" >/dev/null 2>&1 || true\n\necho \"adobe creative cloud installed\"\n" } } diff --git a/ee/maintained-apps/outputs/cleanmymac/darwin.json b/ee/maintained-apps/outputs/cleanmymac/darwin.json index 43a7feb844e..2faf780e851 100644 --- a/ee/maintained-apps/outputs/cleanmymac/darwin.json +++ b/ee/maintained-apps/outputs/cleanmymac/darwin.json @@ -8,7 +8,7 @@ }, "installer_url": "https://updates.cleanmymac.com/com.macpaw.cleanmymac5/releases/CleanMyMac5_50504.0.2605291449.zip", "install_script_ref": "fff893a1", - "uninstall_script_ref": "6b7419ac", + "uninstall_script_ref": "f09da8a8", "sha256": "b66d2f26ce4d1dc6819f1b4dd7e9f020f9f3b3527beaeb6406b9a41cac5b5020", "default_categories": [ "Productivity" @@ -16,7 +16,7 @@ } ], "refs": { - "6b7419ac": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'com.macpaw.CleanMyMac5.HealthMonitor'\nremove_launchctl_service 'com.macpaw.CleanMyMac5.Menu'\nquit_application 'com.macpaw.CleanMyMac5'\nquit_application 'com.macpaw.CleanMyMac5.HealthMonitor'\nquit_application 'com.macpaw.CleanMyMac5.Menu'\nsudo rm -rf '/Library/PrivilegedHelperTools/com.macpaw.CleanMyMac5.Agent'\nsudo rm -rf \"$APPDIR/CleanMyMac_5.app\"\ntrash $LOGGED_IN_USER '/Library/LaunchDaemons/com.macpaw.CleanMyMac5.Agent.plist'\ntrash $LOGGED_IN_USER '/Library/PrivilegedHelperTools/com.macpaw.CleanMyMac5.Agent'\ntrash $LOGGED_IN_USER '/Users/Shared/CleanMyMac_5'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/S8EX82NJP6.com.macpaw.CleanMyMac5'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CleanMyMac_5'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.macpaw.CleanMyMac5'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/S8EX82NJP6.com.macpaw.CleanMyMac5'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.macpaw.CleanMyMac5'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.macpaw.CleanMyMac5.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/com.macpaw.CleanMyMac5.Updater.plist'\ntrash $LOGGED_IN_USER '~/Library/Logs/com.macpaw.CleanMyMac5'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.macpaw.CleanMyMac5.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.macpaw.CleanMyMac5.savedState'\n", + "f09da8a8": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'com.macpaw.CleanMyMac5.HealthMonitor'\nremove_launchctl_service 'com.macpaw.CleanMyMac5.Menu'\nquit_application 'com.macpaw.CleanMyMac5'\nquit_application 'com.macpaw.CleanMyMac5.HealthMonitor'\nquit_application 'com.macpaw.CleanMyMac5.Menu'\nsudo rm -rf '/Library/PrivilegedHelperTools/com.macpaw.CleanMyMac5.Agent'\nsudo rm -rf \"$APPDIR/CleanMyMac_5.app\"\ntrash $LOGGED_IN_USER '/Library/LaunchDaemons/com.macpaw.CleanMyMac5.Agent.plist'\ntrash $LOGGED_IN_USER '/Library/PrivilegedHelperTools/com.macpaw.CleanMyMac5.Agent'\ntrash $LOGGED_IN_USER '/Users/Shared/CleanMyMac_5'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/S8EX82NJP6.com.macpaw.CleanMyMac5'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CleanMyMac_5'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.macpaw.CleanMyMac5'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/S8EX82NJP6.com.macpaw.CleanMyMac5'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.macpaw.CleanMyMac5'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.macpaw.CleanMyMac5.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/com.macpaw.CleanMyMac5.Updater.plist'\ntrash $LOGGED_IN_USER '~/Library/Logs/com.macpaw.CleanMyMac5'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.macpaw.CleanMyMac5.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.macpaw.CleanMyMac5.savedState'\n", "fff893a1": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nunzip \"$INSTALLER_PATH\" -d \"$TMPDIR\"\n# copy to the applications folder\nquit_and_track_application 'com.macpaw.CleanMyMac5'\nif [ -d \"$APPDIR/CleanMyMac_5.app\" ]; then\n\tsudo mv \"$APPDIR/CleanMyMac_5.app\" \"$TMPDIR/CleanMyMac_5.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/CleanMyMac_5.app\" \"$APPDIR\"\nrelaunch_application 'com.macpaw.CleanMyMac5'\n" } } diff --git a/ee/maintained-apps/outputs/expressvpn/darwin.json b/ee/maintained-apps/outputs/expressvpn/darwin.json index 2a5f64dbf8c..e038f51b8ef 100644 --- a/ee/maintained-apps/outputs/expressvpn/darwin.json +++ b/ee/maintained-apps/outputs/expressvpn/darwin.json @@ -7,7 +7,7 @@ "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.expressvpn.ExpressVPN' AND version_compare(bundle_short_version, '14.2.0.13656') < 0);" }, "installer_url": "https://www.expressvpn.works/clients/mac/expressvpn-macos-universal-14.2.0.13656_release.zip", - "install_script_ref": "c5afbbfa", + "install_script_ref": "efad6361", "uninstall_script_ref": "f6060d51", "sha256": "17d4f67c581ac4cb184ce3bc9fec51bb16f6da88f6ced87589fed266ae0468d6", "default_categories": [ @@ -16,7 +16,7 @@ } ], "refs": { - "c5afbbfa": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(mktemp -d)\n\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n# extract contents\nunzip \"$INSTALLER_PATH\" -d \"$TMPDIR\"\n\n# discover the installer app by finding any .app that contains an installer executable\nINSTALLER_APP=\"\"\nfor app in \"$TMPDIR\"/*.app; do\n if [ -d \"$app\" ] && [ -d \"$app/Contents/MacOS\" ]; then\n INSTALLER_APP=\"$app\"\n break\n fi\ndone\n\nif [ -z \"$INSTALLER_APP\" ] || [ ! -d \"$INSTALLER_APP\" ]; then\n echo \"Error: Installer app not found in $TMPDIR\"\n exit 1\nfi\n\nquit_application 'com.expressvpn.ExpressVPN'\n\n# Remove quarantine attributes so Gatekeeper won't block binaries during install\nsudo xattr -r -d com.apple.quarantine \"$INSTALLER_APP\" 2>/dev/null || true\n\n# Run the bundled installer script which handles copying to /Applications,\n# setting permissions, creating groups, installing the LaunchDaemon, and\n# starting the daemon\nINSTALLER_SCRIPT=\"$INSTALLER_APP/Contents/Resources/vpn-installer.sh\"\nif [ ! -f \"$INSTALLER_SCRIPT\" ]; then\n echo \"Error: vpn-installer.sh not found in $INSTALLER_APP/Contents/Resources\"\n exit 1\nfi\n\nchmod +x \"$INSTALLER_SCRIPT\"\nsudo bash \"$INSTALLER_SCRIPT\"\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -ne 0 ]; then\n echo \"Error: Installer exited with code $EXIT_CODE\"\n exit $EXIT_CODE\nfi\n\n", + "efad6361": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(mktemp -d)\n\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n# extract contents\nunzip \"$INSTALLER_PATH\" -d \"$TMPDIR\"\n\n# discover the installer app by finding any .app that contains an installer executable\nINSTALLER_APP=\"\"\nfor app in \"$TMPDIR\"/*.app; do\n if [ -d \"$app\" ] && [ -d \"$app/Contents/MacOS\" ]; then\n INSTALLER_APP=\"$app\"\n break\n fi\ndone\n\nif [ -z \"$INSTALLER_APP\" ] || [ ! -d \"$INSTALLER_APP\" ]; then\n echo \"Error: Installer app not found in $TMPDIR\"\n exit 1\nfi\n\nquit_application 'com.expressvpn.ExpressVPN'\n\n# Remove quarantine attributes so Gatekeeper won't block binaries during install\nsudo xattr -r -d com.apple.quarantine \"$INSTALLER_APP\" 2>/dev/null || true\n\n# Run the bundled installer script which handles copying to /Applications,\n# setting permissions, creating groups, installing the LaunchDaemon, and\n# starting the daemon\nINSTALLER_SCRIPT=\"$INSTALLER_APP/Contents/Resources/vpn-installer.sh\"\nif [ ! -f \"$INSTALLER_SCRIPT\" ]; then\n echo \"Error: vpn-installer.sh not found in $INSTALLER_APP/Contents/Resources\"\n exit 1\nfi\n\nchmod +x \"$INSTALLER_SCRIPT\"\nsudo bash \"$INSTALLER_SCRIPT\"\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -ne 0 ]; then\n echo \"Error: Installer exited with code $EXIT_CODE\"\n exit $EXIT_CODE\nfi\n\n", "f6060d51": "#!/bin/bash\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n # A wildcard label can't be used with launchctl or as a plist name, so expand\n # it to the labels of currently loaded services that match the pattern.\n local services=(\"$service\")\n if [[ \"$service\" == *\"*\"* ]]; then\n local regex\n # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so\n # it matches a full label rather than a substring.\n regex=$(printf '%s' \"$service\" | sed -e 's/[][(){}.^$+?|\\\\]/\\\\&/g' -e 's/\\*/.*/g')\n regex=\"^${regex}$\"\n services=()\n local id\n # Match every loaded job by label regardless of PID; launchctl list reports\n # loaded-but-not-running jobs with a \"-\" in the PID column.\n while read -r _ _ id; do\n [[ \"$id\" =~ $regex ]] && services+=(\"$id\")\n done < <(launchctl list 2>/dev/null | tail -n +2)\n if [[ ${#services[@]} -eq 0 ]]; then\n echo \"No loaded launchctl service matches ${service}\"\n return\n fi\n fi\n\n local service_label\n for service_label in \"${services[@]}\"; do\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service_label}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service_label}\"\n else\n launchctl remove \"${service_label}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service_label}.plist\"\n \"/Library/LaunchDaemons/${service_label}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n done\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'com.express.vpn.client'\nremove_launchctl_service 'com.express.vpn.daemon'\nremove_launchctl_service 'com.express.vpn.installhelper'\nquit_application 'com.express.vpn'\nsudo rm -rf '/Applications/ExpressVPN.app'\ntrash $LOGGED_IN_USER '/Library/Application Support/com.express.vpn'\ntrash $LOGGED_IN_USER '/Library/Preferences/com.express.vpn'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.express.vpn'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.express.vpn'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.express.vpn'\n" } } diff --git a/ee/maintained-apps/outputs/google-chrome/darwin.json b/ee/maintained-apps/outputs/google-chrome/darwin.json index ff61b88d19b..45755d7414a 100644 --- a/ee/maintained-apps/outputs/google-chrome/darwin.json +++ b/ee/maintained-apps/outputs/google-chrome/darwin.json @@ -1,13 +1,13 @@ { "versions": [ { - "version": "150.0.7871.101", + "version": "150.0.7871.115", "queries": { "exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.google.Chrome';", - "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.google.Chrome' AND version_compare(bundle_short_version, '150.0.7871.101') < 0);" + "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.google.Chrome' AND version_compare(bundle_short_version, '150.0.7871.115') < 0);" }, "installer_url": "https://dl.google.com/dl/chrome/mac/universal/stable/gcem/GoogleChrome.pkg", - "install_script_ref": "6981ff84", + "install_script_ref": "bf744c88", "uninstall_script_ref": "112a34ce", "sha256": "no_check", "default_categories": [ @@ -17,6 +17,6 @@ ], "refs": { "112a34ce": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n # A wildcard label can't be used with launchctl or as a plist name, so expand\n # it to the labels of currently loaded services that match the pattern.\n local services=(\"$service\")\n if [[ \"$service\" == *\"*\"* ]]; then\n local regex\n # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so\n # it matches a full label rather than a substring.\n regex=$(printf '%s' \"$service\" | sed -e 's/[][(){}.^$+?|\\\\]/\\\\&/g' -e 's/\\*/.*/g')\n regex=\"^${regex}$\"\n services=()\n local id\n # Match every loaded job by label regardless of PID; launchctl list reports\n # loaded-but-not-running jobs with a \"-\" in the PID column.\n while read -r _ _ id; do\n [[ \"$id\" =~ $regex ]] && services+=(\"$id\")\n done < <(launchctl list 2>/dev/null | tail -n +2)\n if [[ ${#services[@]} -eq 0 ]]; then\n echo \"No loaded launchctl service matches ${service}\"\n return\n fi\n fi\n\n local service_label\n for service_label in \"${services[@]}\"; do\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service_label}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service_label}\"\n else\n launchctl remove \"${service_label}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service_label}.plist\"\n \"/Library/LaunchDaemons/${service_label}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n done\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/Google Chrome.app\"\nremove_launchctl_service 'com.google.keystone.agent'\nremove_launchctl_service 'com.google.keystone.daemon'\nsudo rmdir '/Library/Google'\nsudo rmdir '~/Library/Application Support/Google'\nsudo rmdir '~/Library/Caches/Google'\nsudo rmdir '~/Library/Google'\ntrash $LOGGED_IN_USER '/Library/Caches/com.google.SoftwareUpdate.*'\ntrash $LOGGED_IN_USER '/Library/Google/Google Chrome Brand.plist'\ntrash $LOGGED_IN_USER '/Library/Google/GoogleSoftwareUpdate'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.google.chrome.app.*.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.google.chrome.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.google.Chrome'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.google.Chrome.helper.*'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.google.Keystone'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.google.Keystone.Agent'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.google.SoftwareUpdate'\ntrash $LOGGED_IN_USER '~/Library/Caches/Google/Chrome'\ntrash $LOGGED_IN_USER '~/Library/Google/Google Chrome Brand.plist'\ntrash $LOGGED_IN_USER '~/Library/Google/GoogleSoftwareUpdate'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/com.google.keystone.agent.plist'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/com.google.keystone.xpcservice.plist'\ntrash $LOGGED_IN_USER '~/Library/Logs/GoogleSoftwareUpdateAgent.log'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.google.Chrome.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.google.Keystone.Agent.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.google.Chrome.app.*.savedState'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.google.Chrome.savedState'\ntrash $LOGGED_IN_USER '~/Library/WebKit/com.google.Chrome'\n", - "6981ff84": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local console_user=\"$2\"\n local timeout_duration=10\n\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\nrestart_chrome() {\n local console_user=\"$1\"\n \n if [[ -n \"$console_user\" && \"$console_user\" != \"root\" ]]; then\n echo \"Restarting Chrome for user: $console_user\"\n sudo -u \"$console_user\" open -a \"Google Chrome\" --args --restore-last-session\n else\n echo \"No console user found, attempting direct Chrome start...\"\n open -a \"Google Chrome\" --args --restore-last-session\n fi\n}\n\n# Get console user once (used by both quit and restart)\nCONSOLE_USER=$(stat -f \"%Su\" /dev/console 2>/dev/null || echo \"\")\n\n# Check if Chrome is running (only check once)\nCHROME_WAS_RUNNING=false\nif osascript -e \"application id \\\"com.google.Chrome\\\" is running\" 2>/dev/null; then\n CHROME_WAS_RUNNING=true\n quit_application 'com.google.Chrome' \"$CONSOLE_USER\"\nfi\n\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\n# Restart Chrome if it was running before installation\nif [[ \"$CHROME_WAS_RUNNING\" == \"true\" ]]; then\n sleep 2\n restart_chrome \"$CONSOLE_USER\" || true\nfi" + "bf744c88": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local console_user=\"$2\"\n local timeout_duration=10\n\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\nrestart_chrome() {\n local console_user=\"$1\"\n \n if [[ -n \"$console_user\" && \"$console_user\" != \"root\" ]]; then\n echo \"Restarting Chrome for user: $console_user\"\n sudo -u \"$console_user\" open -a \"Google Chrome\" --args --restore-last-session\n else\n echo \"No console user found, attempting direct Chrome start...\"\n open -a \"Google Chrome\" --args --restore-last-session\n fi\n}\n\n# Get console user once (used by both quit and restart)\nCONSOLE_USER=$(stat -f \"%Su\" /dev/console 2>/dev/null || echo \"\")\n\n# Check if Chrome is running (only check once)\nCHROME_WAS_RUNNING=false\nCHROME_RUNNING=$(osascript -e \"application id \\\"com.google.Chrome\\\" is running\" 2>/dev/null)\nif [[ \"$CHROME_RUNNING\" == \"true\" ]]; then\n CHROME_WAS_RUNNING=true\n quit_application 'com.google.Chrome' \"$CONSOLE_USER\"\nfi\n\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\n# Restart Chrome if it was running before installation\nif [[ \"$CHROME_WAS_RUNNING\" == \"true\" ]]; then\n sleep 2\n restart_chrome \"$CONSOLE_USER\" || true\nfi" } } diff --git a/ee/maintained-apps/outputs/gpg-suite/darwin.json b/ee/maintained-apps/outputs/gpg-suite/darwin.json index b283c94315d..6bc60e07117 100644 --- a/ee/maintained-apps/outputs/gpg-suite/darwin.json +++ b/ee/maintained-apps/outputs/gpg-suite/darwin.json @@ -8,7 +8,7 @@ }, "installer_url": "https://releases.gpgtools.org/GPG_Suite-2023.3.dmg", "install_script_ref": "38a0515f", - "uninstall_script_ref": "e3b19a58", + "uninstall_script_ref": "cf6a6135", "sha256": "57468a4adc55d954ead4fe1f88b07eac1b70ada40fcbc810765fd521ef21eef1", "default_categories": [ "Productivity" @@ -17,6 +17,6 @@ ], "refs": { "38a0515f": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# install pkg files\nquit_and_track_application 'org.gpgtools.updater'\nsudo installer -pkg \"$TMPDIR/Install.pkg\" -target /\nrelaunch_application 'org.gpgtools.updater'\n", - "e3b19a58": "#!/bin/bash\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nexpand_pkgid_and_map() {\n local PKGID=\"$1\"\n local FUNC=\"$2\"\n if [[ \"$PKGID\" == *\"*\" ]]; then\n local prefix=\"${PKGID%\\*}\"\n echo \"Expanding wildcard for PKGID: $PKGID\"\n for receipt in $(pkgutil --pkgs | grep \"^${prefix}\"); do\n echo \"Processing $receipt\"\n \"$FUNC\" \"$receipt\"\n done\n else\n \"$FUNC\" \"$PKGID\"\n fi\n}\n\nforget_pkg() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" forget_receipt\n}\n\nforget_receipt() {\n local PKGID=\"$1\"\n sudo pkgutil --forget \"$PKGID\"\n}\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n}\n\nremove_pkg_files() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" remove_receipt_files\n}\n\nremove_receipt_files() {\n local PKGID=\"$1\"\n local PKGINFO VOLUME INSTALL_LOCATION FULL_INSTALL_LOCATION\n\n echo \"pkgutil --pkg-info-plist \\\"$PKGID\\\"\"\n PKGINFO=$(pkgutil --pkg-info-plist \"$PKGID\")\n VOLUME=$(echo \"$PKGINFO\" | awk '/volume<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n INSTALL_LOCATION=$(echo \"$PKGINFO\" | awk '/install-location<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n\n if [ -z \"$INSTALL_LOCATION\" ] || [ \"$INSTALL_LOCATION\" = \"/\" ]; then\n FULL_INSTALL_LOCATION=\"$VOLUME\"\n else\n FULL_INSTALL_LOCATION=\"$VOLUME/$INSTALL_LOCATION\"\n FULL_INSTALL_LOCATION=$(echo \"$FULL_INSTALL_LOCATION\" | sed 's|//|/|g')\n fi\n\n echo \"sudo pkgutil --only-files --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|/${INSTALL_LOCATION}/|\" | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n echo \"sudo pkgutil --only-dirs --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | grep '\\\\.app$' | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n root_app_dir=$(\n sudo pkgutil --only-dirs --files \"$PKGID\" \\\n | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" \\\n | grep 'Applications' \\\n | awk '{ print length, $0 }' \\\n | sort -n \\\n | head -n1 \\\n | cut -d' ' -f2-\n )\n if [ -n \"$root_app_dir\" ]; then\n echo \"sudo rmdir -p \\\"$root_app_dir\\\" 2>/dev/null || :\"\n sudo rmdir -p \"$root_app_dir\" 2>/dev/null || :\n fi\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'org.gpgtools.gpgmail.enable-bundles'\nremove_launchctl_service 'org.gpgtools.gpgmail.patch-uuid-user'\nremove_launchctl_service 'org.gpgtools.gpgmail.user-uuid-patcher'\nremove_launchctl_service 'org.gpgtools.gpgmail.uuid-patcher'\nremove_launchctl_service 'org.gpgtools.Libmacgpg.xpc'\nremove_launchctl_service 'org.gpgtools.macgpg2.fix'\nremove_launchctl_service 'org.gpgtools.macgpg2.gpg-agent'\nremove_launchctl_service 'org.gpgtools.macgpg2.shutdown-gpg-agent'\nremove_launchctl_service 'org.gpgtools.macgpg2.updater'\nremove_launchctl_service 'org.gpgtools.updater'\nquit_application 'com.apple.mail'\nquit_application 'org.gpgtools.gpgkeychain'\nquit_application 'org.gpgtools.gpgkeychainaccess'\nquit_application 'org.gpgtools.gpgmail.upgrader'\nquit_application 'org.gpgtools.gpgservices'\n\n# Try to find and run GPG Suite's Uninstaller\n# GPG Suite installs Uninstall.app in /Library/Application Support/GPGTools/Uninstall.app\n# or it might be embedded in the app bundle\nUNINSTALLER_PATH=\"\"\nif [ -d \"/Library/Application Support/GPGTools/Uninstall.app\" ]; then\n UNINSTALLER_PATH=\"/Library/Application Support/GPGTools/Uninstall.app/Contents/Resources/GPG Suite Uninstaller.app/Contents/Resources/uninstall.sh\"\nelif [ -d \"/Applications/GPG Keychain.app/Contents/Resources/Uninstall.app\" ]; then\n UNINSTALLER_PATH=\"/Applications/GPG Keychain.app/Contents/Resources/Uninstall.app/Contents/Resources/GPG Suite Uninstaller.app/Contents/Resources/uninstall.sh\"\nfi\n\nif [ -n \"$UNINSTALLER_PATH\" ] && [ -f \"$UNINSTALLER_PATH\" ]; then\n echo \"Running GPG Suite Uninstaller from: $UNINSTALLER_PATH\"\n (cd /Users/$LOGGED_IN_USER && sudo \"$UNINSTALLER_PATH\") || echo \"GPG Suite Uninstaller failed, continuing with manual removal\"\nelse\n echo \"GPG Suite Uninstaller not found, performing manual removal\"\n # Explicitly remove the app bundle to ensure it's gone\n sudo rm -rf '/Applications/GPG Keychain.app'\n sudo rm -rf '/Applications/GPG Mail.app' || true\nfi\n\nremove_pkg_files 'org.gpgtools.*'\nforget_pkg 'org.gpgtools.*'\nsudo rm -rf '/Library/Application Support/GPGTools'\nsudo rm -rf '/Library/Frameworks/Libmacgpg.framework'\nsudo rm -rf '/Library/Mail/Bundles.gpgmail*'\nsudo rm -rf '/Library/Mail/Bundles/GPGMail.mailbundle'\nsudo rm -rf '/Library/PreferencePanes/GPGPreferences.prefPane'\nsudo rm -rf '/Library/Services/GPGServices.service'\nsudo rm -rf '/Network/Library/Mail/Bundles/GPGMail.mailbundle'\nsudo rm -rf '/private/etc/manpaths.d/MacGPG2'\nsudo rm -rf '/private/etc/paths.d/MacGPG2'\nsudo rm -rf '/private/tmp/gpg-agent'\nsudo rm -rf '/usr/local/MacGPG2'\ntrash $LOGGED_IN_USER '~/Library/Application Support/GPGTools'\ntrash $LOGGED_IN_USER '~/Library/Caches/org.gpgtools.gpg*'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.apple.mail/Data/Library/Frameworks/Libmacgpg.framework'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.apple.mail/Data/Library/Preferences/org.gpgtools.*'\ntrash $LOGGED_IN_USER '~/Library/Frameworks/Libmacgpg.framework'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/org.gpgtools.*'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/org.gpgtools.*'\ntrash $LOGGED_IN_USER '~/Library/Mail/Bundles/GPGMail.mailbundle'\ntrash $LOGGED_IN_USER '~/Library/PreferencePanes/GPGPreferences.prefPane'\ntrash $LOGGED_IN_USER '~/Library/Preferences/org.gpgtools.*'\ntrash $LOGGED_IN_USER '~/Library/Services/GPGServices.service'\n\n" + "cf6a6135": "#!/bin/bash\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nexpand_pkgid_and_map() {\n local PKGID=\"$1\"\n local FUNC=\"$2\"\n if [[ \"$PKGID\" == *\"*\" ]]; then\n local prefix=\"${PKGID%\\*}\"\n echo \"Expanding wildcard for PKGID: $PKGID\"\n for receipt in $(pkgutil --pkgs | grep \"^${prefix}\"); do\n echo \"Processing $receipt\"\n \"$FUNC\" \"$receipt\"\n done\n else\n \"$FUNC\" \"$PKGID\"\n fi\n}\n\nforget_pkg() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" forget_receipt\n}\n\nforget_receipt() {\n local PKGID=\"$1\"\n sudo pkgutil --forget \"$PKGID\"\n}\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n}\n\nremove_pkg_files() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" remove_receipt_files\n}\n\nremove_receipt_files() {\n local PKGID=\"$1\"\n local PKGINFO VOLUME INSTALL_LOCATION FULL_INSTALL_LOCATION\n\n echo \"pkgutil --pkg-info-plist \\\"$PKGID\\\"\"\n PKGINFO=$(pkgutil --pkg-info-plist \"$PKGID\")\n VOLUME=$(echo \"$PKGINFO\" | awk '/volume<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n INSTALL_LOCATION=$(echo \"$PKGINFO\" | awk '/install-location<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n\n if [ -z \"$INSTALL_LOCATION\" ] || [ \"$INSTALL_LOCATION\" = \"/\" ]; then\n FULL_INSTALL_LOCATION=\"$VOLUME\"\n else\n FULL_INSTALL_LOCATION=\"$VOLUME/$INSTALL_LOCATION\"\n FULL_INSTALL_LOCATION=$(echo \"$FULL_INSTALL_LOCATION\" | sed 's|//|/|g')\n fi\n\n echo \"sudo pkgutil --only-files --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|/${INSTALL_LOCATION}/|\" | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n echo \"sudo pkgutil --only-dirs --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | grep '\\\\.app$' | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n root_app_dir=$(\n sudo pkgutil --only-dirs --files \"$PKGID\" \\\n | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" \\\n | grep 'Applications' \\\n | awk '{ print length, $0 }' \\\n | sort -n \\\n | head -n1 \\\n | cut -d' ' -f2-\n )\n if [ -n \"$root_app_dir\" ]; then\n echo \"sudo rmdir -p \\\"$root_app_dir\\\" 2>/dev/null || :\"\n sudo rmdir -p \"$root_app_dir\" 2>/dev/null || :\n fi\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'org.gpgtools.gpgmail.enable-bundles'\nremove_launchctl_service 'org.gpgtools.gpgmail.patch-uuid-user'\nremove_launchctl_service 'org.gpgtools.gpgmail.user-uuid-patcher'\nremove_launchctl_service 'org.gpgtools.gpgmail.uuid-patcher'\nremove_launchctl_service 'org.gpgtools.Libmacgpg.xpc'\nremove_launchctl_service 'org.gpgtools.macgpg2.fix'\nremove_launchctl_service 'org.gpgtools.macgpg2.gpg-agent'\nremove_launchctl_service 'org.gpgtools.macgpg2.shutdown-gpg-agent'\nremove_launchctl_service 'org.gpgtools.macgpg2.updater'\nremove_launchctl_service 'org.gpgtools.updater'\nquit_application 'com.apple.mail'\nquit_application 'org.gpgtools.gpgkeychain'\nquit_application 'org.gpgtools.gpgkeychainaccess'\nquit_application 'org.gpgtools.gpgmail.upgrader'\nquit_application 'org.gpgtools.gpgservices'\n\n# Try to find and run GPG Suite's Uninstaller\n# GPG Suite installs Uninstall.app in /Library/Application Support/GPGTools/Uninstall.app\n# or it might be embedded in the app bundle\nUNINSTALLER_PATH=\"\"\nif [ -d \"/Library/Application Support/GPGTools/Uninstall.app\" ]; then\n UNINSTALLER_PATH=\"/Library/Application Support/GPGTools/Uninstall.app/Contents/Resources/GPG Suite Uninstaller.app/Contents/Resources/uninstall.sh\"\nelif [ -d \"/Applications/GPG Keychain.app/Contents/Resources/Uninstall.app\" ]; then\n UNINSTALLER_PATH=\"/Applications/GPG Keychain.app/Contents/Resources/Uninstall.app/Contents/Resources/GPG Suite Uninstaller.app/Contents/Resources/uninstall.sh\"\nfi\n\nif [ -n \"$UNINSTALLER_PATH\" ] && [ -f \"$UNINSTALLER_PATH\" ]; then\n echo \"Running GPG Suite Uninstaller from: $UNINSTALLER_PATH\"\n (cd /Users/$LOGGED_IN_USER && sudo \"$UNINSTALLER_PATH\") || echo \"GPG Suite Uninstaller failed, continuing with manual removal\"\nelse\n echo \"GPG Suite Uninstaller not found, performing manual removal\"\n # Explicitly remove the app bundle to ensure it's gone\n sudo rm -rf '/Applications/GPG Keychain.app'\n sudo rm -rf '/Applications/GPG Mail.app' || true\nfi\n\nremove_pkg_files 'org.gpgtools.*'\nforget_pkg 'org.gpgtools.*'\nsudo rm -rf '/Library/Application Support/GPGTools'\nsudo rm -rf '/Library/Frameworks/Libmacgpg.framework'\nsudo rm -rf '/Library/Mail/Bundles.gpgmail*'\nsudo rm -rf '/Library/Mail/Bundles/GPGMail.mailbundle'\nsudo rm -rf '/Library/PreferencePanes/GPGPreferences.prefPane'\nsudo rm -rf '/Library/Services/GPGServices.service'\nsudo rm -rf '/Network/Library/Mail/Bundles/GPGMail.mailbundle'\nsudo rm -rf '/private/etc/manpaths.d/MacGPG2'\nsudo rm -rf '/private/etc/paths.d/MacGPG2'\nsudo rm -rf '/private/tmp/gpg-agent'\nsudo rm -rf '/usr/local/MacGPG2'\ntrash $LOGGED_IN_USER '~/Library/Application Support/GPGTools'\ntrash $LOGGED_IN_USER '~/Library/Caches/org.gpgtools.gpg*'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.apple.mail/Data/Library/Frameworks/Libmacgpg.framework'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.apple.mail/Data/Library/Preferences/org.gpgtools.*'\ntrash $LOGGED_IN_USER '~/Library/Frameworks/Libmacgpg.framework'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/org.gpgtools.*'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/org.gpgtools.*'\ntrash $LOGGED_IN_USER '~/Library/Mail/Bundles/GPGMail.mailbundle'\ntrash $LOGGED_IN_USER '~/Library/PreferencePanes/GPGPreferences.prefPane'\ntrash $LOGGED_IN_USER '~/Library/Preferences/org.gpgtools.*'\ntrash $LOGGED_IN_USER '~/Library/Services/GPGServices.service'\n\n" } } diff --git a/ee/maintained-apps/outputs/grammarly-desktop/darwin.json b/ee/maintained-apps/outputs/grammarly-desktop/darwin.json index 03f86ad0bdb..76914c08c16 100644 --- a/ee/maintained-apps/outputs/grammarly-desktop/darwin.json +++ b/ee/maintained-apps/outputs/grammarly-desktop/darwin.json @@ -7,7 +7,7 @@ "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.grammarly.ProjectLlama' AND version_compare(bundle_short_version, '1.173.1') < 0);" }, "installer_url": "https://download-mac.grammarly.com/versions/1.173.1.0/Grammarly.dmg", - "install_script_ref": "20d5bd8f", + "install_script_ref": "df3d0525", "uninstall_script_ref": "e14b2d61", "sha256": "8962481209b3547873e211bf75c315fc1d54590f185778d1096c876eddbfc889", "default_categories": [ @@ -16,7 +16,7 @@ } ], "refs": { - "20d5bd8f": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nhdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\"\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\"\n\n# copy to the applications folder\n# Homebrew uses: app \"Grammarly Installer.app\", target: \"Grammarly Desktop.app\"\n# This means we extract \"Grammarly Installer.app\" and copy it to \"/Applications/Grammarly Desktop.app\"\nquit_application 'com.grammarly.ProjectLlama'\n\n# Remove existing app if present\nif [ -d \"$APPDIR/Grammarly Desktop.app\" ]; then\n\tsudo rm -rf \"$APPDIR/Grammarly Desktop.app\"\nfi\n\n# Copy Grammarly Installer.app from temp directory to Applications as Grammarly Desktop.app\nif [ -d \"$TMPDIR/Grammarly Installer.app\" ]; then\n\tsudo cp -R \"$TMPDIR/Grammarly Installer.app\" \"$APPDIR/Grammarly Desktop.app\"\n\techo \"Installation verified\"\nelse\n\techo \"Error: Grammarly Installer.app not found in extracted files\"\n\texit 1\nfi\n\n", + "df3d0525": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nhdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\"\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\"\n\n# copy to the applications folder\n# Homebrew uses: app \"Grammarly Installer.app\", target: \"Grammarly Desktop.app\"\n# This means we extract \"Grammarly Installer.app\" and copy it to \"/Applications/Grammarly Desktop.app\"\nquit_application 'com.grammarly.ProjectLlama'\n\n# Remove existing app if present\nif [ -d \"$APPDIR/Grammarly Desktop.app\" ]; then\n\tsudo rm -rf \"$APPDIR/Grammarly Desktop.app\"\nfi\n\n# Copy Grammarly Installer.app from temp directory to Applications as Grammarly Desktop.app\nif [ -d \"$TMPDIR/Grammarly Installer.app\" ]; then\n\tsudo cp -R \"$TMPDIR/Grammarly Installer.app\" \"$APPDIR/Grammarly Desktop.app\"\n\techo \"Installation verified\"\nelse\n\techo \"Error: Grammarly Installer.app not found in extracted files\"\n\texit 1\nfi\n\n", "e14b2d61": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/Grammarly Desktop.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.grammarly.ProjectLlama'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.grammarly.ProjectLlama'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.grammarly.GRLlamaOnboarding.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.grammarly.ProjectLlama'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.grammarly.ProjectLlama.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/com.grammarly.ProjectLlama.Shepherd.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.grammarly.ProjectLlama.plist'\ntrash $LOGGED_IN_USER '~/Library/WebKit/com.grammarly.GRLlamaOnboarding'\ntrash $LOGGED_IN_USER '~/Library/WebKit/com.grammarly.ProjectLlama'\n" } } diff --git a/ee/maintained-apps/outputs/logitune/darwin.json b/ee/maintained-apps/outputs/logitune/darwin.json index 032d5f34950..72cc1094cc5 100644 --- a/ee/maintained-apps/outputs/logitune/darwin.json +++ b/ee/maintained-apps/outputs/logitune/darwin.json @@ -7,7 +7,7 @@ "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.logitech.logitune' AND version_compare(bundle_short_version, '3.14.72') < 0);" }, "installer_url": "https://software.vc.logitech.com/downloads/tune/LogiTuneInstaller.pkg", - "install_script_ref": "584e269e", + "install_script_ref": "93aa8f2a", "uninstall_script_ref": "8a23a81e", "sha256": "no_check", "default_categories": [ @@ -16,7 +16,7 @@ } ], "refs": { - "584e269e": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local console_user=\"$2\"\n local timeout_duration=10\n\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\nCONSOLE_USER=$(stat -f \"%Su\" /dev/console 2>/dev/null || echo \"\")\n\n# Quit Logi Tune gracefully before the PKG's preinstall force-kills it. The\n# PKG's default RUNAPP choice relaunches the app for logged-in console users\n# after installation, so no relaunch step is needed here.\nif osascript -e \"application id \\\"com.logitech.logitune\\\" is running\" 2>/dev/null; then\n quit_application 'com.logitech.logitune' \"$CONSOLE_USER\"\nfi\n\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n", - "8a23a81e": "#!/bin/bash\n\n# Logi Tune installs a vendor uninstall script that unloads its launchd\n# services, kills running processes, removes the RightSight daemon, and\n# deletes the app bundle, support files, and pkg receipts. Prefer it when\n# present (any install of Logi Tune 3.4+ has it).\nVENDOR_UNINSTALLER=\"/Library/Application Support/logitune/uninstall_app.sh\"\n\nif [ -f \"$VENDOR_UNINSTALLER\" ]; then\n sh \"$VENDOR_UNINSTALLER\"\n exit $?\nfi\n\n# Fallback cleanup for installs missing the vendor uninstaller.\n\n# stop and remove per-user launch agents\nfor agent in com.logitech.logitune.launcher com.logitech.logitune.agent; do\n for user in $(who | grep console | awk '{print $1}'); do\n user_id=$(id -u \"$user\")\n launchctl asuser \"$user_id\" launchctl unload \"/Library/LaunchAgents/${agent}.plist\" 2>/dev/null\n done\n rm -f \"/Library/LaunchAgents/${agent}.plist\"\ndone\n\n# stop and remove launch daemons (incl. the bundled RightSight daemon)\nfor daemon in com.logitech.logitune.updater com.logitech.logitune.crashpad com.logitech.LogiRightSight; do\n launchctl unload \"/Library/LaunchDaemons/${daemon}.plist\" 2>/dev/null\n rm -f \"/Library/LaunchDaemons/${daemon}.plist\"\ndone\n\n# kill any remaining processes\nfor process in LogiTune LogiTuneAgent LogiTuneUpdater LogiTuneCrashpadHandler; do\n pkill -9 -x \"$process\" 2>/dev/null\ndone\n\n# remove the app bundle (current and legacy install paths) and support files\nrm -rf \"/Applications/Logi Tune.app\"\nrm -rf \"/Applications/LogiTune.app\"\nrm -rf \"/Applications/LogiTuneInstaller.app\"\nrm -rf \"/Library/Application Support/logitune\"\nrm -rf \"/Users/Shared/logitune\"\nrm -f \"/Users/Shared/LogiTuneInstallerStarted.txt\"\n\n# forget pkg receipts\npkgutil --forget com.logitech.pkg.logitune 2>/dev/null\npkgutil --forget com.logitech.logitune.installer 2>/dev/null\n\nexit 0\n" + "8a23a81e": "#!/bin/bash\n\n# Logi Tune installs a vendor uninstall script that unloads its launchd\n# services, kills running processes, removes the RightSight daemon, and\n# deletes the app bundle, support files, and pkg receipts. Prefer it when\n# present (any install of Logi Tune 3.4+ has it).\nVENDOR_UNINSTALLER=\"/Library/Application Support/logitune/uninstall_app.sh\"\n\nif [ -f \"$VENDOR_UNINSTALLER\" ]; then\n sh \"$VENDOR_UNINSTALLER\"\n exit $?\nfi\n\n# Fallback cleanup for installs missing the vendor uninstaller.\n\n# stop and remove per-user launch agents\nfor agent in com.logitech.logitune.launcher com.logitech.logitune.agent; do\n for user in $(who | grep console | awk '{print $1}'); do\n user_id=$(id -u \"$user\")\n launchctl asuser \"$user_id\" launchctl unload \"/Library/LaunchAgents/${agent}.plist\" 2>/dev/null\n done\n rm -f \"/Library/LaunchAgents/${agent}.plist\"\ndone\n\n# stop and remove launch daemons (incl. the bundled RightSight daemon)\nfor daemon in com.logitech.logitune.updater com.logitech.logitune.crashpad com.logitech.LogiRightSight; do\n launchctl unload \"/Library/LaunchDaemons/${daemon}.plist\" 2>/dev/null\n rm -f \"/Library/LaunchDaemons/${daemon}.plist\"\ndone\n\n# kill any remaining processes\nfor process in LogiTune LogiTuneAgent LogiTuneUpdater LogiTuneCrashpadHandler; do\n pkill -9 -x \"$process\" 2>/dev/null\ndone\n\n# remove the app bundle (current and legacy install paths) and support files\nrm -rf \"/Applications/Logi Tune.app\"\nrm -rf \"/Applications/LogiTune.app\"\nrm -rf \"/Applications/LogiTuneInstaller.app\"\nrm -rf \"/Library/Application Support/logitune\"\nrm -rf \"/Users/Shared/logitune\"\nrm -f \"/Users/Shared/LogiTuneInstallerStarted.txt\"\n\n# forget pkg receipts\npkgutil --forget com.logitech.pkg.logitune 2>/dev/null\npkgutil --forget com.logitech.logitune.installer 2>/dev/null\n\nexit 0\n", + "93aa8f2a": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local console_user=\"$2\"\n local timeout_duration=10\n\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\nCONSOLE_USER=$(stat -f \"%Su\" /dev/console 2>/dev/null || echo \"\")\n\n# Quit Logi Tune gracefully before the PKG's preinstall force-kills it. The\n# PKG's default RUNAPP choice relaunches the app for logged-in console users\n# after installation, so no relaunch step is needed here.\nLOGITUNE_RUNNING=$(osascript -e \"application id \\\"com.logitech.logitune\\\" is running\" 2>/dev/null)\nif [[ \"$LOGITUNE_RUNNING\" == \"true\" ]]; then\n quit_application 'com.logitech.logitune' \"$CONSOLE_USER\"\nfi\n\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n" } } diff --git a/ee/maintained-apps/outputs/microsoft-edge/darwin.json b/ee/maintained-apps/outputs/microsoft-edge/darwin.json index 80936697b87..f02bfc4f3a3 100644 --- a/ee/maintained-apps/outputs/microsoft-edge/darwin.json +++ b/ee/maintained-apps/outputs/microsoft-edge/darwin.json @@ -7,7 +7,7 @@ "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.microsoft.edgemac' AND version_compare(bundle_short_version, '150.0.4078.50') < 0);" }, "installer_url": "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/d269d021-b72c-4afd-9486-41bec03d66fb/MicrosoftEdge-150.0.4078.50.dmg", - "install_script_ref": "caf6f785", + "install_script_ref": "81ff19c2", "uninstall_script_ref": "afe8f338", "sha256": "7b1febf17546e623ce6a08b50526f2a00931817399ff8af590170c41344c984b", "default_categories": [ @@ -16,7 +16,7 @@ } ], "refs": { - "afe8f338": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n # A wildcard label can't be used with launchctl or as a plist name, so expand\n # it to the labels of currently loaded services that match the pattern.\n local services=(\"$service\")\n if [[ \"$service\" == *\"*\"* ]]; then\n local regex\n # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so\n # it matches a full label rather than a substring.\n regex=$(printf '%s' \"$service\" | sed -e 's/[][(){}.^$+?|\\\\]/\\\\&/g' -e 's/\\*/.*/g')\n regex=\"^${regex}$\"\n services=()\n local id\n # Match every loaded job by label regardless of PID; launchctl list reports\n # loaded-but-not-running jobs with a \"-\" in the PID column.\n while read -r _ _ id; do\n [[ \"$id\" =~ $regex ]] && services+=(\"$id\")\n done < <(launchctl list 2>/dev/null | tail -n +2)\n if [[ ${#services[@]} -eq 0 ]]; then\n echo \"No loaded launchctl service matches ${service}\"\n return\n fi\n fi\n\n local service_label\n for service_label in \"${services[@]}\"; do\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service_label}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service_label}\"\n else\n launchctl remove \"${service_label}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service_label}.plist\"\n \"/Library/LaunchDaemons/${service_label}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n done\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'com.microsoft.EdgeUpdater.wake'\nsudo rm -rf \"$APPDIR/Microsoft Edge.app\"\nsudo rmdir '~/Library/Application Support/Microsoft'\nsudo rmdir '~/Library/Microsoft'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.microsoft.edgemac.wdgExtension'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft/EdgeUpdater'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.microsoft.edgemac'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.microsoft.EdgeUpdater'\ntrash $LOGGED_IN_USER '~/Library/Caches/Microsoft Edge'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.microsoft.edgemac.wdgExtension'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.microsoft.edgemac'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.microsoft.EdgeUpdater'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/com.microsoft.EdgeUpdater.*.plist'\ntrash $LOGGED_IN_USER '~/Library/Microsoft/MicrosoftSoftwareUpdate/Actives/com.microsoft.edgemac'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.microsoft.edgemac.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.microsoft.edgemac.savedState'\ntrash $LOGGED_IN_USER '~/Library/WebKit/com.microsoft.edgemac'\n", - "caf6f785": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nhdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\"\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\"\n\n# Clean up any backup files that might exist from previous failed installations\n# This ensures we start with a clean slate\ncleanup_backup_files() {\n # Clean up backup in the installer's temp directory\n if [ -d \"$TMPDIR/Microsoft Edge.app.bkp\" ]; then\n echo \"Removing existing backup file: $TMPDIR/Microsoft Edge.app.bkp\"\n sudo rm -rf \"$TMPDIR/Microsoft Edge.app.bkp\" 2>/dev/null || true\n fi\n\n # Search for backup files in all common temp locations\n # Use -exec to avoid pipe subshell issues\n for search_base in /tmp /var/folders /private/var/folders; do\n if [ -d \"$search_base\" ]; then\n find \"$search_base\" -type d -name \"Microsoft Edge.app.bkp\" -exec sudo rm -rf {} + 2>/dev/null || true\n fi\n done\n}\n\n# copy to the applications folder\nquit_application 'com.microsoft.edgemac'\n\n# Clean up any existing backup files before creating a new one\ncleanup_backup_files\n\n# Remove existing app if present (like Homebrew does)\nif [ -d \"$APPDIR/Microsoft Edge.app\" ]; then\n\tsudo rm -rf \"$APPDIR/Microsoft Edge.app\"\nfi\n\n# Install the new app\nsudo cp -R \"$TMPDIR/Microsoft Edge.app\" \"$APPDIR\"\n\n# Verify installation and do final cleanup\nif [ -d \"$APPDIR/Microsoft Edge.app\" ]; then\n\t# Installation successful - ensure no backup files remain\n\tcleanup_backup_files\n\techo \"Installation verified\"\nelse\n\techo \"Installation failed\"\n\texit 1\nfi\n\n\n" + "81ff19c2": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nhdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\"\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\"\n\n# Clean up any backup files that might exist from previous failed installations\n# This ensures we start with a clean slate\ncleanup_backup_files() {\n # Clean up backup in the installer's temp directory\n if [ -d \"$TMPDIR/Microsoft Edge.app.bkp\" ]; then\n echo \"Removing existing backup file: $TMPDIR/Microsoft Edge.app.bkp\"\n sudo rm -rf \"$TMPDIR/Microsoft Edge.app.bkp\" 2>/dev/null || true\n fi\n\n # Search for backup files in all common temp locations\n # Use -exec to avoid pipe subshell issues\n for search_base in /tmp /var/folders /private/var/folders; do\n if [ -d \"$search_base\" ]; then\n find \"$search_base\" -type d -name \"Microsoft Edge.app.bkp\" -exec sudo rm -rf {} + 2>/dev/null || true\n fi\n done\n}\n\n# copy to the applications folder\nquit_application 'com.microsoft.edgemac'\n\n# Clean up any existing backup files before creating a new one\ncleanup_backup_files\n\n# Remove existing app if present (like Homebrew does)\nif [ -d \"$APPDIR/Microsoft Edge.app\" ]; then\n\tsudo rm -rf \"$APPDIR/Microsoft Edge.app\"\nfi\n\n# Install the new app\nsudo cp -R \"$TMPDIR/Microsoft Edge.app\" \"$APPDIR\"\n\n# Verify installation and do final cleanup\nif [ -d \"$APPDIR/Microsoft Edge.app\" ]; then\n\t# Installation successful - ensure no backup files remain\n\tcleanup_backup_files\n\techo \"Installation verified\"\nelse\n\techo \"Installation failed\"\n\texit 1\nfi\n\n\n", + "afe8f338": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n # A wildcard label can't be used with launchctl or as a plist name, so expand\n # it to the labels of currently loaded services that match the pattern.\n local services=(\"$service\")\n if [[ \"$service\" == *\"*\"* ]]; then\n local regex\n # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so\n # it matches a full label rather than a substring.\n regex=$(printf '%s' \"$service\" | sed -e 's/[][(){}.^$+?|\\\\]/\\\\&/g' -e 's/\\*/.*/g')\n regex=\"^${regex}$\"\n services=()\n local id\n # Match every loaded job by label regardless of PID; launchctl list reports\n # loaded-but-not-running jobs with a \"-\" in the PID column.\n while read -r _ _ id; do\n [[ \"$id\" =~ $regex ]] && services+=(\"$id\")\n done < <(launchctl list 2>/dev/null | tail -n +2)\n if [[ ${#services[@]} -eq 0 ]]; then\n echo \"No loaded launchctl service matches ${service}\"\n return\n fi\n fi\n\n local service_label\n for service_label in \"${services[@]}\"; do\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service_label}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service_label}\"\n else\n launchctl remove \"${service_label}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service_label}.plist\"\n \"/Library/LaunchDaemons/${service_label}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n done\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'com.microsoft.EdgeUpdater.wake'\nsudo rm -rf \"$APPDIR/Microsoft Edge.app\"\nsudo rmdir '~/Library/Application Support/Microsoft'\nsudo rmdir '~/Library/Microsoft'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.microsoft.edgemac.wdgExtension'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft/EdgeUpdater'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.microsoft.edgemac'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.microsoft.EdgeUpdater'\ntrash $LOGGED_IN_USER '~/Library/Caches/Microsoft Edge'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.microsoft.edgemac.wdgExtension'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.microsoft.edgemac'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.microsoft.EdgeUpdater'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/com.microsoft.EdgeUpdater.*.plist'\ntrash $LOGGED_IN_USER '~/Library/Microsoft/MicrosoftSoftwareUpdate/Actives/com.microsoft.edgemac'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.microsoft.edgemac.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.microsoft.edgemac.savedState'\ntrash $LOGGED_IN_USER '~/Library/WebKit/com.microsoft.edgemac'\n" } } diff --git a/ee/maintained-apps/outputs/microsoft-word/darwin.json b/ee/maintained-apps/outputs/microsoft-word/darwin.json index 3647a343460..e304e8f6653 100644 --- a/ee/maintained-apps/outputs/microsoft-word/darwin.json +++ b/ee/maintained-apps/outputs/microsoft-word/darwin.json @@ -8,7 +8,7 @@ }, "installer_url": "https://res.public.onecdn.static.microsoft/mro1cdnstorage/C1297A47-86C4-4C1F-97FA-950631F94777/MacAutoupdate/Microsoft_Word_16.110.26070318_Installer.pkg", "install_script_ref": "3adefd29", - "uninstall_script_ref": "6d6819ed", + "uninstall_script_ref": "f085ec16", "sha256": "4d42f7e1b6b602fdde777b0d424db68ad9b5d989d7240b6e57729cd7c08e61c9", "default_categories": [ "Productivity" @@ -17,6 +17,6 @@ ], "refs": { "3adefd29": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# install pkg files\nquit_and_track_application 'com.microsoft.Word'\n\nCHOICE_XML=$(mktemp /tmp/choice_xml_XXX)\n\ncat << EOF > \"$CHOICE_XML\"\n\n\n\n\n \n attributeSetting\n 0\n choiceAttribute\n selected\n choiceIdentifier\n com.microsoft.autoupdate\n \n\n\n\nEOF\n\nsudo installer -pkg \"$TMPDIR\"/Microsoft_Word_16.110.26070318_Installer.pkg -target / -applyChoiceChangesXML \"$CHOICE_XML\"\n\nrelaunch_application 'com.microsoft.Word'\n", - "6d6819ed": "#!/bin/bash\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nexpand_pkgid_and_map() {\n local PKGID=\"$1\"\n local FUNC=\"$2\"\n if [[ \"$PKGID\" == *\"*\" ]]; then\n local prefix=\"${PKGID%\\*}\"\n echo \"Expanding wildcard for PKGID: $PKGID\"\n for receipt in $(pkgutil --pkgs | grep \"^${prefix}\"); do\n echo \"Processing $receipt\"\n \"$FUNC\" \"$receipt\"\n done\n else\n \"$FUNC\" \"$PKGID\"\n fi\n}\n\nforget_pkg() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" forget_receipt\n}\n\nforget_receipt() {\n local PKGID=\"$1\"\n sudo pkgutil --forget \"$PKGID\"\n}\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n}\n\nremove_pkg_files() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" remove_receipt_files\n}\n\nremove_receipt_files() {\n local PKGID=\"$1\"\n local PKGINFO VOLUME INSTALL_LOCATION FULL_INSTALL_LOCATION\n\n echo \"pkgutil --pkg-info-plist \\\"$PKGID\\\"\"\n PKGINFO=$(pkgutil --pkg-info-plist \"$PKGID\")\n VOLUME=$(echo \"$PKGINFO\" | awk '/volume<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n INSTALL_LOCATION=$(echo \"$PKGINFO\" | awk '/install-location<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n\n if [ -z \"$INSTALL_LOCATION\" ] || [ \"$INSTALL_LOCATION\" = \"/\" ]; then\n FULL_INSTALL_LOCATION=\"$VOLUME\"\n else\n FULL_INSTALL_LOCATION=\"$VOLUME/$INSTALL_LOCATION\"\n FULL_INSTALL_LOCATION=$(echo \"$FULL_INSTALL_LOCATION\" | sed 's|//|/|g')\n fi\n\n echo \"sudo pkgutil --only-files --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|/${INSTALL_LOCATION}/|\" | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n echo \"sudo pkgutil --only-dirs --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | grep '\\\\.app$' | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n root_app_dir=$(\n sudo pkgutil --only-dirs --files \"$PKGID\" \\\n | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" \\\n | grep 'Applications' \\\n | awk '{ print length, $0 }' \\\n | sort -n \\\n | head -n1 \\\n | cut -d' ' -f2-\n )\n if [ -n \"$root_app_dir\" ]; then\n echo \"sudo rmdir -p \\\"$root_app_dir\\\" 2>/dev/null || :\"\n sudo rmdir -p \"$root_app_dir\" 2>/dev/null || :\n fi\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'com.microsoft.office.licensingV2.helper'\nquit_application 'com.microsoft.autoupdate2'\nremove_pkg_files 'com.microsoft.package.Microsoft_Word.app'\nforget_pkg 'com.microsoft.package.Microsoft_Word.app'\nremove_pkg_files 'com.microsoft.pkg.licensing'\nforget_pkg 'com.microsoft.pkg.licensing'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.microsoft.Word'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.microsoft.word.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CrashReporter/Microsoft Word_*.plist'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.microsoft.Word'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.microsoft.Word.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.microsoft.Word.savedState'\n" + "f085ec16": "#!/bin/bash\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nexpand_pkgid_and_map() {\n local PKGID=\"$1\"\n local FUNC=\"$2\"\n if [[ \"$PKGID\" == *\"*\" ]]; then\n local prefix=\"${PKGID%\\*}\"\n echo \"Expanding wildcard for PKGID: $PKGID\"\n for receipt in $(pkgutil --pkgs | grep \"^${prefix}\"); do\n echo \"Processing $receipt\"\n \"$FUNC\" \"$receipt\"\n done\n else\n \"$FUNC\" \"$PKGID\"\n fi\n}\n\nforget_pkg() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" forget_receipt\n}\n\nforget_receipt() {\n local PKGID=\"$1\"\n sudo pkgutil --forget \"$PKGID\"\n}\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n}\n\nremove_pkg_files() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" remove_receipt_files\n}\n\nremove_receipt_files() {\n local PKGID=\"$1\"\n local PKGINFO VOLUME INSTALL_LOCATION FULL_INSTALL_LOCATION\n\n echo \"pkgutil --pkg-info-plist \\\"$PKGID\\\"\"\n PKGINFO=$(pkgutil --pkg-info-plist \"$PKGID\")\n VOLUME=$(echo \"$PKGINFO\" | awk '/volume<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n INSTALL_LOCATION=$(echo \"$PKGINFO\" | awk '/install-location<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n\n if [ -z \"$INSTALL_LOCATION\" ] || [ \"$INSTALL_LOCATION\" = \"/\" ]; then\n FULL_INSTALL_LOCATION=\"$VOLUME\"\n else\n FULL_INSTALL_LOCATION=\"$VOLUME/$INSTALL_LOCATION\"\n FULL_INSTALL_LOCATION=$(echo \"$FULL_INSTALL_LOCATION\" | sed 's|//|/|g')\n fi\n\n echo \"sudo pkgutil --only-files --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|/${INSTALL_LOCATION}/|\" | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n echo \"sudo pkgutil --only-dirs --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | grep '\\\\.app$' | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n root_app_dir=$(\n sudo pkgutil --only-dirs --files \"$PKGID\" \\\n | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" \\\n | grep 'Applications' \\\n | awk '{ print length, $0 }' \\\n | sort -n \\\n | head -n1 \\\n | cut -d' ' -f2-\n )\n if [ -n \"$root_app_dir\" ]; then\n echo \"sudo rmdir -p \\\"$root_app_dir\\\" 2>/dev/null || :\"\n sudo rmdir -p \"$root_app_dir\" 2>/dev/null || :\n fi\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'com.microsoft.office.licensingV2.helper'\nquit_application 'com.microsoft.autoupdate2'\nremove_pkg_files 'com.microsoft.package.Microsoft_Word.app'\nforget_pkg 'com.microsoft.package.Microsoft_Word.app'\nremove_pkg_files 'com.microsoft.pkg.licensing'\nforget_pkg 'com.microsoft.pkg.licensing'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.microsoft.Word'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.microsoft.word.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CrashReporter/Microsoft Word_*.plist'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.microsoft.Word'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.microsoft.Word.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.microsoft.Word.savedState'\n" } } diff --git a/ee/maintained-apps/outputs/p4v/darwin.json b/ee/maintained-apps/outputs/p4v/darwin.json index 16014336ee9..426b1a9f785 100644 --- a/ee/maintained-apps/outputs/p4v/darwin.json +++ b/ee/maintained-apps/outputs/p4v/darwin.json @@ -7,8 +7,8 @@ "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.perforce.p4v' AND version_compare(bundle_short_version, '2026.2') < 0);" }, "installer_url": "https://filehost.perforce.com/perforce/r26.2/bin.macosx12u/P4V.dmg", - "install_script_ref": "bbe80cf5", - "uninstall_script_ref": "428bb3f6", + "install_script_ref": "7f44eda5", + "uninstall_script_ref": "f67991ce", "sha256": "9c9367ab96f667d4f1c0fd7e283e4e3678fbed1f570c8238121914b204ad3aac", "default_categories": [ "Developer tools" @@ -16,7 +16,7 @@ } ], "refs": { - "428bb3f6": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" >/dev/null 2>&1; then return; fi\n local console_user; console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then return; fi\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1 || true\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then break; fi\n sleep 1\n done\n}\n\nfor id in \"com.perforce.p4v\" \"com.perforce.p4merge\" \"com.perforce.p4admin\"; do\n quit_application \"$id\"\ndone\n\nrm -rf \"/Applications/p4v.app\" \"/Applications/p4merge.app\" \"/Applications/p4admin.app\" >/dev/null 2>&1 || true\n\n# Remove p4vc command line binary\nrm -f /usr/local/bin/p4vc >/dev/null 2>&1 || true\n\nfor udir in /Users/* /var/root; do\n [[ -d \"$udir/Library\" ]] || continue\n rm -f \"$udir/Library/Preferences/com.perforce.p4v.plist\" \\\n \"$udir/Library/Preferences/com.perforce.p4merge.plist\" \\\n \"$udir/Library/Preferences/com.perforce.p4admin.plist\" >/dev/null 2>&1 || true\n rm -rf \"$udir/Library/Caches/com.perforce.p4v\" \\\n \"$udir/Library/Caches/com.perforce.p4merge\" \\\n \"$udir/Library/Caches/com.perforce.p4admin\" >/dev/null 2>&1 || true\n rm -rf \"$udir/Library/Application Support/Perforce\" \\\n \"$udir/Library/Application Support/P4V\" >/dev/null 2>&1 || true\ndone\n\necho \"p4v suite uninstalled\"\n", - "bbe80cf5": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" >/dev/null 2>&1; then return; fi\n local console_user; console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then echo \"Skipping quit for '$bundle_id'.\"; return; fi\n echo \"Quitting '$bundle_id'...\"\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1 || true\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then echo \"'$bundle_id' quit successfully.\"; return; fi\n sleep 1\n done\n echo \"'$bundle_id' did not quit.\"\n}\n\n[[ -n \"$INSTALLER_PATH\" && -f \"$INSTALLER_PATH\" ]] || { echo \"missing installer\"; exit 1; }\n\nAPPDIR=\"/Applications\"\n\nquit_application \"com.perforce.p4v\"\nquit_application \"com.perforce.p4merge\"\nquit_application \"com.perforce.p4admin\"\n\nMOUNT_POINT=\"$(hdiutil attach -nobrowse -readonly \"$INSTALLER_PATH\" | awk '/\\/Volumes\\//{print $3; exit}')\"\n[[ -n \"$MOUNT_POINT\" ]] || { echo \"failed to mount dmg\"; exit 1; }\n\nfor app in p4v.app p4merge.app p4admin.app; do\n if [[ -d \"$MOUNT_POINT/$app\" ]]; then\n rm -rf \"$APPDIR/$app\" >/dev/null 2>&1 || true\n ditto \"$MOUNT_POINT/$app\" \"$APPDIR/$app\" >/dev/null 2>&1\n fi\ndone\n\n# Install p4vc command line binary to /usr/local/bin\nif [[ -f \"$MOUNT_POINT/p4vc\" ]]; then\n cp \"$MOUNT_POINT/p4vc\" /usr/local/bin/p4vc\n chmod +x /usr/local/bin/p4vc\n chown root:wheel /usr/local/bin/p4vc\nfi\n\nhdiutil detach \"$MOUNT_POINT\" >/dev/null 2>&1 || true\n\necho \"p4v installed\"\n" + "7f44eda5": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n local app_running; app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then return; fi\n local console_user; console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then echo \"Skipping quit for '$bundle_id'.\"; return; fi\n echo \"Quitting '$bundle_id'...\"\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1 || true\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then echo \"'$bundle_id' quit successfully.\"; return; fi\n sleep 1\n done\n echo \"'$bundle_id' did not quit.\"\n}\n\n[[ -n \"$INSTALLER_PATH\" && -f \"$INSTALLER_PATH\" ]] || { echo \"missing installer\"; exit 1; }\n\nAPPDIR=\"/Applications\"\n\nquit_application \"com.perforce.p4v\"\nquit_application \"com.perforce.p4merge\"\nquit_application \"com.perforce.p4admin\"\n\nMOUNT_POINT=\"$(hdiutil attach -nobrowse -readonly \"$INSTALLER_PATH\" | awk '/\\/Volumes\\//{print $3; exit}')\"\n[[ -n \"$MOUNT_POINT\" ]] || { echo \"failed to mount dmg\"; exit 1; }\n\nfor app in p4v.app p4merge.app p4admin.app; do\n if [[ -d \"$MOUNT_POINT/$app\" ]]; then\n rm -rf \"$APPDIR/$app\" >/dev/null 2>&1 || true\n ditto \"$MOUNT_POINT/$app\" \"$APPDIR/$app\" >/dev/null 2>&1\n fi\ndone\n\n# Install p4vc command line binary to /usr/local/bin\nif [[ -f \"$MOUNT_POINT/p4vc\" ]]; then\n cp \"$MOUNT_POINT/p4vc\" /usr/local/bin/p4vc\n chmod +x /usr/local/bin/p4vc\n chown root:wheel /usr/local/bin/p4vc\nfi\n\nhdiutil detach \"$MOUNT_POINT\" >/dev/null 2>&1 || true\n\necho \"p4v installed\"\n", + "f67991ce": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n local app_running; app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then return; fi\n local console_user; console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then return; fi\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1 || true\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then break; fi\n sleep 1\n done\n}\n\nfor id in \"com.perforce.p4v\" \"com.perforce.p4merge\" \"com.perforce.p4admin\"; do\n quit_application \"$id\"\ndone\n\nrm -rf \"/Applications/p4v.app\" \"/Applications/p4merge.app\" \"/Applications/p4admin.app\" >/dev/null 2>&1 || true\n\n# Remove p4vc command line binary\nrm -f /usr/local/bin/p4vc >/dev/null 2>&1 || true\n\nfor udir in /Users/* /var/root; do\n [[ -d \"$udir/Library\" ]] || continue\n rm -f \"$udir/Library/Preferences/com.perforce.p4v.plist\" \\\n \"$udir/Library/Preferences/com.perforce.p4merge.plist\" \\\n \"$udir/Library/Preferences/com.perforce.p4admin.plist\" >/dev/null 2>&1 || true\n rm -rf \"$udir/Library/Caches/com.perforce.p4v\" \\\n \"$udir/Library/Caches/com.perforce.p4merge\" \\\n \"$udir/Library/Caches/com.perforce.p4admin\" >/dev/null 2>&1 || true\n rm -rf \"$udir/Library/Application Support/Perforce\" \\\n \"$udir/Library/Application Support/P4V\" >/dev/null 2>&1 || true\ndone\n\necho \"p4v suite uninstalled\"\n" } } diff --git a/ee/maintained-apps/outputs/slack/darwin.json b/ee/maintained-apps/outputs/slack/darwin.json index cc822e645d6..89ebcc9a4a7 100644 --- a/ee/maintained-apps/outputs/slack/darwin.json +++ b/ee/maintained-apps/outputs/slack/darwin.json @@ -7,7 +7,7 @@ "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.tinyspeck.slackmacgap' AND version_compare(bundle_short_version, '4.50.143') < 0);" }, "installer_url": "https://slack.com/api/desktop.latestRelease?redirect=1&variant=pkg&arch=universal", - "install_script_ref": "6025885d", + "install_script_ref": "92608bef", "uninstall_script_ref": "d3fcc8c2", "sha256": "no_check", "default_categories": [ @@ -16,7 +16,7 @@ } ], "refs": { - "6025885d": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\nquit_application 'com.tinyspeck.slackmacgap'\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\n", + "92608bef": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\nquit_application 'com.tinyspeck.slackmacgap'\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\n", "d3fcc8c2": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nquit_application 'com.tinyspeck.slackmacgap'\nsudo rm -rf \"$APPDIR/Slack.app\"\ntrash $LOGGED_IN_USER '/Library/Logs/DiagnosticReports/Slack_*'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.tinyspeck.slackmacgap'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.tinyspeck.slackmacgap.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Slack'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.tinyspeck.slackmacgap*'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.tinyspeck.slackmacgap*'\ntrash $LOGGED_IN_USER '~/Library/Cookies/com.tinyspeck.slackmacgap.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/*.com.tinyspeck.slackmacgap'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/*.slack'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.tinyspeck.slackmacgap*'\ntrash $LOGGED_IN_USER '~/Library/Logs/Slack'\ntrash $LOGGED_IN_USER '~/Library/Preferences/ByHost/com.tinyspeck.slackmacgap.ShipIt.*.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.tinyspeck.slackmacgap*'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.tinyspeck.slackmacgap.savedState'\ntrash $LOGGED_IN_USER '~/Library/WebKit/com.tinyspeck.slackmacgap'\n" } } diff --git a/ee/maintained-apps/outputs/zoom/darwin.json b/ee/maintained-apps/outputs/zoom/darwin.json index c77abff62b6..3e5298f5922 100644 --- a/ee/maintained-apps/outputs/zoom/darwin.json +++ b/ee/maintained-apps/outputs/zoom/darwin.json @@ -7,7 +7,7 @@ "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'us.zoom.xos' AND version_compare(bundle_short_version, '7.1.0.83064') < 0);" }, "installer_url": "https://zoom.us/client/latest/ZoomInstallerIT.pkg", - "install_script_ref": "05e6a85c", + "install_script_ref": "ab84b572", "uninstall_script_ref": "1edaf31e", "sha256": "no_check", "default_categories": [ @@ -16,7 +16,7 @@ } ], "refs": { - "05e6a85c": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local console_user=\"$2\"\n local timeout_duration=10\n\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\nrestart_zoom() {\n local console_user=\"$1\"\n \n if [[ -n \"$console_user\" && \"$console_user\" != \"root\" ]]; then\n echo \"Restarting Zoom for user: $console_user\"\n sudo -u \"$console_user\" open -a \"zoom.us\"\n else\n echo \"No console user found, attempting direct Zoom start...\"\n open -a \"zoom.us\"\n fi\n}\n\n# Get console user once (used by both quit and restart)\nCONSOLE_USER=$(stat -f \"%Su\" /dev/console 2>/dev/null || echo \"\")\n\n# Check if Zoom is running\nZOOM_WAS_RUNNING=false\nif osascript -e \"application id \\\"us.zoom.xos\\\" is running\" 2>/dev/null; then\n ZOOM_WAS_RUNNING=true\n quit_application 'us.zoom.xos' \"$CONSOLE_USER\"\nfi\n\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\n# Restart Zoom if it was running before installation\nif [[ \"$ZOOM_WAS_RUNNING\" == \"true\" ]]; then\n sleep 2\n restart_zoom \"$CONSOLE_USER\" || true\nfi\n\n", - "1edaf31e": "#!/bin/bash\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nexpand_pkgid_and_map() {\n local PKGID=\"$1\"\n local FUNC=\"$2\"\n if [[ \"$PKGID\" == *\"*\" ]]; then\n local prefix=\"${PKGID%\\*}\"\n echo \"Expanding wildcard for PKGID: $PKGID\"\n for receipt in $(pkgutil --pkgs | grep \"^${prefix}\"); do\n echo \"Processing $receipt\"\n \"$FUNC\" \"$receipt\"\n done\n else\n \"$FUNC\" \"$PKGID\"\n fi\n}\n\nforget_pkg() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" forget_receipt\n}\n\nforget_receipt() {\n local PKGID=\"$1\"\n sudo pkgutil --forget \"$PKGID\"\n}\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n # A wildcard label can't be used with launchctl or as a plist name, so expand\n # it to the labels of currently loaded services that match the pattern.\n local services=(\"$service\")\n if [[ \"$service\" == *\"*\"* ]]; then\n local regex\n # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so\n # it matches a full label rather than a substring.\n regex=$(printf '%s' \"$service\" | sed -e 's/[][(){}.^$+?|\\\\]/\\\\&/g' -e 's/\\*/.*/g')\n regex=\"^${regex}$\"\n services=()\n local id\n # Match every loaded job by label regardless of PID; launchctl list reports\n # loaded-but-not-running jobs with a \"-\" in the PID column.\n while read -r _ _ id; do\n [[ \"$id\" =~ $regex ]] && services+=(\"$id\")\n done < <(launchctl list 2>/dev/null | tail -n +2)\n if [[ ${#services[@]} -eq 0 ]]; then\n echo \"No loaded launchctl service matches ${service}\"\n return\n fi\n fi\n\n local service_label\n for service_label in \"${services[@]}\"; do\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service_label}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service_label}\"\n else\n launchctl remove \"${service_label}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service_label}.plist\"\n \"/Library/LaunchDaemons/${service_label}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n done\n}\n\nremove_pkg_files() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" remove_receipt_files\n}\n\nremove_receipt_files() {\n local PKGID=\"$1\"\n local PKGINFO VOLUME INSTALL_LOCATION FULL_INSTALL_LOCATION\n\n echo \"pkgutil --pkg-info-plist \\\"$PKGID\\\"\"\n PKGINFO=$(pkgutil --pkg-info-plist \"$PKGID\")\n VOLUME=$(echo \"$PKGINFO\" | awk '/volume<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n INSTALL_LOCATION=$(echo \"$PKGINFO\" | awk '/install-location<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n\n if [ -z \"$INSTALL_LOCATION\" ] || [ \"$INSTALL_LOCATION\" = \"/\" ]; then\n FULL_INSTALL_LOCATION=\"$VOLUME\"\n else\n FULL_INSTALL_LOCATION=\"$VOLUME/$INSTALL_LOCATION\"\n FULL_INSTALL_LOCATION=$(echo \"$FULL_INSTALL_LOCATION\" | sed 's|//|/|g')\n fi\n\n echo \"sudo pkgutil --only-files --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|/${INSTALL_LOCATION}/|\" | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n echo \"sudo pkgutil --only-dirs --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | grep '\\\\.app$' | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n root_app_dir=$(\n sudo pkgutil --only-dirs --files \"$PKGID\" \\\n | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" \\\n | grep 'Applications' \\\n | awk '{ print length, $0 }' \\\n | sort -n \\\n | head -n1 \\\n | cut -d' ' -f2-\n )\n if [ -n \"$root_app_dir\" ]; then\n echo \"sudo rmdir -p \\\"$root_app_dir\\\" 2>/dev/null || :\"\n sudo rmdir -p \"$root_app_dir\" 2>/dev/null || :\n fi\n}\n\nsend_signal() {\n local signal=\"$1\"\n local bundle_id=\"$2\"\n local logged_in_user=\"$3\"\n local logged_in_uid pids\n\n if [ -z \"$signal\" ] || [ -z \"$bundle_id\" ] || [ -z \"$logged_in_user\" ]; then\n echo \"Usage: uninstall_signal \"\n return 1\n fi\n\n logged_in_uid=$(id -u \"$logged_in_user\")\n if [ -z \"$logged_in_uid\" ]; then\n echo \"Could not find UID for user '$logged_in_user'.\"\n return 1\n fi\n\n echo \"Signalling '$signal' to application ID '$bundle_id' for user '$logged_in_user'\"\n\n pids=$(/bin/launchctl asuser \"$logged_in_uid\" sudo -iu \"$logged_in_user\" /bin/launchctl list | awk -v bundle_id=\"$bundle_id\" '\n $3 ~ bundle_id { print $1 }')\n\n if [ -z \"$pids\" ]; then\n echo \"No processes found for bundle ID '$bundle_id'.\"\n return 0\n fi\n\n echo \"Unix PIDs are $pids for processes with bundle identifier $bundle_id\"\n for pid in $pids; do\n if kill -s \"$signal\" \"$pid\" 2>/dev/null; then\n echo \"Successfully signaled PID $pid with signal $signal.\"\n else\n echo \"Failed to kill PID $pid with signal $signal. Check permissions.\"\n fi\n done\n\n sleep 3\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'us.zoom.ZoomDaemon'\nsend_signal 'KILL' 'us.zoom.xos' \"$LOGGED_IN_USER\"\nremove_pkg_files 'us.zoom.pkg.videomeeting'\nforget_pkg 'us.zoom.pkg.videomeeting'\nsudo rm -rf '/Applications/zoom.us.app'\nsudo rm -rf '/Library/Audio/Plug-Ins/HAL/ZoomAudioDevice.driver'\nsudo rm -rf '/Library/Internet Plug-Ins/ZoomUsPlugIn.plugin'\nsudo rm -rf '/Library/Logs/DiagnosticReports/zoom.us*'\nsudo rm -rf '/Library/PrivilegedHelperTools/us.zoom.ZoomDaemon'\ntrash $LOGGED_IN_USER '/Library/Preferences/us.zoom.config.plist'\ntrash $LOGGED_IN_USER '~/.zoomus'\ntrash $LOGGED_IN_USER '~/Desktop/Zoom'\ntrash $LOGGED_IN_USER '~/Documents/Zoom'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/*.ZoomClient3rd'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CloudDocs/session/containers/iCloud.us.zoom.videomeetings'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CloudDocs/session/containers/iCloud.us.zoom.videomeetings.plist'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CrashReporter/zoom.us*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/zoom.us'\ntrash $LOGGED_IN_USER '~/Library/Caches/us.zoom.xos'\ntrash $LOGGED_IN_USER '~/Library/Cookies/us.zoom.xos.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/*.ZoomClient3rd'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/us.zoom.xos'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/us.zoom.xos.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/Internet Plug-Ins/ZoomUsPlugIn.plugin'\ntrash $LOGGED_IN_USER '~/Library/Logs/zoom.us'\ntrash $LOGGED_IN_USER '~/Library/Logs/zoominstall.log'\ntrash $LOGGED_IN_USER '~/Library/Logs/ZoomPhone'\ntrash $LOGGED_IN_USER '~/Library/Mobile Documents/iCloud~us~zoom~videomeetings'\ntrash $LOGGED_IN_USER '~/Library/Preferences/us.zoom.airhost.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/us.zoom.caphost.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/us.zoom.Transcode.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/us.zoom.xos.Hotkey.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/us.zoom.xos.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/us.zoom.ZoomAutoUpdater.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/ZoomChat.plist'\ntrash $LOGGED_IN_USER '~/Library/Safari/PerSiteZoomPreferences.plist'\ntrash $LOGGED_IN_USER '~/Library/SafariTechnologyPreview/PerSiteZoomPreferences.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/us.zoom.xos.savedState'\ntrash $LOGGED_IN_USER '~/Library/WebKit/us.zoom.xos'\n" + "1edaf31e": "#!/bin/bash\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nexpand_pkgid_and_map() {\n local PKGID=\"$1\"\n local FUNC=\"$2\"\n if [[ \"$PKGID\" == *\"*\" ]]; then\n local prefix=\"${PKGID%\\*}\"\n echo \"Expanding wildcard for PKGID: $PKGID\"\n for receipt in $(pkgutil --pkgs | grep \"^${prefix}\"); do\n echo \"Processing $receipt\"\n \"$FUNC\" \"$receipt\"\n done\n else\n \"$FUNC\" \"$PKGID\"\n fi\n}\n\nforget_pkg() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" forget_receipt\n}\n\nforget_receipt() {\n local PKGID=\"$1\"\n sudo pkgutil --forget \"$PKGID\"\n}\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n # A wildcard label can't be used with launchctl or as a plist name, so expand\n # it to the labels of currently loaded services that match the pattern.\n local services=(\"$service\")\n if [[ \"$service\" == *\"*\"* ]]; then\n local regex\n # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so\n # it matches a full label rather than a substring.\n regex=$(printf '%s' \"$service\" | sed -e 's/[][(){}.^$+?|\\\\]/\\\\&/g' -e 's/\\*/.*/g')\n regex=\"^${regex}$\"\n services=()\n local id\n # Match every loaded job by label regardless of PID; launchctl list reports\n # loaded-but-not-running jobs with a \"-\" in the PID column.\n while read -r _ _ id; do\n [[ \"$id\" =~ $regex ]] && services+=(\"$id\")\n done < <(launchctl list 2>/dev/null | tail -n +2)\n if [[ ${#services[@]} -eq 0 ]]; then\n echo \"No loaded launchctl service matches ${service}\"\n return\n fi\n fi\n\n local service_label\n for service_label in \"${services[@]}\"; do\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service_label}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service_label}\"\n else\n launchctl remove \"${service_label}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service_label}.plist\"\n \"/Library/LaunchDaemons/${service_label}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n done\n}\n\nremove_pkg_files() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" remove_receipt_files\n}\n\nremove_receipt_files() {\n local PKGID=\"$1\"\n local PKGINFO VOLUME INSTALL_LOCATION FULL_INSTALL_LOCATION\n\n echo \"pkgutil --pkg-info-plist \\\"$PKGID\\\"\"\n PKGINFO=$(pkgutil --pkg-info-plist \"$PKGID\")\n VOLUME=$(echo \"$PKGINFO\" | awk '/volume<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n INSTALL_LOCATION=$(echo \"$PKGINFO\" | awk '/install-location<\\/key>/ {getline; gsub(/.*|<\\/string>.*/, \"\"); print}')\n\n if [ -z \"$INSTALL_LOCATION\" ] || [ \"$INSTALL_LOCATION\" = \"/\" ]; then\n FULL_INSTALL_LOCATION=\"$VOLUME\"\n else\n FULL_INSTALL_LOCATION=\"$VOLUME/$INSTALL_LOCATION\"\n FULL_INSTALL_LOCATION=$(echo \"$FULL_INSTALL_LOCATION\" | sed 's|//|/|g')\n fi\n\n echo \"sudo pkgutil --only-files --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|/${INSTALL_LOCATION}/|\" | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n echo \"sudo pkgutil --only-dirs --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | grep '\\\\.app$' | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n root_app_dir=$(\n sudo pkgutil --only-dirs --files \"$PKGID\" \\\n | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" \\\n | grep 'Applications' \\\n | awk '{ print length, $0 }' \\\n | sort -n \\\n | head -n1 \\\n | cut -d' ' -f2-\n )\n if [ -n \"$root_app_dir\" ]; then\n echo \"sudo rmdir -p \\\"$root_app_dir\\\" 2>/dev/null || :\"\n sudo rmdir -p \"$root_app_dir\" 2>/dev/null || :\n fi\n}\n\nsend_signal() {\n local signal=\"$1\"\n local bundle_id=\"$2\"\n local logged_in_user=\"$3\"\n local logged_in_uid pids\n\n if [ -z \"$signal\" ] || [ -z \"$bundle_id\" ] || [ -z \"$logged_in_user\" ]; then\n echo \"Usage: uninstall_signal \"\n return 1\n fi\n\n logged_in_uid=$(id -u \"$logged_in_user\")\n if [ -z \"$logged_in_uid\" ]; then\n echo \"Could not find UID for user '$logged_in_user'.\"\n return 1\n fi\n\n echo \"Signalling '$signal' to application ID '$bundle_id' for user '$logged_in_user'\"\n\n pids=$(/bin/launchctl asuser \"$logged_in_uid\" sudo -iu \"$logged_in_user\" /bin/launchctl list | awk -v bundle_id=\"$bundle_id\" '\n $3 ~ bundle_id { print $1 }')\n\n if [ -z \"$pids\" ]; then\n echo \"No processes found for bundle ID '$bundle_id'.\"\n return 0\n fi\n\n echo \"Unix PIDs are $pids for processes with bundle identifier $bundle_id\"\n for pid in $pids; do\n if kill -s \"$signal\" \"$pid\" 2>/dev/null; then\n echo \"Successfully signaled PID $pid with signal $signal.\"\n else\n echo \"Failed to kill PID $pid with signal $signal. Check permissions.\"\n fi\n done\n\n sleep 3\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'us.zoom.ZoomDaemon'\nsend_signal 'KILL' 'us.zoom.xos' \"$LOGGED_IN_USER\"\nremove_pkg_files 'us.zoom.pkg.videomeeting'\nforget_pkg 'us.zoom.pkg.videomeeting'\nsudo rm -rf '/Applications/zoom.us.app'\nsudo rm -rf '/Library/Audio/Plug-Ins/HAL/ZoomAudioDevice.driver'\nsudo rm -rf '/Library/Internet Plug-Ins/ZoomUsPlugIn.plugin'\nsudo rm -rf '/Library/Logs/DiagnosticReports/zoom.us*'\nsudo rm -rf '/Library/PrivilegedHelperTools/us.zoom.ZoomDaemon'\ntrash $LOGGED_IN_USER '/Library/Preferences/us.zoom.config.plist'\ntrash $LOGGED_IN_USER '~/.zoomus'\ntrash $LOGGED_IN_USER '~/Desktop/Zoom'\ntrash $LOGGED_IN_USER '~/Documents/Zoom'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/*.ZoomClient3rd'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CloudDocs/session/containers/iCloud.us.zoom.videomeetings'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CloudDocs/session/containers/iCloud.us.zoom.videomeetings.plist'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CrashReporter/zoom.us*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/zoom.us'\ntrash $LOGGED_IN_USER '~/Library/Caches/us.zoom.xos'\ntrash $LOGGED_IN_USER '~/Library/Cookies/us.zoom.xos.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/*.ZoomClient3rd'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/us.zoom.xos'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/us.zoom.xos.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/Internet Plug-Ins/ZoomUsPlugIn.plugin'\ntrash $LOGGED_IN_USER '~/Library/Logs/zoom.us'\ntrash $LOGGED_IN_USER '~/Library/Logs/zoominstall.log'\ntrash $LOGGED_IN_USER '~/Library/Logs/ZoomPhone'\ntrash $LOGGED_IN_USER '~/Library/Mobile Documents/iCloud~us~zoom~videomeetings'\ntrash $LOGGED_IN_USER '~/Library/Preferences/us.zoom.airhost.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/us.zoom.caphost.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/us.zoom.Transcode.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/us.zoom.xos.Hotkey.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/us.zoom.xos.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/us.zoom.ZoomAutoUpdater.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/ZoomChat.plist'\ntrash $LOGGED_IN_USER '~/Library/Safari/PerSiteZoomPreferences.plist'\ntrash $LOGGED_IN_USER '~/Library/SafariTechnologyPreview/PerSiteZoomPreferences.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/us.zoom.xos.savedState'\ntrash $LOGGED_IN_USER '~/Library/WebKit/us.zoom.xos'\n", + "ab84b572": "#!/bin/bash\n\nquit_application() {\n local bundle_id=\"$1\"\n local console_user=\"$2\"\n local timeout_duration=10\n\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\nrestart_zoom() {\n local console_user=\"$1\"\n \n if [[ -n \"$console_user\" && \"$console_user\" != \"root\" ]]; then\n echo \"Restarting Zoom for user: $console_user\"\n sudo -u \"$console_user\" open -a \"zoom.us\"\n else\n echo \"No console user found, attempting direct Zoom start...\"\n open -a \"zoom.us\"\n fi\n}\n\n# Get console user once (used by both quit and restart)\nCONSOLE_USER=$(stat -f \"%Su\" /dev/console 2>/dev/null || echo \"\")\n\n# Check if Zoom is running\nZOOM_WAS_RUNNING=false\nZOOM_RUNNING=$(osascript -e \"application id \\\"us.zoom.xos\\\" is running\" 2>/dev/null)\nif [[ \"$ZOOM_RUNNING\" == \"true\" ]]; then\n ZOOM_WAS_RUNNING=true\n quit_application 'us.zoom.xos' \"$CONSOLE_USER\"\nfi\n\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\n# Restart Zoom if it was running before installation\nif [[ \"$ZOOM_WAS_RUNNING\" == \"true\" ]]; then\n sleep 2\n restart_zoom \"$CONSOLE_USER\" || true\nfi\n\n" } }