Browse Source

updater.sh v2.0 (#543)

* lots of new arguments

`usage: ./updater.sh [-h] [-p PROFILE] [-u] [-d] [-s] [-n] [-b] [-c] [-v] [-r] [-o OVERRIDE]`

Args can be written separately or together. Examples:

```txt
./updater.sh -sdc
./updater.sh -sd -o relaxed.js
./updater.sh -s -d
```

Deprecated arguments still work (for now!)
Pat Johnson 6 years ago
parent
commit
62351bfbf5
1 changed files with 293 additions and 102 deletions
  1. 293 102
      updater.sh

+ 293 - 102
updater.sh

@@ -2,104 +2,169 @@
 
 ## ghacks-user.js updater for macOS and Linux
 
-## version: 1.5
+## version: 2.0
 ## Author: Pat Johnson (@overdodactyl)
 ## Additional contributors: @earthlng, @ema-pe
 
-## DON'T GO HIGHER THAN VERSION x.9 !! ( because of ASCII comparison in check_for_update() )
+## 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     #
 #########################
-update_pref=${1:--ask}
+
+# Colors used for printing
 RED='\033[0;31m'
 BLUE='\033[0;34m'
-BBLUE='\033[1;34m' 
+BBLUE='\033[1;34m'
 GREEN='\033[0;32m'
 ORANGE='\033[0;33m'
-CYAN='\033[0;36m'  
+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
 
 #########################
 #   Working directory   #
 #########################
 
-# get current directory
-currdir=$(pwd)
-## get the full path of this script (readlink for Linux, greadlink for Mac with coreutils installed)
-sfp=$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null)
-## fallback for Macs without coreutils
-if [ -z "$sfp" ]; then sfp=${BASH_SOURCE[0]}; fi
-## store the Firefox profile directory
-ff_profile="$(dirname "${sfp}")"
+set_wd () {
+  declare -r macdir=~/Library/Application\ Support/Firefox/Profiles/
+  declare -r nixdir=~/.mozilla/firefox/
+  local ff_profile
+  if [ "$PROFILE_PATH" = false ]; then
+    ff_profile="$SCRIPT_DIR"
+  elif [ "$PROFILE_PATH" = "list" ]; then
+    local firefox_dir=""
+    if [ -d "$macdir" ]; then
+      firefox_dir=$macdir
+    elif [ -d $nixdir ]; then
+      firefox_dir=$nixdir
+    else
+      echo -e ${RED}"Error: Sorry, -l is not supported for your OS"${NC}
+      exit 1
+    fi
+    if [ $(find "$firefox_dir" -maxdepth 1 -type d | wc -l) == "2" ]; then
+      ff_profile=$(ls -d "$firefox_dir"*)
+    else 
+      echo -e ${GREEN}"The following profiles were found:\n"${ORANGE}
+      ls -d "$firefox_dir"*
+      echo -e ${RED}"\nWhich profile would you like to update?"${NC}
+      read -p ""
+      echo -e ""
+      ff_profile=$REPLY
+    fi
+  else
+    ff_profile="$PROFILE_PATH"
+  fi
+  cd "$ff_profile"
+}
+
+#########################
+#      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 -e "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 -e "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 Handeling    #
+#     File Handling     #
 #########################
 
-# Download method priority: curl -> wget -> pearl
-DOWNLOAD_METHOD="not_pearl"
-if [[ $(command -v "curl") ]] > /dev/null 2>&1; then
-  DOWNLOAD_TO_FILE="curl -O"  
-elif [[ $(command -v "wget") ]] > /dev/null 2>&1; then
-  DOWNLOAD_TO_FILE="wget"
-elif [[ $(command -v "perl") ]]; then
-  DOWNLOAD_METHOD="perl"
+# 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, wget or perl to be installed.\nProcess aborted"${NC}
+  echo -e ${RED}"This script requires curl or wget.\nProcess aborted"${NC}
   exit 0
 fi
 
 # Download files
 download_file () {
-  mkdir -p userjs_temps
-  cd userjs_temps
-  url=$1
+  declare -r url=$1
+  declare -r tf=$(mktemp)
+  local dlcmd=""
 
-  if [ $DOWNLOAD_METHOD = "not_pearl" ]; then
-    $DOWNLOAD_TO_FILE ${url}
+  if [ $DOWNLOAD_METHOD = "curl" ]; then
+    dlcmd="curl -o $tf"
   else
-    http_url=${url/https/http}
-    # Variables from the shell are available in Perl's %ENV hash
-    # Need to export shell variable so it is visible to subprocesses
-    export http_url
-
-    perl -e '
-            use File::Fetch;
-            my $ff = File::Fetch->new(uri => $ENV{http_url});
-            my $where = $ff->fetch() or die $ff->error;
-            my $where = $ff->fetch( to => "." );
-            '
+    dlcmd="wget -O $tf" 
   fi
 
-  cd ..
+  $dlcmd "${url}" &>/dev/null && echo "$tf" || echo "" # return the temp-filename (or empty string on error)
 }
 
-# Backup a file into userjs_backups
-# Replace current version of a file with new one in userjs_temps
-backup_file () {
-  filename=$1
-  mkdir -p userjs_backups
-  mv $filename "userjs_backups/${filename}.backup.$(date +"%Y-%m-%d_%H%M")"
-  mv "userjs_temps/${filename}" $filename
-  echo -e "Status: ${GREEN}${filename} has been backed up and replaced with the latest version!${NC}"
+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
 }
 
-#########################
-#      Initiation       #
-#########################
 
-initiate () {
+show_banner () {
   echo -e
   echo -e
   echo -e        ${BBLUE}"  ############################################################################"
   echo -e                "  ####                                                                    ####"
-  echo -e 				 "  ####                           ghacks user.js                           ####"
+  echo -e                "  ####                           ghacks user.js                           ####"
   echo -e                "  ####       Hardening the Privacy and Security Settings of Firefox       ####"
-  echo -e                "  ####           Maintained by @Thorin-Oakenpants and @earthlng           ####"                            ####"
-  echo -e                "  ####            Updater for macOS and Linux by @overdodactyl            ####"            									 ####"
+  echo -e                "  ####           Maintained by @Thorin-Oakenpants and @earthlng           ####"
+  echo -e                "  ####            Updater for macOS and Linux by @overdodactyl            ####"
   echo -e                "  ####                                                                    ####"
   echo -e                "  ############################################################################"${NC}
   echo -e
@@ -107,23 +172,6 @@ initiate () {
   echo -e "Documentation for this script is available here: ${CYAN}https://github.com/ghacksuserjs/ghacks-user.js/wiki/3.3-Updater-Scripts${NC}\n"
 }
 
-confirmation () {
-  download_file "https://raw.githubusercontent.com/ghacksuserjs/ghacks-user.js/master/user.js" &>/dev/null
-  echo -e "Please observe the following information:"
-  echo -e "\tFirefox profile:  ${ORANGE}$(pwd)${NC}"
-  echo -e "\tAvailable online: ${ORANGE}$(get_userjs_version userjs_temps/user.js)${NC}"
-  echo -e "\tCurrently using:  ${ORANGE}$(get_userjs_version user.js)\n${NC}\n"
-
-  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}
-    return 1
-  fi
-}
-
 
 #########################
 #   Update updater.sh   #
@@ -131,9 +179,7 @@ confirmation () {
 
 # Returns the version number of a updater.sh file
 get_updater_version () {
-  filename=$1
-  version_regex='5 s/.*[[:blank:]]\([[:digit:]]*\.[[:digit:]]*\)/\1/p'
-  echo "$(sed -n "$version_regex" "${ff_profile}/${filename}")"
+  echo $(sed -n '5 s/.*[[:blank:]]\([[:digit:]]*\.[[:digit:]]*\)/\1/p' "$1")
 }
 
 # Update updater.sh
@@ -142,32 +188,27 @@ get_updater_version () {
 #   -donotupdate: New version will not be looked for and update will not occur
 #   -update: Check for update, if available, execute without asking
 update_updater () {
-  update_pref="$(echo $update_pref | tr '[A-Z]' '[a-z]')"
-  if [ $update_pref = "-donotupdate" ]; then
-    # User signified not to check for updates
-    return 0
+  if [ $UPDATE = "no" ]; then
+    return 0 # User signified not to check for updates
   fi
 
-  download_file "https://raw.githubusercontent.com/ghacksuserjs/ghacks-user.js/master/updater.sh" &>/dev/null
+  declare -r tmpfile=$(download_file 'https://raw.githubusercontent.com/ghacksuserjs/ghacks-user.js/master/updater.sh')
 
-  if [[ $(get_updater_version updater.sh) < $(get_updater_version userjs_temps/updater.sh) ]]; then
-    if [ $update_pref != "-update" ]; then
-      echo -e "There is a newer version of updater.sh available. ${RED}Download and execute Y/N?${NC}"
+  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
-        # Update available, but user chooses not to update
-        return 0
+        return 0 # Update available, but user chooses not to update
       fi
     fi
   else
-    # No update available
-    return 0
+    return 0 # No update available
   fi
-  # Backup current updater, execute latest version
-  backup_file updater.sh
-  chmod +x updater.sh
-  ./updater.sh -donotupdate
+  mv "${tmpfile}" "${SCRIPT_DIR}/updater.sh"
+  chmod u+x "${SCRIPT_DIR}/updater.sh"
+  "${SCRIPT_DIR}/updater.sh" "$@ -d"
   exit 1
 }
 
@@ -178,28 +219,178 @@ update_updater () {
 
 # Returns version number of a user.js file
 get_userjs_version () {
-  filename=$1
-  echo "$(sed -n "4p" "${ff_profile}/${filename}")"
+  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 () {
-  backup_file user.js
-  if [ -e user-overrides.js ]; then
-    cat user-overrides.js >> user.js
-    echo -e "Status: ${GREEN}Your user-overrides.js customizations have been applied!${NC}"
+  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        #
 #########################
 
-## change directory to the Firefox profile directory
-cd "$ff_profile"
+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
 
-initiate
+show_banner
 update_updater
-confirmation && update_userjs
-rm -rf userjs_temps
+set_wd		# changes directory to the Firefox profile (or script-dir)
+update_userjs
+
 cd "${currdir}"