#!/bin/bash
#
#  Nautilus file split script v1.99
#  Written by comicinker, January 2008 - comicinker@gmx.de
#
#  This  split  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.
# 
#  Featues:
#  Splits one file
#  Resulting file name: "file name.dum_000"
#  Prepared file sizes as well as manual input
#  Don't touch the origin file
#  confirm overwrites
#  Warning if more than 30 files (optional) will be created
#  Creates Md5 sum (optional)
#
#  Don'ts
#  Won't check for disk space
#  Won't split in more than 1000 files
#
#  You can merge your files in a terminal with cat filename_* > new_file
#  Or use the merge script File_Merge for Nautilus from me
#  To check the file md5 sum type md5sum -c yourarchive.md5 in a terminal
#  or use the File_Merge script from me
#
#  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  #
##################

# Gives a warnig if more than ... files are created
# set to 1000 if no wanted
FILE_NUMBER_WARING="30"

# Set to no if you don't need to check file integrity.
# The File_Merge_2 script supports that option seamless.
CREATE_MD5SUM="yes"

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

# Set some script variables
FILE_NUMBER_MAXIMUM="1000"
the_file=$1
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`
split_file=`which split`
check=`which md5sum`
error_input="no"
error_file_number="no"


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

	dialog_title="Select file size"
	dialog_type="--list"
	dialog_subtype="--radiolist"
	dialog_height="350"
	dialog_width="250"
	dialog_text="Please select the desired file size"
	dialog_column1=""
	dialog_column2="Size"
	dialog_column3="Info"
	RESULT=`zenity "$dialog_type" "$dialog_subtype" --title "$dialog_title" --text="$dialog_text" --width="$dialog_width" --height="$dialog_height" \
		--column "$dialog_column1" --column "$dialog_column2" --column "$dialog_column3" --hide-column=2 \
		\"\" Manual			"Input own file size"	\
		\"\" 1474k			"Floppy (1.44 MB)"	\
		\"\" 5m				"Email (5 MB)"		\
		\"\" 15m			"Share (15 MB)"		\
		\"\" 100m			"100 MB"		\
		\"\" 650m			"CD (650 MB)"		\
		\"\" 700m			"CD (700 MB)"		\
		\"\" 1024m			"Best for DVD (1 GB)"	\
		\"\" 4400m			"DVD single layer (4.7 GB)"\
	`	#<- important sign `

	#if $RESULT has zero-length
	if [ -z "$RESULT" ];then
		return
	fi

	if [ "$RESULT" = "Manual" ];then
		split_size=`zenity --entry --text "Enter file size manually. Example: 10 MegaByte: 10m" --title "Enter size"`
		if [ -z "$split_size" ]; then
			return	# cancel if nothing or cancel entered
		fi
	else
		split_size="$RESULT"
	fi

	# The orign file size in bytes
	file_size=`stat -c%s "$the_file"`

	# the divider for byte, kilo or mega is hidden in the end of split_size. just delete all numbers, the last left digit is a hint for our divider
	divider=`echo "$split_size" | tr -d '[0-9]'`

	# if nothing left
	if [ -z "$divider" ];then
		divider="1"
	elif [ "$divider" == "b" -o "$divider" == "B" ]; then
		divider="1"
	elif [ "$divider" == "k" -o "$divider" == "K" ]; then
		divider="1024"
	elif [ "$divider" == "m" -o "$divider" == "M" ]; then
		divider="1048576"
	elif [ "$divider" == "g" -o "$divider" == "G" ]; then
		divider="1073741824"
	elif [ "$divider" == "t" -o "$divider" == "T" ]; then
		divider="1099511627776"
	else
		error_input="yes"
		return		#return for functions, exit for subshells
		#wrong value entered!
	fi

	#calculate the resulting number of files
	temp1=`expr "$file_size" / "$divider"`
	temp2=`echo "$split_size" | tr -d '[a-z]'`
	file_count=`expr "$temp1" / "$temp2"`
	
	# check resulting file count
	if [ "$file_count" -gt "$FILE_NUMBER_WARING" ];then	# see man test for more info about -gt
		zenity --question --title "Split files" --text "The number of resulting files exceeds $FILE_NUMBER_WARING files. Proceed?"
		if [ $? = 1 ];then	# check the last return value ("No" was answered)
			# error_file_number="yes"   # This would display a error message. unnessesary
			return
		fi
	fi
	# we only allow 1000 files!
	if [ "$file_count" -gt "$FILE_NUMBER_MAXIMUM" ];then
		error_file_number="yes"
		return
	fi
	
	# Check file existens	
	file_name=`basename "$the_file"| sed -e "s/ /\ /g"` # get the filename only and replace " " with "\ "
	found=`find . -name "${file_name}_*"`	# find files in current directory only
	if [[ -n "${found}" ]]; then	#found something similar (found non-zero)
		zenity --question --title "Confirm overwrite" --text "Files with name scheme \n`echo $file_name`_000 \nalready exists. \n\nOverwrite?"
		if [[ $? = "1" ]]; then		# cancel clicked
			return
		fi
	fi

	# Create md5 checksum
	# Create md5 checksum file name
	check_file_name=`echo ${the_file}.md5`
	# Check file existens
	found=`find . -name "${file_name}.md5"` #find files in current directory only
	if [[ -n "${found}" && "$CREATE_MD5SUM" == "yes" ]]; then    # found something (found non-zero)
		zenity --question --title "Confirm overwrite" --text "The checksum already exists: \n${file_name}.md5\n\nOverwrite?"
		if [[ $? = "0" ]]; then   # OK clicked
			CREATE_MD5SUM="yes"	# this is also a user option
		else
			CREATE_MD5SUM="no"
		fi		
	fi

	( # For zenity output
		
		echo "" # Random output to trigger zenity status bar
		# 3 digits(->1000Files maximum) for file ending, verbose should do progress status
		(
			split --bytes="$split_size" --suffix-length=3 --numeric-suffixes --verbose "${the_file}" "${the_file}"_ 
		) 
		# split stops after current part is finished if canceled

		if [[ "${CREATE_MD5SUM}" == "yes" ]]; then
			md5sum "${the_file}" > "${check_file_name}"
			# prepare input for md5sum
			# we have a format where files are 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 "${the_file}_[0-9][0-9][0-9]" )) IFS=$O
			md5sum "${arFILES[@]}" >> "$check_file_name"	# append to file
		fi
	) | zenity --progress --pulsate --text "Splitting" --auto-kill 
} 

# 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 "$split_file" ]; then
		result=`echo "$result"`
	else
		result=`echo "$result split 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
	if [ "$error_input" = "yes" ]; then
		display_error="yes"
		result=`echo "$result Input error. Read man split which values are allowed; "`
	fi
	if [ "$error_file_number" = "yes" ]; then
		display_error="yes"
		result=`echo "$result Too many Files (1000 Maximum); "`
	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 "$split_file" && -x "$check" ]]; then
	func_split
fi

func_errors

exit 0

