# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-

HELPERS="$HELPERS dup:incremental_encrypted_remote_filesystem_backup"

### Functions

do_dup_host_includes() {
   set -o noglob
   # choose the files to backup
   REPLY=
   while [ -z "$REPLY" ]; do
      formBegin "$dup_title - host system: includes"
         [ -z "$dup_includes" ] && dup_includes="$dup_default_includes"
         for i in $dup_includes; do
            formItem include "$i"
	 done
	 formItem include ""
	 formItem include ""
	 formItem include ""
	 formDisplay
      [ $? = 0 ] || return 1
      dup_includes="$REPLY"
   done
   set +o noglob
}

do_dup_vserver() {
   # choose the vservers to backup (into $selected_vservers)
   choose_one_or_more_vservers "$dup_title"
   [ $? = 0 ] || return 1

   set -o noglob
   # choose the files to backup
   REPLY=
   while [ -z "$REPLY" ]; do
      formBegin "$dup_title - vservers: vsincludes (backup these directories from every selected vserver)"
         [ -z "$dup_vsincludes" ] && dup_vsincludes="$dup_default_includes"
         for i in $dup_vsincludes; do
            formItem include "$i"
	 done
	 formItem include ""
	 formItem include ""
	 formItem include ""
      formDisplay
      [ $? = 0 ] || return 1
      dup_vsincludes="$REPLY"
   done
   set +o noglob
}

do_dup_excludes() {
   set -o noglob
   formBegin "$dup_title: excludes"
     [ -z "$dup_excludes" ] && dup_excludes="$dup_default_excludes"
     for i in $dup_excludes; do
        formItem exclude "$i"
     done
     formItem exclude ""
     formItem exclude ""
     formItem exclude ""
   formDisplay
   [ $? = 0 ] || return 1
   dup_excludes="$REPLY"
   set +o noglob
}

do_dup_src() {
   choose_host_or_vservers_or_both "$dup_title"
   [ $? = 0 ] || return 1
   case $host_or_vservers in
      'host')
	 do_dup_host_includes
	 [ $? = 0 ] || return 1
	 ;;
      'vservers')
	 do_dup_vserver
	 [ $? = 0 ] || return 1
	 ;;
      'both')
	 do_dup_host_includes
	 [ $? = 0 ] || return 1
	 do_dup_vserver
	 [ $? = 0 ] || return 1
	 ;;
      *)
	 return 1
	 ;;
   esac
   do_dup_excludes
   [ $? = 0 ] || return 1
   
   _src_done="(DONE)"
   setDefault dest
}

do_dup_dest() {

   local replyconverted
   local thereply

   set -o noglob
   REPLY=
   while [ -z "$REPLY" -o -z "$dup_destdir" -o -z "$dup_desthost" -o -z "$dup_destuser" ]; do
      formBegin "$dup_title - destination: first three items are compulsory"
	formItem "desthost" "$dup_desthost"
	formItem "destuser" "$dup_destuser"
	formItem "destdir" "$dup_destdir"
	formItem "keep" "$dup_keep"
        formItem "incremental" "$dup_incremental"
	formItem "bandwidthlimit" "$dup_bandwidth"
	formItem "sshoptions" "$dup_sshoptions"
      formDisplay
      [ $? = 0 ] || return 1

      IFS=$''
      replyconverted=`echo $REPLY | tr '\n' :`
      IFS=$':'
      thereply=($replyconverted)
      IFS=$' \t\n'
      
      dup_desthost=${thereply[0]}
      dup_destuser=${thereply[1]}
      dup_destdir=${thereply[2]}
      dup_keep=${thereply[3]}
      dup_incremental=${thereply[4]}
      dup_bandwidth=${thereply[5]}
      dup_sshoptions=${thereply[6]}

   done
   set +o noglob

   _dest_done="(DONE)"
   setDefault gpg
}

do_dup_gpg_encryptkey() {
   REPLY=
   while [ -z "$REPLY" -o -z "$dup_gpg_encryptkey" ]; do
      inputBox "$dup_title - GnuPG" "Enter ID of the public GnuPG key to be used to encrypt the backups:" "$dup_gpg_encryptkey"
      [ $? = 0 ] || return 1
      dup_gpg_encryptkey="$REPLY"
   done
}

do_dup_gpg_sign() {
   # sign ?
   booleanBox "$dup_title - GnuPG" "Sign the backups?" "$dup_gpg_sign"
   if [ $? = 0 ]; then
      dup_gpg_sign=yes
   else
      dup_gpg_sign=no
   fi
}

do_dup_gpg_signkey() {
   # one key pair ?
   booleanBox "$dup_title - GnuPG" "Use the same GnuPG key pair for encryption and signing?" "$dup_gpg_onekeypair"
   if [ $? = 0 ]; then
      dup_gpg_onekeypair=yes
   else
      dup_gpg_onekeypair=no
   fi

   if [ "$dup_gpg_onekeypair" == "no" }; then
      # signkey ?
      REPLY=
      while [ -z "$REPLY" -o -z "$dup_gpg_signkey" ]; do
	 inputBox "$dup_title - GnuPG" "Enter the ID of the private GnuPG key to be used to sign the backups:" "$dup_gpg_signkey"
	 [ $? = 0 ] || return 1
	 dup_gpg_signkey="$REPLY"
      done
   fi
}

do_dup_gpg_passphrase() {
   local question="Enter the passphrase needed to unlock the GnuPG key:"
   REPLY=
   while [ -z "$REPLY" -o -z "$dup_gpg_password" ]; do
      passwordBox "$dup_title - GnuPG" "$question"
      [ $? = 0 ] || return 1
      dup_gpg_password="$REPLY"
   done
}

do_dup_gpg() {
   
   # symmetric or public key encryption ?
   booleanBox "$dup_title - GnuPG" "Use public key encryption? Otherwise, symmetric encryption will be used, and data signing will be impossible." "$dup_gpg_asymmetric_encryption"
   if [ $? = 0 ]; then
      dup_gpg_asymmetric_encryption=yes
   else
      dup_gpg_asymmetric_encryption=no
   fi

   # when using public/private key pair encryption, ask for the keys to use
   if [ "$dup_gpg_asymmetric_encryption" == yes ]; then
      do_dup_gpg_encryptkey ; [ $? = 0 ] || return 1
      do_dup_gpg_sign ; [ $? = 0 ] || return 1
      if [ "$dup_gpg_sign" == yes ]; then
	 do_dup_gpg_signkey ; [ $? = 0 ] || return 1
      fi
   else
      dup_gpg_sign=no
   fi

   # a passphrase is alway needed
   do_dup_gpg_passphrase

   _gpg_done="(DONE)"
   setDefault adv
   # TODO: replace the above line by the following when do_dup_conn is written
   # setDefault conn
}

# TODO: share rdiff.helper code in some lib, and use it here
do_dup_conn() {
   _con_done="(DONE)"
   setDefault adv
}

do_dup_misc_options() {

   set -o noglob
   local replyconverted
   local thereply

   formBegin "$dup_title - misc. options"
     formItem "nicelevel" "$dup_nicelevel"
     formItem "testconnect" "$dup_testconnect"
     formItem "options" "$dup_options"
   formDisplay
   [ $? = 0 ] || return 1

   IFS=$''
   replyconverted=`echo $REPLY | tr '\n' :`
   IFS=$':'
   thereply=($replyconverted)
   IFS=$' \t\n'

   dup_nicelevel=${thereply[0]}
   dup_testconnect=${thereply[1]}
   dup_options=${thereply[2]}

   set +o noglob
}

# (rdiff.helper compatible interface... there could be some sode to share, hmmm.)
do_dup_adv() {
   do_dup_misc_options
   [ $? = 0 ] || return 1
   _adv_done="(DONE)"
   setDefault finish
}

do_dup_finish() {
   get_next_filename $configdirectory/90.dup
   cat > $next_filename <<EOF
# passed directly to duplicity
#options = --verbosity 8
options = $dup_options

# default is 0, but set to 19 if you want to lower the priority.
nicelevel = $dup_nicelevel

# default is yes. set to no to skip the test if the remote host is alive
testconnect = $dup_testconnect

######################################################
## gpg section
## (how to encrypt and optionally sign the backups)
##
## WARNING: old (pre-0.9.4) example.dup used to give wrong information about
##          the way the following options are used. Please read the following
##          carefully.
##
## If the encryptkey variable is set:
##   - data is encrypted with the GnuPG public key specified by the encryptkey
##     variable
##   - if signing is enabled, data is signed with the GnuPG private
##     key specified by the signkey variable
##   - the password variable is used to unlock the GnuPG key(s) used
##     for encryption and (optionnal) signing
##
## If the encryptkey option is not set:
##   - data signing is not possible
##   - the password variable is used to encrypt the data with symmetric
##     encryption: no GnuPG key pair is needed

[gpg]

# when set to yes, encryptkey variable must be set below; if you want to use
# two different keys for encryption and signing, you must also set the signkey
# variable below.
# default is no, for backwards compatibility with backupninja <= 0.5.
sign = $dup_gpg_sign

# ID of the GnuPG public key used for data encryption.
# if not set, symmetric encryption is used, and data signing is not possible.
encryptkey = $dup_gpg_encryptkey

# ID of the GnuPG private key used for data signing.
# if not set, encryptkey will be used.
signkey = $dup_gpg_signkey

# password
# NB: neither quote this, nor should it include any quotes
password = $dup_gpg_password

######################################################
## source section
## (where the files to be backed up are coming from)

[source]

# A few notes about includes and excludes:
# 1. include, exclude and vsinclude statements support globbing with '*'
# 2. Symlinks are not dereferenced. Moreover, an include line whose path
#    contains, at any level, a symlink to a directory, will only have the
#    symlink backed-up, not the target directory's content. Yes, you have to
#    dereference yourself the symlinks, or to use 'mount --bind' instead.
#    Example: let's say /home is a symlink to /mnt/crypt/home ; the following
#    line will only backup a "/home" symlink ; neither /home/user nor
#    /home/user/Mail will be backed-up :
#      include = /home/user/Mail
#    A workaround is to 'mount --bind /mnt/crypt/home /home' ; another one is to
#    write :
#      include = /mnt/crypt/home/user/Mail
# 3. All the excludes come after all the includes. The order is not otherwise
#    taken into account.

# files to include in the backup
EOF

   if [ "$host_or_vservers" == host -o "$host_or_vservers" == both ]; then
      set -o noglob
      for i in $dup_includes; do
	 echo "include = $i" >> $next_filename
      done
      set +o noglob
   fi

   cat >> $next_filename <<EOF

# If vservers = yes in /etc/backupninja.conf then the following variables can
# be used:
# vsnames = all | <vserver1> <vserver2> ... (default = all)
# vsinclude = <path>
# vsinclude = <path>
# ...
# Any path specified in vsinclude is added to the include list for each vserver
# listed in vsnames (or all if vsnames = all, which is the default).
#
# For example, vsinclude = /home will backup the /home directory in every
# vserver listed in vsnames. If you have 'vsnames = foo bar baz', this
# vsinclude will add to the include list /vservers/foo/home, /vservers/bar/home
# and /vservers/baz/home.
# Vservers paths are derived from $VROOTDIR.

EOF

   if [ "$host_or_vservers" == vservers -o "$host_or_vservers" == both ]; then
      set -o noglob
      echo -e "vsnames = $selected_vservers\n" >> $next_filename
      for i in $dup_vsincludes; do
         echo "vsinclude = $i" >> $next_filename
      done
      set +o noglob
   fi

   # excludes
   cat >> $next_filename <<EOF

# files to exclude from the backup
EOF
    set -o noglob
    for i in $dup_excludes; do
        echo "exclude = $i" >> $next_filename
    done
    set +o noglob

    cat >> $next_filename <<EOF

######################################################
## destination section
## (where the files are copied to)

[dest]

# perform an incremental backup? (default = yes)
# if incremental = no, perform a full backup in order to start a new backup set
incremental = $dup_incremental

# how many days of data to keep ; default is 60 days.
# (you can also use the time format of duplicity)
# 'keep = yes' means : do not delete old data, the remote host will take care of this
#keep = 60
#keep = yes
keep = $dup_keep

# full destination URL, in duplicity format; if set, desturl overrides
# sshoptions, destdir, desthost and destuser; it also disables testconnect and
# bandwithlimit. For details, see duplicity manpage, section "URL FORMAT".
#desturl = file:///usr/local/backup
#desturl = rsync://user@other.host//var/backup/bla

# bandwith limit, in kbit/s ; default is 0, i.e. no limit
#bandwidthlimit = 128
bandwidthlimit = $dup_bandwidth

# passed directly to ssh, scp (and sftp in duplicity >=0.4.2)
# warning: sftp does not support all scp options, especially -i; as
# a workaround, you can use "-o <SSHOPTION>"
#sshoptions = -o IdentityFile=/root/.ssh/id_dsa_duplicity
sshoptions = $dup_sshoptions

# put the backups under this directory
destdir = $dup_destdir

# the machine which will receive the backups
desthost = $dup_desthost

# make the files owned by this user
# note: you must be able to ssh backupuser@backhost
# without specifying a password (if type = remote).
destuser = $dup_destuser

EOF

    chmod 600 $next_filename

}

dup_main_menu() {

  while true; do
     srcitem="choose files to include & exclude $_src_done"
     destitem="configure backup destination $_dest_done"
     gpgitem="configure GnuPG encryption/signing $_gpg_done"
     conitem="set up ssh keys and test remote connection $_con_done"
     advitem="edit advanced settings $_adv_done"
     # TODO: add the following to the menu when do_dup_conn is written
     # conn "$conitem" \
     menuBox "$dup_title" "choose a step:" \
        src "$srcitem" \
        dest "$destitem" \
        gpg "$gpgitem" \
	adv "$advitem" \
        finish "finish and create config file"
     [ $? = 0 ] || return 1
     result="$REPLY"

     case "$result" in
	"src") do_dup_src;;
	"dest") do_dup_dest;;
	"gpg") do_dup_gpg;;
	# TODO: enable the following when do_dup_conn is written
	# "conn") do_dup_conn;;
	"adv") do_dup_adv;;
	"finish")
           if [[ "$_dest_done$_gpg_done$_src_done" != "(DONE)(DONE)(DONE)" ]]; then
	   # TODO: replace the previous test by the following when do_dup_conn is written
           # if [[ "$_con_done$_dest_done$_gpg_done$_src_done" != "(DONE)(DONE)(DONE)(DONE)" ]]; then
              msgBox "$dup_title" "You cannot create the configuration file until the four first steps are completed."
           else
              do_dup_finish
              break
           fi
           ;;
     esac

  done
}

### Main function

dup_wizard() {
   
   require_packages duplicity

   # Global variables
   dup_title="Duplicity action wizard"
   _src_done=
   _dest_done=
   _con_done=
   _gpg_done=
   _adv_done=
   dup_includes=
   dup_excludes=
   dup_vsincludes=
   dup_incremental=yes
   dup_keep=60
   dup_bandwidth=
   dup_sshoptions=
   dup_destdir="/backups/`hostname`"
   dup_desthost=
   dup_destuser=
   dup_gpg_asymmetric_encryption="yes"
   dup_gpg_encryptkey=""
   dup_gpg_sign="yes"
   dup_gpg_onekeypair="yes"
   dup_gpg_signkey=""
   dup_gpg_password=""
   dup_nicelevel=19
   dup_testconnect=yes
   dup_options=

   # Global variables whose '*' shall not be expanded
   set -o noglob
   dup_default_includes="/var/spool/cron/crontabs /var/backups /etc /root /home /usr/local/*bin /var/lib/dpkg/status*"
   dup_default_excludes="/home/*/.gnupg /home/*/.gnupg /home/*/.local/share/Trash /home/*/.Trash /home/*/.thumbnails /home/*/.beagle /home/*/.aMule /home/*/gtk-gnutella-downloads"
   set +o noglob

   dup_main_menu
}