#!/bin/bash
#
#  Nautilus file merge script v2.00
#  Written by comicinker, Febuary 2008 - comicinker@gmx.de
#
#  This  merge  script  must be  called from  Nautilus!
#  Place this script in your  nautilus-scripts directory and make sure
#  it's executable  (chmod 775 this_script.sh)  and it will show up in
#  the,  "Scripts" menu when files are right-clicked  from within your
#  Nautilus file  manager.  Please report any bugs to comicinker@gmx.de.
#
#  Features: 
#  This script merges selected files to one without touching the origin files.
#  It is the pendent for the split file script for Nautilus. 
#  It will ask you before overwriting something.
#
#  Don'ts:
#  It's optimised for my split script. Not tested with files splitted
#  in another way (it expects files with file_123 names)
#  The script won't check for enough disc space#  
#
#  This  program is free  software.  It  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.
#
######################################################################

##################
#  USER OPTIONS  #
##################

# Set to "no" if you don't want to check the data integrity. If no 
# checksum file is found, you can set one or just cancel.
CHECK_MD5_SUM="yes"

#####################################################
#  YOU SHOULDN'T MODIFY ANYTHING BELOW THIS POINT!  #
#####################################################

# Set some script variables

the_files=`"$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS" | sed -e 's/^file:\/\///; s/%20/\ /g'`
FILES=${NAUTILUS_SCRIPT_SELECTED_FILE_PATHS}
if [ "$NAUTILUS_SCRIPT_CURRENT_URI" == "x-nautilus-desktop:///" ]; then
	files_path=$HOME"/Desktop"
else
	files_path=`echo "$NAUTILUS_SCRIPT_CURRENT_URI" | sed -e 's/^file:\/\///; s/%20/\ /g'`
fi

gui=`which zenity`
check=`which md5sum`
merge_files=`which cat`

# Merge function
func_merge()
{	# Watch out! () would create a subshell with own variables.

	# prepare input for cat
	# nautilus gives us files seperated by new lines like that:
	# 	path/to/file number 1
	#	path/to/file number 2
	#	....
	# we need the following format:
	# 	"path/to/file number 1" "path/to/file number 2" "...."
	# or
	#	path/to/file\ number\ 1 path/to/file\ number\2 ....

	# we load the selected files in a array. each file one element. Input Field Seperator is a new line ('\n')
	O=$IFS IFS=$'\n' arFILES=($(echo "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS" )) IFS=$O

	# The array looks now like that:
	# 	arFILES[0]= path/to/file number 1
	#	arFILES[1]= path/to/file number 2
	#	....
	# We can now return all elemets with the @ operator in this format:
	# 	"path/to/file number 1" "path/to/file number 2" "...."


	# prepare the output filename (get from user)
	# first make a suggestion
	suggestion=`basename "${arFILES[0]}"`

	# take a filename from input and cut the last 4 chars 
	suggestion="${suggestion%?}" #remove the last character
	suggestion="${suggestion%?}"; suggestion="${suggestion%?}"; suggestion="${suggestion%?}"

	merge_output=$(zenity --file-selection --save --confirm-overwrite --filename="$suggestion" --title "Select Merged file name"); echo $merge_output

	# Prepare md5 check
	if [[ "$CHECK_MD5_SUM" == "yes" ]]; then
		# Check for the md5sum file
		# TODO: if outputfile differs from original one, what then? -> no md5sum will be checked for that file, error occures. Give a hint for file names
		# we assume a file from our split script. so we expect that our filename has 4 signs (_000) added to the orign file name. remove them
		md5sum_file_name_expected="${arFILES[0]}"  # the first element in array
		md5sum_file_name_expected="${md5sum_file_name_expected%?}"; md5sum_file_name_expected="${md5sum_file_name_expected%?}"
		md5sum_file_name_expected="${md5sum_file_name_expected%?}"; md5sum_file_name_expected="${md5sum_file_name_expected%?}"
		md5sum_file_name_expected="${md5sum_file_name_expected}.md5"  # finnaly our expected filename
		md5sum_file_name_expected=`basename "$md5sum_file_name_expected"`
		found=`find . -name "${md5sum_file_name_expected}"`
		
		if [[ -z "${found}" ]]; then	# zero, file not found
			md5_file_name=`zenity --file-selection --title "Select md5 checksum file" --text "Please select the checksum file"`
			if [[ -z "${md5_file_name}" ]]; then	# if cancel clicked -> no md5sum check wanted
				CHECK_MD5_SUM="no"
			fi
		else
			md5_file_name="${md5sum_file_name_expected}"
		fi
	fi

	if [ -n "$merge_output" ]; then		#if non-zero, that means cancel was not clicked on output file selection

		(
			echo "" 	# Random output for zenity to trigger pulsating
			`cat "${arFILES[@]}" > "$merge_output"` \
		) | zenity --progress --pulsate --auto-kill --auto-close --text "Merging Files" --title "Merging"
	else
		return
	fi

	if [[ "$CHECK_MD5_SUM" == "yes" ]]; then	
		# the important line
		# too feed our log and zenity status output with a single stdout from md5sum we use tee to make a copy of stdout -> zenity

		md5_log=$(
			{
				echo "" 	# new line output to trigger zenity pulsating progress bar
				md5sum -c "$md5_file_name"
				echo $?	   	# return the exit status
			} | tee >(zenity --progress --pulsate --auto-kill --auto-close --title "md5sum" --text "Checking files with \n$md5_file_name")
		)
		md5_errors=${md5_log:(-1)}	# the last char should be the return value. md5sum creates only 0, 1, 2 as exit stats
		md5_log=${md5_log%?}		# remove that exit status from log, we don't need to show it

		if [[ "$md5_errors" == "0" ]]; then
			zenity --info --title "md5sum info" --text "Merging finished succesful"
		else
			zenity --warning --title "md5sum errors" --text \
"File check errors. Please make shure that you\n\
1. use the same file names as in \n\"$md5_file_name\"\n\
2. selected _all_ and _only_ parts of your splitted file.\n\
Otherwise please copy some parts again: \n$md5_log"
		fi
	fi

} 

# Errors function
func_errors()
{
	display_error="no"

	if [ -x "$gui" ]; then
		result=""
	else
		result="Zenity NOT found.  This utility is required!; "
		display_error="yes"
	fi
	if [ -x "$merge_files" ]; then
		result=`echo "$result"`
	else
		result=`echo "$result cat NOT found.  This utility is required!; "`
		display_error="yes"
	fi
	if [ -x "$check" ]; then
		result=`echo "$result"`
	else
		result=`echo "$result md5sum NOT found.  This utility is required!; "`
		display_error="yes"
	fi

	echo $result

	dialog_title="Split File Error!"
	dialog_type="--error"

	if [ "$display_error" = "yes" ];then
		zenity --title "$dialog_title" "$dialog_type" --text "$result"
	fi

	exit 1	
}

# Check for required Tools. actually, this is the beginning point of the script
if [[ -x "$gui" && -x "$merge_files" &&"$check" ]]; then
	func_merge
else
	func_errors
fi

exit 0

