#!/bin/bash # a7crypt v1.0.0 last mod 2012/01/09 # Latest version at # Copyright 2011, 2012 Ryan Sawhill # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. #------------------------------------------------------------------------------- # System requirements: zenity and one of either gpg, gpg2, or openssl. # # The original goal of this project was to make symmetric text {en,de}cryption # more accessible and easy to use. While GPG rocks (for both symmetric & # public-key) if you're comfortable on the commandline, and there are GUI # encryption options for key-based, there's not much out there for people who # need to do the simplest kind of encryption -- with a shared passphrase. # # First I developed a super-simple wrapper for the commandline. (To see an # evolution of that, check out a3crypt at , which # doesn't have any of the bells and whistles of a7crypt.) Once that was # complete, I decided it was time to the fill the hole of a GUI for symmetric # encryption, and began fleshing it out and adding features, quickly adding the # ability to pick files (and have the script automatically choose ASCII or # binary output type based on the chosen file). # # It almost goes without saying, but from the beginning, a requirement of all # this was that security not be in any way sacrificed for the convenience. # # To that end: No processes are run with arguments of a passphrase, nor are # passphrases or message data stored on disk; the script creates a working dir # in ram that is only readable by the current user and whenever message data or # passphrases need to be stored, they are stored there and deleted as soon as # they have served their purpose. (Note: We WILL fall-back to creating a # working dir on disk in users' HOME if /dev/shm is unavailable for some crazy # reason.) # # We of course want to ensure that all tmpfiles are cleaned up on exit, even # though they're hidden away in directories only available to the user. A simple # trap will cover exiting due to receiving a sigterm or sigint, but for sigkill, # we need something more. So each time the script runs it creates lockfiles with # its PID and the location of the temp working directory. That way, if an old # instance of the script ever dies without cleaning up its potentially-sensitive # data, we can take out the trash on the next run. # # And a final note: When lockfiles & temp directories are created by this # script, they're named based on the script's current filename; not some static # project name. This means that you can feel free to rename the script. # Everything else will go along with the new name--you don't need to change # anything in the content. Caveat: Don't be stupid & put spaces in the name. :) # # Feel free to hit me/the tracker up if you have any questions or suggestions! # # PS: If you like this you should check out a8crypt -- a gui frontend with more # features implemented in Python & GTK. #------------------------------------------------------------------------------- ## If the filename of our script is /usr/local/bin/a7crypt, then this variable would end up being "a7crypt", which we will use throughout zero=${0##*/} ; [[ -z ${zero##* *} ]] && zero=a7crypt #=============================================================================== #-------------------------------------------------- 1) BEGIN SANITY CHECKS ----> ## Print help message if no X or if run with any arguments if [[ -z $DISPLAY || $# -ne 0 ]]; then echo -e "$zero provides symmetric encryption/decryption using GPG, GPG2, or OpenSSL\nIt is meant to be run with no arguments from a GUI desktop" exit ## Ensure we have zenity elif ! command -v zenity >/dev/null; then tty --silent || notify-send --urgency=critical "$zero Critical Error" "You tried to execute $zero but it relies on Zenity (a small helper-application you don't have installed) to produce GUI menus and dialog boxes. You can install 'zenity' using your add/remove software management application." echo -e "This program relies on Zenity (a small helper-application you don't have\ninstalled) to produce GUI menus and dialog boxes. You can install 'zenity' using\nyour add/remove software management application.\nCtrl-c to quit." sleep 20 exit 255 ## Need writable home elif [[ ! -w $HOME ]]; then zenity --error --title="$zero: CRITICAL ERROR" --text="You are running $zero as $USER and your home directory ($HOME) is not writable. Cannot continue." exit 250 ## Do we have gpg2? elif command -v gpg2 >/dev/null; then mode=GPG2 ## Next up, check for gpg elif command -v gpg >/dev/null; then mode=GPG ## If no gpg funness, use openssl elif command -v openssl >/dev/null; then mode=OpenSSL-AES ## On the off-chance that none of those three are on the system... else zenity --error --title="You pulling my leg?" --text='Neither GPG, GPG2, nor OpenSSL were found in your $PATH..? Right. If you say so.' exit 250 fi #=============================================================================== #------------------------------------------------ 2) SETUP OUR ENVIRONMENT ----> ## Uber-restrictive umask, because we can umask 077 ## Create settings dotdir in ~ if not already there dotdir=$HOME/.$zero ; [[ ! -d $dotdir ]] && mkdir $dotdir ## Setup a private working directory in ram or in ~ if [[ -w /dev/shm/ ]]; then wd=$(mktemp -d /dev/shm/.$zero.$UID.XXX) else wd=$(mktemp -d $dotdir/wd.XXX) fi ## If there are existing lockfiles not associated with a running process, rm them and their stale working dirs for lockfile in $dotdir/lock-*; do [[ $(/dev/null ## Create new lockfile, e.g. ~/.a7crypt/lock-PID, which is a link to the working dir lockfile=$dotdir/lock-$$ ; ln -s $wd $lockfile ## Set up trap to clean-up working dir & kill any child processes (zenity) on exit trap "{ pkill -P $$; rm -r $wd $lockfile 2>/dev/null; }" EXIT ## Set filemanager for optionally looking at files for filemgr in nautilus dolphin konqueror thunar pcmanfm firefox; do command -v $filemgr >/dev/null && break done ## Set viewer for optionally looking at encrypted/decrypted text for viewer in gedit gvim kedit; do command -v $viewer >/dev/null && break done #=============================================================================== #-------------------------------------------------- 3) ENUMERATE FUNCTIONS ----> ## Functions to initialize the variables for each mode (see beginning of MAIN function for $gpg enumeration) init_env_GPG() { switch_to=OpenSSL encrypt="$gpg --batch --no-tty --yes --passphrase-file $wd/pass -o $wd/output -c --force-mdc --cipher-algo aes256" decrypt="$gpg --batch --no-tty --yes --passphrase-file $wd/pass -o $wd/output -d" } init_env_OPENSSL() { switch_to=GPG encrypt="openssl aes-256-cbc -pass file:$wd/pass -out $wd/output -salt" decrypt="openssl aes-256-cbc -pass file:$wd/pass -out $wd/output -d" } #---------------------------------------------- 3.1) FUNCTION: MAIN THREAD ----> # MAIN manages menu & dialogs, encryption, decryption, & loading of UPDATE func. MAIN() { ## Ensure buffers are clear >$wd/pass; rm $wd/input $wd/output 2>/dev/null ## (re-)Initialize our variables, depending on which mode we're in if [[ $mode = GPG2 ]]; then gpg="gpg2" init_env_GPG elif [[ $mode = GPG ]]; then gpg="gpg --no-use-agent" init_env_GPG elif [[ $mode = OpenSSL-AES ]]; then init_env_OPENSSL fi ## Set main menu content for 'zenity --list' menu_head_enc="[----- ENCRYPTION -----]" menu_enc_text=" • Type or paste text" menu_enc_file=" • Select file" menu_head_dec="[----- DECRYPTION -----]" menu_dec_text=" • Paste text" menu_dec_file=" • Select file " ## Trailing space to make different than $menu_enc_file menu_blanksep=" --------------------------" menu_switchto="Switch to $switch_to-mode" menu_ckupdate="Check online for update" ## Display main menu and grab the user's choice menu_choice=$(zenity --list --hide-header --title="$zero [$mode]" --text="What would you like to do?" --column=1 "$menu_head_enc" "$menu_enc_text" "$menu_enc_file" "$menu_head_dec" "$menu_dec_text" "$menu_dec_file" "$menu_blanksep" "$menu_switchto" "$menu_ckupdate" --cancel-label="Quit" --height=340) || exit #------------------------------------------------ ## BEGIN PARSING MENU CHOICES ## Reload menu if user picks one of the header lines if [[ $menu_choice = $menu_head_enc || $menu_choice = $menu_head_dec || $menu_choice = $menu_blanksep ]]; then MAIN ## Run our UPDATE function if they choose updates elif [[ $menu_choice = $menu_ckupdate ]]; then UPDATE #------------------------------------------------ ## 3.1.1) ENCRYPT: TYPE/PASTE TEXT elif [[ $menu_choice = $menu_enc_text ]]; then ## Warn user about openssl obscurity if [[ $mode = OpenSSL-AES && ! -f $dotdir/nowarn.openssl-txt ]]; then zenity --info --title="$zero [$mode]: NOTICE" --text="OpenSSL text-input mode uses 'openssl aes-256-cbc -salt -a' to encrypt text to ASCII-armored (plain-text) output. OpenSSL doesn't add any pretty envelope info to its encrypted data like GPG does, meaning there are no GUI applications (AFAIK) that will know what to do with files containing said data.\n\nIn short, to decrypt data encrypted with this mode, you can either:\n1) use this app\n2) use OpenSSL directly on a terminal, i.e., drop the data into a file of SOMENAME and run\n\topenssl aes-256-cbc -a -d -in SOMENAME\n\n[Press Enter or Esc if you can't see OK button.]" touch $dotdir/nowarn.openssl-txt fi ## Encrypt command for openssl needs -a (ASCII) and this doesn't hurt gpg encrypt="$encrypt -a" ## Ask for text message to be encrypted zenity --text-info --editable --title="$zero [$mode]: Type or paste text to be encrypted" --width=800 --height=600 --no-wrap >$wd/input || MAIN ## Keep prompting until user actually enters some data until [[ -s $wd/input ]]; do zenity --text-info --editable --title="$zero [$mode]: You must enter text to be encrypted" --width=800 --height=600 --no-wrap >$wd/input || MAIN done ## Ask for encryption passphrase ## TODO: I designed this to be fast and simple; I don't like the idea of having to enter a passphrase twice, but I also don't like the idea of accidentally mistyping a long passphrase. That's why I decided not to use --hide-text to hide the passphrase when doing encryption. Need to get feedback from users on this choice though. zenity --entry --title="$zero [$mode]" --text="Enter passphrase very carefully" --ok-label="Encrypt" >$wd/pass || MAIN ## Keep prompting until user enters a passphrase (zenity --entry inserts a newline even if no input so we can't use "test -s" like we can with --text-info) until [[ $(wc -c <$wd/pass) -gt 1 ]]; do zenity --entry --title="$zero [$mode]" --text="You must enter a passphrase" --ok-label="Encrypt" >$wd/pass || MAIN done ## Start a progress bar dialog for those really big jobs or slow machines (this gives the user feedback and a chance to cancel) coproc zenity --progress --pulsate --title="$mode: Please wait" --text="Encrypting text..." --auto-kill --auto-close; echo 1 >&${COPROC[1]} ## Run our encrytion; if failed, save & report back errors, cleanup, and go to main menu if ! $encrypt <$wd/input 2>$wd/errlog; then >$wd/pass; >$wd/input ## Clear passphrase & input buffers ASAP echo 100 >&${COPROC[1]} ## Set our progress dialog to 100% so it closes zenity --error --title="$zero [$mode]: ENCRYPTION ERROR!" --text="$(<$wd/errlog)" --no-wrap MAIN fi ## If encryption succeeded... >$wd/pass; >$wd/input ## Clear passphrase & input buffers ASAP echo 100 >&${COPROC[1]} ## Set our progress dialog to 100% so it closes ## Display encrypted data back to user, loop back to main menu if they don't hit quit zenity --text-info --title="$zero [$mode]: Your encrypted text" --width=650 --height=400 --no-wrap --cancel-label="Show in txt editor" --ok-label="Menu" <$wd/output || { $viewer $wd/output; sleep 3; } MAIN #------------------------------------------------ ## 3.1.2) ENCRYPT: SELECT FILE elif [[ $menu_choice = $menu_enc_file ]]; then ## Warn user about openssl obscurity if [[ $mode = OpenSSL-AES && ! -f $dotdir/nowarn.openssl-file ]]; then zenity --info --title="$zero [$mode]: NOTICE" --text="OpenSSL file-input mode uses 'openssl aes-256-cbc -salt' to encrypt non-text files to binary output and the same plus an option of '-a' to encrypt text files to ASCII-armored (plain-text) output. (Output files get the same name with an extension of 'aes256' appended.) OpenSSL doesn't add any pretty envelope info to its encrypted data like GPG does, meaning there are no GUI applications (AFAIK) that will know what to do with files containing said data.\n\nIn short, to decrypt files encrypted with this mode, you can either:\n1) use this app\n2) use OpenSSL directly on a terminal, e.g.,\n openssl aes-256-cbc -a -d -in FILE.txt.aes256\n\t(to decrypt the ASCII-files)\n openssl aes-256-cbc -d -in FILE.zip.aes256\n\t(to decrypt the binary files)\n\n[Press Enter or Esc if you can't see OK button.]" touch $dotdir/nowarn.openssl-file fi ## Get file to encrypt via file-selection dialog file_to_encrypt=$(zenity --file-selection --title="$zero [$mode]: Select file to be encrypted") || MAIN ## Keep prompting until user chooses a proper file while [[ ! -s $file_to_encrypt || ! -r $file_to_encrypt ]]; do file_to_encrypt=$(zenity --file-selection --title="$zero [$mode]: Could not read file; select another") || MAIN done ## Detect whether input is binary or text and set output mode and output filename accordingly file_type=$(file -b -e soft "$file_to_encrypt") ## Get filetype if [[ ${file_type%% *} = ASCII ]]; then encrypt="$encrypt -a" ascii_yesno="ASCII-armored output" ; encrypted_file=$file_to_encrypt.asc else ascii_yesno="binary output" ; encrypted_file=$file_to_encrypt.gpg fi [[ $mode = OpenSSL-AES ]] && encrypted_file=$file_to_encrypt.aes256 ## Now that we know what our input and output files are going to be, setup symlinks ln -sf "$file_to_encrypt" $wd/input ln -sf "$encrypted_file" $wd/output ## Ask for encryption passphrase zenity --entry --title="$zero [$mode]" --text="Enter passphrase very carefully" --ok-label="Encrypt" >$wd/pass || MAIN ## Keep prompting until user enters a passphrase (zenity --entry inserts a newline even if no input so we can't use "test -s" like we can with --text-info) until [[ $(wc -c <$wd/pass) -gt 1 ]]; do zenity --entry --title="$zero [$mode]" --text="You must enter a passphrase" --ok-label="Encrypt" >$wd/pass || MAIN done ## Start a progress bar dialog for those really big jobs or slow machines (this gives the user feedback and a chance to cancel) coproc zenity --progress --pulsate --title="$mode: Please wait" --text="Encrypting $file_to_encrypt..." --auto-kill --auto-close; echo 1 >&${COPROC[1]} ## Run our encrytion; if failed, save & report back errors, cleanup, and go to main menu if ! $encrypt <$wd/input 2>/$wd/errlog; then >$wd/pass ## Clear the passphrase buffer echo 100 >&${COPROC[1]} ## Set our progress dialog to 100% so it closes zenity --error --title="$zero [$mode]: ENCRYPTION ERROR!" --text="$(<$wd/errlog)" --no-wrap MAIN fi ## If encryption succeeded... >$wd/pass ## Clear the passphrase buffer echo 100 >&${COPROC[1]} ## Set our progress dialog to 100% so it closes ## Report final encrypted filename back to user; give them a chance to see the file in their filemanager (hopefully) echo -en "Successfully encrypted [ $file_to_encrypt ] with $ascii_yesno. Saved encrypted copy to:\n$encrypted_file" | zenity --text-info --title="$zero [$mode]: Your encrypted file is ready" --width=500 --height=160 --cancel-label="Show file" --ok-label="Menu" || $filemgr "${encrypted_file%/*}" MAIN #------------------------------------------------ ## 3.1.3) DECRYPT: PASTE ENCRYPTED ASCII elif [[ $menu_choice = $menu_dec_text ]]; then ## Decrypt command for openssl needs -a (ASCII) and this doesn't hurt gpg decrypt="$decrypt -a" ## Ask for text message to be decrypted zenity --text-info --editable --title="$zero [$mode]: Paste $mode-encrypted message" --width=650 --height=400 --no-wrap >$wd/input || MAIN ## Keep prompting until user actually enters some data until [[ -s $wd/input ]]; do zenity --text-info --editable --title="$zero [$mode]: You must enter an encrypted message" --width=650 --height=400 --no-wrap >$wd/input || MAIN done ## Ask for decryption passphrase zenity --entry --title="$zero [$mode]" --text="Enter passphrase" --hide-text --ok-label="Decrypt" >$wd/pass || MAIN ## Keep prompting until user enters a passphrase (zenity --entry inserts a newline even if no input so we can't use "test -s" like we can with --text-info) until [[ $(wc -c <$wd/pass) -gt 1 ]]; do zenity --entry --title="$zero [$mode]" --text="You must enter a passphrase" --hide-text --ok-label="Decrypt" >$wd/pass || MAIN done ## Start a progress bar dialog for those really big jobs or slow machines (this gives the user feedback and a chance to cancel) coproc zenity --progress --pulsate --title="$mode: Please wait" --text="Decrypting text..." --auto-kill --auto-close; echo 1 >&${COPROC[1]} ## Run our decrytion; if failed, save & report back errors, cleanup, and go to main menu if ! $decrypt <$wd/input 2>$wd/errlog; then >$wd/pass; >$wd/input ## Clear passphrase & input buffers ASAP echo 100 >&${COPROC[1]} ## Set our progress dialog to 100% so it closes zenity --error --title="$zero [$mode]: DECRYPTION ERROR!" --text="$(<$wd/errlog)" --no-wrap MAIN fi ## If decryption succeeded... >$wd/pass; >$wd/input ## Clear passphrase & input buffers ASAP echo 100 >&${COPROC[1]} ## Set our progress dialog to 100% so it closes ## Display decrypted data back to user, loop back to main menu if they don't hit quit zenity --text-info --title="$zero [$mode]: Your decrypted text" --width=650 --height=600 --no-wrap --cancel-label="Show in txt editor" --ok-label="Menu" <$wd/output || { $viewer $wd/output; sleep 3; } MAIN #------------------------------------------------ ## 3.1.4) DECRYPT: SELECT FILE elif [[ $menu_choice = $menu_dec_file ]]; then ## Get file to decrypt via file-selection dialog file_to_decrypt=$(zenity --file-selection --title="$zero [$mode]: Select file to be decrypted") || MAIN ## Keep prompting until user chooses a proper file while [[ ! -s $file_to_decrypt || ! -r $file_to_decrypt ]]; do file_to_decrypt=$(zenity --file-selection --title="$zero [$mode]: Could not read file; select another") || MAIN done ## Try to figure out what to suggest for the save dialog box ## We start with a default, but if the file ends in these extensions, set the suggestion to the filename minus that extension decrypted_file_suggestion=${file_to_decrypt}-decrypted for ext in .asc .gpg .pgp .aes256; do [[ $ext = ${file_to_decrypt/%*$ext/$ext} ]] && { decrypted_file_suggestion=${file_to_decrypt%$ext}; break; } done ## Prompt user for where to save decrypted file decrypted_file=$(zenity --file-selection --save --confirm-overwrite --filename="$decrypted_file_suggestion" --title="$zero [$mode]: Choose decrypted file name of '${file_to_decrypt##*/}'") || MAIN ## Prevent user from nuking their file by reading and writing to it at the same time while [[ $file_to_decrypt = $decrypted_file ]]; do zenity --error --title="I just saved your life" --text="Source and destination files cannot be the same\!" decrypted_file=$(zenity --file-selection --save --confirm-overwrite --filename="$decrypted_file_suggestion" --title="$zero [$mode]: Choose decrypted file name of '${file_to_decrypt##*/}'") || MAIN done ## Set ASCII option for openssl, if needed if [[ $mode = OpenSSL-AES ]]; then file_type=$(file -b -e soft "$file_to_decrypt") [[ ${file_type%% *} = ASCII ]] && decrypt="$decrypt -a" fi ## Now that we know what our input and output files are going to be, setup symlinks ln -sf "$file_to_decrypt" $wd/input ln -sf "$decrypted_file" $wd/output ## Ask for decryption passphrase zenity --entry --title="$zero [$mode]" --text="Enter passphrase" --hide-text --ok-label="Decrypt" >$wd/pass || MAIN ## Keep prompting until user enters a passphrase (zenity --entry inserts a newline even if no input so we can't use "test -s" like we can with --text-info) until [[ $(wc -c <$wd/pass) -gt 1 ]]; do zenity --entry --title="$zero [$mode]" --text="You must enter a passphrase" --hide-text --ok-label="Decrypt" >$wd/pass || MAIN done ## Start a progress bar dialog for those really big jobs or slow machines (this gives the user feedback and a chance to cancel) coproc zenity --progress --pulsate --title="$mode: Please wait" --text="Decrypting $file_to_decrypt..." --auto-kill --auto-close; echo 1 >&${COPROC[1]} ## Run our decryption; if failed, save & report back errors, cleanup, and go to main menu if ! $decrypt <$wd/input 2>/$wd/errlog; then >$wd/pass ## Clear the passphrase buffer echo 100 >&${COPROC[1]} ## Set our progress dialog to 100% so it closes zenity --error --title="$zero [$mode]: DECRYPTION ERROR!" --text="$(<$wd/errlog)" --no-wrap MAIN fi ## If decryption succeeded... >$wd/pass ## Clear the passphrase buffer echo 100 >&${COPROC[1]} ## Set our progress dialog to 100% so it closes ## Report final decrypted filename back to user; give them a chance to see the file in their filemanager (hopefully) echo -en "Successfully decrypted [ $file_to_decrypt ] to new file:\n$decrypted_file" | zenity --text-info --title="$zero [$mode]: Your decrypted file is ready" --width=500 --height=160 --cancel-label="Show file" --ok-label="Menu" || $filemgr "${decrypted_file%/*}" MAIN #------------------------------------------------ ## 3.1.5) SWITCH MODES else ## If switching to openssl mode, ensure we have openssl (haha) before setting our mode if [[ $switch_to = OpenSSL ]]; then if command -v openssl >/dev/null; then mode=OpenSSL-AES else zenity --error --title="Missing OpenSSL" --text="OpenSSL not found in your \$PATH. That's so shocking I almost don't believe it. In any case, if you really want to try it out, you can install it using your software-management application." --width=400 fi ## If switching to gpg mode, check for gpg2 first; otherwise gpg; in the unlikely event of neither, display an error elif [[ $switch_to = GPG ]]; then if command -v gpg2 >/dev/null; then mode=GPG2 elif command -v gpg >/dev/null; then mode=GPG else zenity --error --title="Missing GPG" --text="Neither GPG nor GPG2 were found in your \$PATH. You can install either of them using your software-management application." --width=400 fi fi ## Reload the main menu MAIN fi } #-------------------------------------------------- 3.2) FUNCTION: UPDATES ----> # UPDATE is called by MAIN in order to check for & optionally download updates UPDATE() { ## Set some variables red=""; blue="" orange=""; end_color="" file_dL=$dotdir/latest_update diff_file=$dotdir/latest_changes.patch ## Make sure we CAN download something if command -v wget >/dev/null; then downloader=wget; out='-O' elif command -v curl >/dev/null; then downloader=curl; out='-o' else zenity --error --title="$zero [UPDATE]" --text="${red}Need either wget or curl installed to perform the download\!${end_color}" MAIN fi ## Start a progress bar coproc zenity --progress --pulsate --title="$zero [UPDATE]" --text="Downloading latest version of a7crypt from github..." --auto-kill --auto-close echo 1 >&${COPROC[1]} ## Download latest version of a7crypt with wget or curl if ! $downloader https://raw.github.com/ryran/a7crypt/master/a7crypt $out $file_dL; then echo 100 >&${COPROC[1]} zenity --error --title="$zero [UPDATE]" --text="${red}There was a problem downloading the file\! Try running $zero from a terminal for more info.${end_color}" MAIN fi ## Close progress bar echo 100 >&${COPROC[1]} ## Grab version strings from files version=$(head -n2 $0 | grep -o "a7crypt v.*") file_dL_version=$(head -n2 $file_dL | grep -o "a7crypt v.*") ## Compare currently running a7crypt with downloaded file -- if they're the same ... if diff -u $0 $file_dL >$diff_file; then zenity --info --title="$zero [UPDATE]" --text="$0 is the same version as what is on github, i.e.,\n\t${blue}$version${end_color}" MAIN ## Else, if they're different, give user a chance to look at differences else if ! zenity --question --title="$zero [UPDATE]" --text="The version you are running reports as:\n\t${blue}$version${end_color}\nThe version on github appears to be different and reports as:\n\t${orange}$file_dL_version${end_color}" --cancel-label="Show differences" --ok-label="Next"; then $viewer $diff_file sleep 4 fi ## Confirm update zenity --question --title="$zero [UPDATE]" --text="Replace $0 with the latest version?" --cancel-label="Back to Menu" --ok-label="UPDATE" || MAIN ## If script location is writable, then let's do the do and save output to errlog if [[ -w $0 ]]; then { cp -v $0 $dotdir/$zero.bak; cp -v $file_dL $0; chmod -v +x $0; } >$wd/errlog 2>&1 ## Otherwise we have to use a GUI su/sudo program, so first we search & pick one else for Gsu in beesu kdesu gksu ktsuss NO_tenemos_Gsu; do command -v $Gsu >/dev/null && break done ## If we don't have one, display error + return to menu [[ $Gsu = NO_tenemos_Gsu ]] && { zenity --error --title="$zero [UPDATE]" --text="${orange}Unable to authenticate as root in order to modify $0. You can re-run $zero with root privileges from a terminal (sudo $zero or su -lc a7crypt)${end_color}"; MAIN; } ## Finally, run our commands with whichever GUI su program we found, saving output to errlog $Gsu "cp -v $0 $dotdir/$zero.bak; cp -v $file_dL $0; chmod -v +x $0" >$wd/errlog 2>&1 ## TODO: Need to test this with different programs; perhaps output should be inside quotes fi rm -v $dotdir/nowarn* 2>/dev/null ## TODO: Decide if really want this. (There might be important updates to warning messages?) ## Pipe some messages + the errlog to a zenity window for the user { echo "Backing up current version and replacing it with downloaded version..."; cat $wd/errlog; echo -n 'ALL DONE!'; } | zenity --text-info --title="$zero [UPDATE]" --no-wrap --cancel-label="Quit" --ok-label="Re-load $zero new version" --width=510 --height=300 && exec $0 || exit fi ## Script should never get here, but... MAIN } #=============================================================================== #---------------------------------------------- 4) BEGIN USER-INTERACTION! ----> ## First-run information if [[ ! -f $dotdir/nowarn.1strun ]]; then zenity --info --title="$zero: First-run message" --text="This app is designed to be a frontend for utilities that provide symmetric (i.e., one passphrase used for both) encryption and decryption of files or blocks of text. It doesn't set any limits on the size of the input, so be warned: if e.g., you paste in a 150 MB text file for encryption, $zero will do it, but you'll lose upwards of 150 megs of RAM temporarily as it stores input in /dev/shm to speed operations. So you'd be better off using the file-selection mode for giant text files, as the file will be fed directly into the encryption program.\n\nAlso, a random tip: When in the main menu, you can double-click to make your choice; you don't have to use the OK button. Enjoy\!\n\n[Press Enter or Esc if you can't see OK button.]" touch $dotdir/nowarn.1strun fi ## All setup is complete & we're ready to start the main menu (function above) MAIN