diff --git a/utils/remove-bridge/README.md b/utils/remove-bridge/README.md new file mode 100644 index 00000000..7b72981a --- /dev/null +++ b/utils/remove-bridge/README.md @@ -0,0 +1,116 @@ +# Clean Bridge + +## Description + +This repository contains scripts with which just by running them Bridge will quit, uninstall, and remove all leftover resources from your device. On Windows it will delete the entry(ies) in the Credential Manager, on macOS it will delete the entries from the Keychain Access, and on Linux distros it will try to delete the credentials both from `gnome-keyring` and `pass`. +There's a PowerShell script for Windows, and a Shell script for Linux & macOS. + +--- + +### --WARNING-- + +These scripts are made with the assumption that there isn't another process with the `bridge` name in it. Be careful when using it on your own devices, it might kill another process with `bridge` in it's name. + +The Shell script [remove_bridge](/remove_bridge) does not quit the process of Bridge V2. You'll need to manually quit it before executing this script. In the current implementation the process that the script quits is `bridge-gui` because when it was `bridge` previously, on Ubuntu the script closed itself not Bridge. + +--- + +## Installation + +There's no installation needed. Just download the script relevant for your Operating System, or clone the whole repo. + +## Prerequisites + +The `remove_bridge` script requires `zsh` to be executed. + +## Usage + +Run the script on your device when you need it. + +On Linux distros it needs to be ran with `sudo` so it can uninstall Bridge. + +### Linux & macOS + +Recommendation for Linux & macOS is to place it in you `$PATH` location so you can run it immediately from the terminal when needed. + +### Windows + +To use the script without the need to input the full path of it, you can place it in a specific directory and add that directory to the PowerShell profile ([wiki link](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles?view=powershell-7.3)) of the PowerShell version you are using so it's loaded in each session. Then you can just enter the name of the script to run it no matter the active directory in the session. + +The `$PROFILE` automatic variable stores the paths to the PowerShell profiles that are available in the current session. +To view a profile path, display the value of the `$PROFILE` variable. + +```PowerShell +PS C:\Users\Gjorgji> Write-Output $PROFILE +C:\Users\Gjorgji\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 +PS C:\Users\Gjorgji> +``` + +The `$PROFILE` variable stores the path to the "Current User, Current Host" profile. The other profiles are saved in note properties of the $PROFILE variable. +For example, the `$PROFILE` variable has the following values in the Windows PowerShell console. + +- Current User, Current Host - $PROFILE +- Current User, Current Host - $PROFILE.CurrentUserCurrentHost +- Current User, All Hosts - $PROFILE.CurrentUserAllHosts +- All Users, Current Host - $PROFILE.AllUsersCurrentHost +- All Users, All Hosts - $PROFILE.AllUsersAllHosts + +The script folder can be added to the profile at `$PROFILE.AllUsersAllHosts`, but where you place it it's up to you. The guide continues by just using `$PROFILE` for "Current User, Current Host". + +#### **Create the Profile file** + +By default, the Profile file is not created so you'll need to create it yourself before adding the script directory in it. If you have the Profile file already created skip to the [next step](#adding-the-script-directory-to-the-profile). + +To create the file, open a PowerShell terminal and input: + +```PowerShell +if (!(Test-Path -Path )) { + New-Item -ItemType File -Path -Force +} +``` + +For example, to create a profile for the current user in the current PowerShell host application, use the following command: + +```PowerShell +if (!(Test-Path -Path $PROFILE)) { + New-Item -ItemType File -Path $PROFILE -Force +} +``` + +#### **Adding the script directory to the Profile** + +To edit the $PROFILE file, open it with your favorite text editor, or just open your PowerShell terminal and input: + +```PowerShell +PS C:\Users\Gjorgji> notepad $PROFILE +``` + +This will open the Profile file with the default Windows Notepad. + +Once the file is opened, add the following and save the file: + +```PowerShell +# Load scripts from the following locations +$env:Path += ";" +``` + +As an example, if the script is placed in `C:\Users\Gjorgji\Documents\PowerShell\Scripts`, this line will be in the Profile: + +```PowerShell +# Load scripts from the following location +$env:Path += ";$HOME\Documents\PowerShell\Scripts" +``` + +#### **Finally** + +After doing all the above, restart your PowerShell terminal so the changes take effect, and whenever needed just run `Remove-Bridge` + +```PowerShell +╭─    ~\bridge    devel ≡  ?1 ~1   ✔  08:43:49  ─╮ +╰─ Remove-Bridge ─╯ +All Bridge resource folders deleted! + +CMDKEY: Credential deleted successfully. +╭─    ~\bridge    devel ≡  ?1 ~1   37.152s   ✔  08:45:43  ─╮ +╰─ ─╯ +``` diff --git a/utils/remove-bridge/Remove-Bridge.ps1 b/utils/remove-bridge/Remove-Bridge.ps1 new file mode 100644 index 00000000..74496a87 --- /dev/null +++ b/utils/remove-bridge/Remove-Bridge.ps1 @@ -0,0 +1,169 @@ +# Copyright (c) 2024 Proton AG +# +# This file is part of Proton Mail Bridge. +# +# Proton Mail Bridge is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Proton Mail Bridge is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Proton Mail Bridge. If not, see . + +# Remove-Bridge is a script for quitting, uninstalling, and deleted all Bridge related files on Windows + +# Define variables with path to Bridge files (vault, cache, startup entry etc) +$RoamProtonmail = "$env:APPDATA\protonmail" +$RoamProtonAG = "$env:APPDATA\Proton AG" +$LocalProtonmail = "$env:LOCALAPPDATA\protonmail" +$LocalProtonAG = "$env:LOCALAPPDATA\Proton AG" +$StartUpProtonBridge = "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\Proton Mail Bridge.lnk" + +function Uninstall-PMBridge { + # Uninstalling REBRANDED version of Bridge + # Find the UninstallSTring in the registry (64bit & 32bit) + # Use the UninstallString with `msiexec.exe` to uninstall Bridge + + $registry64 = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_ -match "Proton Mail Bridge" } | Select-Object UninstallString + + if ($registry64) { + $registry64 = $registry64 | Select-Object -Last 1 + $registry64 = $registry64.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X","" + $registry64 = $registry64.Trim() + Start-Process "msiexec.exe" -arg "/X $registry64 /passive" -Wait + } + + $registry32 = Get-ChildItem "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_ -match "Proton Mail Bridge" } | Select-Object UninstallString + + if ($registry32) { + $registry32 = $registry32 | Select-Object -Last 1 + $registry32 = $registry32.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X","" + $registry32 = $registry32.Trim() + Start-Process "msiexec.exe" -arg "/X $registry32 /passive" -Wait + } + + + # Uninstalling PRE-REBRANDED version of Bridge + # Find the UninstallSTring in the registry (64bit & 32bit) + # Use the UninstallString with `msiexec.exe` to uninstall Bridge + + $preRebrandRegistry64 = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_ -match "ProtonMail Bridge" } | Select-Object UninstallString + + if ($preRebrandRegistry64) { + $preRebrandRegistry64 = $preRebrandRegistry64 | Select-Object -Last 1 + $preRebrandRegistry64 = $preRebrandRegistry64.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X","" + $preRebrandRegistry64 = $preRebrandRegistry64.Trim() + Start-Process "msiexec.exe" -arg "/X $preRebrandRegistry64 /passive" -Wait + } + + $preRebrandRegistry32 = Get-ChildItem "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_ -match "ProtonMail Bridge" } | Select-Object UninstallString + + if ($preRebrandRegistry32) { + $preRebrandRegistry32 = $preRebrandRegistry32 | Select-Object -Last 1 + $preRebrandRegistry32 = $preRebrandRegistry32.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X","" + $preRebrandRegistry32 = $preRebrandRegistry32.Trim() + Start-Process "msiexec.exe" -arg "/X $preRebrandRegistry32 /passive" -Wait + } + +} + + +function Stop-PMBridge { + # Stop the `bridge` process to completely quit Bridge + + $bridge = Get-Process "bridge" -ErrorAction SilentlyContinue + + if ($bridge){ + + $bridge | Stop-Process -Force + + } + +} + + +function Remove-PMBridgeResources { + # Delete all the Bridge resource folders + # They should be deleted with uninstalling Bridge + # But to just make sure do this again + + Remove-Item $RoamProtonmail -Force -Recurse -ErrorAction SilentlyContinue + Remove-Item $RoamProtonAG -Force -Recurse -ErrorAction SilentlyContinue + Remove-Item $LocalProtonmail -Force -Recurse -ErrorAction SilentlyContinue + Remove-Item $LocalProtonAG -Force -Recurse -ErrorAction SilentlyContinue + Remove-Item $StartUpProtonBridge -Force -Recurse -ErrorAction SilentlyContinue + +} + + +function Find-PMBridgeResources { + # Search and check if the Bridge resource folders + # Are deleted + # Write to Output the result + + $FolderExists = $false + + if ( Test-Path -Path $RoamProtonmail ){ + Write-Host "`r`n'$RoamProtonmail' is not deleted!" -ForegroundColor Red + $FolderExists = $true + } + + if ( Test-Path -Path $RoamProtonAG ) { + Write-Host "`r`n'$RoamProtonAG' is not deleted!" -ForegroundColor Red + $FolderExists = $true + } + + if ( Test-Path -Path $LocalProtonmail ) { + Write-Host "`r`n'$LocalProtonmail' is not deleted!" -ForegroundColor Red + $FolderExists = $true + } + + if ( Test-Path -Path $LocalProtonAG ) { + Write-Host "`r`n'$LocalProtonAG' is not deleted!" -ForegroundColor Red + $FolderExists = $true + } + + if ( Test-Path -Path $StartUpProtonBridge ) { + Write-Host "`r`n'$StartUpProtonBridge' is not deleted!" -ForegroundColor Red + $FolderExists = $true + } + + if ( $FolderExists ) { + Write-Host "`r`nSome directories were not deleted properly!`r`n" -ForegroundColor Red + } + + else { + Write-Host "`r`nAll Bridge resource folders deleted!`r`n" -ForegroundColor Green + } + +} + + +function Remove-PMBridgeCredentials { + # Delete the entries in the credential manager + + $CredentialsData = @((cmdkey /listall | Where-Object{$_ -like "*LegacyGeneric:target=protonmail*"}).replace("Target: ","")) + + for($i =0; $i -le ($CredentialsData.Count -1); $i++){ + [string]$DeleteData = $CredentialsData[$i].trim() + cmdkey /delete:$DeleteData + } + +} + + +function Invoke-BridgeFunctions { + Stop-PMBridge + Uninstall-PMBridge + Remove-PMBridgeResources + Find-PMBridgeResources + Remove-PMBridgeCredentials +} + + +Invoke-BridgeFunctions diff --git a/utils/remove-bridge/remove_bridge b/utils/remove-bridge/remove_bridge new file mode 100755 index 00000000..aabb8b9a --- /dev/null +++ b/utils/remove-bridge/remove_bridge @@ -0,0 +1,268 @@ +#!/bin/zsh + +# Copyright (c) 2024 Proton AG +# +# This file is part of Proton Mail Bridge. +# +# Proton Mail Bridge is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Proton Mail Bridge is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Proton Mail Bridge. If not, see . + +# remove_bridge is a script for quitting, uninstalling, and deleted all Bridge related files on macOS, and Linux distros. + +# Colours for prettying up the terminal output +NC='\033[0m' +GREEN='\033[0;32m' +RED='\033[0;31m' + +# Variables with path to Bridge files (vault, cache, etc) +BRIDGE_PROCESS=bridge-gui +MAC_BRIDGE_APP_NAME=(Proton\ Mail\ Bridge.app) +MAC_SUPPORT_PROTONMAIL=~/Library/Application\ Support/protonmail +MAC_CACHE_PROTONMAIL=~/Library/Caches/protonmail +MAC_CACHE_PROTON=~/Library/Caches/Proton\ AG +MAC_BRIDGE_CREDS_V2="Proton Mail Bridge" +MAC_BRIDGE_CREDS_V3="Proton Mail Bridge-V3" +MAC_LAUNCH_AGENTS=~/Library/LaunchAgents/Proton\ Mail\ Bridge.plist +LINUX_CACHE_PROTON=~/.cache/Proton\ AG +LINUX_CACHE_PROTONMAIL=~/.cache/protonmail +LINUX_CONFIG_PROTONMAIL=~/.config/protonmail +LINUX_LOCAL_PROTONMAIL=~/.local/share/protonmail +LINUX_BRIDGE_USER_INFO=~/.config/protonmail/bridge/cache/c11/user_info.json +LINUX_STARTUP_ENTRY=~/.config/autostart/Proton\ Mail\ Bridge.desktop + + +quit_bridge() { +# Quit a running Bridge + pkill $BRIDGE_PROCESS + +} + + +uninstall_bridge() { +# Uninstall Bridge + + if [[ "$OSTYPE" == "darwin"* ]]; then + + rm -rf /Applications/"${MAC_BRIDGE_APP_NAME[@]}" + + elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + + if [ -f "/usr/bin/apt-get" ]; then + + sudo dpkg -P protonmail-bridge + + elif [ -f "/bin/dnf" ]; then + + sudo dnf remove -y protonmail-bridge + + fi + + else + + echo -e "${RED}Unknown operating system!{$NC}" + + fi + +} + + +get_user_info() { +# Get the UserID from `user_info.json` file to be used when +# Deleting keychain entries from `gnome-keyring` + + result=( $(cat $LINUX_BRIDGE_USER_INFO | jq -r '. | keys[]') ) + +} + + +delete_credentials() { + + if [[ "$OSTYPE" == "darwin"* ]]; then + + while security delete-generic-password -s "${MAC_BRIDGE_CREDS_V2}" >/dev/null + do + true; + done + + security delete-generic-password -s "${MAC_BRIDGE_CREDS_V3}" + + elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + + if [[ $(which gnome-keyring | grep 'gnome-keyring') ]]; then + + secret-tool clear username bridge-vault-key + + get_user_info + + for value in "${result[@]}"; do + + secret-tool clear username "$value" + + done + + fi + + if [[ $(which pass | grep 'pass') ]]; then + + pass remove -rf protonmail-credentials + + fi + + else + + echo -e "${RED}Unknown operating system!{$NC}" + + fi + +} + + +delete_resource_folders() { + + if [[ "$OSTYPE" == "darwin"* ]]; then + + rm -rf $MAC_SUPPORT_PROTONMAIL + rm -rf $MAC_CACHE_PROTONMAIL + rm -rf $MAC_CACHE_PROTON + rm $MAC_LAUNCH_AGENTS + + elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + + rm -rf $LINUX_CACHE_PROTON + rm -rf $LINUX_CACHE_PROTONMAIL + rm -rf $LINUX_CONFIG_PROTONMAIL + rm -rf $LINUX_LOCAL_PROTONMAIL + rm -rf $LINUX_STARTUP_ENTRY + + else + + echo -e "${RED}Unknown operating system!{$NC}" + + fi + +} + + +check_resource_folders() { + + FOLDER_EXISTS=false + + if [[ "$OSTYPE" == "darwin"* ]]; then + + if [ -d "$MAC_SUPPORT_PROTONMAIL" ]; then + + echo -e "\n${RED}$MAC_SUPPORT_PROTONMAIL still exists!${NC}" + FOLDER_EXISTS=true + + fi + + if [ -d "$MAC_CACHE_PROTONMAIL" ]; then + + echo -e "\n${RED}$MAC_CACHE_PROTONMAIL still exists!${NC}" + FOLDER_EXISTS=true + + fi + + if [ -d "$MAC_CACHE_PROTON" ]; then + + echo -e "\n${RED}$MAC_CACHE_PROTON still exists!${NC}" + FOLDER_EXISTS=true + + fi + + if [ -f "$MAC_LAUNCH_AGENTS" ]; then + + echo -e "\n${RED}$MAC_LAUNCH_AGENTS still exists!${NC}" + FOLDER_EXISTS=true + + fi + + if [ "$FOLDER_EXISTS" = true ]; then + + echo -e "\n${RED}Some directories were not deleted properly!${NC}\n" + + else + + echo -e "\n${GREEN}All Bridge resource folders deleted!${NC}\n" + + fi + + elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + + if [ -d "$LINUX_CACHE_PROTON" ]; then + + echo -e "\n${RED}$LINUX_CACHE_PROTON still exists!${NC}" + FOLDER_EXISTS=true + + fi + + if [ -d "$LINUX_CACHE_PROTONMAIL" ]; then + + echo -e "\n${RED}$LINUX_CACHE_PROTONMAIL still exists!${NC}" + FOLDER_EXISTS=true + + fi + + if [ -d "$LINUX_CONFIG_PROTONMAIL" ]; then + + echo -e "\n${RED}$LINUX_CONFIG_PROTONMAIL still exists!${NC}" + FOLDER_EXISTS=true + + fi + + if [ -d "$LINUX_LOCAL_PROTONMAIL" ]; then + + echo -e "\n${RED}$LINUX_LOCAL_PROTONMAIL still exists!${NC}" + FOLDER_EXISTS=true + + fi + + if [ -f "$LINUX_STARTUP_ENTRY" ]; then + + echo -e "\n${RED}$LINUX_STARTUP_ENTRY still exists!${NC}" + FOLDER_EXISTS=true + + fi + + if [ "$FOLDER_EXISTS" = true ]; then + + echo -e "\n${RED}Some directories were not deleted properly!${NC}\n" + + else + + echo -e "\n${GREEN}All Bridge resource folders deleted!${NC}\n" + + fi + + else + + echo -e "${RED}Unknown operating system!{$NC}" + + fi + +} + + +execute_script() { + + echo -e "\n${GREEN}Quitting and uninstalling Bridge!${NC}\n" + quit_bridge + delete_credentials + uninstall_bridge + delete_resource_folders + check_resource_folders + +} + + +execute_script