updater.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. #!/usr/bin/env bash
  2. ## ghacks-user.js updater for macOS and Linux
  3. ## version: 2.0
  4. ## Author: Pat Johnson (@overdodactyl)
  5. ## Additional contributors: @earthlng, @ema-pe
  6. ## DON'T GO HIGHER THAN VERSION x.9 !! ( because of ASCII comparison in update_updater() )
  7. readonly currdir=$(pwd)
  8. sfp=$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null || greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null)
  9. if [ -z "$sfp" ]; then sfp=${BASH_SOURCE[0]}; fi
  10. readonly SCRIPT_DIR=$(dirname "${sfp}")
  11. #########################
  12. # Base variables #
  13. #########################
  14. # Colors used for printing
  15. RED='\033[0;31m'
  16. BLUE='\033[0;34m'
  17. BBLUE='\033[1;34m'
  18. GREEN='\033[0;32m'
  19. ORANGE='\033[0;33m'
  20. CYAN='\033[0;36m'
  21. NC='\033[0m' # No Color
  22. # Argument defaults
  23. UPDATE="check"
  24. CONFIRM="yes"
  25. OVERRIDE="user-overrides.js"
  26. BACKUP="multiple"
  27. COMPARE=false
  28. SKIPOVERRIDE=false
  29. VIEW=false
  30. PROFILE_PATH=false
  31. #########################
  32. # Working directory #
  33. #########################
  34. set_wd () {
  35. declare -r macdir=~/Library/Application\ Support/Firefox/Profiles/
  36. declare -r nixdir=~/.mozilla/firefox/
  37. local ff_profile
  38. if [ "$PROFILE_PATH" = false ]; then
  39. ff_profile="$SCRIPT_DIR"
  40. elif [ "$PROFILE_PATH" = "list" ]; then
  41. local firefox_dir=""
  42. if [ -d "$macdir" ]; then
  43. firefox_dir=$macdir
  44. elif [ -d $nixdir ]; then
  45. firefox_dir=$nixdir
  46. else
  47. echo -e ${RED}"Error: Sorry, -l is not supported for your OS"${NC}
  48. exit 1
  49. fi
  50. if [ $(find "$firefox_dir" -maxdepth 1 -type d | wc -l) == "2" ]; then
  51. ff_profile=$(ls -d "$firefox_dir"*)
  52. else
  53. echo -e ${GREEN}"The following profiles were found:\n"${ORANGE}
  54. ls -d "$firefox_dir"*
  55. echo -e ${RED}"\nWhich profile would you like to update?"${NC}
  56. read -p ""
  57. echo -e ""
  58. ff_profile=$REPLY
  59. fi
  60. else
  61. ff_profile="$PROFILE_PATH"
  62. fi
  63. cd "$ff_profile"
  64. }
  65. #########################
  66. # Arguments #
  67. #########################
  68. usage() {
  69. 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
  70. echo -e "Optional Arguments:"
  71. echo -e "\t-h,\t\t Show this help message and exit."
  72. echo -e "\t-p PROFILE,\t Path to your Firefox profile (if different than the dir of this script)"
  73. echo -e "\t\t\t IMPORTANT: if the path include spaces, wrap the entire argument in quotes."
  74. echo -e "\t-l, \t\t Choose your Firefox profile from a list"
  75. echo -e "\t-u,\t\t Update updater.sh and execute silently. Do not seek confirmation."
  76. echo -e "\t-d,\t\t Do not look for updates to updater.sh."
  77. echo -e "\t-s,\t\t Silently update user.js. Do not seek confirmation."
  78. echo -e "\t-b,\t\t Only keep one backup of each file."
  79. echo -e "\t-c,\t\t Create a diff file comparing old and new user.js within userjs_diffs. "
  80. echo -e "\t-o OVERRIDE,\t Filename or path to overrides file (if different than user-overrides.js)."
  81. echo -e "\t\t\t If used with -p, paths should be relative to PROFILE or absolute paths"
  82. echo -e "\t\t\t If given a directory, all files inside will be appended recursively."
  83. echo -e "\t\t\t You can pass multiple files or directories by passing a comma separated list."
  84. echo -e "\t\t\t\t Note: If a directory is given, only files inside ending in the extension .js are appended"
  85. echo -e "\t\t\t\t IMPORTANT: do not add spaces between files/paths. Ex: -o file1.js,file2.js,dir1"
  86. echo -e "\t\t\t\t IMPORTANT: if any files/paths include spaces, wrap the entire argument in quotes."
  87. echo -e "\t\t\t\t\t Ex: -o \"override folder\" "
  88. echo -e "\t-n,\t\t Do not append any overrides, even if user-overrides.js exists."
  89. echo -e "\t-v,\t\t Open the resulting user.js file."
  90. echo -e "\t-r,\t\t Only download user.js to a temporary file and open it."
  91. echo -e
  92. echo -e "Deprecated Arguments (they still work for now):"
  93. echo -e "\t-donotupdate,\t Use instead -d"
  94. echo -e "\t-update,\t Use instead -u"
  95. echo -e
  96. exit 1
  97. }
  98. legacy_argument () {
  99. echo -e ${ORANGE}"\nWarning: command line arguments have changed."
  100. echo -e "$1 has been deprecated and may not work in the future.\n"
  101. echo -e "Please view the new options using the -h argument."${NC}
  102. }
  103. #########################
  104. # File Handling #
  105. #########################
  106. # Download method priority: curl -> wget
  107. DOWNLOAD_METHOD=""
  108. if [[ $(command -v "curl") ]]; then
  109. DOWNLOAD_METHOD="curl"
  110. elif [[ $(command -v "wget") ]]; then
  111. DOWNLOAD_METHOD="wget"
  112. else
  113. echo -e ${RED}"This script requires curl or wget.\nProcess aborted"${NC}
  114. exit 0
  115. fi
  116. # Download files
  117. download_file () {
  118. declare -r url=$1
  119. declare -r tf=$(mktemp)
  120. local dlcmd=""
  121. if [ $DOWNLOAD_METHOD = "curl" ]; then
  122. dlcmd="curl -o $tf"
  123. else
  124. dlcmd="wget -O $tf"
  125. fi
  126. $dlcmd "${url}" &>/dev/null && echo "$tf" || echo "" # return the temp-filename (or empty string on error)
  127. }
  128. open_file () { #expects one argument: file_path
  129. if [ "$(uname)" == "Darwin" ]; then
  130. open "$1"
  131. elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
  132. xdg-open "$1"
  133. else
  134. echo -e ${RED}"Error: Sorry, opening files is not supported for your OS."${NC}
  135. fi
  136. }
  137. show_banner () {
  138. echo -e
  139. echo -e
  140. echo -e ${BBLUE}" ############################################################################"
  141. echo -e " #### ####"
  142. echo -e " #### ghacks user.js ####"
  143. echo -e " #### Hardening the Privacy and Security Settings of Firefox ####"
  144. echo -e " #### Maintained by @Thorin-Oakenpants and @earthlng ####"
  145. echo -e " #### Updater for macOS and Linux by @overdodactyl ####"
  146. echo -e " #### ####"
  147. echo -e " ############################################################################"${NC}
  148. echo -e
  149. echo -e
  150. echo -e "Documentation for this script is available here: ${CYAN}https://github.com/ghacksuserjs/ghacks-user.js/wiki/3.3-Updater-Scripts${NC}\n"
  151. }
  152. #########################
  153. # Update updater.sh #
  154. #########################
  155. # Returns the version number of a updater.sh file
  156. get_updater_version () {
  157. echo $(sed -n '5 s/.*[[:blank:]]\([[:digit:]]*\.[[:digit:]]*\)/\1/p' "$1")
  158. }
  159. # Update updater.sh
  160. # Default: Check for update, if available, ask user if they want to execute it
  161. # Args:
  162. # -donotupdate: New version will not be looked for and update will not occur
  163. # -update: Check for update, if available, execute without asking
  164. update_updater () {
  165. if [ $UPDATE = "no" ]; then
  166. return 0 # User signified not to check for updates
  167. fi
  168. declare -r tmpfile=$(download_file 'https://raw.githubusercontent.com/ghacksuserjs/ghacks-user.js/master/updater.sh')
  169. if [[ $(get_updater_version "${SCRIPT_DIR}/updater.sh") < $(get_updater_version "${tmpfile}") ]]; then
  170. if [ $UPDATE = "check" ]; then
  171. echo -e "There is a newer version of updater.sh available. ${RED}Update and execute Y/N?${NC}"
  172. read -p "" -n 1 -r
  173. echo -e "\n\n"
  174. if [[ $REPLY =~ ^[Nn]$ ]]; then
  175. return 0 # Update available, but user chooses not to update
  176. fi
  177. fi
  178. else
  179. return 0 # No update available
  180. fi
  181. mv "${tmpfile}" "${SCRIPT_DIR}/updater.sh"
  182. chmod u+x "${SCRIPT_DIR}/updater.sh"
  183. "${SCRIPT_DIR}/updater.sh" "$@ -d"
  184. exit 1
  185. }
  186. #########################
  187. # Update user.js #
  188. #########################
  189. # Returns version number of a user.js file
  190. get_userjs_version () {
  191. echo "$(sed -n '4p' "$1")"
  192. }
  193. add_override () {
  194. input=$1
  195. if [ -f "$input" ]; then
  196. echo "" >> user.js
  197. cat "$input" >> user.js
  198. echo -e "Status: ${GREEN}Override file appended:${NC} ${input}"
  199. elif [ -d "$input" ]; then
  200. FSAVEIFS=$IFS
  201. IFS=$'\n\b' # Set IFS
  202. FILES="${input}"/*.js
  203. for f in $FILES
  204. do
  205. add_override "$f"
  206. done
  207. IFS=$SAVEIFS # restore $IFS
  208. else
  209. echo -e "${ORANGE}Warning: Could not find override file:${NC} ${input}"
  210. fi
  211. }
  212. remove_comments () { # expects 2 arguments: from-file and to-file
  213. sed -e 's/^[[:space:]]*\/\/.*$//' -e '/^\/\*/,/\*\//d' -e '/^[[:space:]]*$/d' -e 's/);[[:space:]]*\/\/.*/);/' "$1" > "$2"
  214. }
  215. # Applies latest version of user.js and any custom overrides
  216. update_userjs () {
  217. declare -r newfile=$(download_file 'https://raw.githubusercontent.com/ghacksuserjs/ghacks-user.js/master/user.js')
  218. echo 'Please observe the following information:'
  219. echo -e "\tFirefox profile: ${ORANGE}$(pwd)${NC}"
  220. echo -e "\tAvailable online: ${ORANGE}$(get_userjs_version $newfile)${NC}"
  221. echo -e "\tCurrently using: ${ORANGE}$(get_userjs_version user.js)\n${NC}\n"
  222. if [ $CONFIRM = "yes" ]; then
  223. 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}"
  224. read -p "" -n 1 -r
  225. echo -e "\n"
  226. if [[ $REPLY =~ ^[Nn]$ ]]; then
  227. echo -e ${RED}"Process aborted"${NC}
  228. rm $newfile
  229. return 1
  230. fi
  231. fi
  232. # Copy a version of user.js to diffs folder for later comparison
  233. if [ "$COMPARE" = true ]; then
  234. mkdir -p userjs_diffs
  235. cp user.js userjs_diffs/past_user.js
  236. fi
  237. # backup user.js
  238. mkdir -p userjs_backups
  239. local bakname="userjs_backups/user.js.backup.$(date +"%Y-%m-%d_%H%M")"
  240. if [ $BACKUP = "single" ]; then
  241. bakname="userjs_backups/user.js.backup"
  242. fi
  243. cp user.js "$bakname"
  244. mv "${newfile}" user.js
  245. echo -e "Status: ${GREEN}user.js has been backed up and replaced with the latest version!${NC}"
  246. # apply overrides
  247. if [ "$SKIPOVERRIDE" = false ]; then
  248. while IFS=',' read -ra FILE; do
  249. add_override "$FILE"
  250. done <<< "$OVERRIDE"
  251. fi
  252. # create diff
  253. if [ "$COMPARE" = true ]; then
  254. pastuserjs=userjs_diffs/past_user.js
  255. past_nocomments=userjs_diffs/past_userjs.txt
  256. current_nocomments=userjs_diffs/current_userjs.txt
  257. remove_comments $pastuserjs $past_nocomments
  258. remove_comments user.js $current_nocomments
  259. diffname="userjs_diffs/diff_$(date +"%Y-%m-%d_%H%M").txt"
  260. diff=$(diff -w -B -U 0 $past_nocomments $current_nocomments)
  261. if [ ! -z "$diff" ]; then
  262. echo "$diff" > "$diffname"
  263. echo -e "Status: ${GREEN}A diff file was created:${NC} ${PWD}/${diffname}"
  264. else
  265. echo -e "Warning: ${ORANGE}Your new user.js file appears to be identical. No diff file was created."${NC}
  266. fi
  267. rm $past_nocomments $current_nocomments $pastuserjs
  268. fi
  269. if [ "$VIEW" = true ]; then
  270. open_file "${PWD}/user.js"
  271. fi
  272. }
  273. #########################
  274. # Execute #
  275. #########################
  276. if [ $# != 0 ]; then
  277. readonly legacy_lc=$(echo $1 | tr '[A-Z]' '[a-z]')
  278. # Display usage if first argument is -help or --help
  279. if [ $1 = '--help' ] || [ $1 = '-help' ]; then
  280. usage
  281. elif [ $legacy_lc = '-donotupdate' ]; then
  282. UPDATE="no"
  283. legacy_argument $1
  284. elif [ $legacy_lc = '-update' ]; then
  285. UPDATE="yes"
  286. legacy_argument $1
  287. else
  288. while getopts ":hp:ludsno:bcvr" opt; do
  289. case $opt in
  290. h)
  291. usage
  292. ;;
  293. p)
  294. PROFILE_PATH=${OPTARG}
  295. ;;
  296. l)
  297. PROFILE_PATH="list"
  298. ;;
  299. u)
  300. UPDATE="yes"
  301. ;;
  302. d)
  303. UPDATE="no"
  304. ;;
  305. s)
  306. CONFIRM="no"
  307. ;;
  308. n)
  309. SKIPOVERRIDE=true
  310. ;;
  311. o)
  312. OVERRIDE=${OPTARG}
  313. ;;
  314. b)
  315. BACKUP="single"
  316. ;;
  317. c)
  318. COMPARE=true
  319. ;;
  320. v)
  321. VIEW=true
  322. ;;
  323. r)
  324. tfile=$(download_file 'https://raw.githubusercontent.com/ghacksuserjs/ghacks-user.js/master/user.js')
  325. mv $tfile "${tfile}.js"
  326. echo -e ${ORANGE}"Warning: user.js was saved to temporary file ${tfile}.js"${NC}
  327. open_file "${tfile}.js"
  328. exit 1
  329. ;;
  330. \?)
  331. echo -e ${RED}"\n Error! Invalid option: -$OPTARG"${NC} >&2
  332. usage
  333. ;;
  334. :)
  335. echo -e ${RED}"Error! Option -$OPTARG requires an argument."${NC} >&2
  336. exit 1
  337. ;;
  338. esac
  339. done
  340. fi
  341. fi
  342. show_banner
  343. update_updater
  344. set_wd # changes directory to the Firefox profile (or script-dir)
  345. update_userjs
  346. cd "${currdir}"