#!/bin/bash
############################################
# WSI format database converter
# Usage: ./wsi-genddb <no parameter or "config">
# It is called in the dtb-reconfigure, when non-DTB sync is performed (manual import, LDAP, SFTP)
# It is called by the DTB-Wine, when a DTB sync is performed (DISPLAY_NAME, PERSDAT of Assistant or Manager), and the sync was successful (SyncTrig.cfg=0)
# Note: only in case of PERSDAT sync + manual import, the DTB_WSI.rsp will be converted, instead of the imported kunde.nam
#
# Changelog:
# rpm62 - added the Inventory file transfer commands
#		- added the switch state condition from wsi.xml
# rpm64 - replaced sed with grep to keep only the necessary attributes.
#		- remove the old WSI_DB before copying the new version
# rpm67 - checking for empty attributes
#		- working with kunde.nam from DTBMaster, otherwise it can happen that the old kunde.nam is processed from DTBServer, before it is overwritten
# rpm69 - OSFOURK-18160 - adding DTB restart after synchronization. The wsi-gendb is always called after sync is finished, so this is the best place to stop the DTB
# rpm71 - Using DTBconfigFile.xml
# rpm74 - Addig quotation marks for -z when checking the IP list
# rpm76 - Replacing newline with space in the inventory command, using | tr "\n" " "
#		- adding IP validation function
# rpm77 - moving from /var/tmp/dtb into /var/pgsql/dtb_config/
#		- modifying the inventory command for sending to the ID instead of IP
# rpm79 - removing switchstate check. Send the DB+config anyway.
# rpm82 - adding "config" parameter to be able to send only the config to SG
# rpm83 - adding the check of number of parameter: when calling from wine, the script is stucked at $1 check
# rpm2.0-1 - correcting log messages for IP check
# rpm2.0-3  - OSFOURK-23022 - wait for HDMS conversion
############################################

# 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

function stopDTB(){
# Stop the DTB after synchronization: OSFOURK-18160 - PRB000049920: iDTB - DTB Server crash after long runtime
syncsetting="$(cat /var/opt/dtb_sync)"
if  [[ $syncsetting -eq 1 ]] || [[ $syncsetting -eq 4 ]] || [[ $syncsetting -eq 2 ]] || [[ $syncsetting -eq 5 ]]; then # PERSDAT and DISPLAY_NAME (assistant + manager)
	plog "Calling the dtb-syncstatus script to update the syncstatus file"
	/opt/dtb/bin/dtb-syncstatus
	plog "Waiting for 15 seconds to terminate the script"
	# wait for the syncstatus to be updated.
	sleep 15
	# Check if the hdms conversion is finished. Wait for 30 seconds if needed.
	if [ -f $DTB_DRBD_SHARE/DTBMaster/winedir/conversion.txt ]; then
		value=$(<$DTB_DRBD_SHARE/DTBMaster/winedir/conversion.txt)
		value="${value//$'\r'/}"
		retry=0;
		while [[ $value == "converting" && $retry -le 10 ]]; do
			plog "HDMS conversion is not yet finished, waiting 3 seconds"
			sleep 3
			value=$(<$DTB_DRBD_SHARE/DTBMaster/winedir/conversion.txt)
			value="${value//$'\r'/}"
			retry=$((retry+1))
		done
		if [ $value == "converting" ]; then
			plog "Warning: the HDMS conversion doesn't finished. The DB can be incomplete."
		fi
		if [ $value == "converted" ]; then
			plog "HDMS conversion complete. DTB can be restarted safely"
		fi
	else
		plog "The $DTB_DRBD_SHARE/DTBMaster/winedir/conversion.txt does not exist"
	fi
	# Stopping the DTB will trigger the HA to restart the DTB
	plog "Stopping the DTB..."
	$DTB_WRAPPER DTBMaster stop
	$DTB_WRAPPER DTBServer stop
	# After the DTB has started automatically, the syncstatus will be overwritten with 11, because the sync parameters are reloaded
	# To solve this problem the SyncTrig.cfg has to be overwrited again with the backed-up version, after DTB has started. It is done in the HA script (Dtb)
	plog "DTB is stopped! The HA will restart it soon, if needed."
fi
}

function checkIP(){
	IP=$1;
	validIP=1;
	plog "Checking element $IP"
	if [ `echo $IP | grep -o '\.' | wc -l` -ne 3 ]; then
		#plog "Invalid IP: does not contain 3 dots!"
		plog "The element is an ID!"
		validIP=0
	elif [ `echo $IP | tr '.' ' ' | wc -w` -ne 4 ]; then
		plog "Invalid IP: does not contain 4 octets!"
		validIP=0
	else
		for OCTET in `echo $IP | tr '.' ' '`; do
				if ! [[ $OCTET =~ ^[0-9]+$ ]]; then
						plog "Invalid IP: an octet is not numeric!"
						validIP=0
				elif [[ $OCTET -lt 0 || $OCTET -gt 255 ]]; then
						plog "Invalid IP: an octet in not in range 0-255!"
						validIP=0
				fi
		done
	fi
	
	if [ $validIP == 1 ]; then
		#plog "Valid IP!"
		plog "The element is an IP!"
	fi
}

function Distribute(){
	SendDB=$1 #true if the DB needs to be sent
	SendCfg=$2 # true of the wsi.xml needs to be sent
	WSI_DB=$3 #database to be sent
	
	sg_list=$(sudo /opt/inventory/inventory appliance_list --initialized --search=sg | tr "\n" " ")
	plog "SoftGate list: $sg_list"
	
	stmix_list=$(sudo /opt/inventory/inventory appliance_list --initialized --search=stmix | tr "\n" " ")
	plog "STMIX list: $stmix_list"
	
	combined_list="$sg_list$stmix_list"
	plog "Combined list: $combined_list"
	
	# get the numbers one-by-one: read the first (until space), do the transfer then delete it.
	# first mark the end of the list, if it is not empty
	if [ ! -z "$combined_list" ]; then
		combined_list="${combined_list}"
		# read the first entry, until the first space
		entry=$(sed 's/ .*//' <<< $combined_list)
		entry_id=0;
		entry_ip="0.0.0.0";
		while [ "$entry" != "" ]; do
			# check if the entry is a valid IP address
			checkIP "$entry"
			if [ $validIP == 0 ]; then
				entry_id=$entry; #invalid IP means ID
			else
				entry_ip=$entry;
				if [ $SendDB == "true" ]; then
					result_DB=600;
					retry=0;
					plog "Sending the WSI Database to SoftGate with IP $entry_ip and ID $entry_id"
					while [[ $result_DB -ne 0 && $retry -le 10 ]]; do
						sudo /opt/inventory/inventory put $entry_id $WSI_DB /var/opt/soco/config/wsi/WSI_DB.txt
						result_DB=$?
						if [ $result_DB -eq 0 ]; then
							plog "WSI Database transfer was successful!"
						else
							if [ $retry -eq 10 ]; then
								plog "WSI Database transfer failed! Retrying limit reached."
							else
								plog "WSI Database transfer failed! Retrying the transfer...($retry)"
							fi
							retry=$((retry+1))
							sleep 3
						fi
					done	
				fi
				# if both DB and cfg needs to be sent, then send the cfg only if DB is sent successfully
				if [[ $SendDB == "true" && $SendCfg == "true" ]]; then
					if [ $result_DB -eq 0 ]; then
						result_xml=600;
						retry=0;	
						plog "Sending the XML to SoftGate with IP $entry_ip and ID $entry_id"		
						while [[ $result_xml -ne 0 && $retry -le 10 ]]; do
							sudo /opt/inventory/inventory put $entry_id $WSI_CFG /var/opt/soco/config/wsi/wsi.xml
							result_xml=$?
							if [ $result_xml -eq 0 ]; then
								plog "XML transfer was successful!"
							else
								if [ $retry -eq 10 ]; then
									plog "XML transfer failed! Retrying limit reached."
								else
									plog "XML transfer failed! Retrying the transfer...($retry)"
								fi
								retry=$((retry+1))
								sleep 3
							fi		
						done
					else
						plog "Database transfer failed. Configuration transfer aborted."
					fi
				fi
				# if only the config needs to be sent
				if [[ $SendDB == "false" && $SendCfg == "true" ]]; then
					result_xml=600;
					retry=0;	
					plog "Sending the XML to SoftGate with IP $entry_ip and ID $entry_id"		
					while [[ $result_xml -ne 0 && $retry -le 10 ]]; do
						sudo /opt/inventory/inventory put $entry_id $WSI_CFG /var/opt/soco/config/wsi/wsi.xml
						result_xml=$?
						if [ $result_xml -eq 0 ]; then
							plog "XML transfer was successful!"
						else
							if [ $retry -eq 10 ]; then
								plog "XML transfer failed! Retrying limit reached."
							else
								plog "XML transfer failed! Retrying the transfer...($retry)"
							fi
							retry=$((retry+1))
							sleep 3
						fi		
					done
				fi
			fi
			#delete the checked entry.
			combined_list=${combined_list#* }
			# read the next entry
			entry=$(sed 's/ .*//' <<< $combined_list)
		done
	else
		plog "Aborting file transfer, IP list is empty!"
	fi
}

if [ ! -f "$WSI_CFG" ]; then
	# no config file = no wsi
	plog "No WSI configuration file. Exiting script..."
	stopDTB
	exit 1
else
	plog "WSI configuration file found"
fi

# switchstate=$(xmllint --shell $WSI_CFG <<<'cat //switch' | perl -ne '/(?<=>)(.*)(?=<)/ and print($1)')

if [ ! -d $DTB_DRBD_SHARE ]; then
	plog "DTB is not installed. Exiting script..."
	stopDTB
	exit 1
else
	plog "DTB is installed!"
fi

plog "checking the parameters..."
if [ $# -gt 0 ]; then
	if [ $1 == "config" ]; then
		plog "Transferring only the WSI configuration file"
		Distribute "false" "true" ""
		exit 0
	else
		plog "Unknown parameter"
	fi
else 
	plog "No parameters are provided, Transferring both WSI configuration and database"
fi

# The following file will contain the WSI database:
plog "Setting the database file..."
WSI_DB=$DTB_DRBD_SHARE/DTBServer/winedir/WSI_DB.txt

# Every type of database file must be converted into a common format for WSI:
#  - One entry per line, sorted alphabetically (the lines will start with names)
#  - In each entry, the values are separated with pipes
#  - Every values must be assigned to a valid WSI XML field (e.g. Organization: Atos)
# Check the synchronization type to know which database file must be used
plog "Checking the existance of the sync flag file..."
if [ -f $DTB_SYNC_FLAG_FILE ]; then
	#DTB_SYNC_FLAG_FILE has root rights
	plog "Reading the $DTB_SYNC_FLAG_FILE ..."
	sync_c=$(cat $DTB_SYNC_FLAG_FILE) # current sync config: 0=off, 1=Assistant PERSDAT, 2=Manager PERSDAT, 3=SFTP, 4=Assistant DISPLAY_NAME, 5=Manager DISPLAY_NAME, 6=LDAP
	plog "Sync flag is $sync_c"
else
	plog "Sync flag file doesn't exists."
	stopDTB
	exit 1;
fi
	
if [[ $sync_c -eq 1 || $sync_c -eq 2 ]]; then
	plog "Synchronization with PERSDAT"
	RSP_FILE=$DTB_DRBD_SHARE/DTBMaster/winedir/DTB_WSI.rsp
	if [ ! -f $RSP_FILE ]; then
		plog "PERSDAT database doesn't exist! Exiting script."
		stopDTB
		exit 1;
	else
		PERSDAT_DB=$DTB_DRBD_SHARE/DTBMaster/winedir/PERSDAT.tmp
		rm -f $PERSDAT_DB
		cp $RSP_FILE $PERSDAT_DB
		# The entries are separated by lines, the values are separated by pipes (empty valye = ||)
		# The number of value fileds is constant. Only the mapping can be changed in the .req file.
		# The value names are: SURNAME,FIRSTNAME,PHONE,PHONE2,PHONE3,ORGANIZATION,FAX,CITY,EMAIL,GROUP (10 values: DisplayName and the 2 picture urls are not present in PERSDAT)
		# These names must be assigned for each value (e.g. Brasov => City: Brasov)
		
		#Remove lines with # commentary
		sed -i "/#/d" $PERSDAT_DB
		
		plog "Creating DisplayName field..."
		# The DisplayName field can be created by concatenating Firstname+Surname
		# Add a pipe to the beginning of every line:Firstname|Surname|... => |Firstname|Surname|...
		sed -i 's/^/|/' $PERSDAT_DB
		# Copy the second word to the begining: |Firstname|Surname| => Surname |Firstname|Surname|
		awk 'BEGIN{FS = "|"};{print $3,$0}' $PERSDAT_DB > $PERSDAT_DB"_tmp" && mv -f $PERSDAT_DB"_tmp" $PERSDAT_DB
		# Delete the space before the first pipe: Surname |Firstname|Surname| => Surname|Firstname|Surname|
		sed -i 's/ |/|/1' $PERSDAT_DB
		# Copy the first word to the begining: Surname Surname|Firstname| => Firstname Surname Surname|Firstname|
		awk 'BEGIN {FS = "|"};{print $2,$0}' $PERSDAT_DB > $PERSDAT_DB"_tmp" && mv -f $PERSDAT_DB"_tmp" $PERSDAT_DB
		
		plog "Adding WSI XML field names..."
		# Add the WSI XML field names after the pipes
		sed -i 's/^/DisplayName: /' $PERSDAT_DB
		sed -i 's/|/|Firstname: /1' $PERSDAT_DB
		sed -i 's/|/|Surname: /2' $PERSDAT_DB
		sed -i 's/|/|Phone: /3' $PERSDAT_DB 
		sed -i 's/|/|Phone2: /4' $PERSDAT_DB 
		sed -i 's/|/|Phone3: /5' $PERSDAT_DB 
		sed -i 's/|/|Organization: /6' $PERSDAT_DB 
		sed -i 's/|/|Fax: /7' $PERSDAT_DB 
		sed -i 's/|/|City: /8' $PERSDAT_DB 
		sed -i 's/|/|Email: /9' $PERSDAT_DB 
		sed -i 's/|/|Group: /10' $PERSDAT_DB
		
		# Sort the lines alphabetycally by second column (first is "DisplayName:")
		plog "Sorting by name..."
		sort -k 2 -o $PERSDAT_DB $PERSDAT_DB
		plog "Copying the final file into DTBServer..."
		rm -f $WSI_DB
		cp $PERSDAT_DB $WSI_DB
		rm -f $PERSDAT_DB
	fi
	
elif [[ $sync_c -eq 3 || $sync_c -eq 4 || $sync_c -eq 5 || $sync_c -eq 0 ]]; then
	if [[ $sync_c -eq 3 || $sync_c -eq 0 ]]; then
		plog "Synchronization with SFTP or manual import"
		IMPORT_DIR="/var/pgsql/dtb/DTBServer/import" 
		KUNDE_DB=$IMPORT_DIR/KUNDE.tmp
		rm -f $KUNDE_DB
		cp $IMPORT_DIR/kunde.nam $KUNDE_DB
		# The SFTP sync imports the files into import dir.
	else
		plog "Synchronization with DISPLAY_NAME"
		KUNDE_DB=$DTB_DRBD_SHARE/DTBMaster/winedir/KUNDE.tmp
		rm -f $KUNDE_DB
		cp $DTB_DRBD_SHARE/DTBMaster/winedir/kunde.nam $KUNDE_DB
	fi
	
	# insert newline after every 48th character
	plog "Breaking into lines..."
	sed -i 's/.\{48\}/&\n/g' $KUNDE_DB
	# add pipes for value separation after every 24th character
	sed -i 's/.\{24\}/&|/g' $KUNDE_DB
	# replace multiple spaces with one space
	sed -i 's/  */ /g' $KUNDE_DB
	# remove one space+pipe (" |") with pipe
	sed -i 's/ |/|/g' $KUNDE_DB
	plog "Adding WSI XML field names..."
	# Add "Surname: " at the beginning of every line
	# WSI servlet is searching for DisplayName and Surname from where only the Surname can be used to display the actual name.
	sed -i 's/^/Surname: /' $KUNDE_DB
	# Add Phone name after the first pipe
	sed -i 's/|/|Phone: /1' $KUNDE_DB
		
	plog "Copying the final file into DTBServer..."
	rm -f $WSI_DB
	cp $KUNDE_DB $WSI_DB
	rm -f $KUNDE_DB
	
elif [ $sync_c -eq 6 ]; then
	plog "Synchronization with LDAP"
	LDAP_ORIG=$DTB_DRBD_SHARE/DTBMaster/winedir/ldap_wsi.csv
	if [ ! -f $LDAP_ORIG ]; then
		plog "LDAP database doesn't exist! Exiting script."
		stopDTB
		exit 1;
	elif [ ! -f $WSI_CFG ]; then
		# to map the attribute name with WSI field, the config file can be used.
		plog "The database configuration file of LDAP doesn't exist! Exiting script."
		stopDTB
		exit 1;
	else
		LDAP_DB=$DTB_DRBD_SHARE/DTBMaster/winedir/LDAP.tmp
		rm -f $LDAP_DB
		cp $LDAP_ORIG $LDAP_DB
		# somehow the readConfigXML function is not visible anymore from this point => reimporting it
		. /opt/dtb/bin/_common_definitions
		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	
		
		plog "The confnigured fields are:"
		plog "DisplayName = $DisplayName"
		plog "Phone = $Phone"
		plog "Surname = $Surname"
		plog "Firstname = $Firstname"
		plog "Phone2 = $Phone2"
		plog "Phone3 = $Phone3"
		plog "Organization = $Organization"
		plog "Fax = $Fax"
		plog "City = $City"
		plog "Email = $Email"
		plog "Group = $Group"
		plog "Purl = $Purl"
		plog "Psurl = $Psurl"
		
		plog "Replacing LDAP attribute names with WSI field names..."
		# check if the attribute names are empty.
		if [ ! -z "$DisplayName" ]; then sed -i 's/\b'$DisplayName'\b/DisplayName/g' $LDAP_DB; else DisplayName="_empty"; fi
		if [ ! -z "$Phone" ]; then sed -i 's/\b'$Phone'\b/Phone/g' $LDAP_DB; else Phone="_empty"; fi
		if [ ! -z "$Surname" ]; then sed -i 's/\b'$Surname'\b/Surname/g' $LDAP_DB; else Surname="_empty"; fi
		if [ ! -z "$Firstname" ]; then sed -i 's/\b'$Firstname'\b/Firstname/g' $LDAP_DB; else Firstname="_empty"; fi
		if [ ! -z "$Phone2" ]; then sed -i 's/\b'$Phone2'\b/Phone2/g' $LDAP_DB; else Phone2="_empty"; fi
		if [ ! -z "$Phone3" ]; then sed -i 's/\b'$Phone3'\b/Phone3/g' $LDAP_DB; else Phone3="_empty"; fi
		if [ ! -z "$Organization" ]; then sed -i 's/\b'$Organization'\b/Organization/g' $LDAP_DB; else Organization="_empty"; fi
		if [ ! -z "$Fax" ]; then sed -i 's/\b'$Fax'\b/Fax/g' $LDAP_DB; else Fax="_empty"; fi
		if [ ! -z "$City" ]; then sed -i 's/\b'$City'\b/City/g' $LDAP_DB; else City="_empty";fi
		if [ ! -z "$Email" ]; then sed -i 's/\b'$Email'\b/Email/g' $LDAP_DB; else Email="_empty"; fi
		if [ ! -z "$Group" ]; then sed -i 's/\b'$Group'\b/Group/g' $LDAP_DB; else Group="_empty"; fi
		if [ ! -z "$Purl" ]; then sed -i 's/\b'$Purl'\b/Purl/g' $LDAP_DB; else Purl="_empty"; fi
		if [ ! -z "$Psurl" ]; then sed -i 's/\b'$Psurl'\b/Psurl/g' $LDAP_DB; else Psurl="_empty"; fi
		
		#Remove unnecessary lines
		TEMP_FILE=$DTB_DRBD_SHARE/DTBMaster/winedir/tempfile
		grep "DisplayName:\|Phone:\|Firstname:\|Surname:\|Phone3:\|Phone2:\|Organization:\|Fax:\|City:\|Email:\|Group:\|Purl:\|Psurl:\|^$" $LDAP_DB > $TEMP_FILE
		cp $TEMP_FILE $LDAP_DB
		rm -f $TEMP_FILE
		
		# possibly not all attributes are present, especially if they are empty. The separation between entries is the empty line
		# every newline character must be replaced with pipe
		plog "Adding pipes..."
		sed -i ':a;N;$!ba;s/\n/|/g' $LDAP_DB
		# a create a label 'a'
		# N append the next line to the pattern space
		# $! if not the last line, ba branch (go to) label 'a'
		# s substitute, /\n/ regex for new line, /|/ by a pipe, /g global match (as many times as it can)
		# Now there is one big line, where the previous empty lines is shown as ||, which must be replaced with newline
		plog "Breaking into lines..."
		sed -i 's/||/\n/g' $LDAP_DB
		# Add a pipe to the end of each line
		sed -i 's/$/|/' $LDAP_DB
		
		# Sort the lines alphabetycally by second column (first is DisplayName:)
		plog "Sorting by name..."
		sort -k 2 -o $LDAP_DB $LDAP_DB
		plog "Copying the final file into DTBServer..."
		rm -f $WSI_DB
		cp $LDAP_DB $WSI_DB
		rm -f $LDAP_DB
	fi
else
	plog "Unknown synchronization!"
	stopDTB
	exit 1;
fi

chmod -R 777 $WSI_DB
chown -R dtbuser:users $WSI_DB

if [[ ! -f $WSI_DB || ! -f $WSI_CFG ]]; then
	plog "The Database and/or configuration file doesn't exist. Aborting file transfer."
	stopDTB
	exit 1;
fi

plog "The database is ready, trying to transfer it to the SoftGate"
Distribute "true" "true" "$WSI_DB"

#OSFOURK-18160 - restart only after everything is done. Only for Assistant and Manager - when no dtb-reconfigure is called before (=> no restart was made before)
stopDTB
