updater 21 KB

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