#!/bin/bash
############################################
# Script for reading the LDAP data
# Usage: ./dtb-ldap (now)  
#
# Changelog:
# rpm65 - replaced sed with grep to keep only the necessary attributes.
#		- corrected secure port check
#		- ignoring SSL certificate with export LDAPTLS_REQCERT=never;
# rpm68 - removing german text
#		- adding chmod 777 for syncstatus
# rpm71 - using DTBconfigFile.xml
# rpm77 - moving from /var/tmp/dtb into /var/pgsql/dtb_config/
# rpm2.0-1 - removing password from logs
# rpm2.0-12 - OSFOURK-25807 - converting downloaded special characters to ascii
# rpm2.0-13 - OSFOURK-26159 - replacing grep with sed
############################################

# This script is set to run in every second via crontab added in the Dtb HA script. 
# But it will execute actions only at the time set in the sftpserver file.
# The ldap file will be saved to haipsetup.xml only when DTB is stopped (in Dtb HA script).

# Import definitions
CMD=$(basename $0)
if [ -f /opt/dtb/bin/_common_definitions ]; then
	. /opt/dtb/bin/_common_definitions
else
	logger -t $CMD -p ERROR -s "The /opt/dtb/bin/_common_definitions file does not exist, exiting the script..."
	exit 1
fi

outputInFile () {
	chmod 666 /var/pgsql/dtb_config/syncstatus; 
	sed -i '2d' /var/pgsql/dtb_config/syncstatus;
	echo $1>>/var/pgsql/dtb_config/syncstatus;
}

stime=$(readConfigXML "ldap-time")
ctime=$(date +"%H:%M") # get the current time in hh:mm format

if ([ "$1" == "now" ] || [ "$stime" == "$ctime" ]); then	
	
	if [ -f $CONFIG_FILE ]; then # This file is created by the portal
		IP=$(readConfigXML "ldap-ip")
		port=$(readConfigXML "ldap-port")
		usr=$(readConfigXML "ldap-user")
		pwd=$(readConfigXML "ldap-password")
		pwd=$(echo $pwd | openssl aes-256-cbc -a -d -salt -k '1825e09252d7c6f66f5e1be666154306')
		baseDN=$(readConfigXML "ldap-baseDN")
		filter=$(readConfigXML "ldap-searchFilter")
		DisplayName=$(readConfigXML "ldap-name") # cn
		Phone=$(readConfigXML "ldap-telephoneNumber") # telephoneNumber
		Firstname=$(readConfigXML "wsi-firstName") # givenName
		Surname=$(readConfigXML "wsi-surname") # sn
		Phone3=$(readConfigXML "wsi-mobile") # mobile
		Phone2=$(readConfigXML "wsi-homePhone") #homePhone
		Organization=$(readConfigXML "wsi-organization") # ou
		Fax=$(readConfigXML "wsi-fax") # facsimileTelephoneNumber
		City=$(readConfigXML "wsi-city") # l
		Email=$(readConfigXML "wsi-email") # mail
		Group=$(readConfigXML "wsi-group") # group
		Purl=$(readConfigXML "wsi-purl") # jpegPhoto
		Psurl=$(readConfigXML "wsi-psurl") # photo	
	else
		plog "ERROR: The $CONFIG_FILE file does not exist, exiting the script..."
		outputInFile "The $CONFIG_FILE file does not exist"
		exit 1
	fi
	
	# Check if IP format is 0..255.0..255.0..255.0..255
	if [ `echo $IP | grep -o '\.' | wc -l` -ne 3 ]; then
		plog "ERROR: Exiting with: Invalid IP: does not contain 3 dots!"
		outputInFile "Invalid IP: does not contain 3 dots!"
		exit 1;
	elif [ `echo $IP | tr '.' ' ' | wc -w` -ne 4 ]; then
		plog "ERROR: Exiting with: Invalid IP: does not contain 4 octets!"
		outputInFile "Invalid IP: does not contain 34 octets!"
		exit 1;
	else
		for OCTET in `echo $IP | tr '.' ' '`; do
				if ! [[ $OCTET =~ ^[0-9]+$ ]]; then
						plog "ERROR: Exiting with: Invalid IP: an octet is not numeric!"
						outputInFile "Invalid IP: does not contain 3 dots!"
						exit 1;
				elif [[ $OCTET -lt 0 || $OCTET -gt 255 ]]; then
						plog "ERROR: Exiting with: Invalid IP: an octet in not in range 0-255!"
						outputInFile "Invalid IP: an octet in not in range 0-255"
						exit 1;
				fi
		done
	fi
	
	# Log the input parameters
	plog "LDAP host = $IP"
	plog "LDAP port = $port" 
	plog "LDAP username = $usr"
	plog "LDAP baseDN = $baseDN"
	plog "LDAP filter = $filter"
	plog "LDAP DisplayName field = $DisplayName"
	plog "LDAP Phone field = $Phone"
	plog "LDAP Surname field = $Surname"
	plog "LDAP Firstname field = $Firstname"
	plog "LDAP Phone2 field = $Phone2"
	plog "LDAP Phone3 field = $Phone3"
	plog "LDAP Organization field = $Organization"
	plog "LDAP Fax field = $Fax"
	plog "LDAP City field = $City"
	plog "LDAP Email field = $Email"
	plog "LDAP Group field = $Group"
	plog "LDAP Purl field = $Purl"
	plog "LDAP Psurl field = $Psurl"
	
	# The * cannot be used as parameter
	if [ "$filter" == "all" ]; then 
		filter='';
	else
		filter=$filter;
	fi
	
	# Port 636 means secure LDAP
	if [[ "$port" == "s"* ]]; then 
		protocol="ldaps";
		port=${port:1};
	else
		protocol="ldap";
	fi
	
	CSV_FILE="/var/tmp/ldap.csv"
	
	# Anonymous search
	if [ "$usr" == "Anonymous" ]; then
		plog "Executing ldapsearch anonymously";
		plog "calling export LDAPTLS_REQCERT=never; ldapsearch -LLL -x -b \"$baseDN\" -H $protocol://$IP:$port $filter $DisplayName $Phone $Surname $Firstname $Phone2 $Phone3 $Organization $Fax $City $Email $Group $Purl $Psurl | perl -MMIME::Base64 -MEncode=decode -n -00 -e 's/\n +//g;s/(?<=:: )(\S+)/decode(\"UTF-8\",decode_base64($1))/eg;print'> $CSV_FILE"
		export LDAPTLS_REQCERT=never;
		ldapsearch -LLL -x -b "$baseDN" -H $protocol://$IP:$port $filter $DisplayName $Phone $Surname $Firstname $Phone2 $Phone3 $Organization $Fax $City $Email $Group $Purl $Psurl | perl -MMIME::Base64 -MEncode=decode -n -00 -e 's/\n +//g;s/(?<=:: )(\S+)/decode("UTF-8",decode_base64($1))/eg;print' > $CSV_FILE
		EXITCODE=$?
		if [[ ${EXITCODE} -eq 0 ]]; then
			plog "Auth success. The ldap.csv created"
		else
			plog "Auth failed"
			exit ${EXITCODE}
		fi
	else
	# Credential search
	# -LLL: avoid printing ldap comments on output
	# -x: simple authentication
	# -b: base DN to bind
	# -H: ldap host
	# -D: username
	# -w: password
		plog "calling export LDAPTLS_REQCERT=never; ldapsearch -LLL -x -b \"$baseDN\" -H $protocol://$IP:$port -D \"$usr\" -w \"********\" $filter $DisplayName $Phone $Surname $Firstname $Phone2 $Phone3 $Organization $Fax $City $Email $Group $Purl $Psurl | perl -MMIME::Base64 -MEncode=decode -n -00 -e 's/\n +//g;s/(?<=:: )(\S+)/decode(\"UTF-8\",decode_base64($1))/eg;print' > $CSV_FILE"
		export LDAPTLS_REQCERT=never;
		ldapsearch -LLL -x -b "$baseDN" -H $protocol://$IP:$port -D "$usr" -w "$pwd" $filter $DisplayName $Phone $Surname $Firstname $Phone2 $Phone3 $Organization $Fax $City $Email $Group $Purl $Psurl | perl -MMIME::Base64 -MEncode=decode -n -00 -e 's/\n +//g;s/(?<=:: )(\S+)/decode("UTF-8",decode_base64($1))/eg;print' > $CSV_FILE
		EXITCODE=$?
		if [[ ${EXITCODE} -eq 0 ]]; then
			plog "Auth success. The ldap.csv created"
		else
			plog "Auth failed"
			exit ${EXITCODE}
		fi
	fi
	
	#Replace :: with : (base64 indication)
	sed -i 's/::/:/g' $CSV_FILE
	
	#Backup the file for WSI before being modified
	WSI_FILE="/var/tmp/ldap_wsi.csv"
	TEMP_FILE="/var/tmp/tempfile"
	cp $CSV_FILE $WSI_FILE
	
	#Remove lines with unnecessary attributes for DTB
	#grep "$DisplayName:\|$Phone:\|^$" $CSV_FILE > $TEMP_FILE //this is not working with automatic synchronization and umlaut characters (OSFOURK-26159)
	sed -n -e "/^$DisplayName/p" -e "/^$Phone/p" -e "/^$/p" $CSV_FILE > $TEMP_FILE
	cp $TEMP_FILE $CSV_FILE
	rm -f $TEMP_FILE
	
	#OSFOURK-18259 - Verify the health of the entries: 
	#There are 3 possible line beginnings: "", "cn:", "telephoneNumber:"
	#In normal case, the empty line must be followed by a line starting with "cn:"
	while IFS= read -r line1; do
		if [[ $line1 == "$Phone:"* ]]; then
			IFS= read -r line2
			if [[ $line2 == "$DisplayName:"*  ]]; then
				echo $line2 >> $TEMP_FILE
				echo $line1 >> $TEMP_FILE
			else
				echo $line1 >> $TEMP_FILE
				echo $line2 >> $TEMP_FILE
			fi
		else
			echo $line1 >> $TEMP_FILE
			if [[ $line1 == "" ]]; then
				IFS= read -r line2
				if [[ $line2 == "$Phone:"* ]]; then
					IFS= read -r line3
					if [[ $line3 == "$DisplayName:"*  ]]; then
						echo $line3 >> $TEMP_FILE
						echo $line2 >> $TEMP_FILE
					else
						echo $line2 >> $TEMP_FILE
						echo $line3 >> $TEMP_FILE
					fi
				else
					echo $line2 >> $TEMP_FILE
				fi
			fi
		fi
	done < "$CSV_FILE"
	
	cp $TEMP_FILE $CSV_FILE
	rm -f $TEMP_FILE
	
	#Replace the Phone attributename with semicolon
	sed -i ':a;N;$!ba;s/\n'$Phone': /;/g' $CSV_FILE
	
	#Remove "cn: "
	sed -i "s/$DisplayName: //g" $CSV_FILE
	
	#Remove empty lines
	sed -i '/^$/d' $CSV_FILE
	
	#Note: if there are entries with empty Phone field, they will be ignored by PEDIT
	#Note: if there are entries with multiple Phone fileds, PEDIT will consider only the first one
	
	# At this point we have /var/tmp/ldap.csv. Let's move it to winedir for PEDIT conversion
	
	if [ -d $DTB_DRBD_SHARE ]; then
		mv $CSV_FILE $DTB_DRBD_SHARE/DTBMaster/winedir/
		plog "/var/tmp/ldap.csv moved to DTBMaster/winedir/ for PEDIT conversion"
		mv $WSI_FILE $DTB_DRBD_SHARE/DTBMaster/winedir/
		plog "$WSI_FILE moved to DTBMaster/winedir/ for further processing"
		#change the current directory, because PEDIT needs some external files (uml, dll, ini)
		cd $DTB_DRBD_SHARE/DTBMaster/winedir/
		chown -R dtbuser:users $DTB_DRBD_SHARE/DTBMaster/winedir/
	else
		plog "DTB is not installed. Exiting script"
		exit 1
	fi
	
	# Generate ldap.nam with pedit -g input.csv output.nam
	wine PEDIT.EXE -g ldap.csv ldap.nam
	sleep 10 # wait for the conversion
	if [ -f ldap.nam ]; then
		plog "ldap.nam created with PEDIT"
	fi
				
	# PEDIT can convert also the rnr or t9i from csv, but if a lot of data need's to be trunkated / removed then it's faster to do it once at the nam conversion
	# Generate ldap.rnr
	wine PEDIT.EXE -c ldap.nam ldap.rnr
	if [ -f ldap.rnr ]; then
		plog "ldap.rnr created with PEDIT"
	fi
	
	# Generate ldap.t9i
	wine PEDIT.EXE -i ldap.nam
	if [ -f ldap.t9i ]; then
		plog "ldap.t9i created with PEDIT"
	fi
	
	# Move the ldap files to import directory and rename them to kunde
	mv ldap.nam /var/pgsql/dtb/DTBServer/import/kunde.nam
	mv ldap.rnr /var/pgsql/dtb/DTBServer/import/kunde.rnr
	mv ldap.t9i /var/pgsql/dtb/DTBServer/import/kunde.t9i
	cd $DTB_DRBD_SHARE/DTBServer/import
	if ([[ -f kunde.nam ]] && [[ -f kunde.rnr ]] && [[ -f kunde.t9i ]]); then
		plog "ldap files are moved to import dir and renamed to kunde"
		#set user/group of all files
		chown -R $DTB_USER:$DTB_GROUP $DTB_DRBD_SHARE/DTBServer/import
		chmod 751 $DTB_DRBD_SHARE/DTBServer/import
		
		plog "Restarting DTB via dtb-reconfigure script."
		
		# Run the reconfigureing script which will copy the files into winedir and restart DT. 
		. /etc/profile
		export HOME=/root
		/opt/dtb/bin/dtb-reconfigure
	else
		plog "The kunde database files are not found in the import directory"
	fi

	# Update the syncstatus file regarding to the result
	updated_state=$?
	
	# Verify if the syncstatus file exsists. If not create it.
	if [ ! -f $DTB_SYNCSTATUS ]; then
		echo "" > $DTB_SYNCSTATUS
		plog "File syncstatus created."
	fi
	
	chmod 777 $DTB_SYNCSTATUS
	
	d=$(date +%Y-%m-%d)" "$(date +%H:%M:%S)
	
	if [ $updated_state -eq 0 ]; then # No DTB restart performed
		echo "Successfully completed at $d with LDAP (files were not changed)." > $DTB_SYNCSTATUS;
	elif [ $updated_state -eq 2 ]; then # The import directory was changed
		echo "Successfully completed at $d with LDAP." > $DTB_SYNCSTATUS;
	elif [ $updated_state -eq 3 ]; then # The import directory was empty
		echo "Failed at $d with LDAP. No data downloaded." > $DTB_SYNCSTATUS;
	elif [ $updated_state -eq 4 ]; then # The import directory was changed but the mandatory files are missing
		echo "Failed at $d with LDAP, because one or more mandatory files are missing." > $DTB_SYNCSTATUS;
	fi	
	
	status="$(cat $DTB_SYNCSTATUS)"
	plog $status

fi	