#!/bin/bash

## A Porteus savefile container manager. 
## Occasionally people experience corruption of their change files
## when using FAT or NTFS file systems. This is due to POSIX overlay
## mismatches. Using a savefile container formated with an xfs file
## system will help towards keeping safe from corruption.

## This program is offered without any guarantee. Use it at your own
## risk. I will not be held responsible for any loss of data or corruption
## caused through the use of this tool. In short, be smart ... backup.
## No guarantee is given, hinted at, implied or inferred in any way
## shape or manner. If you hear voices telling you anything different
## then it's time to change your meds.

## Author: Brokenman <brokenman@porteus.org>
#140405 gettext localize PuppyRus linux Team

export TEXTDOMAIN=make-changes
. gettext.sh

## Switch to root
CHSCRIPT="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
TMP=/tmp/.gtkpns.tmp
if [ ! $DISPLAY ]; then
  if [ `whoami` != "root" ]; then
    echo "$(gettext 'This application requires an xsession.')"
    exit
  fi
else
  if [ `whoami` != "root" ]; then
    echo $HOME > $TMP
    /opt/porteus-scripts/xorg/psu "$CHSCRIPT" || sleep 1
    exit
	else
    [ ! -f $TMP ] && echo $HOME > $TMP
  fi
fi
pth=`<$TMP`
rm $TMP

trap cleanup SIGHUP SIGINT SIGTERM
exec 2>/dev/null

#### Vars
export wrk=/tmp/savefile
PIDLOCK=$wrk/.svdlock
DUMP=$wrk/.dump
EDITOR=`which leafpad||which kwrite||which kate`
export PDIR=`grep -A1 "Porteus data found" /var/log/porteus-livedbg|tail -n1`
PTEST=`echo $PDIR|rev|cut -d / -f1`
if [ "$PTEST" = "" ]; then
 PDIR=${PDIR%/}
fi
PBASE=${PDIR%/*}
PBOOT=${PBASE}/boot
PBASE=${PDIR%/*}
export PBOOT=${PBASE}/boot
export PCFG=${PBOOT}/porteus.cfg
CHANGESTRING=`grep -o "[^ ]*changes=[^ ]*" $PCFG|head -n1`
export SCRIPT="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"

#### Create
[ -d $wrk ] && rm -rf $wrk
mkdir $wrk
echo "0" > $PIDLOCK

#### Functions

function check_close(){
## See if user canceled
if [ `egrep "abort|Cancel" $DUMP` ]; then
	cleanup
	exit
fi
}

function manual_progress(){
# Open a window for progress
export MANUAL_PROGRESS='
<window title="'$(gettext 'Processing now')'"  icon-name="cdr">
<vbox>
  <frame>
    <text width-request="310">
      <label>"'$1'"</label>
      <variable>PROGRESS_TXT</variable>
    </text>
    <progressbar visible="true">
      <variable>PROGRESS_BAR</variable>
      <label>...</label>
      <input>prog_counter</input>
    </progressbar>
  </frame>
</vbox>
</window>
'
gtkdialog -c -p MANUAL_PROGRESS 2>$wrk/.progress_trap &
}; export -f manual_progress

## This is called by the manual_progress function. 
function prog_counter(){
case $STATE in
DOWNLOAD )
while [ A != B ]; do
    if [ -f $wrk/.cdload ]; then M=`cat $wrk/.cdload`; echo "$M"; fi
    sleep 0.3
    [ `grep "100%" $wrk/in` ] && echo 1
    i=$(grep -o "[^ ]*%[^ ]*" $wrk/in|sed "s/%//g"|tail -n1)
    [ "$i" == "100" ] && i=1
    [ "$i" != "" ] && echo "$i"
    sleep 0.3
done
echo "$(gettext 'ALL DONE')"
unset STATE
;;
MANUAL )
while [ A != B ]; do
    MSG=`cat $wrk/in`
    echo "$MSG"
    sleep 0.3
done
unset STATE
[ -f $wrk/.cdload ] && rm $wrk/.cdload 2>&-
esac

}; export -f prog_counter

function kill_manual_progress() {
unset DOWNLOAD MANUAL
myself=`ps ax|grep MANUAL_PROGRESS|awk '{print$1}'|head -n1`
for children in `ps -o pid --ppid $myself|sed '/PID/d'`; do
kill $children >/dev/null 2>&-
done
kill $myself >/dev/null 2>&-
}; export -f kill_manual_progress

function gtk_message(){
export PMESSAGE='
<window window_position="1" title="'$(gettext 'Porteus message')'" icon-name="cdr" allow-shrink="false" width-request="'$2'">
<vbox>
 <hbox>
  <frame>
  <pixmap icon_size="6">
   <input file stock="'$3'"></input>
  </pixmap>
  </frame>
  <frame>
  <text wrap="true"><label>"'$1'"</label></text>
  </frame>
 </hbox>
 <hbox>
  <button ok></button>
 </hbox>
</vbox>
</window>
'
gtkdialog -p PMESSAGE > $wrk/junk
}; export -f gtk_message

## Check that we are not in aufs. Although the file will be generated new users
## might think they can leave the savefile in aufs. Anyway there is limited
## space in aufs and sometimes user may want a large savefile.
function check_aufs(){
if [ `df -T $TARG|tail -n1|awk '{print$1}'` == "aufs" ]; then
  gtk_message "$(eval_gettext "Sorry, \$TARG is inside the live filesystem. You must store your change file outside of aufs.")" 500 gtk-dialog-warning
  unset NOSPACE SSIZE BYTES TARG
  main_menu
  return
fi
}; export -f check_aufs

## A yes/no dialog that dumps to $wrk/.yesno
## 1=text 2=width 3=gtk-stock icon
function gtk_yesno(){
export YESNO='
<window window_position="1" title="'$(gettext 'yes or no')'" icon-name="cdr" allow-shrink="false" width-request="'$2'">
<vbox>
 <hbox>
  <frame>
  <pixmap icon_size="6">
   <input file stock="'$3'"></input>
  </pixmap>
  </frame>
  <frame>
  <text><label>"'$1'"</label></text>
  </frame>
 </hbox>
 <hbox>
  <button yes></button>
  <button no></button>
 </hbox>
</vbox>
</window>
'
gtkdialog -c -p YESNO > $wrk/.yesno
}; export -f gtk_yesno

function check_free_space(){
FSPACE=`df $1|tail -n1|awk '{print$4}'`
#FSPACE=$(($FSPACEB/1024))
echo "FSPACE=$FSPACE" >> $DUMP
[ $BYTES -gt $FSPACE ] && export NOSPACE=1 || unset NOSPACE
}

function cleanup(){
rm -rf $wrk >/dev/null 2>&1
rm -rf /mnt/vault*
[ -f $PIDLOCK ] && rm $PIDLOCK
}

function check_loop(){
x=`ls -1 /dev/loop*|tr -d [:alpha:][:punct:]|sort -g|tail -n1`
let y=x+1
loop=/dev/loop$y
[ ! -e $loop ] && mknod $loop b 7 $y
}

function create_encrypted_savefile(){
export STATE=MANUAL
echo "$(eval_gettext "Creating \$NAME.dat")" > $wrk/in
manual_progress "$(gettext 'Creating file')"
dd if=/dev/urandom of=$TARG/$NAME.dat bs=1024 count=$BYTES 2> /dev/null
check_loop
losetup $loop $TARG/$NAME.dat
cryptsetup -y -s 256 luksFormat $loop <<< $PPHRASE
cryptsetup luksOpen $loop crypt <<< $PPHRASE || bad_passphrase
newcrypt=1
format_savefile
cryptsetup luksClose crypt
losetup -d $loop
kill_manual_progress
}

function bad_passphrase(){
gtk_message "$(gettext 'No key available with this passphrase.')" 500 gtk-dialog-warning
cleanup
exit
};export -f bad_passphrase

function resize_old_dat(){
## Check all options are present
NSIZE=`grep "NSIZE=" $DUMP|awk -F= '{print$NF}'`
OLDAT=`grep "RESIZEDAT=" $DUMP|awk -F= '{print$NF}'`
NEWLOC=`grep "NEWLOCATION2=" $DUMP|awk -F= '{print$NF}'`
[ -z $NEWLOC ] && MISSING=1
[ -z $OLDAT ] && MISSING=1
[ -z $NSIZE ] && MISSING=1
if [ $MISSING ]; then
  gtk_message "$(gettext 'You seem to have missed a setting. Aborting.')" 500 gtk-dialog-warning
  unset MISSING
  main_menu
fi

## Get the name of the existing savefile
SAVENAME=${OLDAT##*/}
NAME=${SAVENAME%.*}
TARG=${NEWLOC}

## Make sure we are not on aufs file system
check_aufs

## If a savefile exists in same place with same name then give new one a new name
#if [ -f $TARG/$NAME.dat ]; then $NAME=$NAME-2; fi

mpoint=/mnt/vault
[ ! -d $mpoint ] && mkdir $mpoint || umount $mpoint >/dev/null 2>&1
check_loop

## Get size of new file
SSIZE=`grep "NSIZE=" $DUMP|tr -d [:alpha:][:punct:]`
BYTES=$(($SSIZE*1024))
echo "BYTES=$BYTES" >> $DUMP

## Make sure we have enough room in chosen destination
## this will compare SSIZE to destination
check_free_space $NEWLOC
if [ $NOSPACE ]; then
	gtk_message "$(eval_gettext "Sorry. The location you chose is smaller than \$SSIZE Mb")" 500 gtk-dialog-warning
	unset NOSPACE
	main_menu
fi

## Is the dat file encrypted?
if blkid $OLDAT 2>/dev/null| grep -o _LUKS; then
	export ENCRYPTED=1
	create_passphrase
	losetup $loop $OLDAT
	cryptsetup luksOpen $loop crypt <<< $PPHRASE || bad_passphrase
	mount /dev/mapper/crypt $mpoint
		else
	mount -t auto -o loop $OLDAT $mpoint
fi

## Get current file system of savefile
if [ $ENCRYPTED ]; then
	OLDATYPE=`df -T $mpoint|tail -n1|awk '{print$2}'`
		else
	OLDATYPE=`blkid $OLDAT|egrep -o "reiserfs|xfs|ext4"`
fi

[ "$OLDATYPE" == "reiserfs" ] && formatme="mkfs.reiserfs -q"
[ "$OLDATYPE" == "xfs" ] && formatme="mkfs.xfs"
[ "$OLDATYPE" == "ext4" ] && formatme="mkfs.ext4"

## Create the new savefile (encrypted if old one is encrypted)
nmpoint=/mnt/vault2
[ ! -d $nmpoint ] && mkdir $nmpoint || umount $nmpoint 2>/dev/null


## We need to create another loop. one for old and one for new.
loop1=${loop}
check_loop
loop2=${loop}

## Change name if destination file already exists
[ -f $TARG/$NAME.dat ] && NAME=$NAME-2

## Create the new savefile
if [ $ENCRYPTED ]; then
	export STATE=MANUAL
	echo "$(eval_gettext "Creating \$NAME.dat")" > $wrk/in
	manual_progress "$(gettext 'Creating file')"
	dd if=/dev/zero of=$TARG/$NAME.dat bs=1024 count=$BYTES 2> /dev/null
	losetup $loop2 $TARG/$NAME.dat
	cryptsetup -y -s 256 luksFormat $loop2 <<< $PPHRASE
	cryptsetup luksOpen $loop2 crypt2 <<< $PPHRASE || bad_passphrase
	$formatme /dev/mapper/crypt2 >/dev/null 2>&1
	mount /dev/mapper/crypt2 $nmpoint 2>/dev/null
		else
	export STATE=MANUAL
	echo "$(eval_gettext "Creating \$NAME.dat")" > $wrk/in
	manual_progress "$(gettext 'Working now ...')"
	dd if=/dev/zero of=$TARG/$NAME.dat bs=1024 count=$BYTES 2> /dev/null
	echo "$(gettext 'Formating savefile ...')" > $wrk/in
	$formatme $TARG/$NAME.dat <<<y > /dev/null 2>&1
	sleep 2
	unset STATE
	mount -t auto -o loop $NEWLOC/$NAME.dat $nmpoint
fi

## Copy old data across to new container
echo "$(gettext 'Copying data to new container ...')" > $wrk/in
cp -a $mpoint/. $nmpoint/

## Unmount the old savefile and delete if requested
umount $mpoint
umount $nmpoint

if [ $ENCRYPTED ]; then
cryptsetup luksClose crypt
cryptsetup luksClose crypt2
losetup -d $loop1
losetup -d $loop2
unset ENCRYPTED
fi

[ `grep "DELETEME2=true" $DUMP` ] && rm -f $OLDAT
echo "ALL DONE !!!" > $wrk/in
sleep 4
kill_manual_progress

gtk_message "$(eval_gettext "Your savefile has been created at:
\$TARG/$NAME.dat. 

To have the changes stored in this file you will need to edit a line in your porteus.cfg file.")" 500 gtk-yes
cleanup
exit
}

function encrypt_savefile(){
OLDAT=`grep "OLDAT=" $DUMP|awk -F= '{print$NF}'`
NEWLOC=`grep "NEWLOCATION=" $DUMP|awk -F= '{print$NF}'`
[ -z $NEWLOC ] && MISSING=1
[ -z $OLDAT ] && MISSING=1
if [ $MISSING ]; then
  gtk_message "$(gettext 'You seem to have missed a setting. Aborting.')" 500 gtk-dialog-warning
  unset MISSING
  main_menu
fi

## Get the name of the existing savefile
SAVENAME=${OLDAT##*/}
NAME=${SAVENAME%.*}
TARG=${NEWLOC}

## Check if savefile is already encrypted
ISENCRYPTED=`file $OLDAT|grep LUKS`
if [ `file $OLDAT|grep -o LUKS` ]; then
	gtk_message "$(eval_gettext "\$SAVENAME is already encrypted!")" 400 gtk-dialog-warning
	unset OLDAT NEWLOC ISENCRYPTED NAME SAVENAME TARG
	main_menu
	exit
fi

## Get existing savefile size
SSIZEKB=`du $OLDAT|awk '{print$1}'`
TARGSIZE=`df $TARG|tail -n1|awk '{print$4}'`
SREQMB=$(($SSIZEKB/1024))
if [ $SSIZEKB -gt $TARGSIZE ]; then
	gtk_message "$(eval_gettext "Sorry. The location you chose requires at least \$SREQMB Mb of free space.")" 500 gtk-dialog-warning
	unset NOSPACE
	main_menu
fi

## Create the new savefile (encrypted if old one is encrypted)
mpoint=/mnt/vault
[ ! -d $mpoint ] && mkdir $mpoint || umount $mpoint 2>/dev/null
nmpoint=/mnt/vault2
[ ! -d $nmpoint ] && mkdir $nmpoint || umount $nmpoint 2>/dev/null


## We need to create another loop, just in case there are none free.
check_loop

## Get passphrase for new encrypted savefile
create_passphrase

## Mount old savefile
mount -t auto -o loop $OLDAT $mpoint

## Get current file system
## Get current file system of savefile
OLDATYPE=`blkid $OLDAT|egrep -o "reiserfs|xfs|ext4"`
[ "$OLDATYPE" == "reiserfs" ] && formatme="mkfs.reiserfs -q"
[ "$OLDATYPE" == "xfs" ] && formatme="mkfs.xfs"
[ "$OLDATYPE" == "ext4" ] && formatme="mkfs.ext4"

## Create the new encrypted savefile and mount
[ -f $TARG/$NAME.dat ] && NAME=$NAME-enc
export STATE=MANUAL
echo "$(eval_gettext "Creating \$NAME.dat")" > $wrk/in
manual_progress "$(gettext 'Creating file')"
dd if=/dev/urandom of=$TARG/$NAME.dat bs=1024 count=$SSIZEKB 2> /dev/null
losetup $loop $TARG/$NAME.dat
cryptsetup -y -s 256 luksFormat $loop <<< $PPHRASE
cryptsetup luksOpen $loop crypt <<< $PPHRASE || bad_passphrase
$formatme /dev/mapper/crypt >/dev/null 2>&1
mount /dev/mapper/crypt $nmpoint 2>/dev/null

## Copy old data to new savefile
echo "$(gettext 'Transfering data to vault ...')" > $wrk/in
cp -a $mpoint/. $nmpoint/

## Unmount old save file and delete if requested
umount $mpoint
if [ `grep "DELETEME=true" $DUMP` ]; then
	rm -f $OLDAT
fi

## Unmount new savfile
umount $nmpoint
cryptsetup luksClose crypt
losetup -d $loop
kill_manual_progress

## Notify that we are done
gtk_message "$(eval_gettext "Your savefile has been created at:
\$TARG/\$NAME.dat. 

To have the changes stored in this file you will need to edit a line in your porteus.cfg file.")" 500 gtk-yes
cleanup
}

function create_passphrase(){
secret=$wrk/.passphrase
export CREATE_A_PASSPRASE='
<window window_position="1" title="'$(gettext 'Passphrase')'" width-request="400" icon-name="cdr" resizable="false">
<vbox margin="20">
	<text use-markup="true">
		<label>"'$(gettext 'Please provide a passphrase which will be used to decrypt your savefile container.')'"</label>
	</text>
	<frame>
		<hbox>
			<text width-request="90"><label>'$(gettext 'Passphrase:')'</label></text>
			<entry visibility="false" invisible-char="120" tooltip-text="visibility, invisible-char">
				<default>""</default>
				<variable>pp</variable>
				<action signal="changed">enable:pp2</action>
			</entry>
		</hbox>
		<hbox>
			<text width-request="90"><label>'$(gettext 'Repeat:')'</label></text>
			<entry visibility="false" invisible-char="120" tooltip-text="visibility, invisible-char" sensitive="false">
				<default>""</default>
				<variable>pp2</variable>
			</entry>
		</hbox>
	</frame>
	<hbox>
		<button ok></button>
		<button cancel></button>
	</hbox>
</vbox>
</window>'
gtkdialog -p CREATE_A_PASSPRASE > $secret
[ `egrep "Exit|exit|abort|Cancel|cancel" $secret` ] && { rm $secret; exit; }

## Make sure the passwords matched
sed -i 's@"@@g' $secret
p1=`grep "pp=" $secret|awk -F= '{print$NF}'`
p2=`grep "pp2=" $secret|awk -F= '{print$NF}'`
rm $secret
if [ "$p1" != "$p2" ]; then
	gtk_message "$(gettext 'PASSWORDS DO NOT MATCH!!!')" 500 gtk-dialog-warning
	unset p1 p2
	$FUNCNAME
	return
fi

## Make sure password is not blank
if [ -z "$p1" -o -z "$p2" ]; then
	gtk_message "$(gettext 'BLANK PASSWORDS NOT ALLOWED!!!')" 500 gtk-dialog-warning
	unset p1 p2
	$FUNCNAME
	return
fi
export PPHRASE=${p2}
unset p1 p2
}; export -f create_passphrase

function create_savefile(){
## Check that all values were given
[ -z `grep "SDIR=" $DUMP|awk -F= '{print$NF}'` ] && MISSING=1
[ -z `grep "SNAME=" $DUMP|awk -F= '{print$NF}'` ] && MISSING=1
if [ $MISSING ]; then
  gtk_message "$(gettext 'You seem to have missed a setting. Start again.')" 500 gtk-dialog-warning
  unset MISSING
  main_menu
  exit
fi

## Check we have sufficient space
SSIZE=`grep "SSIZE=" $DUMP|tr -d [:alpha:][:punct:]`
BYTES=$(($SSIZE*1024))
TARG=`grep "SDIR=" $DUMP|awk -F= '{print$NF}'`
check_free_space $TARG
if [ $NOSPACE ]; then
  gtk_message "$(eval_gettext "Sorry, there is not enough space at:\$TARG")" 500 gtk-dialog-warning
  unset NOSPACE
  main_menu
fi

# Check we are not saving to aufs
check_aufs

## Remove the savefile extension if it exists
SNAME1=`grep "SNAME=" $DUMP|awk -F= '{print$NF}'`
NAME=${SNAME1%.*}

## Are we encrypting the save file?
grep "ENCRYPTME=true" $DUMP && ENCRYPTME=1 || unset ENCRYPTME

## Make sure the target is writable
if [ ! -w $TARG ]; then
  gtk_message "$(gettext 'Sorry, your target directory is NOT writable!')" 500 gtk-dialog-warning
  unset SNAME1 NAME TARG ENCRYPTME SSIZE BYTES
  $FUNCNAME
  return
  exit
fi

## If encrypting then ask for passphrase
if [ $ENCRYPTME ]; then
	create_passphrase
	create_encrypted_savefile
	kill_manual_progress
		else
	export STATE=MANUAL
	echo "$(eval_gettext "Creating \$NAME.dat")" > $wrk/in
	manual_progress "$(gettext 'Working now ...')"
	[ -f $TARG/$NAME.dat ] && NAME=$NAME-2
	dd if=/dev/zero of=$TARG/$NAME.dat bs=1024 count=$BYTES 2> /dev/null
	echo "$(gettext 'Formating savefile ...')" > $wrk/in
#	mkfs.xfs $TARG/$NAME.dat > /dev/null 2>&1
	format_savefile
	sleep 2
	unset STATE
	kill_manual_progress
fi

gtk_message "$(eval_gettext "Your savefile has been created at:
\$TARG/\$NAME.dat

To have the changes stored in this file you will need to edit a line in your porteus.cfg file.")" 500 gtk-yes
exit
}; export -f create_savefile

function format_savefile(){
dmc=/dev/mapper/crypt
## Check which filesystem user chose in $DUMP file.
## We need to feed 'yes' to terminal because it will complain
## about the device not being valid block.
case `grep "FSYSTEM=" $DUMP|awk -F= '{print$NF}'` in
reiserfs )
if [ $newcrypt ]; then
	mkreiserfs -f $dmc <<<YES
		else
	mkreiserfs -f $TARG/$NAME.dat <<<y
fi
return
;;
ext4 )
if [ $newcrypt ]; then
	mkfs.ext4 $dmc <<<YES
		else
	mkfs.ext4 $TARG/$NAME.dat <<<y
fi
return
;;
xfs )
if [ $newcrypt ]; then
	mkfs.xfs $dmc <<<YES
		else
	mkfs.xfs $TARG/$NAME.dat <<<y
fi
return
;;
esac
}

function slay_rogues(){
## Kill any stray process
KSCRIPT=${SCRIPT##*/}
for a in `ps x|grep $KSCRIPT|egrep -v "grep|kwrite|leafpad|mousepad"|awk '{print$1}'`; do
	kill $a >/dev/null 2>&1
done
}

function recover_savefile(){
export STATE=MANUAL
OLDAT=`grep "RECSRC=" $DUMP|awk -F= '{print$NF}'`
[ -z $OLDAT ] && MISSING=1

if [ $MISSING ]; then
  gtk_message "$(gettext 'You seem to have missed a setting. Aborting.')" 500 gtk-dialog-warning
  unset MISSING OLDAT
  main_menu
fi

## If the file system is encrypted then we can't attempt recovery
if [[ `file $OLDAT|grep LUKS` ]]; then
	gtk_message "$(gettext 'Sorry, your savefile has been encrypted and recovery is not possible using this tool.')" 500 gtk-dialog-warning
	unset MISSING OLDAT
	main_menu
	exit
fi

## Find the filesystem for the savefile container
OLDATYPE=`blkid $OLDAT |egrep -o "reiserfs|xfs|ext4"`

## Repair savefile based on filesystem
case $OLDATYPE in
reiserfs )
echo "$(gettext 'Attempting resierfs repair now ...')" > $wrk/in
manual_progress "$(gettext 'Recovery')"
fsck.reiserfs --fix-fixable -y $OLDAT 2> /tmp/savefile-recovery.log
echo "$(gettext 'Repair attempt complete!!')" > $wrk/in
sleep 4
kill_manual_progress
gtk_message "$(gettext 'Please read log file in /tmp/savefile-recovery.log')" 500 gtk-yes
cleanup
;;
xfs )
echo "$(gettext 'Attempting xfs repair now ...')" > $wrk/in
manual_progress "$(gettext 'Recovery')"
xfs_repair -f $OLDAT 2> /tmp/savefile-recovery.log
echo "$(gettext 'Repair attempt complete!!')" > $wrk/in
sleep 4
kill_manual_progress
gtk_message "$(gettext 'Please read log file in /tmp/savefile-recovery.log')" 500 gtk-yes
cleanup
;;
ext4 )
echo "$(gettext 'Attempting ext4 repair now ...')" > $wrk/in
manual_progress "$(gettext 'Recovery')"
fsck.ext4 -p -f -v $OLDAT > /tmp/savefile-recovery.log
echo "$(gettext 'Repair attempt complete!!')" > $wrk/in
sleep 4
kill_manual_progress
gtk_message "$(gettext 'Please read log file in /tmp/savefile-recovery.log')" 500 gtk-yes
cleanup
;;
esac

exit
}; export -f recover_savefile

function main_menu(){
export varSize="$(gettext 'Existing size: ')"
export MAIN_MENU_SAVEDAT='
<window window_position="1" title="'$(gettext 'Savefile manager')'"  icon-name="gtk-save" resizable="false">
<notebook show-tabs="false" show-border="false" labels="Main|Create|Resize|Encrypt|Repair|Help">
<vbox margin="15">
	<hseparator></hseparator>
	<text use-markup="true">
		<label>"<span color='"'darkred'"' weight='"'bold'"' size='"'x-large'"'>'$(gettext 'Manage your savefile.')'</span>"</label>
	</text>
	<text use-markup="true" xalign="0" width-request="540"><label>"'$(gettext '<b>Only required for saving changes on FATx or NTFS filesystems.</b>')'"</label></text>
	<hbox>
	<frame>
		<vbox homogeneous="true">
		<text use-markup="true" width-request="450"><label>"<span color='"'darkblue'"' weight='"'bold'"' size='"'large'"'>'$(gettext 'I want to create a new savefile')'</span>"</label></text>
		<text xalign="0"><label>'$(gettext 'Create a savefile for Porteus')'</label></text>
		</vbox>
	</frame>
		<button image-position="2" height-request="36">
			<label>"'$(gettext ' Create ')'"</label>
			<input file stock="gtk-add"></input>
			<action>echo 1 > '$PIDLOCK'</action>
			<action>Refresh:nbkSvd</action>
		</button>
	</hbox>
	<hbox>
	<frame>
		<vbox homogeneous="true">
		<text use-markup="true" width-request="450"><label>"<span color='"'darkblue'"' weight='"'bold'"' size='"'large'"'>'$(gettext 'I want to resize a savefile')'</span>"</label></text>
		<text xalign="0"><label>'$(gettext 'Resize an existing savefile')'</label></text>
		</vbox>
	</frame>
		<button image-position="2" height-request="36">
			<label>"'$(gettext ' Resize ')'"</label>
			<input file stock="gtk-goto-top"></input>
			<action>echo 2 > '$PIDLOCK'</action>
			<action>Refresh:nbkSvd</action>
		</button>
	</hbox>
	<hbox>
	<frame>
		<vbox homogeneous="true">
		<text use-markup="true" width-request="450"><label>"<span color='"'darkblue'"' weight='"'bold'"' size='"'large'"'>'$(gettext 'I want to encrypt a savefile')'</span>"</label></text>
		<text xalign="0"><label>'$(gettext 'Encrypt an existing savefile. Requires password during boot.')'</label></text>
		</vbox>
	</frame>
		<button image-position="2" height-request="36">
			<label>'$(gettext 'Encrypt')'</label>
			<input file stock="gtk-dialog-authentication"></input>
			<action>echo 3 > '$PIDLOCK'</action>
			<action>Refresh:nbkSvd</action>
		</button>
	</hbox>
	<hbox>
	<frame>
		<vbox homogeneous="true">
		<text use-markup="true" width-request="450"><label>"<span color='"'darkblue'"' weight='"'bold'"' size='"'large'"'>'$(gettext 'I want to recover a savefile')'</span>"</label></text>
		<text xalign="0"><label>'$(gettext 'Recover an existing savefile after corruption')'</label></text>
		</vbox>
	</frame>
		<button image-position="2" height-request="36">
			<label>"'$(gettext ' Repair ')'"</label>
			<input file stock="gtk-revert-to-saved"></input>
			<action>echo 4 > '$PIDLOCK'</action>
			<action>Refresh:nbkSvd</action>
		</button>
	</hbox>
	<text><label>""</label></text>
	<hbox>
		<button height-request="36">
			<label>'$(gettext 'Help')'</label>
			<input file stock="gtk-help"></input>
			<action>echo 5 > '$PIDLOCK'</action>
			<action>Refresh:nbkSvd</action>
		</button>
		<button width-request="90">
		        <input file stock="gtk-quit"></input>
			<label>'$(gettext 'Exit')'</label>
		</button>
	</hbox>
</vbox>




<vbox margin="10">
	<text use-markup="true" width-request="450"><label>"<span color='"'darkblue'"' weight='"'bold'"' size='"'large'"'>'$(gettext 'Create new save container')'</span>"</label></text>
	<text xalign="0" width-request="530" use-markup="true">
		<label>"'$(gettext '
1) Enter the preferred name of your savefile. 

2) Type the desired size for your savefile. <b>(Mb)</b>

3) Choose the directory where you would like to keep your save file.

4) Choose if you would like an encrypted savefile. <i>(requires password at boot)</i>')'"</label></text>

	<text><label>""</label></text>
	<hseparator></hseparator>
 	<hbox>
		<text>
			<label>'$(gettext 'Savefile name:')'</label>
		</text>
		<entry>
			<input>echo `hostname`-save</input>
			<variable>SNAME</variable>
		</entry>
		<text>
			<label>'$(gettext 'Savefile size:')'</label>
		</text>
		<entry>
			<input>echo 512</input>
			<variable>SSIZE</variable>
		</entry>
		<text use-markup="true">
			<label>"'$(gettext '<b>(Mb)</b>')'"</label>
		</text>
	</hbox>
	<hseparator></hseparator>
	<hbox>
		<text label="'$(gettext 'Location:  ')'" width-request="80"></text>
		<entry editable="false" fs-title="'$(gettext 'Select an existing folder')'" fs-action="folder" fs-folder="/mnt">
			<variable>SDIR</variable>
		</entry>
		<button>
			<input file stock="gtk-directory"></input>
			<action>fileselect:SDIR</action>
		</button>
	</hbox>
	<hseparator></hseparator>
	<text use-markup="true"><label>"'$(gettext '<b>The options below are for advanced users only:</b>')'"</label></text>
	<hbox>
	<comboboxtext fs-action="file">
		<variable>FSYSTEM</variable>
		<item>ext4</item>
'

##sfs
if [ ! "`which ntf 2>/dev/null`" ] ;then
export MAIN_MENU_SAVEDAT="$MAIN_MENU_SAVEDAT"'
		<item>xfs</item>
		<item>reiserfs</item>
'
else
export MAIN_MENU_SAVEDAT="$MAIN_MENU_SAVEDAT"'
		<item>pfs</item>
'
fi

export MAIN_MENU_SAVEDAT="$MAIN_MENU_SAVEDAT"'
	</comboboxtext>
	<text xalign="0" use-markup="true" width-request="430">
		<label>"<span color='"'darkred'"' weight='"'bold'"' size='"'small'"'>'$(gettext '(Please choose your preferred linux file system for the savefile)')'</span>"</label>
	</text>
	</hbox>
	<hbox>
	<checkbox active="false" tooltip-text="'$(gettext 'Create an encrypted savefile.')'">
		<label>'$(gettext 'Encrypt my savefile')'</label>
		<variable>ENCRYPTME</variable>
	</checkbox>
	<text xalign="0" use-markup="true">
		<label>"<span color='"'darkred'"' weight='"'bold'"' size='"'small'"'>'$(gettext '(Choosing to encrypt requires a password during boot)')'</span>"</label>
	</text>
	</hbox>
	<text use-markup="true"><label>""</label></text>

<hbox>
		<button width-request="72" height-request="36">
			<label>'$(gettext 'OK')'</label>
			<input file stock="gtk-yes"></input>
			<action>exit:CREATESAVEFILE</action>
			<action signal="activate">exit:CREATESAVEFILE</action>
		</button>
		<button height-request="36">
			<label>'$(gettext 'Back')'</label>
			<input file stock="gtk-go-back"></input>
			<action>echo 0 > '$PIDLOCK'</action>
			<action>refresh:nbkSvd</action>
		</button>
</hbox>
</vbox>




<vbox margin="10">
	<text use-markup="true" width-request="450"><label>"<span color='"'darkblue'"' weight='"'bold'"' size='"'large'"'>'$(gettext 'Resize existing savefile')'</span>"</label></text>
		<frame>
			<text width-request="500"><label>"'$(gettext 'Use this function to resize an existing savefile (encrypted or unencrypted) when you are running out of space in your existing savefile and need to enlarge it. This function could be also used to shrink existing container if needed. Existing changes will not be lost during this process.')'"</label></text>
		</frame>
	<text xalign="0" use-markup="true"><label>"'$(gettext '
1) Choose the location of your existing savefile

2) Choose the new size of your savefile

3) Press OK')'"</label></text>
	<hseparator></hseparator>
	<hbox>
		<text label="'$(gettext 'Existing file: ')'"></text>
		<entry editable="false" fs-title="'$(gettext 'Select an existing savefile')'" fs-action="file" fs-folder="/mnt">
			<variable>RESIZEDAT</variable>
		</entry>
		<button>
			<input file stock="gtk-directory"></input>
			<action>fileselect:RESIZEDAT</action>
			<action>enable:DELETEME2</action>
			<action>enable:ENCRYPTME</action>
			<action type="command">du -sh $RESIZEDAT|cut -d/ -f1 > /tmp/file.tmp</action>
			<action>enable:existingsize</action>
			<action>refresh:existingsize</action>
			<action type="command">rm /tmp/file.tmp</action>
		</button>
	</hbox>
	<hbox>
		<text label="'$(gettext 'New location:  ')'" width-request="120"></text>
		<entry editable="false" fs-title="'$(gettext 'Select a destination')'" fs-action="folder" fs-folder="/mnt">
			<variable>NEWLOCATION2</variable>
		</entry>
		<button>
			<input file stock="gtk-directory"></input>
			<action>fileselect:NEWLOCATION2</action>
		</button>
	</hbox>
	<hbox>
		<text>
			<label>'$(gettext 'New size:')'</label>
		</text>
		<entry>
			<input>echo 512</input>
			<variable>NSIZE</variable>
		</entry>
		<text use-markup="true">
			<label>"'$(gettext '<b>(Mb)</b>  | ')'"</label>
		</text>
		<text width-request="140"><label>'$(gettext 'Current savefile size: ')'</label></text>
		<text><label>'$(gettext 'Unknown')'</label><sensitive>false</sensitive><variable>existingsize</variable><input file>/tmp/file.tmp</input></text>
	</hbox>
	<checkbox active="false" sensitive="false" tooltip-text="'$(gettext 'Delete the old savefile when done.')'">
		<label>'$(gettext 'Delete existing savefile when done')'</label>
		<variable>DELETEME2</variable>
	</checkbox>
	<hbox>
		<button width-request="72" height-request="36">
			<label>'$(gettext 'OK')'</label>
			<input file stock="gtk-yes"></input>
			<action>exit:RESIZESAVEFILE</action>
		</button>
		<button height-request="36">
			<label>'$(gettext 'Back')'</label>
			<input file stock="gtk-go-back"></input>
			<action>echo 0 > '$PIDLOCK'</action>
			<action>refresh:nbkSvd</action>
		</button>
	</hbox>
</vbox>


<vbox margin="10">
	<text use-markup="true" width-request="450" xalign="0"><label>"<span color='"'darkblue'"' weight='"'bold'"' size='"'large'"'>'$(gettext 'Encrypt an existing savefile')'</span>"</label></text>
		<frame>
			<text width-request="500"><label>"'$(gettext 'Use this function to encrypt an existing savefile to help protect your Porteus files. This is useful if you carry Porteus on portable media, and it falls into the wrong hands. A password is required during boot in order to decrypt the changes savefile. If an incorrect password is entered Porteus will boot into Always Fresh Mode.')'"</label></text>
		</frame>
	<text xalign="0" use-markup="true"><label>"'$(gettext '
1) Choose the location of your existing savefile

2) Choose the location of your new savefile

3) Press OK')'"</label></text>
	<hseparator></hseparator>
	<hbox>
		<text label="'$(gettext 'Existing savefile:  ')'" width-request="120"></text>
		<entry editable="false" fs-title="'$(gettext 'Select an existing savefile')'" fs-action="file" fs-folder="/mnt">
			<variable>OLDAT</variable>
		</entry>
		<button>
			<input file stock="gtk-directory"></input>
			<action>fileselect:OLDAT</action>
			<action>enable:DELETEME</action>
		</button>
	</hbox>
	<hbox>
		<text label="'$(gettext 'New location:  ')'" width-request="120"></text>
		<entry editable="false" fs-title="'$(gettext 'Select a destination')'" fs-action="folder" fs-folder="/mnt">
			<variable>NEWLOCATION</variable>
		</entry>
		<button>
			<input file stock="gtk-directory"></input>
			<action>fileselect:NEWLOCATION</action>
		</button>
	</hbox>
<checkbox active="false" sensitive="false" tooltip-text="'$(gettext 'Delete the old savefile when done.')'">
		<label>'$(gettext 'Delete existing savefile when done')'</label>
		<variable>DELETEME</variable>
	</checkbox>
	<hbox>
		<button width-request="72" height-request="36">
			<label>'$(gettext 'OK')'</label>
			<input file stock="gtk-yes"></input>
			<action>exit:ENCRYPTSAVEFILE</action>
		</button>
		<button height-request="36">
			<label>'$(gettext 'Back')'</label>
			<input file stock="gtk-go-back"></input>
			<action>echo 0 > '$PIDLOCK'</action>
			<action>refresh:nbkSvd</action>
		</button>
	</hbox>
</vbox>


<vbox margin="10">
	<text use-markup="true" width-request="450" xalign="0"><label>"<span color='"'darkblue'"' weight='"'bold'"' size='"'large'"'>'$(gettext 'Repair a corrupt savefile')'</span>"</label></text>
		<frame>
			<text width-request="500"><label>"'$(gettext 'If you experience corruption of your savefile you can attempt to recover the file using this function. It uses the appropriate repair executable depending on which file system you have for your savefile container.

The recovery process is not always successfull and a log final will be left at
 /tmp/savefile-recovery.log')'"</label></text>
		</frame>
	<text xalign="0" use-markup="true"><label>"'$(gettext '
1) Choose the location of your existing savefile

2) Click recover

	')'"</label></text>
	<hseparator></hseparator>
	<hbox>
		<text label="'$(gettext 'Existing savefile:  ')'" width-request="120"></text>
		<entry editable="false" fs-title="'$(gettext 'Select an existing savefile')'" fs-action="file" fs-folder="/mnt">
			<variable>RECSRC</variable>
		</entry>
		<button>
			<input file stock="gtk-directory"></input>
			<action>fileselect:RECSRC</action>
		</button>
	</hbox>
	<hbox>
		<button>
			<label>'$(gettext 'Recover')'</label>
			<input file stock="gtk-yes"></input>
			<action>exit:RECOVERSAVEFILE</action>
		</button>
		<button height-request="36">
			<label>'$(gettext 'Back')'</label>
			<input file stock="gtk-go-back"></input>
			<action>echo 0 > '$PIDLOCK'</action>
			<action>refresh:nbkSvd</action>
		</button>
	</hbox>
</vbox>


<vbox margin="10" scrollable="true">
	<text use-markup="true" width-request="450" xalign="0"><label>"<span color='"'darkblue'"' weight='"'bold'"' size='"'large'"'>'$(gettext 'Savefile help')'</span>"</label></text>
	<frame>
	<text use-markup="true"width-request="480" xalign="0"><label>"'$(gettext 'By default Porteus will save changes when started in lxde, kde and xfce. If you are using Porteus on a <b>FAT or NTFS</b> filesystem then you should create a savefile  to store your changes. This is simply a file that acts as a container <i>(formatted with a native linux filesystem)</i> to hold your changes. 

If you do not create this container you may experience corruption due to POSIX overlay mismatches. Using the container negates the need for POSIX and your changes will be mounted into the live filesystem during boot. You have the option to encrypt your savefile container which adds a layer of security. You will be required to enter a password during boot in order to inject the changes into the system. 

This application contains a savefile recovery option which can be used if your savefile container becomes corrupt. Keep in mind that an encrypted container <b>can not</b> be recovered using this tool.


<i>Team Porteus</i>
')'"</label></text>
	</frame>
	<hbox>
		<button>
			<label>'$(gettext 'Back')'</label>
			<input file stock="gtk-go-back"></input>
			<action>echo 0 > '$PIDLOCK'</action>
			<action>refresh:nbkSvd</action>
		</button>
	</hbox>
</vbox>

<variable>nbkSvd</variable>
<input file>"'$PIDLOCK'"</input>
</notebook>
</window>
'
gtkdialog -p MAIN_MENU_SAVEDAT > $DUMP

## Did user close the window?
check_close
[ "`egrep '^FSYSTEM="pfs"$' $DUMP`" ]  && (create-save-pfs &) && exit ##sfs

## Cleanup the info dump
sed -i 's/"//g' $DUMP
sed -i '/_ALL/d' $DUMP



## Check user answer
[ `grep CREATESAVEFILE $DUMP` ] && create_savefile

[ `grep RESIZESAVEFILE $DUMP` ] && resize_old_dat

[ `grep ENCRYPTSAVEFILE $DUMP` ] && encrypt_savefile

[ `grep RECOVERSAVEFILE $DUMP` ] && recover_savefile

};export -f main_menu

main_menu

[ -d $wrk ] && rm -rf $wrk
