mirror of
https://github.com/arkenfox/user.js.git
synced 2024-10-01 01:35:52 -04:00
d4907faa8e
when argument `-l` is used, parse profiles.ini instead of just listing folders in the default profiles dir. This allows to select profiles located outside of the default profiles directory and makes selection easier because it also shows the profile name (and selection is by number instead of having to copy-paste a path)
412 lines
13 KiB
Bash
Executable File
412 lines
13 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
## ghacks-user.js updater for macOS and Linux
|
|
|
|
## version: 2.1
|
|
## Author: Pat Johnson (@overdodactyl)
|
|
## Additional contributors: @earthlng, @ema-pe
|
|
|
|
## DON'T GO HIGHER THAN VERSION x.9 !! ( because of ASCII comparison in update_updater() )
|
|
|
|
readonly CURRDIR=$(pwd)
|
|
|
|
sfp=$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null)
|
|
if [ -z "$sfp" ]; then sfp=${BASH_SOURCE[0]}; fi
|
|
readonly SCRIPT_DIR=$(dirname "${sfp}")
|
|
|
|
|
|
#########################
|
|
# Base variables #
|
|
#########################
|
|
|
|
# Colors used for printing
|
|
RED='\033[0;31m'
|
|
BLUE='\033[0;34m'
|
|
BBLUE='\033[1;34m'
|
|
GREEN='\033[0;32m'
|
|
ORANGE='\033[0;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Argument defaults
|
|
UPDATE='check'
|
|
CONFIRM='yes'
|
|
OVERRIDE='user-overrides.js'
|
|
BACKUP='multiple'
|
|
COMPARE=false
|
|
SKIPOVERRIDE=false
|
|
VIEW=false
|
|
PROFILE_PATH=false
|
|
|
|
# Download method priority: curl -> wget
|
|
DOWNLOAD_METHOD=''
|
|
if [[ $(command -v 'curl') ]]; then
|
|
DOWNLOAD_METHOD='curl'
|
|
elif [[ $(command -v 'wget') ]]; then
|
|
DOWNLOAD_METHOD='wget'
|
|
else
|
|
echo -e "${RED}This script requires curl or wget.\nProcess aborted${NC}"
|
|
exit 0
|
|
fi
|
|
|
|
|
|
show_banner () {
|
|
echo -e "${BBLUE}\n"
|
|
echo ' ############################################################################'
|
|
echo ' #### ####'
|
|
echo ' #### ghacks user.js ####'
|
|
echo ' #### Hardening the Privacy and Security Settings of Firefox ####'
|
|
echo ' #### Maintained by @Thorin-Oakenpants and @earthlng ####'
|
|
echo ' #### Updater for macOS and Linux by @overdodactyl ####'
|
|
echo ' #### ####'
|
|
echo ' ############################################################################'
|
|
echo -e "${NC}\n"
|
|
echo -e "Documentation for this script is available here: ${CYAN}https://github.com/ghacksuserjs/ghacks-user.js/wiki/3.3-Updater-Scripts${NC}\n"
|
|
}
|
|
|
|
#########################
|
|
# Arguments #
|
|
#########################
|
|
|
|
usage() {
|
|
echo -e "${BLUE}\nUsage: $0 [-h] [-p PROFILE] [-u] [-d] [-s] [-n] [-b] [-c] [-v] [-r] [-o OVERRIDE]\n${NC}" 1>&2 # Echo usage string to standard error
|
|
echo 'Optional Arguments:'
|
|
echo -e "\t-h,\t\t Show this help message and exit."
|
|
echo -e "\t-p PROFILE,\t Path to your Firefox profile (if different than the dir of this script)"
|
|
echo -e "\t\t\t IMPORTANT: if the path include spaces, wrap the entire argument in quotes."
|
|
echo -e "\t-l, \t\t Choose your Firefox profile from a list"
|
|
echo -e "\t-u,\t\t Update updater.sh and execute silently. Do not seek confirmation."
|
|
echo -e "\t-d,\t\t Do not look for updates to updater.sh."
|
|
echo -e "\t-s,\t\t Silently update user.js. Do not seek confirmation."
|
|
echo -e "\t-b,\t\t Only keep one backup of each file."
|
|
echo -e "\t-c,\t\t Create a diff file comparing old and new user.js within userjs_diffs. "
|
|
echo -e "\t-o OVERRIDE,\t Filename or path to overrides file (if different than user-overrides.js)."
|
|
echo -e "\t\t\t If used with -p, paths should be relative to PROFILE or absolute paths"
|
|
echo -e "\t\t\t If given a directory, all files inside will be appended recursively."
|
|
echo -e "\t\t\t You can pass multiple files or directories by passing a comma separated list."
|
|
echo -e "\t\t\t\t Note: If a directory is given, only files inside ending in the extension .js are appended"
|
|
echo -e "\t\t\t\t IMPORTANT: do not add spaces between files/paths. Ex: -o file1.js,file2.js,dir1"
|
|
echo -e "\t\t\t\t IMPORTANT: if any files/paths include spaces, wrap the entire argument in quotes."
|
|
echo -e "\t\t\t\t\t Ex: -o \"override folder\" "
|
|
echo -e "\t-n,\t\t Do not append any overrides, even if user-overrides.js exists."
|
|
echo -e "\t-v,\t\t Open the resulting user.js file."
|
|
echo -e "\t-r,\t\t Only download user.js to a temporary file and open it."
|
|
echo -e
|
|
echo 'Deprecated Arguments (they still work for now):'
|
|
echo -e "\t-donotupdate,\t Use instead -d"
|
|
echo -e "\t-update,\t Use instead -u"
|
|
echo -e
|
|
exit 1
|
|
}
|
|
|
|
legacy_argument () {
|
|
echo -e "${ORANGE}\nWarning: command line arguments have changed."
|
|
echo -e "$1 has been deprecated and may not work in the future.\n"
|
|
echo -e "Please view the new options using the -h argument.${NC}"
|
|
}
|
|
|
|
#########################
|
|
# File Handling #
|
|
#########################
|
|
|
|
# Download files
|
|
download_file () {
|
|
declare -r url=$1
|
|
declare -r tf=$(mktemp)
|
|
local dlcmd=''
|
|
|
|
if [ $DOWNLOAD_METHOD = 'curl' ]; then
|
|
dlcmd="curl -o $tf"
|
|
else
|
|
dlcmd="wget -O $tf"
|
|
fi
|
|
|
|
$dlcmd "${url}" &>/dev/null && echo "$tf" || echo '' # return the temp-filename (or empty string on error)
|
|
}
|
|
|
|
open_file () { #expects one argument: file_path
|
|
if [ "$(uname)" == 'Darwin' ]; then
|
|
open "$1"
|
|
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
|
|
xdg-open "$1"
|
|
else
|
|
echo -e "${RED}Error: Sorry, opening files is not supported for your OS.${NC}"
|
|
fi
|
|
}
|
|
|
|
readIniFile () { # expects one argument: absolute path of profiles.ini
|
|
declare -r inifile="$1"
|
|
declare -r tfile=$(mktemp)
|
|
|
|
if [ $(grep '^\[Profile' "$inifile" | wc -l) == "1" ]; then ### only 1 profile found
|
|
grep '^\[Profile' -A 4 "$inifile" | grep -v '^\[Profile' > $tfile
|
|
else
|
|
grep -E -v '^\[General\]|^StartWithLastProfile=|^IsRelative=' "$inifile"
|
|
echo ''
|
|
read -p 'Select the profile number ( 0 for Profile0, 1 for Profile1, etc ) : ' -r
|
|
echo -e "\n"
|
|
if [[ $REPLY =~ ^(0|[1-9][0-9]*)$ ]]; then
|
|
grep '^\[Profile'${REPLY} -A 4 "$inifile" | grep -v '^\[Profile'${REPLY} > $tfile
|
|
if [ !$? ]; then
|
|
echo "Profile${REPLY} does not exist!" && exit 1
|
|
fi
|
|
else
|
|
echo "Invalid selection!" && exit 1
|
|
fi
|
|
fi
|
|
|
|
declare -r profpath=$(grep '^Path=' $tfile)
|
|
declare -r pathisrel=$(grep '^IsRelative=' $tfile)
|
|
|
|
rm "$tfile"
|
|
|
|
# update global variable
|
|
if [[ ${pathisrel#*=} == "1" ]]; then
|
|
PROFILE_PATH="$(dirname "$inifile")/${profpath#*=}"
|
|
else
|
|
PROFILE_PATH="${profpath#*=}"
|
|
fi
|
|
}
|
|
|
|
getProfilePath () {
|
|
declare -r f1=~/Library/Application\ Support/Firefox/profiles.ini
|
|
declare -r f2=~/.mozilla/firefox/profiles.ini
|
|
|
|
if [ "$PROFILE_PATH" = false ]; then
|
|
PROFILE_PATH="$SCRIPT_DIR"
|
|
elif [ "$PROFILE_PATH" = 'list' ]; then
|
|
local ini=''
|
|
if [[ -f "$f1" ]]; then
|
|
ini="$f1"
|
|
elif [[ -f "$f2" ]]; then
|
|
ini="$f2"
|
|
else
|
|
echo -e "${RED}Error: Sorry, -l is not supported for your OS${NC}"
|
|
exit 1
|
|
fi
|
|
readIniFile "$ini" # updates PROFILE_PATH or exits on error
|
|
#else
|
|
# PROFILE_PATH already set by user with -p
|
|
fi
|
|
}
|
|
|
|
#########################
|
|
# Update updater.sh #
|
|
#########################
|
|
|
|
# Returns the version number of a updater.sh file
|
|
get_updater_version () {
|
|
echo $(sed -n '5 s/.*[[:blank:]]\([[:digit:]]*\.[[:digit:]]*\)/\1/p' "$1")
|
|
}
|
|
|
|
# Update updater.sh
|
|
# Default: Check for update, if available, ask user if they want to execute it
|
|
# Args:
|
|
# -donotupdate: New version will not be looked for and update will not occur
|
|
# -update: Check for update, if available, execute without asking
|
|
update_updater () {
|
|
if [ $UPDATE = 'no' ]; then
|
|
return 0 # User signified not to check for updates
|
|
fi
|
|
|
|
declare -r tmpfile=$(download_file 'https://raw.githubusercontent.com/ghacksuserjs/ghacks-user.js/master/updater.sh')
|
|
|
|
if [[ $(get_updater_version "${SCRIPT_DIR}/updater.sh") < $(get_updater_version "${tmpfile}") ]]; then
|
|
if [ $UPDATE = 'check' ]; then
|
|
echo -e "There is a newer version of updater.sh available. ${RED}Update and execute Y/N?${NC}"
|
|
read -p "" -n 1 -r
|
|
echo -e "\n\n"
|
|
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
|
return 0 # Update available, but user chooses not to update
|
|
fi
|
|
fi
|
|
else
|
|
return 0 # No update available
|
|
fi
|
|
mv "${tmpfile}" "${SCRIPT_DIR}/updater.sh"
|
|
chmod u+x "${SCRIPT_DIR}/updater.sh"
|
|
"${SCRIPT_DIR}/updater.sh" "$@ -d"
|
|
exit 1
|
|
}
|
|
|
|
|
|
#########################
|
|
# Update user.js #
|
|
#########################
|
|
|
|
# Returns version number of a user.js file
|
|
get_userjs_version () {
|
|
echo "$(sed -n '4p' "$1")"
|
|
}
|
|
|
|
add_override () {
|
|
input=$1
|
|
if [ -f "$input" ]; then
|
|
echo "" >> user.js
|
|
cat "$input" >> user.js
|
|
echo -e "Status: ${GREEN}Override file appended:${NC} ${input}"
|
|
elif [ -d "$input" ]; then
|
|
FSAVEIFS=$IFS
|
|
IFS=$'\n\b' # Set IFS
|
|
FILES="${input}"/*.js
|
|
for f in $FILES
|
|
do
|
|
add_override "$f"
|
|
done
|
|
IFS=$SAVEIFS # restore $IFS
|
|
else
|
|
echo -e "${ORANGE}Warning: Could not find override file:${NC} ${input}"
|
|
fi
|
|
}
|
|
|
|
remove_comments () { # expects 2 arguments: from-file and to-file
|
|
sed -e 's/^[[:space:]]*\/\/.*$//' -e '/^\/\*/,/\*\//d' -e '/^[[:space:]]*$/d' -e 's/);[[:space:]]*\/\/.*/);/' "$1" > "$2"
|
|
}
|
|
|
|
# Applies latest version of user.js and any custom overrides
|
|
update_userjs () {
|
|
declare -r newfile=$(download_file 'https://raw.githubusercontent.com/ghacksuserjs/ghacks-user.js/master/user.js')
|
|
|
|
echo 'Please observe the following information:'
|
|
echo -e "\tFirefox profile: ${ORANGE}$(pwd)${NC}"
|
|
echo -e "\tAvailable online: ${ORANGE}$(get_userjs_version $newfile)${NC}"
|
|
echo -e "\tCurrently using: ${ORANGE}$(get_userjs_version user.js)\n${NC}\n"
|
|
|
|
if [ $CONFIRM = 'yes' ]; then
|
|
echo -e "This script will update to the latest user.js file and append any custom configurations from user-overrides.js. ${RED}Continue Y/N? ${NC}"
|
|
read -p "" -n 1 -r
|
|
echo -e "\n"
|
|
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
|
echo -e "${RED}Process aborted${NC}"
|
|
rm $newfile
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# Copy a version of user.js to diffs folder for later comparison
|
|
if [ "$COMPARE" = true ]; then
|
|
mkdir -p userjs_diffs
|
|
cp user.js userjs_diffs/past_user.js
|
|
fi
|
|
|
|
# backup user.js
|
|
mkdir -p userjs_backups
|
|
local bakname="userjs_backups/user.js.backup.$(date +"%Y-%m-%d_%H%M")"
|
|
if [ $BACKUP = 'single' ]; then
|
|
bakname='userjs_backups/user.js.backup'
|
|
fi
|
|
cp user.js "$bakname"
|
|
|
|
mv "${newfile}" user.js
|
|
echo -e "Status: ${GREEN}user.js has been backed up and replaced with the latest version!${NC}"
|
|
|
|
# apply overrides
|
|
if [ "$SKIPOVERRIDE" = false ]; then
|
|
while IFS=',' read -ra FILE; do
|
|
add_override "$FILE"
|
|
done <<< "$OVERRIDE"
|
|
fi
|
|
|
|
# create diff
|
|
if [ "$COMPARE" = true ]; then
|
|
pastuserjs='userjs_diffs/past_user.js'
|
|
past_nocomments='userjs_diffs/past_userjs.txt'
|
|
current_nocomments='userjs_diffs/current_userjs.txt'
|
|
|
|
remove_comments $pastuserjs $past_nocomments
|
|
remove_comments user.js $current_nocomments
|
|
|
|
diffname="userjs_diffs/diff_$(date +"%Y-%m-%d_%H%M").txt"
|
|
diff=$(diff -w -B -U 0 $past_nocomments $current_nocomments)
|
|
if [ ! -z "$diff" ]; then
|
|
echo "$diff" > "$diffname"
|
|
echo -e "Status: ${GREEN}A diff file was created:${NC} ${PWD}/${diffname}"
|
|
else
|
|
echo -e "Warning: ${ORANGE}Your new user.js file appears to be identical. No diff file was created.${NC}"
|
|
fi
|
|
|
|
rm $past_nocomments $current_nocomments $pastuserjs
|
|
fi
|
|
|
|
if [ "$VIEW" = true ]; then open_file "${PWD}/user.js"; fi
|
|
}
|
|
|
|
#########################
|
|
# Execute #
|
|
#########################
|
|
|
|
if [ $# != 0 ]; then
|
|
readonly legacy_lc=$(echo $1 | tr '[A-Z]' '[a-z]')
|
|
# Display usage if first argument is -help or --help
|
|
if [ $1 = '--help' ] || [ $1 = '-help' ]; then
|
|
usage
|
|
elif [ $legacy_lc = '-donotupdate' ]; then
|
|
UPDATE='no'
|
|
legacy_argument $1
|
|
elif [ $legacy_lc = '-update' ]; then
|
|
UPDATE='yes'
|
|
legacy_argument $1
|
|
else
|
|
while getopts ":hp:ludsno:bcvr" opt; do
|
|
case $opt in
|
|
h)
|
|
usage
|
|
;;
|
|
p)
|
|
PROFILE_PATH=${OPTARG}
|
|
;;
|
|
l)
|
|
PROFILE_PATH='list'
|
|
;;
|
|
u)
|
|
UPDATE='yes'
|
|
;;
|
|
d)
|
|
UPDATE='no'
|
|
;;
|
|
s)
|
|
CONFIRM='no'
|
|
;;
|
|
n)
|
|
SKIPOVERRIDE=true
|
|
;;
|
|
o)
|
|
OVERRIDE=${OPTARG}
|
|
;;
|
|
b)
|
|
BACKUP='single'
|
|
;;
|
|
c)
|
|
COMPARE=true
|
|
;;
|
|
v)
|
|
VIEW=true
|
|
;;
|
|
r)
|
|
tfile=$(download_file 'https://raw.githubusercontent.com/ghacksuserjs/ghacks-user.js/master/user.js')
|
|
mv $tfile "${tfile}.js"
|
|
echo -e "${ORANGE}Warning: user.js was saved to temporary file ${tfile}.js${NC}"
|
|
open_file "${tfile}.js"
|
|
exit 1
|
|
;;
|
|
\?)
|
|
echo -e "${RED}\n Error! Invalid option: -$OPTARG${NC}" >&2
|
|
usage
|
|
;;
|
|
:)
|
|
echo -e "${RED}Error! Option -$OPTARG requires an argument.${NC}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
fi
|
|
|
|
show_banner
|
|
update_updater
|
|
|
|
getProfilePath # updates PROFILE_PATH or exits on error
|
|
cd "$PROFILE_PATH" && update_userjs
|
|
|
|
cd "$CURRDIR"
|