updater 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. #!/bin/sh
  2. ## Updater für die user.js von Privacy-Handbuch.de
  3. ## Version: 1.4.3
  4. ## by: TotallyLeGIT
  5. ## based on the ghacks user.js updater by:
  6. ## Author: Pat Johnson (@overdodactyl)
  7. ## Additional contributors: @earthlng, @ema-pe, @claustromaniac
  8. ## Dependencies: ·curl or wget
  9. #########################
  10. # Misc/Helper Functions #
  11. #########################
  12. # sets variables based on the operating system reported by uname
  13. abstract_os() {
  14. if [ "$(uname)" = 'Darwin' ]; then
  15. readonly open_command='open'
  16. readonly ff_file_path="${HOME}/Library/Application Support/Firefox/profiles.ini"
  17. readonly tb_file_path="${HOME}/Library/Thunderbird/profiles.ini"
  18. readonly ff_command='/Applications/Firefox.app/Contents/MacOS/firefox --version 2>/dev/null'
  19. else
  20. readonly open_command='xdg-open'
  21. readonly ff_file_path="${HOME}/.mozilla/firefox/profiles.ini"
  22. readonly tb_file_path="${HOME}/.thunderbird/profiles.ini"
  23. readonly ff_command='firefox --version 2>/dev/null'
  24. fi
  25. # set effective path for each profile.ini
  26. [ -f "${ff_file_path}" ] && ff_file="${ff_file_path}" || ff_file=''
  27. [ -f "${tb_file_path}" ] && tb_file="${tb_file_path}" || tb_file=''
  28. readonly ff_file tb_file
  29. }
  30. # parses command line options and sets variables accordingly
  31. parse_options() {
  32. if [ "${#}" -ne 0 ]; then
  33. # display usage if first argument contains -help
  34. if printf '%s' "${1}" | grep -qi '\-help'; then
  35. usage
  36. exit 0
  37. else
  38. while getopts ':abc:de:hilno:p:rsuvy' opt; do
  39. case "${opt}" in
  40. a)
  41. profile_path_option='all'
  42. ;;
  43. b)
  44. backup_multiple='false'
  45. ;;
  46. c)
  47. if ! config_wanted="$(printf '%s' "${OPTARG}" \
  48. | tr '[:upper:]' '[:lower:]' \
  49. | awk '{print $1; exit}' \
  50. | grep '^minimal$\|^moderat$\|^streng$\|^hotspot$\|^tb$\|^tb-streng$')"
  51. then
  52. printf '%s' "${red}Error: Invalid CONFIG.${neutral}"
  53. printf ' Valid values are:'
  54. printf ' minimal, moderat, streng, hotspot, tb or tb-streng\n'
  55. exit 1
  56. fi
  57. ;;
  58. d)
  59. compare='true'
  60. ;;
  61. e)
  62. if ff_version_wanted="$(printf '%s' "${OPTARG}" \
  63. | awk '{print $1; exit}' \
  64. | grep '^[[:digit:]]*$')"
  65. then
  66. ff_version_specified='true'
  67. else
  68. printf '%s\n' "${red}Error: VERSION must be an integer.${neutral}"
  69. exit 1
  70. fi
  71. ;;
  72. h)
  73. usage
  74. exit 0
  75. ;;
  76. i)
  77. view='true'
  78. ;;
  79. l)
  80. profile_path_option='list'
  81. ;;
  82. n)
  83. override='false'
  84. ;;
  85. o)
  86. override='true'
  87. override_path="${OPTARG}"
  88. ;;
  89. p)
  90. update_profile_path "${OPTARG}"
  91. ;;
  92. r)
  93. just_read='true'
  94. ;;
  95. # TODO: remove '-s' in future version
  96. s|u)
  97. update='true'
  98. ;;
  99. v)
  100. printf '%s\n' "PH-userjs-updater ${version}"
  101. exit 0
  102. ;;
  103. y)
  104. confirm='no'
  105. ;;
  106. \?)
  107. printf '%s' "${red}Error! Invalid option:" 1>&2
  108. printf '%s\n' " -${OPTARG}${neutral}" 1>&2
  109. usage
  110. exit 2
  111. ;;
  112. :)
  113. printf '%s' "${red}Error! Option -${OPTARG}" 1>&2
  114. printf '%s\n' " requires an argument.${neutral}" 1>&2
  115. usage
  116. exit 2
  117. ;;
  118. esac
  119. done
  120. fi
  121. fi
  122. }
  123. # initialize misc stuff
  124. # expects one argument: this script's name (usually $0)
  125. prepare() {
  126. tmp_dir="$(mktemp -d)"
  127. readonly tmp_dir
  128. trap 'exit 130' INT HUP QUIT TERM ALRM
  129. # shellcheck disable=SC2154
  130. trap 'rc="${?}"; rm -rf "${tmp_dir}"; exit "${rc}"' EXIT
  131. script_path="$(readlink -f "${1}" 2>/dev/null \
  132. || greadlink -f "${1}" 2>/dev/null || printf '%s' "${1}")"
  133. readonly script_path
  134. # Download method priority: curl > wget
  135. if command -v curl >/dev/null; then
  136. download_command='curl --max-redirs 2 --max-time 30 --fail --silent --output'
  137. elif command -v wget >/dev/null; then
  138. # -O file = --output-document=file
  139. download_command='wget --max-redirect=2 --timeout=30 --quiet -O'
  140. else
  141. printf '%s\n' \
  142. "${red}This script requires curl or wget. Process aborted.${neutral}"
  143. exit 2
  144. fi
  145. }
  146. # determines firefox update channel
  147. # returns 0 for release or the major version number for esr
  148. set_firefox_version() {
  149. if [ "${ff_version_specified}" = 'false' ]; then
  150. if ff_version_wanted="$(eval "${ff_command}")"; then
  151. if printf '%s' "${ff_version_wanted}" | grep -q 'esr'; then
  152. ff_version_wanted="$(printf '%s' "${ff_version_wanted}" \
  153. | cut -d ' ' -f 3 | cut -d '.' -f 1)"
  154. else
  155. ff_version_wanted='0'
  156. fi
  157. else
  158. printf '%s' "${yellow}Warning: No firefox executable in PATH."
  159. printf '%s\n' " Assuming updapte channel 'release'.${neutral}"
  160. ff_version_wanted='0'
  161. fi
  162. fi
  163. [ "${ff_version_wanted}" -eq 0 ] && esr_string='release' \
  164. || esr_string="ESR ${ff_version_wanted}"
  165. printf '%s\n' "Firefox variant: ${green}${esr_string}${neutral}"
  166. }
  167. # initialize variables needed for parse_options()
  168. set_variables() {
  169. # Colors used for printing only when stdout is a terminal
  170. if [ -t 1 ]; then
  171. red="$(tput setaf 1)$(tput bold)"
  172. blue="$(tput setaf 4)"
  173. green="$(tput setaf 2)"
  174. yellow="$(tput setaf 3)"
  175. # No Color
  176. neutral="$(tput sgr0)"
  177. else
  178. red=''
  179. blue=''
  180. green=''
  181. yellow=''
  182. neutral=''
  183. fi
  184. # Argument defaults
  185. backup_multiple='true'
  186. compare='false'
  187. config_wanted='keep'
  188. confirm='yes'
  189. ff_version_specified='false'
  190. just_read='false'
  191. # soft: look for user-overrides.js but only give info when none found
  192. override='soft'
  193. override_path='user-overrides.js'
  194. profile_path_option='false'
  195. pwd_start="$(pwd)"
  196. update='false'
  197. version='1.4.3'
  198. view='false'
  199. # constants
  200. readonly backup_dir='userjs_backups'
  201. readonly diff_dir='userjs_diffs'
  202. }
  203. show_banner() {
  204. printf '%s%s\n\n' "${blue}" \
  205. "┌───────────────────────────────────────────────┐
  206. │ Updater for Privacy-Handbuch's user.js │
  207. │ suitable for both Firefox and Thunderbird │
  208. └───────────────────────────────────────────────┘${neutral}
  209. Updater: ${blue}https://notabug.org/TotallyLeGIT/PH-userjs-updater${neutral}
  210. Firefox user.js: ${blue}https://www.privacy-handbuch.de/handbuch_21u.htm${neutral}
  211. Thunderbird user.js: ${blue}https://www.privacy-handbuch.de/handbuch_31p.htm${neutral}"
  212. }
  213. usage() {
  214. show_banner
  215. printf '%s' "${blue}Usage: ${0} [-abdhilnrsuvy] [-c CONFIG]"
  216. printf '%s\n\n' " [-e VERSION] [-o OVERRIDE] [-p PROFILE]${neutral}
  217. -a Update all Firefox and Thunderbird profiles at once while keeping
  218. CONFIGs the same. Profiles without a user.js will be skipped.
  219. -b Only keep one user.js backup and one diff file.
  220. -c CONFIG Specify the Firefox user.js config you want: minimal, moderat, streng or hotspot
  221. or for Thunderbird: tb or tb-streng .
  222. This is only needed if you want to change to another config.
  223. Note that this option will always have effect on all selected profiles.
  224. -d Create a diff file comparing old and new user.js within ${diff_dir} subdirectory.
  225. -e VERSION Force download of user.js for Firefox ESR with version number VERSION.
  226. Make sure the user.js for this version actually exists.
  227. Example: '-e 91' will download the user.js for Firefox ESR Version 91.x .
  228. Use '-e 0' to force the download of the user.js for the release update channel.
  229. Precedence to find Firefox update channel:
  230. '-e' option > read from user.js > 'firefox --version' > release (fallback)
  231. -h Show this help message and exit.
  232. -i Inspect the resulting user.js file.
  233. -l Interactively choose your profile from a list.
  234. -n Do not append any overrides even if user-overrides.js exists.
  235. -o OVERRIDE Filename or path to overrides file, needed if different than PROFILE/user-overrides.js .
  236. If used with -p, the path may be relative to PROFILE or an absolute path.
  237. If given a directory, all files inside ending in .js will be appended.
  238. -p PROFILE Path to your profile directory, needed if different than this script's location.
  239. May be used multiple times.
  240. IMPORTANT: If the profile path includes spaces, wrap whole path in quotes.
  241. -r Only download user.js to a temporary file and open it. This requires -c.
  242. -s (Deprecated.) This is an alias for '-u' until it is removed.
  243. -u Check for updates of this updater and install if available.
  244. -v Display updater version and exit.
  245. -y Update user.js without confirmation."
  246. }
  247. #########################
  248. # (Pro)File Handling #
  249. #########################
  250. # downloads a resource. expects two arguments:
  251. # $1 the file name, where the resource will be saved to
  252. # $2 the resource to download (a link)
  253. download_file() {
  254. [ -f "${1}" ] && return 0
  255. if ! eval "${download_command} '${1}' '${2}'"; then
  256. printf '%s\n' "${red}Download of resource failed:${neutral} ${2}"
  257. return 33
  258. fi
  259. }
  260. # updates profile_path (especially with list/-l) or exits on error
  261. get_profile_path() {
  262. if [ "${profile_path_option}" = 'list' ]; then
  263. if [ -n "${ff_file}" ]; then
  264. ini="${ff_file}"
  265. [ -n "${tb_file}" ] && ini='both' || printf 'Firefox detected.\n\n'
  266. elif [ -n "${tb_file}" ]; then
  267. ini="${tb_file}"
  268. printf 'Thunderbird detected.\n\n'
  269. else
  270. printf '%s' "${red}Error: Sorry, Thunderbird and Firefox could"
  271. printf '%s' " not be found or -l is not supported for your OS."
  272. printf '%s\n' " Try -p option.${neutral}"
  273. exit 1
  274. fi
  275. if [ "${ini}" = 'both' ]; then
  276. while [ -z "${reply}" ]; do
  277. printf '(F)irefox and (T)hunderbird were detected. Select one: f,t? '
  278. read -r reply
  279. done
  280. reply="$(printf '%s' "${reply}" | tr '[:upper:]' '[:lower:]')"
  281. if [ -z "${reply##f*}" ]; then
  282. ini="${ff_file}"
  283. printf 'Firefox was selected.\n\n'
  284. elif [ -z "${reply##t*}" ]; then
  285. ini="${tb_file}"
  286. printf 'Thunderbird was selected.\n\n'
  287. else
  288. printf '%s' "${red}Error: Could not parse your input.${neutral}"
  289. exit 1
  290. fi
  291. fi
  292. read_ini_file "${ini}"
  293. elif [ "${profile_path_option}" = 'all' ]; then
  294. for file in "${ff_file}" "${tb_file}"; do
  295. [ -f "${file}" ] \
  296. && profile_path_temp="$(sed -ne 's/^Path=\(.*\)$/\1/p' "${file}")"
  297. while read -r line; do
  298. if ! printf '%s' "${line}" | grep -q '^/'; then
  299. profile_path_to_update="${file%profiles.ini}${line}"
  300. else
  301. profile_path_to_update="${line}"
  302. fi
  303. update_profile_path "${profile_path_to_update}"
  304. # we don't want a subshell here
  305. done <<EOF
  306. ${profile_path_temp}
  307. EOF
  308. done
  309. elif [ "${profile_path_option}" = 'false' ]; then
  310. profile_path="$(dirname "${script_path}")"
  311. fi
  312. }
  313. # opens a file for the user to view
  314. # expects one argument: file_path
  315. open_file() {
  316. "${open_command}" "${1}" || printf '%s %s\n' "${red}Error: Sorry," \
  317. "opening files is not supported for your OS.${neutral}"
  318. }
  319. # parses profiles.ini to find the correct profile
  320. # expects one argument: absolute path of profiles.ini
  321. read_ini_file() {
  322. readonly ini_file="${1}"
  323. # only 1 profile found
  324. if [ "$(grep -c '^\[Profile' "${ini_file}")" -eq 1 ]; then
  325. ini_content="$(grep '^\[Profile' -A 4 "${ini_file}")"
  326. # more than 1 profile
  327. else
  328. printf 'Profiles found:\n'
  329. printf '–––––––––––––––––––––––––––––––––––\n'
  330. grep -E 'Default=[^1]|\[Profile[0-9]*\]|Name=|Path=|^$' "${ini_file}"
  331. printf '–––––––––––––––––––––––––––––––––––\n'
  332. printf '%s' \
  333. "Select the profile number ( Profile(0), Profile(1) etc. ): 1,2,…? "
  334. read -r reply
  335. printf '\n'
  336. ini_content="$(grep '^\[Profile'"${reply}" -A 4 "${ini_file}")" \
  337. || { printf '%s\n' "${red}Profile${reply} does not exist!${neutral}"
  338. exit 1 ; }
  339. fi
  340. profile_path_to_add="$(printf '%s' "${ini_content}" \
  341. | sed -n 's/^Path=\(.*\)$/\1/p')"
  342. path_is_rel="$(printf '%s' "${ini_content}" \
  343. | sed -n 's/^IsRelative=\([01]\)$/\1/p')"
  344. readonly path_is_rel
  345. # update global variable if path is relative
  346. [ "${path_is_rel}" -eq 1 ] \
  347. && profile_path_to_add="$(dirname "${ini_file}")/${profile_path_to_add}"
  348. update_profile_path "${profile_path_to_add}"
  349. }
  350. # adds a path to the list of profile paths, separated by newlines
  351. # expects one argument: a profile path
  352. update_profile_path() {
  353. # if profile path empty: update it
  354. if [ -z "${profile_path}" ]; then
  355. profile_path="${1}"
  356. # update profile_path_option var so we know there's a profile path
  357. [ "${profile_path_option}" = 'false' ] && profile_path_option='true'
  358. # append additional profile path
  359. else
  360. profile_path="$(printf '%s\n%s' "${profile_path}" "${1}")"
  361. fi
  362. }
  363. #########################
  364. # Update Updater #
  365. #########################
  366. # update this updater
  367. # expects $@ as arguments
  368. update_updater() {
  369. # update check has not been activated
  370. [ "${update}" = 'false' ] && return 0
  371. readonly new_updater="${tmp_dir}/new_updater"
  372. download_file "${new_updater}" \
  373. 'https://notabug.org/TotallyLeGIT/PH-userjs-updater/raw/main/updater' \
  374. || return 1
  375. chmod u+x "${new_updater}"
  376. current_updater_version="$("${script_path}" -v | cut -d ' ' -f 2)"
  377. new_updater_version="$("${new_updater}" -v | cut -d ' ' -f 2)"
  378. readonly current_updater_version_const="${current_updater_version}"
  379. # compare updater versions, if different
  380. while [ "${current_updater_version}" != "${new_updater_version}" ]; do
  381. difference="$((${new_updater_version%%.*}-${current_updater_version%%.*}))"
  382. # newer version available
  383. if [ "${difference}" -gt 0 ]; then
  384. # apply update
  385. mv "${new_updater}" "${script_path}"
  386. printf 'Updater successfully updated.\n'
  387. printf '%s' "Changelog: ${green}https://notabug.org/TotallyLeGIT/"
  388. printf '%s\n\n' "PH-userjs-updater/raw/main/CHANGELOG.md${neutral}"
  389. # update user.js with new version
  390. "${script_path}" "${@}"
  391. # exit with exit code from updater call above
  392. exit "${?}"
  393. # version number is equal (go to next number)
  394. elif [ "${difference}" -eq 0 ]; then
  395. current_updater_version="${current_updater_version#*.}"
  396. new_updater_version="${new_updater_version#*.}"
  397. # this should not be happening
  398. else
  399. printf '%s' "${red}Error: Something with the updater version"
  400. printf '%s' " seems funny. Check updater homepage"
  401. printf '%s\n' " and/or update manually.${neutral}"
  402. return 2
  403. fi
  404. done
  405. }
  406. #########################
  407. # Update user.js #
  408. #########################
  409. # adds given override file or all files suffixed .js in given directory
  410. # expects one argument: path to a file or directory
  411. add_override() {
  412. input="${1}"
  413. if [ -f "${input}" ]; then
  414. printf '\n' >> 'user.js'
  415. cat "${input}" >> 'user.js'
  416. overrides_status="${green}file appended:${neutral} ${input}"
  417. elif [ -d "${input}" ]; then
  418. files="$(find "${input}" -mindepth 1 -maxdepth 1 -name '*.js')"
  419. if [ -z "${files}" ]; then
  420. overrides_status="${yellow}empty directory:${neutral} ${input}"
  421. else
  422. printf '%s\n' "${files}" \
  423. | while read -r f
  424. do
  425. add_override "${f}"
  426. done
  427. # skip output because every found file produces one
  428. return 0
  429. fi
  430. else
  431. if [ "${override}" = 'soft' ]; then
  432. overrides_status="${green}no overrides found${neutral}"
  433. else
  434. overrides_status="${yellow}invalid path:${neutral} ${input}"
  435. fi
  436. fi
  437. printf '%s\n' "overrides status: ${overrides_status}"
  438. }
  439. # returns a user.js download link
  440. # expects one argument: the full current version (e.g.: ff91_streng_16022020)
  441. get_userjs_link() {
  442. config_is="${1%_*}"
  443. # will be empty or e. g. 'ff91' afterwards
  444. esr_is="$(printf '%s' "${config_is}" \
  445. | sed -ne 's/\(ff[[:digit:]]*\)_.*/\1/p')"
  446. # will be e. g. 'streng' afterwards
  447. config_is="${config_is#*_}"
  448. if [ "${config_wanted}" = 'keep' ]; then
  449. # 'keep' means to try autodetection, so 'Not detected.' is a problem
  450. [ "${config_is}" = 'Not detected.' ] && exit 33
  451. config_wanted="${config_is}"
  452. fi
  453. # TODO: remove %%2* in future version (tb2 leftover)
  454. if [ "${config_wanted%%2*}" != 'tb' ]; then
  455. # version not specified → try autodetection from user.js
  456. if [ "${ff_version_specified}" = 'false' ] && [ -n "${esr_is}" ]; then
  457. esr_url="${esr_is}/"
  458. # version specified or could not extract from user.js
  459. else
  460. [ "${ff_version_wanted}" -eq 0 ] && esr_url='' \
  461. || esr_url="ff${ff_version_wanted}/"
  462. fi
  463. fi
  464. printf '%s' "https://www.privacy-handbuch.de/download/"
  465. printf '%s' "${esr_url}${config_wanted}/user.js"
  466. }
  467. # returns the version number of a user.js file
  468. get_userjs_version() {
  469. [ -e "${1}" ] && userjs_version="$(sed -ne \
  470. '/user\.js\.prhdb/ s/.*"\(\([[:alnum:]]*_\)*[[:alpha:]]*_[0-9]*\)".*/\1/p' \
  471. "${1}")"
  472. [ -z "${userjs_version}" ] && printf 'Not detected.' && exit 33
  473. printf '%s' "${userjs_version}"
  474. }
  475. # downloads a user.js, opens it and exits
  476. read_and_exit() {
  477. [ "${just_read}" = 'false' ] && return 0
  478. if [ "${config_wanted}" = 'keep' ]; then
  479. printf '%s' "${red}Error: -r option requires"
  480. printf '%s\n' " -c option, too.${neutral}"
  481. exit 1
  482. else
  483. userjs_to_read="$(mktemp -dt userjs.XXXX)/user.js"
  484. readonly userjs_to_read
  485. download_file "${userjs_to_read}" \
  486. "$(get_userjs_link "${config_wanted}")" \
  487. || exit 1
  488. fi
  489. printf '%s' "${green}user.js was saved to temporary"
  490. printf '%s\n' " file:${neutral} ${userjs_to_read}"
  491. open_file "${userjs_to_read}"
  492. exit 0
  493. }
  494. # applies chosen version of user.js and any custom overrides
  495. update_userjs() {
  496. current_version_long="$(get_userjs_version 'user.js')"
  497. printf '%s\n' "profile path: ${green}${PWD}${neutral}"
  498. printf '%s\n' "currently using: ${green}${current_version_long}${neutral}"
  499. if ! link="$(get_userjs_link "${current_version_long}")"; then
  500. if [ "${profile_path_option}" = 'all' ]; then
  501. printf '%s\n' "${yellow}Skipping profile.${neutral}"
  502. else
  503. printf '%s' "${red}Error: Could not determine which config to download."
  504. printf '%s\n' " Use -c CONFIG and/or -p PROFILE.${neutral}"
  505. fi
  506. return 1
  507. fi
  508. # prepare extracting CONFIG (e.g. moderat) out of previously generated link
  509. tmp_link="${link%/*}"
  510. new_userjs="${tmp_dir}/new_userjs_${tmp_link##*/}"
  511. download_file "${new_userjs}" "${link}" || exit 1
  512. if ! new_version_long="$(get_userjs_version "${new_userjs}")"; then
  513. printf '%s\n' "${red}Error parsing new user.js${neutral}"
  514. return 1
  515. fi
  516. printf '%s\n' "available online: ${green}${new_version_long}${neutral}"
  517. if [ "${confirm}" = 'yes' ]; then
  518. printf '\nThis script will update to the latest user.js'
  519. if [ "${override}" != 'false' ]; then
  520. printf ' and append custom configurations from user-overrides.js or a specified path'
  521. fi
  522. printf '.\n%s' "${red}Continue? (y)es or (n)o: y,n?${neutral} "
  523. read -r reply </dev/tty
  524. if ! printf '%s' "${reply}" | grep -q '^[yY]*$'; then
  525. printf '%s\n' "${yellow}Skipping profile.${neutral}"
  526. return 1
  527. fi
  528. fi
  529. # backup user.js
  530. mkdir -p "${backup_dir}"
  531. [ "${backup_multiple}" = 'true' ] && backup_date="$(date '+%FT%T')_" \
  532. || backup_date=''
  533. backup_file="${backup_dir}/${backup_date}user.js"
  534. [ -f 'user.js' ] && mv 'user.js' "${backup_file}"
  535. # install newest user.js
  536. mv "${new_userjs}" 'user.js'
  537. printf '%s\n' "user.js status: ${green}backed up and updated${neutral}"
  538. # apply overrides
  539. if [ "${override}" != 'false' ]; then
  540. printf '\n// user-overrides\n' >> 'user.js'
  541. add_override "${override_path}"
  542. fi
  543. # create diff
  544. if [ "${compare}" = 'true' ]; then
  545. diffs="$(diff -wBU 0 "${backup_file}" 'user.js')"
  546. if [ -n "${diffs}" ]; then
  547. diff_file="${diff_dir}/${backup_date}diff.txt"
  548. mkdir -p "${diff_dir}"
  549. printf '%s' "${diffs}" > "${diff_file}"
  550. diff_status="${green}diff file created – user.js changed${neutral}"
  551. else
  552. diff_status="${green}skipped – user.js identical${neutral}"
  553. fi
  554. printf '%s\n' "diff status: ${diff_status}"
  555. fi
  556. [ "${view}" = 'true' ] && open_file "user.js"
  557. }
  558. #########################
  559. # Main() #
  560. #########################
  561. set_variables
  562. parse_options "${@}"
  563. prepare "${0}"
  564. update_updater "${@}"
  565. abstract_os
  566. # if esr wasn't forced, try to detect it
  567. set_firefox_version
  568. read_and_exit
  569. get_profile_path
  570. while read -r line; do
  571. printf '————————————————————————————————————————————\n'
  572. # this enables us to leave relative profile paths as they are
  573. cd "${pwd_start}" || exit 99
  574. if ! cd "${line}" 2>/dev/null; then
  575. printf '%s' "${yellow}Warning: Profile path not found:"
  576. printf '%s\n' " ${green}${line}${neutral}"
  577. continue
  578. fi
  579. update_userjs
  580. done <<EOF
  581. ${profile_path}
  582. EOF
  583. # vim: shiftwidth=2 tabstop=2 expandtab