Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
updater.sh - POSIX
#!/usr/bin/env sh
## ghacks-user.js updater for macOS and Linux
## version: 2.5.1
## Author: Pat Johnson (@overdodactyl)
## Additional contributors: @earthlng, @ema-pe, @claustromaniac, @iamtpage
## DON'T GO HIGHER THAN VERSION x.9 !! ( because of ASCII comparison in update_updater() )
set -e
readonly CURRDIR=$(pwd)
sfp=$(readlink -f "$0" 2>/dev/null || readlink -f "$0" 2>/dev/null)
if [ -z "$sfp" ]; then sfp="$0"; fi
readonly SCRIPT_DIR=$(dirname "${sfp}")
#########################
# Base variables #
#########################
# Argument defaults
UPDATE="check"
CONFIRM="yes"
OVERRIDE="user-overrides.js"
BACKUP="multiple"
COMPARE=false
SKIPOVERRIDE=false
VIEW=false
PROFILE_PATH=false
ESR=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 "This script requires curl or wget."
printf "\n"
echo "Process aborted"
exit 0
fi
show_banner () {
printf "\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 " ############################################################################"
printf "\n"
echo "Documentation for this script is available here: ${CYAN}https://github.com/ghacksuserjs/ghacks-user.js/wiki/3.3-Updater-Scripts"
printf "\n"
}
#########################
# Arguments #
#########################
usage() {
printf "\n"
echo "Usage: $0 [-h] [-p PROFILE] [-u] [-d] [-s] [-n] [-b] [-c] [-v] [-r] [-e] [-o OVERRIDE]" 1>&2 # Echo usage string to standard error
print "\n"
echo "Optional Arguments:"
printf "\t-h,\t\t Show this help message and exit."
printf "\t-p PROFILE,\t Path to your Firefox profile (if different than the dir of this script)"
printf "\t\t\t IMPORTANT: if the path include spaces, wrap the entire argument in quotes."
printf "\t-l, \t\t Choose your Firefox profile from a list"
printf "\t-u,\t\t Update updater.sh and execute silently. Do not seek confirmation."
printf "\t-d,\t\t Do not look for updates to updater.sh."
printf "\t-s,\t\t Silently update user.js. Do not seek confirmation."
printf "\t-b,\t\t Only keep one backup of each file."
printf "\t-c,\t\t Create a diff file comparing old and new user.js within userjs_diffs. "
printf "\t-o OVERRIDE,\t Filename or path to overrides file (if different than user-overrides.js)."
printf "\t\t\t If used with -p, paths should be relative to PROFILE or absolute paths"
printf "\t\t\t If given a directory, all files inside will be appended recursively."
printf "\t\t\t You can pass multiple files or directories by passing a comma separated list."
printf "\t\t\t\t Note: If a directory is given, only files inside ending in the extension .js are appended"
printf "\t\t\t\t IMPORTANT: do not add spaces between files/paths. Ex: -o file1.js,file2.js,dir1"
printf "\t\t\t\t IMPORTANT: if any files/paths include spaces, wrap the entire argument in quotes."
printf "\t\t\t\t\t Ex: -o \"override folder\" "
printf "\t-n,\t\t Do not append any overrides, even if user-overrides.js exists."
printf "\t-v,\t\t Open the resulting user.js file."
printf "\t-r,\t\t Only download user.js to a temporary file and open it."
printf "\t-e,\t\t Activate ESR related preferences."
printf "\n"
echo "Deprecated Arguments (they still work for now):"
printf "\t-donotupdate,\t Use instead -d"
printf "\t-update,\t Use instead -u"
printf "\n"
exit 1
}
legacy_argument () {
printf "\nWarning: command line arguments have changed."
echo "$1 has been deprecated and may not work in the future."
printf "\n"
echo "Please view the new options using the -h argument."
}
#########################
# File Handling #
#########################
# Download files
download_file () {
URL="$1"
TF="$(mktemp)"
export URL
export TF
DLCMD=""
if [ $DOWNLOAD_METHOD = "curl" ]; then
DLCMD="curl -o $TF $URL"
else
DLCMD="wget -O $TF $URL"
fi
export DLCMD
$DLCMD > /dev/null 2>&1 && echo "$TF" || echo "" # return the temp-filename (or empty string on error)
}
open_file () { #expects one argument: file_path
KERNEL="$(uname -s)"
if [ "$(uname)" = "Darwin" ]; then
open "$1"
elif echo "$KERNEL" | grep -q -E -o "^Linux"; then
xdg-open "$1"
else
echo "Error: Sorry, opening files is not supported for your OS."
fi
}
readIniFile () { # expects one argument: absolute path of profiles.ini
inifile="$1"
tfile="$(mktemp)"
if [ "$(grep -c "^\[Profile" "$inifile")" = "1" ]; then ### only 1 profile found
grep "^\[Profile" -A 4 "$inifile" | grep -v "^\[Profile" > "$tfile"
else
grep -E -v "^\[General\]|^StartWithLastProfile=|^IsRelative=" "$inifile"
echo ""
echo "Select the profile number ( 0 for Profile0, 1 for Profile1, etc ) : "
read -r REPLY
echo ""
if echo "$REPLY" | grep -q -E "^(0|[1-9][0-9]*)$"; then
if grep "^\[Profile'${REPLY}" -A 4 "$inifile" | grep -v "^\[Profile'${REPLY}" > "$tfile"; then
echo "Profile${REPLY} does not exist!" && exit 1
fi
else
echo "Invalid selection!" && exit 1
fi
fi
profpath="$(grep "^Path=" "$tfile")"
pathisrel="$(grep "^IsRelative=" "$tfile")"
rm "$tfile"
# update global variable
if [ "${pathisrel#*=}" = "1" ]; then
PROFILE_PATH="$(dirname "$inifile")/${profpath#*=}"
else
PROFILE_PATH="${profpath#*=}"
fi
}
getProfilePath () {
f1="$HOME/Library/Application\ Support/Firefox/profiles.ini"
f2="$HOME/.mozilla/firefox/profiles.ini"
if [ "$PROFILE_PATH" = false ]; then
PROFILE_PATH="$SCRIPT_DIR"
elif [ "$PROFILE_PATH" = "list" ]; then
ini=""
if [ -f "$f1" ]; then
ini="$f1"
elif [ -f "$f2" ]; then
ini="$f2"
else
echo "Error: Sorry, -l is not supported for your OS"
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 () {
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
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 "There is a different version of updater.sh available. Update and execute Y/N?"
read -r REPLY
printf "\n\n"
if echo "$REPLY" | grep -q -E "^[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 () {
if [ -e "$1" ]; then
sed -n "4p" "$1"
else
echo "Not detected."
fi
}
add_override () {
input="$1"
if [ -f "$input" ]; then
printf "\n" >> user.js
cat "$input" >> user.js
echo "Status: Override file appended: ${input}"
elif [ -d "$input" ]; then
FSAVEIFS=$IFS
IFS="$(printf '\n\b')" # Set IFS
FILES="( ${input}/*.js )"
for f in $FILES
do
add_override "$f"
done
IFS=$FSAVEIFS # restore $IFS
else
echo "Warning: Could not find override file: ${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 () {
NEWFILE="$(download_file "https://raw.githubusercontent.com/ghacksuserjs/ghacks-user.js/master/user.js")"
export NEWFILE
echo "Please observe the following information:"
printf "\tFirefox profile: %s\n" "$(pwd)"
printf "\tAvailable online: %s\n" "$(get_userjs_version "$NEWFILE")"
printf "\tCurrently using: %s\n\n" "$(get_userjs_version user.js)"
if [ "$CONFIRM" = "yes" ]; then
echo "This script will update to the latest user.js file and append any custom configurations from user-overrides.js. Continue Y/N? "
read -r REPLY
printf "\n"
if echo "$REPLY" | grep -q -E "^[Nn]$"; then
echo "Process aborted"
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 > /dev/null 2>&1
fi
# backup user.js
mkdir -p userjs_backups
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" > /dev/null 2>&1
mv "$NEWFILE" user.js
echo "Status: user.js has been backed up and replaced with the latest version!"
if [ "$ESR" = true ]; then
sed -e 's/\/\* \(ESR[0-9]\{2,\}\.x still uses all.*\)/\/\/ \1/' user.js > user.js.tmp && mv user.js.tmp user.js
echo "Status: ESR related preferences have been activated!"
fi
# apply overrides
if [ "$SKIPOVERRIDE" = false ]; then
for FILE in $(echo $OVERRIDE | tr "," "\n")
do
add_override "$FILE"
done
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 "Status: A diff file was created: ${PWD}/${diffname}"
else
echo "Warning: Your new user.js file appears to be identical. No diff file was created."
if [ "$BACKUP" = "multiple" ]; then
rm "$bakname" > /dev/null 2>&1
fi
fi
rm "$past_nocomments" "$current_nocomments" "$pastuserjs" > /dev/null 2>&1
fi
if [ "$VIEW" = true ]; then open_file "${PWD}/user.js"; fi
}
#########################
# Execute #
#########################
if [ $# != 0 ]; then
readonly legacy_lc="$(echo "$1" | tr "[:upper:]" "[:lower:]")"
# 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:bcvre" 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
;;
e)
ESR=true
;;
r)
tfile=$(download_file "https://raw.githubusercontent.com/ghacksuserjs/ghacks-user.js/master/user.js")
mv "$tfile" "${tfile}.js"
echo "Warning: user.js was saved to temporary file ${tfile}.js"
open_file "${tfile}.js"
exit 1
;;
\?)
echo "Error! Invalid option: -$OPTARG" >&2
usage
;;
:)
echo "Error! Option -$OPTARG requires an argument." >&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"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.