#!/bin/sh

# ClonePanel - Manages duplicate accounts on two or more webservers,
# including snapshot backups, monitoring and failover dns.
# Copyright (C)2006 Chris Cheers, Internet Lynx.
# Contact chris[at]clonepanel[dot]com.
# Internet Lynx, PO Box 7117, Mannering Park, NSW 2259, Australia

# 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 2
# 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.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

Version=0.33
# restore -h for built-in documentation

set -u
# Be strict about variable declaration

unset PATH
#avoid use of $PATH - limit script to system commands we choose

PROGRAM_DIR=$(/bin/echo $0 |/bin/sed -e "s/\/[a-zA-Z0-9_]*$//")
# Extract the working directory from command line
# NB - if your system doesn't have echo and sed in these locations
# then this line will need to be changed in all shell scripts

# Standard include files:
. $PROGRAM_DIR/includes

# Built-in documentation:
function showdocs {
	$CAT <<-EODOC
		Restore files on a host server to a previously-stored snapshot
		./restore -u myuser -t WEB|MAIL -H myhost -s hourly|daily|weekly|monthly.[01234] [-f subdir/filename.html ] [-d]
		The account must already be set up using setup_account

		Command line options: 
		-h		Print these instructions and exit
		-t WEB|MAIL	Type of documents to sync (web or e-mail) default WEB
		-u user		CPanel username of the account
		-H host		Nickname of the server
		-s version	Which snapshot to restore - default is latest (hourly.0)
		-d path/to/dir	(optional) Path to directory to restore (type WEB only, start with public_html)
		-f filename	(optional) Name of a single file within this directory
		-a		(optional) All files - ignore normal excludes (eg. config files). Use with care!

		Note - restore DOES NOT DELETE existing files (though it will
		replace them). Use restoreclean to remove existing files and 
		fully restore the public_html directory to match a snapshot.
EODOC
	exit $DOC_REQUEST
}

function setup_mirror_dirs {

        case "$stype" in
                WEB)
# define variables for web sync (we can't combine this with the earlier
# case because MIRROR_DIRS may be host dependent)
                        EXCLUDES=$USER_DIR/$EXCLUDESFILE_WEB
                        MIRROR_DIRS[0]=$MIRROR_DIR_WEB
                        MIRROR_SS[0]=$MIRROR_SS_WEB
                        if [ "`$LS $USER_DIR/$DATABASE_DIRNAME`" ]; then
                                MIRROR_DIRS[1]=$DATABASE_STORENAME
                                MIRROR_SS[1]=$DATABASE_STORENAME
                        fi
                        ;;
                MAIL)
# define variables for mail sync
                        EXCLUDES=$USER_DIR/$EXCLUDESFILE_MAIL
                        MIRROR_DIRS[0]=$MIRROR_DIR_MAIL
                        MIRROR_SS[0]=$MIRROR_SS_MAIL
                        ;;
        esac
        mirror_dir_count=${#MIRROR_DIRS[@]}
}


# Initialise own input variables:
stype=''
user=''
compat=''
host=''
filename=''
snap=''
dirpath=''
allfiles='n'

# Start real script

# Check for help request and input variables in the command line options:
while getopts ":ht:u:s:f:d:H:a" opt
do
	case $opt in
		h)	showdocs
			;;
		t)	stype=$OPTARG
			;;
		u)	user=$OPTARG
			;;
		H)	host=$OPTARG
			;;
		f)	filename=$OPTARG
			;;
		s)	snap=$OPTARG
			;;
		d)	dirpath=$OPTARG
			;;
		a)	allfiles='y'
			;;
		*)	$ECHO "Unknown option. Use -h for instructions"
			exit $E_UNKNOWN_OPT
			;;
	esac
done
shift $(($OPTIND - 1))

OPTIND=1
# reset getopts for next time


if [ ! $user ]; then
	cecho -n -c $prompt "Enter account username: "
	read user
	if [ ! $user ]; then
		cecho -c $error "Username must be specified"
		exit $E_BLANK_INPUTS
	fi
fi

if [ ! $host ]; then
	cecho -n -c $prompt "Enter host name: "
	read host
	if [ ! $host ]; then
		cecho -c $error "Host name must be specified"
		exit $E_BLANK_INPUTS
	fi
fi

if [ ! $stype ]; then
	stype=WEB
	cecho -c $warning "Warning - Unspecified sync type defaults to WEB"
fi

if [ ! "$snap" ]; then
	snap='hourly.0'
	cecho -c $warning "Warning - unspecified snapshot defaults to latest"
fi

# User-specific Include files (only after defining $user and $host):
config -u $user -t $stype -H $host

if [ ! -d $SNAPSHOT_SUBDIR/$snap ]; then
	cecho -c $error "Directory $snap does not exist in $SNAPSHOT_SUBDIR"
	exit $E_NO_SOURCE
fi


cecho -c $info "Phase A - Preparing directories" ;

if [ $dirpath ] ; then
# Specified directory / filename - check both exist
	if [ ! -d $SNAPSHOT_SUBDIR/$snap/$dirpath ]; then
		cecho -c $error "Directory $dirpath does not exist in $SNAPSHOT_SUBDIR/$snap"
		exit $E_NO_SOURCE
	fi
	if [ "$filename" ]; then
		if [ ! -f $SNAPSHOT_SUBDIR/$snap/$dirpath/$filename ]; then
			cecho -c $error "File $filename does not exist in $SNAPSHOT_SUBDIR/$snap/$dirpath"
			exit $E_NO_SOURCE
		fi
	fi
	eval remdir=\$"MIRROR_DIR_$stype"
	eval locdir=\$"MIRROR_SS_$stype"
	eval excfile=\$"EXCLUDESFILE_$stype"
	EXCLUDES=$USER_DIR/$excfile
# Standard excludes list will be removed later if -a specified
	MIRROR_DIRS=`$ECHO $dirpath| $SED -e "s/$locdir/$remdir/g"`
# eg. Substitute $MIRROR_SS_WEB (usually public_html) for $MIRROR_DIR_WEB
# (may be something else, eg. domain name on non-CPanel system) in dirpath
	MIRROR_SS=$dirpath
# dirpath by definition is in the local snapshot
	mirror_dir_count=1
else
	if [ "$filename" ]; then
		cecho -c $error "Source directory must be specified (-d) for single file restore"
		exit $E_NO_SOURCE
	fi
	setup_mirror_dirs
# Create the standard list of directories to backup / mirror
# (may depend on push host config)
fi

if [ "$allfiles" ]; then
# Ignore normal excludes (eg. config files)
	EXCLUDES=''
fi

#get host ip address from hosts file
if [ ! $A ]; then
	cecho -c $error "$Host $hostname_pull has no ip - check hosts file"
	exit $E_NO_PUSHTO_IP
fi

#finally get its remote directory (normally /home/username)
if [ ! $REMOTEHOST_HOME ]; then
	cecho -c $error "Host $host has no remote dir - check remote_dir file"
	exit $E_NO_PUSHTO_DIR
fi

cecho -c $info "Phase B - rsync 'push' to $host" ;

remote_ssh="$SSH -p $SSH_PORT -i $AUTH_DIR/$host";

# Step B1 - Pre-process
if [ $dirpath ]; then
	cecho -c $warning "Skipping pre-processing when restoring specified files / directories"
else
	$remote_ssh $REMOTEHOST_USERNAME@$A "pre_process -f -t $stype -d PUSH"
	checkerror $? $E_PRE_PUSH_FAILED
fi

# Step B2 - Sync
for (( i = 0 ; i < $mirror_dir_count ; i++ ))
do
	dir=${MIRROR_DIRS[$i]}
	ssdir=${MIRROR_SS[$i]}
	$RSYNC	--bwlimit=$RSYNC_BWLIMIT		\
		-avz					\
		--exclude-from="$EXCLUDES"		\
		-e "$remote_ssh"	 		\
		$SNAPSHOT_SUBDIR/$snap/$ssdir/$filename $REMOTEHOST_USERNAME@$A:$REMOTEHOST_HOME/$dir
	checkerror $? $E_RSYNC_PUSH_FAILED
done

# Step B3 - Post-process
if [ $dirpath ] ; then
	cecho -c $warning "Skipping post-processing when restoring specified files / directories"
else
	$remote_ssh $REMOTEHOST_USERNAME@$A "post_process -f -t $stype -d PUSH"
	checkerror $? $E_POST_PUSH_FAILED
fi

cecho -c $ok "$($DATE) restore completed successfully"
















